Skip to content

Fix tsx import issue for envio dev - #908

Merged
DZakh merged 19 commits into
mainfrom
claude/fix-envio-jsx-import-fZktL
Jan 15, 2026
Merged

Fix tsx import issue for envio dev#908
DZakh merged 19 commits into
mainfrom
claude/fix-envio-jsx-import-fZktL

Conversation

@DZakh

@DZakh DZakh commented Jan 15, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features

    • TSX/ESM handler loading with auto-discovery and contract-specific handler entries surfaced in generated config.
    • Public access to finalized event registrations after startup.
  • Chores

    • Generated project scripts removed from package metadata; CLI now runs Node-based start, migrations, and benchmarks from the project root.
  • Refactor

    • Centralized handler-loading flow and simplified startup/test sequence to produce final configuration after handlers load.

✏️ Tip: You can customize this high-level summary in your review settings.

- Remove scripts from generated/package.json, execute commands directly from rust binary
- Add tsx-register.mjs to envio package for TypeScript handler support
- Modify codegen_template to pass contract.handler via internal.config.json
- Move handler registration from Generated.res to envio HandlerLoader module
- Update snapshots for internal_config_json tests
- Update tsx-register.mjs to use node:module register() API
- Import tsx-register.mjs in HandlerLoader.res before loading handlers
- Remove --import flag from node command in commands.rs
- Main.start now calls HandlerLoader.registerAllHandlers internally
- Remove registerAllHandlers parameter from Main.start and TestIndexer.initTestWorker
- Update Index.res, TestIndexerWorker.res, and TestHelpers_MockDb.res.hbs
@coderabbitai

coderabbitai Bot commented Jan 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Rate limit exceeded

@DZakh has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 41 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between c61b07d and 681c36a.

📒 Files selected for processing (11)
  • codegenerator/cli/npm/envio/src/Config.res
  • codegenerator/cli/npm/envio/src/HandlerLoader.res
  • codegenerator/cli/npm/envio/src/Main.res
  • codegenerator/cli/npm/envio/src/TestIndexer.res
  • codegenerator/cli/src/hbs_templating/codegen_templates.rs
  • codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
  • codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs
  • codegenerator/cli/templates/static/codegen/src/Index.res
  • codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res
  • scenarios/test_codegen/test/EventFilters_test.res
  • scenarios/test_codegen/test/helpers/Mock.res
📝 Walkthrough

Walkthrough

Adds a centralized HandlerLoader (TSX/ESM + dynamic imports), surfaces per-contract handler metadata in Config, updates generated templates and startup flows to use the new loader, and switches Rust CLI invocations from pnpm to direct Node execution.

Changes

Cohort / File(s) Summary
Config & schemas
\codegenerator/cli/npm/envio/src/Config.res``
Added contractHandler type and contractHandlers: array<contractHandler> to Config.t; extended contractConfigSchema with optional handler; added handlerLoadingParams and getHandlerLoadingParams to surface contract handler data.
Handler loader module
\codegenerator/cli/npm/envio/src/HandlerLoader.res``
New module providing registerTsx, registerContractHandlers, autoLoadFromSrcHandlers, and registerAllHandlers to enable TSX/ESM support, glob-based auto-loading, per-contract handler loading, and orchestration with error handling.
Entrypoints & event register
\codegenerator/cli/npm/envio/src/Main.res`, `codegenerator/cli/npm/envio/src/TestIndexer.res`, `codegenerator/cli/npm/envio/src/EventRegister.res`, `codegenerator/cli/npm/envio/src/EventRegister.resi``
Changed start / initTestWorker signatures to use ~registerAllHandlers: unit => promise<Config.t>; added EventRegister.getRegistrations to read finalized registrations after handler loading.
Generated template changes
\codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs`, `codegenerator/cli/templates/dynamic/codegen/package.json.hbs``
Removed in-template handler-registration logic and removed generated scripts block; added delegation to centralized HandlerLoader.registerAllHandlers and introduced handlerLoadingParams + configWithoutRegistrations usage.
Test template adjustments
\codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs`, `codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res.hbs``
Updated test helpers to obtain config/registrations from new flows (no configWithoutRegistrations); removed pre-import tsx loader registration in worker template.
Templating serialization
\codegenerator/cli/src/hbs_templating/codegen_templates.rs``
Added handler: Option<String> to InternalContractConfig with camelCase serialization and skip-if-none to emit handler paths when present.
Rust CLI -> Node runtime changes
\codegenerator/cli/src/commands.rs``
Replaced pnpm/pnpm-run invocations with direct node execution (uses pathdiff::diff_paths, added to_js_path helper) and runs inline node -e scripts for migrations/benchmarks/entry.
Node ESM bindings
\codegenerator/cli/npm/envio/src/bindings/NodeJs.res``
Added Node bindings: process.cwd, url.pathToFileURL/toString, import.meta.url, and node:module.register to support file:// URLs and module registration at runtime.

Sequence Diagram(s)

sequenceDiagram
    participant CLI as Rust CLI (commands.rs)
    participant Node as Node.js runtime
    participant App as Generated entry (Index.res.mjs)
    participant HL as HandlerLoader
    participant TSX as TSX/ESM loader
    participant FS as Project filesystem

    CLI->>Node: spawn Node to run Generated entry
    Node->>App: execute Generated module
    App->>HL: HandlerLoader.registerAllHandlers(~ecosystem,~multichain,~handlers,~contractHandlers)
    HL->>TSX: registerTsx()
    TSX-->>HL: TSX/ESM enabled
    HL->>FS: glob discover handler files (src/handlers...)
    FS-->>HL: list of handler module paths
    loop per discovered handler
      HL->>Node: dynamic import(handler module path as file:// URL)
      Node-->>HL: handler module loaded
    end
    loop per contractHandler with handler path
      HL->>Node: import contract-specific handler path (if provided)
      Node-->>HL: contract handler loaded
    end
    HL-->>App: handler loading complete
    App->>EventRegister: EventRegister.getRegistrations()
    EventRegister-->>App: registrations
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • JonoPrest
  • JasoonS

Poem

🐇 I hopped through modules with a curious twitch,

TSX awakened, ESM found its niche,
Contracts now carry handler clues,
Node runs straight — no pnpm blues,
The rabbit cheers: imports stitched!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Fix tsx import issue for envio dev' is concise and directly addresses the main technical issue being resolved in the PR. It accurately reflects the primary change (fixing tsx/dynamic import resolution) mentioned throughout the PR objectives and commit messages.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Fix all issues with AI agents
In `@codegenerator/cli/npm/envio/src/HandlerLoader.res`:
- Around line 1-2: The external binding for globIterator is wrong: change the
declaration from promise<Utils.asyncIterator<string>> to return
Utils.asyncIterator<string> (i.e. external globIterator: string =>
Utils.asyncIterator<string> = "glob") and update its usage by removing the
unnecessary await (replace let iterator = await globIterator(srcPattern) with
let iterator = globIterator(srcPattern)); reference symbol: globIterator and its
call site in HandlerLoader.res.
- Around line 8-11: The registerTsx helper uses pathToFileURL("./") as the
parentURL when calling register("tsx/esm", ...), which incorrectly bases
resolution on CWD; change registerTsx to pass the current module's file URL
(import.meta.url) as the parentURL instead. In ReScript, obtain import.meta.url
via %raw("import.meta.url") or an external binding and call register("tsx/esm",
importMetaUrl) (referencing registerTsx, register, pathToFileURL, and
import.meta.url) so module specifier resolution uses the importing module's URL.

In `@codegenerator/cli/src/commands.rs`:
- Around line 401-413: The import string built in migration_script uses
relative_generated.display() which can contain backslashes on Windows and will
break the JS import; convert the path to a POSIX-style path (replace backslashes
with forward slashes or use a to_slash helper) before interpolating it into
migration_script so the generated import always uses forward slashes; update the
code around relative_generated and migration_script (and ensure execute_command
is still called with the same current_dir) to use the sanitized forward-slash
path.
- Around line 382-394: The import path built for migration_script uses
relative_generated directly and will contain Windows backslashes; normalize the
path to use forward slashes before embedding it into migration_script (e.g.,
convert relative_generated to a string and replace backslashes with '/' or use a
cross-platform to-slash helper) so the generated
"import(\"./.../src/db/Migrations.res.mjs\")" string is valid on Windows; update
the code around the migration_script construction in commands.rs (where
relative_generated and migration_script are created) and keep using
execute_command("node", args, current_dir).await.
- Around line 433-446: The benchmark import string in print_summary builds a JS
import using relative_generated.display(), which on Windows yields backslashes;
update print_summary to convert the relative path to a POSIX-style path (use the
existing helper, e.g., to_posix_path or similar) before embedding it in
benchmark_script so the import string uses forward slashes (e.g., use
to_posix_path(&relative_generated) in the format! call that builds
benchmark_script); keep the rest of the logic (args, execute_command) unchanged.
- Around line 173-188: relative_generated is converted to a string using
PathBuf::display which emits platform-specific separators (backslashes on
Windows) that break JS imports; add a helper like to_js_path(path: &Path) ->
String that replaces backslashes with forward slashes and use it when building
index_path (e.g., build index_path from to_js_path(&relative_generated) while
keeping the "./" prefix), and apply the same helper for similar usages in
run_up_migrations and run_drop_schema; leave execute_command invocation the
same.
- Around line 356-368: The relative path used in migration_script is produced by
relative_generated.display() which yields backslashes on Windows and breaks the
JS import; normalize the path to use forward slashes (same fix as start_indexer)
before embedding: convert relative_generated to a string (e.g.,
to_string_lossy()) and replace backslashes with '/' (or otherwise ensure POSIX
separators), then build migration_script from that normalized_path and call
execute_command as before.

In `@codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs`:
- Line 45: Remove the unused module-level binding by deleting the line that
assigns config from Generated.makeGeneratedConfig() (the top-level "let config =
Generated.makeGeneratedConfig()"); the function makeProcessEvents already
creates and uses its own local config, so remove the module-level config to
eliminate dead code and avoid shadowing/confusion.
🧹 Nitpick comments (2)
codegenerator/cli/src/commands.rs (1)

350-368: Consider extracting duplicated relative path computation.

The pattern of computing diff_paths and handling the error is repeated across run_up_migrations, run_drop_schema, and run_db_setup. This could be extracted into a module-level helper to reduce duplication.

Suggested refactor
fn get_relative_generated_path(config: &SystemConfig) -> anyhow::Result<String> {
    let relative = diff_paths(
        &config.parsed_project_paths.generated,
        &config.parsed_project_paths.project_root,
    )
    .ok_or_else(|| anyhow!("Failed to compute relative path to generated directory"))?;
    
    // Normalize to forward slashes for JavaScript compatibility
    Ok(relative.to_string_lossy().replace('\\', "/"))
}

Also applies to: 382-394, 401-413

codegenerator/cli/npm/envio/src/HandlerLoader.res (1)

29-31: Consider including .tsx files in the glob pattern.

Given that this PR is titled "Fix tsx import issue for envio dev" and registerTsx() is called to enable TypeScript/TSX support, the glob pattern should likely include .tsx files: *.{js,mjs,ts,tsx}.

♻️ Proposed fix
 let autoLoadFromSrcHandlers = async (~handlers: string) => {
   // Relative to cwd (project root)
-  let srcPattern = `./${handlers}/**/*.{js,mjs,ts}`
+  let srcPattern = `./${handlers}/**/*.{js,mjs,ts,tsx}`
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5f59a68 and b128e7c.

⛔ Files ignored due to path filters (5)
  • codegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_generated_for_evm.snap is excluded by !**/*.snap
  • codegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_generated_for_fuel.snap is excluded by !**/*.snap
  • codegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_omits_default_values.snap is excluded by !**/*.snap
  • codegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_with_all_options.snap is excluded by !**/*.snap
  • codegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_with_multiple_contracts.snap is excluded by !**/*.snap
📒 Files selected for processing (11)
  • codegenerator/cli/npm/envio/src/Config.res
  • codegenerator/cli/npm/envio/src/HandlerLoader.res
  • codegenerator/cli/npm/envio/src/Main.res
  • codegenerator/cli/npm/envio/src/TestIndexer.res
  • codegenerator/cli/src/commands.rs
  • codegenerator/cli/src/hbs_templating/codegen_templates.rs
  • codegenerator/cli/templates/dynamic/codegen/package.json.hbs
  • codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
  • codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs
  • codegenerator/cli/templates/static/codegen/src/Index.res
  • codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res
💤 Files with no reviewable changes (4)
  • codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res
  • codegenerator/cli/templates/static/codegen/src/Index.res
  • codegenerator/cli/templates/dynamic/codegen/package.json.hbs
  • codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{res,resi}

📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)

**/*.{res,resi}: Always use ReScript 11 documentation
Never suggest ReasonML syntax
Never use [| item |] to create an array. Use [ item ] instead
Must always use = for setting value to a field. Use := only for ref values created using ref function
Use records when working with structured data, and objects to conveniently pass payload data between functions
Never use %raw to access object fields if you know the type

Files:

  • codegenerator/cli/npm/envio/src/Config.res
  • codegenerator/cli/npm/envio/src/TestIndexer.res
  • codegenerator/cli/npm/envio/src/HandlerLoader.res
  • codegenerator/cli/npm/envio/src/Main.res
🧠 Learnings (11)
📓 Common learnings
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For dynamically created contracts identified by lack of address in subgraph.yaml (templates), implement contract registration using `contractRegister` above the handler. Example: `Factory.PairCreated.contractRegister(({ event, context }) => { context.addPair(event.params.pair); });` Remove address field from dynamic contracts in config.yaml.
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Create directory structure matching the original subgraph exactly with contract-specific handler files (not single EventHandlers.ts). Use exact filenames from the original subgraph. Update config.yaml to point to contract-specific handler files instead of a single EventHandlers.ts.
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/EventHandlers.ts : Clear all boilerplate logic from EventHandlers.ts when starting migration. Replace boilerplate with empty handlers containing TODO comments referencing the original subgraph location for implementation.
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Create directory structure matching the original subgraph exactly with contract-specific handler files (not single EventHandlers.ts). Use exact filenames from the original subgraph. Update config.yaml to point to contract-specific handler files instead of a single EventHandlers.ts.

Applied to files:

  • codegenerator/cli/npm/envio/src/Config.res
  • codegenerator/cli/npm/envio/src/HandlerLoader.res
  • codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs
  • codegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For dynamically created contracts identified by lack of address in subgraph.yaml (templates), implement contract registration using `contractRegister` above the handler. Example: `Factory.PairCreated.contractRegister(({ event, context }) => { context.addPair(event.params.pair); });` Remove address field from dynamic contracts in config.yaml.

Applied to files:

  • codegenerator/cli/npm/envio/src/Config.res
  • codegenerator/cli/npm/envio/src/HandlerLoader.res
  • codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs
  • codegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/EventHandlers.ts : Clear all boilerplate logic from EventHandlers.ts when starting migration. Replace boilerplate with empty handlers containing TODO comments referencing the original subgraph location for implementation.

Applied to files:

  • codegenerator/cli/npm/envio/src/TestIndexer.res
  • codegenerator/cli/npm/envio/src/HandlerLoader.res
  • codegenerator/cli/npm/envio/src/Main.res
  • codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs
📚 Learning: 2026-01-14T13:33:41.342Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T13:33:41.342Z
Learning: Applies to **/{src,agents,lib}/**/*.{py,ts,tsx,js,jsx} : Include error handling and fallback strategies in agent implementations

Applied to files:

  • codegenerator/cli/npm/envio/src/HandlerLoader.res
📚 Learning: 2026-01-14T13:34:03.676Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2026-01-14T13:34:03.676Z
Learning: Applies to codegenerator/cli/templates/static/shared/src/schema.graphql : After any change to `schema.graphql` or `config.yaml`, run `pnpm codegen`

Applied to files:

  • codegenerator/cli/src/commands.rs
📚 Learning: 2026-01-14T13:34:03.676Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2026-01-14T13:34:03.676Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Once compilation is successful, run `TUI_OFF=true pnpm dev` to catch any runtime errors

Applied to files:

  • codegenerator/cli/src/commands.rs
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/{utils,helpers}/**/*.ts : Implement helper functions with NO entity/handler dependencies immediately. These include functions that only depend on constants, basic math, static data arrays, or already implemented pieces. Check MDC file for existing implementations before implementing.

Applied to files:

  • codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : In Step 6 (Final Migration Verification), perform systematic handler logic review one by one, comparing to subgraph implementation. Iterate multiple times on each handler until logic is correct. Run quality checks after each review iteration.

Applied to files:

  • codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Import entity types from `generated/src/db/Entities.gen` (e.g., `Pair_t`, `Token_t`) not from `generated` directly. Use exact field names from generated types. Ensure types you set in code match schema entity property types exactly.

Applied to files:

  • codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/config.yaml : When needing access to `event.transaction.hash` or other transaction fields in handlers, MUST add field_selection in config.yaml with `transaction_fields: [hash]` (or other required fields). Apply to ALL events that need transaction data, not just Transfer events.

Applied to files:

  • codegenerator/cli/src/hbs_templating/codegen_templates.rs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_and_test
🔇 Additional comments (14)
codegenerator/cli/src/commands.rs (1)

190-195: LGTM!

The error message update from pnpm start to envio start correctly reflects the new invocation method.

codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs (1)

321-326: LGTM!

The handler registration flow correctly handles both scenarios: completing a pending registration from test setup, or invoking HandlerLoader.registerAllHandlers for fresh registration. The async/await usage is correct.

codegenerator/cli/npm/envio/src/Config.res (5)

56-59: LGTM!

The contractHandler type is well-defined with clear semantics - name identifies the contract and handler optionally specifies the handler file path.


65-65: LGTM!

The contractHandlers field is correctly added to the config type as an array of contractHandler records.


92-92: LGTM!

Schema correctly validates the optional handler field using S.option(S.string).


303-315: LGTM!

The extraction logic correctly handles both scenarios: when contracts are defined (maps to contractHandler records) and when no contracts exist (returns empty array).


321-321: LGTM!

The contractHandlers field is correctly included in the returned config object.

codegenerator/cli/npm/envio/src/HandlerLoader.res (3)

13-27: LGTM!

The function correctly handles optional handler paths and includes comprehensive error handling with both logging and error propagation.


50-61: LGTM!

The import logic with fail-fast error handling is appropriate here - if any handler file fails to load, it's better to fail early with a clear error message than to continue with partial functionality.


63-83: LGTM!

The orchestration is well-structured: tsx support is registered first, then event registration starts, handlers are loaded (first auto-discovered, then contract-specific), and finally registration is finished. The sequencing ensures all handlers are loaded before finalization.

codegenerator/cli/src/hbs_templating/codegen_templates.rs (2)

110-116: LGTM!

The InternalContractConfig struct is properly updated:

  • #[serde(rename_all = "camelCase")] ensures consistent JSON field naming
  • The optional handler field with skip_serializing_if correctly omits the field when None, keeping the JSON output clean

1577-1580: LGTM!

The handler field is correctly populated from contract.handler_path, which will be serialized into the internal config JSON for consumption by the HandlerLoader.

codegenerator/cli/npm/envio/src/Main.res (1)

245-263: LGTM!

The refactored start function has a cleaner signature by removing the ~registerAllHandlers parameter. The handler loading is now properly encapsulated via HandlerLoader.registerAllHandlers(~config), which centralizes the registration logic and reduces coupling between components.

codegenerator/cli/npm/envio/src/TestIndexer.res (1)

444-471: Correct architectural refactoring—handler registration properly centralized.

The removal of the ~registerAllHandlers parameter aligns with the new design where handler registration is orchestrated internally via HandlerLoader.n(~config) inside Main.start. The test worker correctly passes ~makeGeneratedConfig, ~persistence, and ~isTest=true; handler loading is now automatically triggered when Main.start executes, ensuring the test environment properly initializes handlers without requiring explicit parameter passing.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread codegenerator/cli/npm/envio/src/HandlerLoader.res Outdated
Comment thread codegenerator/cli/npm/envio/src/HandlerLoader.res Outdated
Comment thread codegenerator/cli/src/commands.rs
Comment thread codegenerator/cli/src/commands.rs
Comment thread codegenerator/cli/src/commands.rs
Comment thread codegenerator/cli/src/commands.rs
Comment thread codegenerator/cli/src/commands.rs
Comment thread codegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbs Outdated
The Node.js fs/promises glob function returns an AsyncIterator directly,
not a promise of an AsyncIterator. Updated the external binding and
removed the unnecessary await.
Changed registerTsx to use import.meta.url instead of pathToFileURL("./")
so module specifier resolution correctly uses the importing module's URL
rather than being incorrectly based on the current working directory.
PathBuf::display() emits platform-specific separators (backslashes on
Windows) which break JS imports. Added to_js_path helper that replaces
backslashes with forward slashes and applied it to all JS import paths
in start_indexer, run_up_migrations, run_drop_schema, run_db_setup, and
print_summary.
The to_js_path helper was defined but not imported in the nested modules
that use it. Added the import to start, db_migrate, and benchmark modules.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@codegenerator/cli/src/commands.rs`:
- Around line 4-9: The build fails because to_js_path is module-private to
commands.rs and not visible in submodules; open each submodule that uses it
(start, db_migrate, benchmark) and add an import for the helper (e.g., alongside
the existing execute_command import add use super::to_js_path; or use
crate::commands::to_js_path;), so the submodules can reference to_js_path
without changing its definition.
🧹 Nitpick comments (1)
codegenerator/cli/src/commands.rs (1)

359-431: Consistent migration script execution pattern.

All three migration functions (run_up_migrations, run_drop_schema, run_db_setup) follow the same correct pattern for path computation and Node.js execution.

Consider extracting the common path computation and script execution pattern into a helper function to reduce duplication, though this is optional given the straightforward nature of the code.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b128e7c and 97cde70.

📒 Files selected for processing (2)
  • codegenerator/cli/npm/envio/src/HandlerLoader.res
  • codegenerator/cli/src/commands.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.{res,resi}

📄 CodeRabbit inference engine (.cursor/rules/rescript.mdc)

**/*.{res,resi}: Always use ReScript 11 documentation
Never suggest ReasonML syntax
Never use [| item |] to create an array. Use [ item ] instead
Must always use = for setting value to a field. Use := only for ref values created using ref function
Use records when working with structured data, and objects to conveniently pass payload data between functions
Never use %raw to access object fields if you know the type

Files:

  • codegenerator/cli/npm/envio/src/HandlerLoader.res
🧠 Learnings (12)
📓 Common learnings
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Create directory structure matching the original subgraph exactly with contract-specific handler files (not single EventHandlers.ts). Use exact filenames from the original subgraph. Update config.yaml to point to contract-specific handler files instead of a single EventHandlers.ts.
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/EventHandlers.ts : Clear all boilerplate logic from EventHandlers.ts when starting migration. Replace boilerplate with empty handlers containing TODO comments referencing the original subgraph location for implementation.
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For dynamically created contracts identified by lack of address in subgraph.yaml (templates), implement contract registration using `contractRegister` above the handler. Example: `Factory.PairCreated.contractRegister(({ event, context }) => { context.addPair(event.params.pair); });` Remove address field from dynamic contracts in config.yaml.
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/effects/**/*.ts : For contract state fetching, migrate from TheGraph `.bind()` patterns to Effect API. Create effects that use viem's `readContract()` with proper ABI definitions. Implement error handling with fallback values. Support multichain by making RPC URLs dynamic based on event.chainId.
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : In Step 6 (Final Migration Verification), perform systematic handler logic review one by one, comparing to subgraph implementation. Iterate multiple times on each handler until logic is correct. Run quality checks after each review iteration.
📚 Learning: 2026-01-14T13:34:03.676Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2026-01-14T13:34:03.676Z
Learning: Applies to codegenerator/cli/templates/static/shared/src/schema.graphql : After any change to `schema.graphql` or `config.yaml`, run `pnpm codegen`

Applied to files:

  • codegenerator/cli/src/commands.rs
📚 Learning: 2026-01-14T13:34:03.676Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2026-01-14T13:34:03.676Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : After any change to TypeScript files, run `pnpm tsc --noEmit` to ensure it compiles successfully

Applied to files:

  • codegenerator/cli/src/commands.rs
📚 Learning: 2026-01-14T13:34:03.676Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2026-01-14T13:34:03.676Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js,res,graphql,yaml} : Include HyperIndex documentation, example indexers (Uniswap v4 and Safe), and understand that HyperIndex is not a TheGraph subgraph

Applied to files:

  • codegenerator/cli/src/commands.rs
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : In Step 6 (Final Migration Verification), perform systematic handler logic review one by one, comparing to subgraph implementation. Iterate multiple times on each handler until logic is correct. Run quality checks after each review iteration.

Applied to files:

  • codegenerator/cli/src/commands.rs
  • codegenerator/cli/npm/envio/src/HandlerLoader.res
📚 Learning: 2026-01-14T13:34:03.676Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2026-01-14T13:34:03.676Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Once compilation is successful, run `TUI_OFF=true pnpm dev` to catch any runtime errors

Applied to files:

  • codegenerator/cli/src/commands.rs
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Create directory structure matching the original subgraph exactly with contract-specific handler files (not single EventHandlers.ts). Use exact filenames from the original subgraph. Update config.yaml to point to contract-specific handler files instead of a single EventHandlers.ts.

Applied to files:

  • codegenerator/cli/npm/envio/src/HandlerLoader.res
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For dynamically created contracts identified by lack of address in subgraph.yaml (templates), implement contract registration using `contractRegister` above the handler. Example: `Factory.PairCreated.contractRegister(({ event, context }) => { context.addPair(event.params.pair); });` Remove address field from dynamic contracts in config.yaml.

Applied to files:

  • codegenerator/cli/npm/envio/src/HandlerLoader.res
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/EventHandlers.ts : Clear all boilerplate logic from EventHandlers.ts when starting migration. Replace boilerplate with empty handlers containing TODO comments referencing the original subgraph location for implementation.

Applied to files:

  • codegenerator/cli/npm/envio/src/HandlerLoader.res
📚 Learning: 2026-01-14T13:33:41.342Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-14T13:33:41.342Z
Learning: Applies to **/{src,agents,lib}/**/*.{py,ts,tsx,js,jsx} : Include error handling and fallback strategies in agent implementations

Applied to files:

  • codegenerator/cli/npm/envio/src/HandlerLoader.res
📚 Learning: 2026-01-14T13:34:33.837Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2026-01-14T13:34:33.837Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/{utils,helpers}/**/*.ts : When implementing helper functions, implement the COMPLETE business logic from the original subgraph, not just placeholders. Use documented Envio patterns for external calls. Include all fallback logic and error handling. Do NOT just add TODO comments.

Applied to files:

  • codegenerator/cli/npm/envio/src/HandlerLoader.res
📚 Learning: 2026-01-14T13:33:47.702Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-14T13:33:47.702Z
Learning: Applies to **/*.{test.res,test.js,test.ts,test.tsx,spec.res,spec.js,spec.ts,spec.tsx} : Prefer Public module API for testing

Applied to files:

  • codegenerator/cli/npm/envio/src/HandlerLoader.res
🪛 GitHub Actions: Build & Test Scenario
codegenerator/cli/src/commands.rs

[error] 188-188: cannot find function to_js_path in this scope. consider importing it (e.g., use crate::commands::to_js_path;).


[error] 371-371: cannot find function to_js_path in this scope. consider importing it (e.g., use crate::commands::to_js_path;).


[error] 397-397: cannot find function to_js_path in this scope. consider importing it (e.g., use crate::commands::to_js_path;).


[error] 449-449: cannot find function to_js_path in this scope. consider importing it (e.g., use crate::commands::to_js_path;).

🔇 Additional comments (7)
codegenerator/cli/npm/envio/src/HandlerLoader.res (4)

1-10: LGTM! TSX registration setup looks correct.

The external bindings are properly defined:

  • globIterator correctly returns Utils.asyncIterator<string> directly (not wrapped in Promise)
  • import.meta.url is accessed via %raw as recommended for ReScript
  • registerTsx properly passes importMetaUrl as the parentURL argument to register

12-26: LGTM! Contract handler loading with proper error handling.

The function correctly:

  • Skips loading when handler is None
  • Uses NodeJs.ImportMeta.resolve for proper module resolution
  • Logs errors with context before re-raising

28-60: LGTM! Auto-loading handlers with sensible filtering.

The glob-based handler loading is well implemented:

  • Pattern correctly targets JS/TS files in the handlers directory
  • Test/spec files are properly excluded
  • Error message helpfully mentions the Node.js 22+ requirement for fs/promises.glob
  • Files are imported in parallel with Promise.all

62-82: LGTM! Well-orchestrated handler registration flow.

The function correctly sequences:

  1. TSX registration (must happen first for TypeScript support)
  2. Event registration start
  3. Auto-loading general handlers
  4. Loading contract-specific handlers
  5. Event registration finish
codegenerator/cli/src/commands.rs (3)

4-9: Good addition of the cross-platform path helper.

This helper correctly addresses the Windows path separator issue that was flagged in previous reviews. The implementation is straightforward and well-documented.


180-208: LGTM! Direct Node.js execution with proper path handling.

The changes correctly:

  • Compute relative paths using pathdiff::diff_paths
  • Normalize paths for JS imports using to_js_path
  • Execute from project root for proper handler resolution
  • Provide helpful error messages

440-460: LGTM! Benchmark script execution follows the established pattern.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread codegenerator/cli/src/commands.rs
The module-level config binding was unused since makeProcessEvents
creates its own local config. Removed the dead code to avoid
shadowing and confusion.
Added Module.register and ImportMeta.url bindings to NodeJs.res.
Updated HandlerLoader.res to use these bindings instead of local
definitions.
Restore the configWithoutRegistrations binding which is used by tests,
migrations, and other places that need config without handler registration.
@DZakh

DZakh commented Jan 15, 2026

Copy link
Copy Markdown
Member Author

Also, it's a step closer to #499

claude and others added 7 commits January 15, 2026 10:23
Tests need a way to register handlers before running. Added
registerAllHandlers function that delegates to HandlerLoader.
When tests run with --import tsx, calling module.register again throws
an error. Wrapped registerTsx in try-catch to silently ignore when tsx
is already loaded.
Dynamic imports were resolving relative to the HandlerLoader module
location (in node_modules/envio) instead of process.cwd() (project root).

Added toImportUrl helper that:
1. Resolves paths relative to process.cwd()
2. Converts to file:// URL for dynamic import

Also added NodeJs.Process.cwd and NodeJs.Url.pathToFileURL bindings.
The config needs handlers to be registered BEFORE it's created so that
event registrations are captured. This restructures the flow:

1. HandlerLoader.registerAllHandlers now takes individual params instead
   of full Config.t (ecosystem, multichain, handlers, contractHandlers)

2. Config.getHandlerLoadingParams extracts just the params needed for
   handler loading from internalConfigJson without building full config

3. Generated.registerAllHandlers:
   - Extracts handler loading params from internalConfigJson
   - Calls HandlerLoader.registerAllHandlers with these params
   - Returns fresh config after handlers are registered

4. Main.start now takes registerAllHandlers instead of makeGeneratedConfig

5. EventRegister.getRegistrations added to get registrations after
   finishRegistration was called

Updated files:
- HandlerLoader.res: Takes individual params
- Config.res: Added getHandlerLoadingParams
- Generated.res.hbs: Added handlerLoadingParams, updated registerAllHandlers
- Main.res: Takes registerAllHandlers param
- EventRegister.res/resi: Added getRegistrations
- TestIndexer.res: Updated to use registerAllHandlers
- Index.res: Updated Main.start call
- TestIndexerWorker.res: Updated to use registerAllHandlers
- TestHelpers_MockDb.res.hbs: Updated registration flow
Reverted to simpler approach where:
1. configWithoutRegistrations = makeGeneratedConfig()
2. registerAllHandlers(~config=configWithoutRegistrations)
3. config = makeGeneratedConfig() (fresh config with registrations)

Removed the handlerLoadingParams extraction since we can just pass
the initial config to registerAllHandlers.
@DZakh
DZakh enabled auto-merge (squash) January 15, 2026 12:08
@DZakh
DZakh requested a review from JonoPrest January 15, 2026 12:08
@DZakh
DZakh merged commit b0fb0c0 into main Jan 15, 2026
8 checks passed
@DZakh
DZakh deleted the claude/fix-envio-jsx-import-fZktL branch January 15, 2026 14:36
@DZakh

DZakh commented Jan 15, 2026

Copy link
Copy Markdown
Member Author

@JonoPrest I merged the pr since I already released in alpha.7

Still it would be nice to have it reviewed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants