Fix tsx import issue for envio dev - #908
Conversation
- 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
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. 📒 Files selected for processing (11)
📝 WalkthroughWalkthroughAdds 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
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ 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. Comment |
There was a problem hiding this comment.
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_pathsand handling the error is repeated acrossrun_up_migrations,run_drop_schema, andrun_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.tsxfiles 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.tsxfiles:*.{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
⛔ 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.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_generated_for_fuel.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_omits_default_values.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_with_all_options.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_json_code_with_multiple_contracts.snapis excluded by!**/*.snap
📒 Files selected for processing (11)
codegenerator/cli/npm/envio/src/Config.rescodegenerator/cli/npm/envio/src/HandlerLoader.rescodegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/src/commands.rscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbscodegenerator/cli/templates/static/codegen/src/Index.rescodegenerator/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 usingreffunction
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.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/npm/envio/src/HandlerLoader.rescodegenerator/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.rescodegenerator/cli/npm/envio/src/HandlerLoader.rescodegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbscodegenerator/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.rescodegenerator/cli/npm/envio/src/HandlerLoader.rescodegenerator/cli/templates/dynamic/codegen/src/TestHelpers_MockDb.res.hbscodegenerator/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.rescodegenerator/cli/npm/envio/src/HandlerLoader.rescodegenerator/cli/npm/envio/src/Main.rescodegenerator/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 starttoenvio startcorrectly 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.registerAllHandlersfor fresh registration. The async/await usage is correct.codegenerator/cli/npm/envio/src/Config.res (5)
56-59: LGTM!The
contractHandlertype is well-defined with clear semantics -nameidentifies the contract andhandleroptionally specifies the handler file path.
65-65: LGTM!The
contractHandlersfield is correctly added to the config type as an array ofcontractHandlerrecords.
92-92: LGTM!Schema correctly validates the optional
handlerfield usingS.option(S.string).
303-315: LGTM!The extraction logic correctly handles both scenarios: when contracts are defined (maps to
contractHandlerrecords) and when no contracts exist (returns empty array).
321-321: LGTM!The
contractHandlersfield 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
InternalContractConfigstruct is properly updated:
#[serde(rename_all = "camelCase")]ensures consistent JSON field naming- The optional
handlerfield withskip_serializing_ifcorrectly omits the field whenNone, keeping the JSON output clean
1577-1580: LGTM!The
handlerfield is correctly populated fromcontract.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
startfunction has a cleaner signature by removing the~registerAllHandlersparameter. The handler loading is now properly encapsulated viaHandlerLoader.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
~registerAllHandlersparameter aligns with the new design where handler registration is orchestrated internally viaHandlerLoader.n(~config)insideMain.start. The test worker correctly passes~makeGeneratedConfig,~persistence, and~isTest=true; handler loading is now automatically triggered whenMain.startexecutes, 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.
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.
There was a problem hiding this comment.
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
📒 Files selected for processing (2)
codegenerator/cli/npm/envio/src/HandlerLoader.rescodegenerator/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 usingreffunction
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.rscodegenerator/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:
globIteratorcorrectly returnsUtils.asyncIterator<string>directly (not wrapped in Promise)import.meta.urlis accessed via%rawas recommended for ReScriptregisterTsxproperly passesimportMetaUrlas theparentURLargument toregister
12-26: LGTM! Contract handler loading with proper error handling.The function correctly:
- Skips loading when handler is
None- Uses
NodeJs.ImportMeta.resolvefor 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:
- TSX registration (must happen first for TypeScript support)
- Event registration start
- Auto-loading general handlers
- Loading contract-specific handlers
- 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.
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.
|
Also, it's a step closer to #499 |
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.
|
@JonoPrest I merged the pr since I already released in alpha.7 Still it would be nice to have it reviewed |
Summary by CodeRabbit
New Features
Chores
Refactor
✏️ Tip: You can customize this high-level summary in your review settings.