New Testing Framework (main PR)#889
Conversation
….com:enviodev/hyperindex into dz/test-indexer-with-vitest
|
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 (9)
📝 WalkthroughWalkthroughAdds a worker-based TestIndexer harness and proxy storage bridge, migrates tests to Vitest with ReScript bindings, exposes createTestIndexer/TestIndexer in generated outputs, renames rescript-specific schema types to a unified type_schema, and updates templates, runtime Node/worker bindings, and docs. Changes
Sequence Diagram(s)sequenceDiagram
participant Caller as Caller (test/runtime)
participant Main as Main Thread (envio)
participant Proxy as ProxyStorage (Main)
participant Worker as Worker Thread
participant Indexer as Generated Indexer (Worker)
Caller->>Main: createTestIndexer(...).process(chains)
Main->>Worker: spawn(workerPath, workerData={processConfig, initialState})
Worker->>Indexer: initialize/register handlers
Indexer->>Worker: storage request (LoadByIds / LoadByField / WriteBatch)
Worker->>Main: postMessage(workerPayload)
Main->>Proxy: sendRequest(payload) -> Persistence access
Proxy-->>Main: Response/Error
Main-->>Worker: postMessage(mainPayload)
Worker->>Indexer: deliver response -> continue processing
loop per-checkpoint
Indexer->>Worker: more storage ops
Worker->>Main: forward ops
Main-->>Worker: responses
end
Indexer->>Worker: finish -> final changes
Worker->>Main: exit with final changes
Main->>Caller: aggregate and return result
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 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: 4
🤖 Fix all issues with AI agents
In @codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res:
- Around line 62-65: The Error branch currently calls Js.Exn.raiseError(message)
which throws immediately instead of returning an exception to reject; change the
branch to create and pass an Error/exception object to reject (e.g., construct a
JS Error with the message or an Exn value) instead of calling Js.Exn.raiseError
— replace the line in the Error({message}) arm that references Js.Exn.raiseError
with code that builds an Error/exception object and calls reject(thatError) so
reject is actually invoked (look for the switch on msg.payload, the
Error({message}) arm, and the resolve/reject callbacks).
In @codegenerator/cli/templates/dynamic/codegen/index.d.ts.hbs:
- Around line 10-12: The declaration for createTestIndexer is incorrect: update
the signature in index.d.ts.hbs so it matches the actual ReScript export (a
zero-arg function returning the TestIndexer specialized by the
testIndexerProcessConfig type) — e.g. change export const createTestIndexer: ()
=> TestIndexer; to export const createTestIndexer: () =>
TestIndexer<testIndexerProcessConfig> (or the equivalent TypeScript
representation used in ./src/Types.ts), and ensure the testIndexerProcessConfig
type is exported from Types.ts so the generic specialization resolves; reference
the createTestIndexer, TestIndexer and testIndexerProcessConfig symbols to
locate and update the template to match
codegenerator/cli/src/hbs_templating/codegen_templates.rs expected signature.
In @codegenerator/cli/templates/static/erc20_template/typescript/config.yaml:
- Around line 11-14: Update the ERC20 contract entry's address field (under the
contracts list with name: ERC20 and start_block: 20000000) to the canonical UNI
mainnet address 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 so the template
monitors the actual UNI token instead of Loot: Adventure Gold.
🧹 Nitpick comments (8)
codegenerator/cli/npm/envio/index.d.ts (1)
486-492: Consider using more specific types forTestIndexerProgress.The
checkpointsandchangesfields useunknown[]andRecord<string, unknown[]>, which provides minimal type safety. If the structure of checkpoints and entity changes is known, consider exposing more specific types to improve the developer experience when consuming test results.codegenerator/cli/npm/envio/src/bindings/Vitest.res (1)
22-28: Clarify matcher categorization.The
toContainItemmatcher (line 27) is grouped under "String matchers" comment (line 22) but it's actually an array matcher. Consider moving the comment or reorganizing for clarity.♻️ Suggested reorganization
// String matchers toContain: string => unit, toMatch: Js.Re.t => unit, toMatchString: string => unit, + // Array matchers toContainItem: 'a => unit, toHaveLength: int => unit, - // Array matchers - toContainItem: 'a => unit, - toHaveLength: int => unit,codegenerator/cli/src/hbs_templating/codegen_templates.rs (1)
1932-1948: Consider renaming test constants for consistency.The constants are named
RESCRIPT_*_TYPEbut now holdTypeIdentvalues rather thanRescriptTypeIdent. While functionally correct, the naming could be confusing.♻️ Optional rename suggestion
- const RESCRIPT_BIG_INT_TYPE: TypeIdent = TypeIdent::BigInt; - const RESCRIPT_ADDRESS_TYPE: TypeIdent = TypeIdent::Address; - const RESCRIPT_STRING_TYPE: TypeIdent = TypeIdent::String; + const BIG_INT_TYPE: TypeIdent = TypeIdent::BigInt; + const ADDRESS_TYPE: TypeIdent = TypeIdent::Address; + const STRING_TYPE: TypeIdent = TypeIdent::String;scenarios/erc20_multichain_factory/test/Handler_Test.res (1)
18-25: Make thechangesassertion robust (prototype/representation differences).
Deep-equality onJs.Dict.empty()can be brittle if the runtime returns{}vsObject.create(null); consider asserting emptiness via keys/entries instead.Proposed tweak
- Assert.deepEqual( - result, - { - checkpoints: [], - changes: Js.Dict.empty(), - }, - ~message="Test Indexer should return the correct result", - ) + Assert.equal(result.checkpoints->Array.length, 0, ~message="expected no checkpoints") + Assert.equal(result.changes->Js.Dict.keys->Array.length, 0, ~message="expected no changes")codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res (1)
1-13: Don’t skip runtime validation for this worker-thread wiring.
Please run the indexer after these template changes (per team learnings):TUI_OFF=true pnpm dev.codegenerator/cli/src/config_parsing/event_parsing.rs (1)
3-3: Consistent migration to TypeIdent type system.The function correctly updates all type mappings from RescriptTypeIdent to TypeIdent:
- Primitive types (lines 112-118)
- Recursive array handling (lines 119-133)
- Tuple type construction (lines 134-150)
The tests verify the conversions work correctly with the new type system.
Consider renaming
abi_to_rescript_typetoabi_to_type_identto better reflect that it now returnsTypeIdentrather than a ReScript-specific type. This would improve code clarity as part of the broader migration away from ReScript-specific naming.♻️ Optional rename suggestion
-pub fn abi_to_rescript_type(param: &EthereumEventParam) -> TypeIdent { +pub fn abi_to_type_ident(param: &EthereumEventParam) -> TypeIdent {And update all call sites accordingly.
Also applies to: 110-150
codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res (1)
132-134: Consider adding more explicit stubs for test-only methods.The
executeUnsafeandsetChainMetamethods returnObj.magic()which is a potential runtime hazard if these methods are ever called during tests. Consider either:
- Raising an explicit error like the rollback methods do
- Adding a comment explaining why these are safe no-ops in test context
codegenerator/cli/npm/envio/src/TestIndexer.res (1)
188-192: Redundant JSON serialization/deserialization.The pattern
processConfig->Utils.magic->Js.Json.serializeExn->Js.Json.parseExnfollowed by anotherJs.Json.serializeExn->Js.Json.parseExnappears to be an unnecessarily convoluted way to pass data. This double serialize/parse cycle could lose precision or behave unexpectedly with certain data types.♻️ Suggested simplification
If the goal is to ensure the data is a plain JSON object for the worker, consider:
- let workerDataObj = { - "processConfig": processConfig->Utils.magic->Js.Json.serializeExn->Js.Json.parseExn, - "initialState": initialState->Utils.magic, - } - let workerData = workerDataObj->Js.Json.serializeExn->Js.Json.parseExn + let workerData = { + "processConfig": processConfig->Utils.magic, + "initialState": initialState->Utils.magic, + }->Utils.magicOr if serialization is truly needed for worker data cloning, a single round-trip should suffice.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
codegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__indexer_code_generates_correct_types_and_values.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__indexer_code_multiple_chains.snapis excluded by!**/*.snap
📒 Files selected for processing (38)
.cursor/commands/testrust.mdadr/why-vitest.mdcodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/npm/envio/src/TestIndexerProxyStorage.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.rescodegenerator/cli/npm/envio/src/bindings/Vitest.rescodegenerator/cli/src/config_parsing/entity_parsing.rscodegenerator/cli/src/config_parsing/event_parsing.rscodegenerator/cli/src/config_parsing/system_config.rscodegenerator/cli/src/fuel/abi.rscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/src/lib.rscodegenerator/cli/src/type_schema.rscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/dynamic/codegen/index.js.hbscodegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.res.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/blank_template/rescript/rescript.jsoncodegenerator/cli/templates/static/blank_template/rescript/src/Indexer_test.rescodegenerator/cli/templates/static/blank_template/rescript/vitest.config.tscodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/templates/static/erc20_template/typescript/config.yamlcodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/factory_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/svmblock_template/typescript/src/indexer.test.tsscenarios/erc20_multichain_factory/test/Handler_Test.resscenarios/test_codegen/src/handlers/EventHandlers.resscenarios/test_codegen/test/EventHandler_test.ts
💤 Files with no reviewable changes (2)
- codegenerator/cli/templates/dynamic/codegen/src/Types.res.hbs
- codegenerator/cli/templates/static/blank_template/rescript/rescript.json
🧰 Additional context used
📓 Path-based instructions (5)
codegenerator/cli/templates/dynamic/**/*.hbs
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Templates in Handlebars format (.hbs) live under
codegenerator/cli/templates/dynamic/
Files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/templates/dynamic/codegen/index.js.hbs
**/*.{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:
scenarios/test_codegen/src/handlers/EventHandlers.rescodegenerator/cli/templates/static/blank_template/rescript/src/Indexer_test.rescodegenerator/cli/npm/envio/src/bindings/Vitest.rescodegenerator/cli/npm/envio/src/TestIndexerProxyStorage.resscenarios/erc20_multichain_factory/test/Handler_Test.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.rescodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/TestIndexer.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript
.resmodules directly; ignore compiled.jsartifacts
Files:
scenarios/test_codegen/src/handlers/EventHandlers.rescodegenerator/cli/templates/static/blank_template/rescript/src/Indexer_test.rescodegenerator/cli/npm/envio/src/bindings/Vitest.rescodegenerator/cli/npm/envio/src/TestIndexerProxyStorage.resscenarios/erc20_multichain_factory/test/Handler_Test.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.rescodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/TestIndexer.res
**/*.{test,spec}.{ts,tsx,js,jsx,res}
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
**/*.{test,spec}.{ts,tsx,js,jsx,res}: Always use single assert to check the whole value instead of multiple asserts for every field
Prefer Public module API for testing
Use_onlyto specify which tests to run during test development
Files:
codegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.ts
codegenerator/cli/templates/static/**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Static ReScript template files live under
codegenerator/cli/templates/static/and are copied verbatim
Files:
codegenerator/cli/templates/static/blank_template/rescript/src/Indexer_test.rescodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res
🧠 Learnings (52)
📓 Common learnings
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: After any change to TypeScript files, run `pnpm tsc --noEmit` to ensure successful compilation
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Always verify entity type field names match exactly with the generated entity types. For example, use `token0_id` not `token0`, and `transaction_id` not `transaction`. Run `pnpm tsc --noEmit` to catch type mismatches
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/templates/static/erc20_template/typescript/config.yamlcodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/src/config_parsing/entity_parsing.rscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : When updating existing entities in HyperIndex handlers, always use the spread operator for immutability since returned objects are read-only
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbsscenarios/test_codegen/src/handlers/EventHandlers.rescodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/templates/dynamic/codegen/index.js.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/{**/*.ts,**/schema.graphql} : Ensure database schema compatibility: verify that the types you're setting in code match the schema entity property types exactly. Compare with schema.graphql - for example, `Int!` in schema requires `number` in code, `BigInt!` requires `BigInt`, `BigDecimal!` requires `BigDecimal`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/src/type_schema.rscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/src/config_parsing/entity_parsing.rscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : In Envio HyperIndex, use `entity_id` fields (e.g., `token_id: string`) instead of direct object references for entity relationships
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbsscenarios/test_codegen/src/handlers/EventHandlers.rescodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/templates/static/erc20_template/typescript/config.yamlcodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/templates/dynamic/codegen/index.js.hbscodegenerator/cli/src/config_parsing/entity_parsing.rscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Use `!context.isPreload` check to prevent logic from running during preload in HyperIndex handlers
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Import entity types from `generated/src/db/Entities.gen` for type annotations (e.g., `Pair_t`, `Token_t`), NOT from `generated` which exports contract handlers. Use the correct entity type imports to prevent TypeScript errors like 'refers to a value, but is being used as a type'
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbsscenarios/test_codegen/test/EventHandler_test.tsscenarios/test_codegen/src/handlers/EventHandlers.rescodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/src/config_parsing/event_parsing.rscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/src/lib.rscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/src/config_parsing/entity_parsing.rscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 3 - Refactor file structure to mirror the original subgraph EXACTLY using the same filenames, create separate handler files by contract (e.g., contract1.ts, contract2.ts) instead of a single EventHandlers.ts file, and move handlers from EventHandlers.ts to contract-specific files
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbsscenarios/test_codegen/test/EventHandler_test.tscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/static/erc20_template/typescript/config.yamlcodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For Step 6 - Final Migration Verification: Go through each handler and helper function systematically, comparing the logic line-by-line to the original subgraph implementation. Iterate multiple times until logic is completely correct, as first pass often misses subtle differences
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbsscenarios/test_codegen/test/EventHandler_test.tscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Use `string | undefined` for optional string fields in Envio types, not `string | null`, as generated types are strict about null vs undefined
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Verify tests pass by running compiler `pnpm rescript` and tests `pnpm mocha`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/blank_template/rescript/src/Indexer_test.rescodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to codegenerator/cli/templates/static/**/*.res : Static ReScript template files live under `codegenerator/cli/templates/static/` and are copied verbatim
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/blank_template/rescript/src/Indexer_test.rescodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/src/lib.rscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/static/blank_template/rescript/vitest.config.ts
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx,res} : Use `_only` to specify which tests to run during test development
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/blank_template/rescript/vitest.config.ts
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to **/*.res : Prefer reading ReScript `.res` modules directly; ignore compiled `.js` artifacts
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/src/lib.rscodegenerator/cli/templates/static/blank_template/rescript/vitest.config.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Whitelist the following commands for HyperIndex development: `pnpm codegen` and `pnpm tsc --noEmit`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Applied to files:
scenarios/test_codegen/test/EventHandler_test.tscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tsscenarios/erc20_multichain_factory/test/Handler_Test.rescodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/templates/dynamic/codegen/index.js.hbscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/EventHandlers.ts : For Step 1 - Clear all boilerplate code from EventHandlers.ts and replace with empty handlers containing TODO comments referencing the original subgraph implementation
Applied to files:
scenarios/test_codegen/test/EventHandler_test.tscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 4 - Implement contract registration for factory events using `contractRegister` above the handler to track dynamically created contracts: `Factory.EventName.contractRegister(({ event, context }) => { context.addContractName(event.params.contractAddress); });`
Applied to files:
scenarios/test_codegen/test/EventHandler_test.tscodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/static/erc20_template/typescript/config.yamlcodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Import and use the Effect API (`S`, `createEffect`) from 'envio' package for external calls in HyperIndex handlers
Applied to files:
scenarios/test_codegen/test/EventHandler_test.tscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/dynamic/codegen/index.js.hbs
📚 Learning: 2025-11-19T05:36:33.975Z
Learnt from: nikbhintade
Repo: enviodev/hyperindex PR: 822
File: codegenerator/cli/templates/static/multichain_indexer_template/typescript/src/EventHandlers.ts:10-18
Timestamp: 2025-11-19T05:36:33.975Z
Learning: The multichain_indexer_template in codegenerator/cli/templates/static/ is designed to demonstrate multichain indexing features. It intentionally uses minimal event parameters (e.g., only capturing the `pool` address from Uniswap V3 PoolCreated events) to keep the focus on multichain functionality rather than comprehensive event indexing.
Applied to files:
scenarios/test_codegen/test/EventHandler_test.tscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/npm/envio/index.d.tsscenarios/erc20_multichain_factory/test/Handler_Test.rescodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/templates/static/erc20_template/typescript/config.yamlcodegenerator/cli/templates/dynamic/codegen/index.js.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/schema.graphql : For Step 2 - Migrate GraphQL schema from TheGraph format to Envio format: remove `entity` decorators, convert `Bytes!` to `String!`, convert `ID!` to `ID!` (keep as is), and ensure ALL entity arrays have `derivedFrom(field: "fieldName")` directives to prevent 'EE211: Arrays of entities is unsupported' error
Applied to files:
scenarios/test_codegen/src/handlers/EventHandlers.rescodegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/src/type_schema.rscodegenerator/cli/src/config_parsing/entity_parsing.rscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For entity creation patterns, always include all required fields in a single object literal and use `context.Entity.set(entity)` (without await). Update patterns should spread existing entity data and update only changed fields: `const updated = { ...existing, field: newValue }; context.Entity.set(updated);`
Applied to files:
scenarios/test_codegen/src/handlers/EventHandlers.rescodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.graphql : Do not add the entity decorator to GraphQL schema types in HyperIndex
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/src/config_parsing/entity_parsing.rscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/utils/**/*.ts : When implementing Step 5a (Helper Functions), examine ALL function calls within helper functions and recursively implement any dependencies that have NO entity/handler dependencies
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx,res} : Prefer Public module API for testing
Applied to files:
codegenerator/cli/templates/dynamic/init_templates/shared/package.json.hbscodegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/blank_template/rescript/src/Indexer_test.rescodegenerator/cli/npm/envio/src/bindings/Vitest.rescodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbsadr/why-vitest.mdcodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/templates/static/blank_template/rescript/vitest.config.ts
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx,res} : Always use single assert to check the whole value instead of multiple asserts for every field
Applied to files:
codegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/templates/dynamic/contract_import_templates/rescript/src/Indexer_test.res.hbscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/templates/static/blank_template/rescript/vitest.config.ts
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.test.{res,resi} : Never use `Js.Console.log` in test files. Use `Assert` module for all verifications
Applied to files:
codegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/src/bindings/Vitest.rescodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbscodegenerator/cli/templates/static/blank_template/rescript/vitest.config.ts
📚 Learning: 2025-05-27T17:07:12.878Z
Learnt from: JonoPrest
Repo: enviodev/hyperindex PR: 555
File: scenarios/test_codegen/test/lib_tests/EntityHistory_test.res:631-659
Timestamp: 2025-05-27T17:07:12.878Z
Learning: In isolated tests for EntityHistory rollbacks with controlled mock data setup, the ordering of getRollbackDiff results is deterministic and doesn't require sorting before comparison with deepStrictEqual.
Applied to files:
codegenerator/cli/templates/static/greeter_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/greeteronfuel_template/typescript/src/indexer.test.tscodegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : ALWAYS normalize amounts when adding tokens with different decimal places in HyperIndex handlers, creating helper functions to convert to standard decimals (e.g., 18 decimals)
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/static/erc20_template/typescript/config.yaml
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/{src/handlers,src/**}/*.ts : ALL external calls (RPC calls, API calls, blockchain state fetching) MUST use the Effect API with `context.effect()` to enable preload optimization and parallelization. Create Effect API functions in `src/effects/` folder for better organization
Applied to files:
codegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/effects/**/*.ts : When making external RPC calls, use viem with createPublicClient and batching for efficiency. Define Effect functions with proper schemas using the S module from 'envio': S.object(), S.string, S.number, etc.
Applied to files:
codegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.{res,resi} : Always use ReScript 11 documentation
Applied to files:
codegenerator/cli/npm/envio/src/bindings/Vitest.rescodegenerator/cli/src/lib.rscodegenerator/cli/src/fuel/abi.rs
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.test.{res,resi} : Use try/catch as expressions instead of refs for tracking success/failure in tests
Applied to files:
codegenerator/cli/npm/envio/src/bindings/Vitest.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : When accessing entity fields that represent relationships, use the `_id` suffix convention. For example, use `token0_id` not `token0` when storing relationships in entity types
Applied to files:
codegenerator/cli/src/hbs_templating/contract_import_templates.rscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: For multichain indexing, prefix all entity IDs with `event.chainId`: `${event.chainId}-${originalId}`, never hardcode `chainId = 1`, always use `event.chainId`, and use chain-specific Bundle IDs like `${chainId}-1` for accurate pricing per network
Applied to files:
codegenerator/cli/src/hbs_templating/contract_import_templates.rs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to codegenerator/cli/templates/dynamic/**/*.hbs : Templates in Handlebars format (.hbs) live under `codegenerator/cli/templates/dynamic/`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Use `context.effect` to make external calls in HyperIndex handlers and prevent double execution during preload optimization
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/codegen/index.d.ts.hbscodegenerator/cli/templates/dynamic/codegen/index.js.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Entry point for the Rust CLI is `codegenerator/cli/src/lib.rs`
Applied to files:
.cursor/commands/testrust.md
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Command dispatcher for Rust CLI is `codegenerator/cli/src/commands.rs`
Applied to files:
.cursor/commands/testrust.md
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.{res,resi} : Use records when working with structured data, and objects to conveniently pass payload data between functions
Applied to files:
codegenerator/cli/src/type_schema.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/config.yaml : When using multichain indexing, ensure contract names in config.yaml are unique across all networks, place contract definitions in the global contracts section (not in network sections), and only define addresses for those contracts in network sections
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/config.yaml
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/config.yaml : For dynamic contracts created by factories, remove the `address` field from contract definitions in config.yaml since they don't have a fixed address
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/config.yaml
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js,yaml,yml} : Ensure case consistency when matching addresses in configuration objects, using lowercase keys to match `address.toLowerCase()` lookups
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/config.yaml
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Never hardcode contract addresses or configuration values - always use constants defined in the original subgraph or utility files. Reference original subgraph patterns for constants like FACTORY_ADDRESS, ADDRESS_ZERO, etc.
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/config.yaml
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{yaml,yml} : Use the Envio EVM schema file for YAML validation in config.yaml: `yaml-language-server: $schema=./node_modules/envio/evm.schema.json`
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/config.yaml
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.test.{res,resi} : When testing with multiple iterations, collect results in data structures and assert on them
Applied to files:
codegenerator/cli/templates/dynamic/contract_import_templates/typescript/src/indexer.test.ts.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : MAINTAIN BigDecimal precision from the original subgraph. Use BigDecimal and BigInt types for financial calculations, never simplify to JavaScript number type which loses precision. Always use BigDecimal constants (ZERO_BD, ONE_BD) and BigInt constants (ZERO_BI, ONE_BI)
Applied to files:
codegenerator/cli/templates/dynamic/codegen/index.js.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Entry module for generated runtime is `Index.res` which starts HTTP server, loads `Config.res`, calls `RegisterHandlers.res`, spins up `GlobalStateManager.res`
Applied to files:
codegenerator/cli/npm/envio/src/Main.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.graphql : Use `entity_id` fields for relationships in GraphQL schemas (e.g., `user_id: String!`) instead of direct entity references or entity arrays
Applied to files:
codegenerator/cli/src/config_parsing/entity_parsing.rscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/schema.graphql : CRITICAL ENVIO REQUIREMENT: All entity arrays like `[Mint!]!` MUST have `derivedFrom` directives. Without this, codegen will fail with error 'EE211: Arrays of entities is unsupported'
Applied to files:
codegenerator/cli/src/config_parsing/entity_parsing.rs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.graphql : NEVER use arrays of entities (e.g., `[Enter!]!` or `[User!]!`) in HyperIndex GraphQL schemas - use `entity_id` fields instead
Applied to files:
codegenerator/cli/src/config_parsing/entity_parsing.rs
🧬 Code graph analysis (5)
codegenerator/cli/src/config_parsing/event_parsing.rs (1)
codegenerator/cli/src/type_schema.rs (4)
new(20-26)new(113-121)new(366-373)new(398-401)
codegenerator/cli/src/hbs_templating/contract_import_templates.rs (1)
codegenerator/cli/src/type_schema.rs (1)
to_valid_rescript_name(348-364)
codegenerator/cli/src/fuel/abi.rs (1)
codegenerator/cli/src/type_schema.rs (5)
new(20-26)new(113-121)new(366-373)new(398-401)constructors(311-320)
codegenerator/cli/src/config_parsing/entity_parsing.rs (1)
codegenerator/cli/src/type_schema.rs (4)
new(20-26)new(113-121)new(366-373)new(398-401)
codegenerator/cli/src/hbs_templating/codegen_templates.rs (1)
codegenerator/cli/src/type_schema.rs (5)
to_rescript_schema(28-66)to_rescript_schema(158-181)to_rescript_schema(240-288)to_rescript_schema(551-608)option(779-781)
⏰ 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
There was a problem hiding this comment.
Actionable comments posted: 10
🤖 Fix all issues with AI agents
In @codegenerator/cli/npm/envio/src/TestIndexer.res:
- Around line 36-46: handleLoadByIds currently drops missing ids which breaks
"OrThrow" semantics and positional alignment; update handleLoadByIds to (1)
resolve entities in the same order as the input ids (so results array aligns
with ids) and (2) detect any missing ids and throw an error instead of silently
omitting them. Specifically, inside handleLoadByIds use ids->Array.map to look
up each id in entityDict via Js.Dict.get, collect missing ids, and if any exist
call Js.Exn.raiseError (or raise with a descriptive message including the
missing id list) so the test stub matches Persistence.storage.loadByIdsOrThrow
behavior.
- Around line 158-192: The loop uses getUnsafe on multiple arrays
(checkpointIds, checkpointBlockNumbers, checkpointBlockHashes,
checkpointChainIds, checkpointEventsProcessed) assuming they all have identical
lengths; add a single invariant check before the for loop that compares
checkpointIds->Array.length against each of the other checkpoint arrays and
throws/returns a clear error message (e.g., "mismatched checkpoint metadata
lengths") if any differ, so the code fails fast with a helpful message instead
of throwing later from getUnsafe.
- Around line 326-336: The onExit callback currently uses
reject(Js.Exn.raiseError(...)) which throws immediately instead of returning a
rejected promise; change it to call reject with an Error value (e.g. create an
Error with the `Worker exited with code ...` message) so the promise is actually
rejected rather than an exception being thrown inside
worker->NodeJs.WorkerThreads.onExit; update the branch that handles code !== 0
to call reject(new Error(...)) (or otherwise construct an exception object)
instead of using Js.Exn.raiseError.
- Around line 48-82: handleLoadByField currently compares raw Js.Json.t values
with ==, >, < which is unsafe and non‑exhaustive; update the matching in
handleLoadByField to first classify/decode both entityFieldValue and fieldValue
into concrete JS types (number, string, bool, null, object, array) and perform
type‑aware comparisons (numeric comparisons for numbers, lexicographic for
strings, strict equality for booleans/null, deep structural equality for
objects/arrays using a deterministic deepEqual or JSON.stringify fallback), and
make the Persistence.operator match exhaustive (handle any additional operators
like !=, >=, <=) so every operator path is implemented. Ensure you reference
entity->Js.Json.decodeObject and obj->Js.Dict.get(fieldName) to retrieve values,
then decode via Js.Json.classify / Js.Json.decodeNumber / Js.Json.decodeString
and use a deterministic deep equality for complex types before pushing to
results.
- Around line 284-318: The message handler in
worker->NodeJs.WorkerThreads.onMessage currently calls store methods
(handleLoadByIds, handleLoadByField, handleWriteBatch) directly so exceptions
never send a response; wrap each handler invocation in a try/catch, call the
existing respond function in both success and failure paths, and on exception
send TestIndexerProxyStorage.Error({message: Js.Exn.message(exception) |>
Belt.Option.getWithDefault("unknown")}) (or equivalent) as the payload so the
worker-side sendRequest promise always resolves/rejects; apply this to the
LoadByIds, LoadByField branches and the WriteBatch branch (ensure WriteBatch
still responds with Js.Json.null on success and an Error payload on exception).
- Around line 195-221: The code in makeInitialState currently parses chainIdStr
with Int.fromString->Option.getWithDefault(0), which silently converts invalid
keys to 0; instead, detect parse failure and raise a clear error. Replace the
getWithDefault(0) usage by explicitly handling the Option from Int.fromString
(e.g., pattern-match or use an Option.getExn) and throw a descriptive exception
referencing chainIdStr when parsing fails so malformed processConfigChains keys
do not become chainId 0; keep the subsequent use of ChainMap.Chain.makeUnsafe
and the existing validation that the chain exists in config.
- Around line 343-374: The workerData type currently includes an unused
processConfig field; remove that field from the workerData type declaration
(symbol: workerData) and eliminate where processConfig is serialized when
spawning the worker (the earlier workerData construction), ensuring you only
serialize initialState into NodeJs.WorkerThreads.workerData; verify there are no
remaining references to processConfig in this module or in the worker
initialization path (symbols to check: TestIndexerProxyStorage.make,
TestIndexerProxyStorage.makeStorage, Main.start) and adjust any related
serialization logic so the worker receives just the initialState to avoid extra
overhead.
- Around line 84-156: handleWriteBatch currently only processes
update.latestChange and thus ignores update.history; update.history entries must
be applied in order before applying latestChange so all intermediate Set/Delete
events update store.entities and changesByCheckpoint correctly. Modify the loop
over updates in handleWriteBatch to iterate update.history (in order) and apply
each historical change using the same logic used for update.latestChange
(handling Set and Delete: update entityDict via Js.Dict.set/unsafeDeleteKey,
compute checkpointKey from checkpointId->Float.toString, lookup/create
entityChanges and entityChange, parse Set entities with
store.entityConfigs->Js.Dict.unsafeGet(...).schema and push into
entityChange.sets, or push entityId into entityChange.deleted), then apply
update.latestChange last; ensure you reuse the existing code paths for Set and
Delete to avoid duplication.
In @codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res:
- Around line 96-107: sendRequest currently creates a never-settling Promise and
leaves entries in pendingRequests if the worker never responds; update
sendRequest (and if needed nextRequestId) to start a per-request timeout when
creating the promise that will call reject with a timeout error and remove the
pendingRequests entry (Js.Dict.delete) when the timer fires or when the response
resolves, and ensure the timer is cleared on resolve/reject; keep using
Promise.make and postMessage to parentPort but add the timeout logic tied to the
same request id so pendingRequests cannot leak forever.
- Around line 68-91: The message handler currently calls
reject(Js.Exn.raiseError(message)) which throws instead of rejecting the
promise; change it to construct an exception value and pass that to reject
without raising. In the make function's onPortMessage callback (the switch on
msg.payload), replace the direct call to Js.Exn.raiseError with creating an
exception value (e.g., via a Js.Exn constructor/helper) and call reject(err) so
the promise rejects cleanly; ensure proxy.pendingRequests cleanup stays the
same.
🧹 Nitpick comments (2)
codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res (2)
76-91: Unknown response id should not hard-crash the worker.
Line 83 raises if no pending request exists. That can take down tests if the main thread double-sends / sends late after cleanup. Consider logging + ignoring (or at least not throwing) for robustness.
109-212: Avoid silent no-ops /Obj.magic()in storage methods that could be called.
setOrThrowbeing a no-op (Lines 139-142) andexecuteUnsafe/setChainMetareturningObj.magic()(Lines 191-193) can hide real usage bugs and create confusing failures downstream. Prefer explicitraiseError("...not supported in TestIndexer...")for unsupported operations.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
codegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{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/TestIndexerProxyStorage.rescodegenerator/cli/npm/envio/src/TestIndexer.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript
.resmodules directly; ignore compiled.jsartifacts
Files:
codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.rescodegenerator/cli/npm/envio/src/TestIndexer.res
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.{res,resi} : Always use ReScript 11 documentation
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/{**/*.ts,**/schema.graphql} : Ensure database schema compatibility: verify that the types you're setting in code match the schema entity property types exactly. Compare with schema.graphql - for example, `Int!` in schema requires `number` in code, `BigInt!` requires `BigInt`, `BigDecimal!` requires `BigDecimal`
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
⏰ 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 (3)
codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res (1)
7-54: Good separation of worker/main message envelopes and tagged payloads.
The@tag("type")+@as(...)approach looks consistent for cross-thread discriminated messaging.codegenerator/cli/npm/envio/src/TestIndexer.res (2)
26-34: Store initialization looks straightforward and keeps entity configs alongside data.
This is a clean base for schema-aware parsing later inhandleWriteBatch.
231-341: [Rewritten review comment]
[Exactly ONE classification tag]
| let handleLoadByIds = (store: store, ~tableName: string, ~ids: array<string>): Js.Json.t => { | ||
| let entityDict = store.entities->Js.Dict.get(tableName)->Option.getWithDefault(Js.Dict.empty()) | ||
| let results = [] | ||
| ids->Array.forEach(id => { | ||
| switch entityDict->Js.Dict.get(id) { | ||
| | Some(entity) => results->Array.push(entity)->ignore | ||
| | None => () | ||
| } | ||
| }) | ||
| results->Js.Json.array | ||
| } |
There was a problem hiding this comment.
handleLoadByIds likely violates “OrThrow” expectations (missing ids are silently dropped).
If Persistence.storage.loadByIdsOrThrow is expected to error on missing ids (or preserve positional alignment), this will diverge from production behavior and can make tests misleading.
🤖 Prompt for AI Agents
In @codegenerator/cli/npm/envio/src/TestIndexer.res around lines 36 - 46,
handleLoadByIds currently drops missing ids which breaks "OrThrow" semantics and
positional alignment; update handleLoadByIds to (1) resolve entities in the same
order as the input ids (so results array aligns with ids) and (2) detect any
missing ids and throw an error instead of silently omitting them. Specifically,
inside handleLoadByIds use ids->Array.map to look up each id in entityDict via
Js.Dict.get, collect missing ids, and if any exist call Js.Exn.raiseError (or
raise with a descriptive message including the missing id list) so the test stub
matches Persistence.storage.loadByIdsOrThrow behavior.
| let makeInitialState = ( | ||
| ~config: Config.t, | ||
| ~processConfigChains: Js.Dict.t<chainConfig>, | ||
| ): Persistence.initialState => { | ||
| let chainKeys = processConfigChains->Js.Dict.keys | ||
| let chains = chainKeys->Array.map(chainIdStr => { | ||
| let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0) | ||
| let chain = ChainMap.Chain.makeUnsafe(~chainId) | ||
|
|
||
| if !(config.chainMap->ChainMap.has(chain)) { | ||
| Js.Exn.raiseError(`Chain ${chainIdStr} is not configured in config.yaml`) | ||
| } | ||
|
|
||
| let processChainConfig = processConfigChains->Js.Dict.unsafeGet(chainIdStr) | ||
| { | ||
| Persistence.id: chainId, | ||
| startBlock: processChainConfig.startBlock, | ||
| endBlock: Some(processChainConfig.endBlock), | ||
| maxReorgDepth: 0, // No reorg support in test indexer | ||
| progressBlockNumber: -1, | ||
| numEventsProcessed: 0, | ||
| firstEventBlockNumber: None, | ||
| timestampCaughtUpToHeadOrEndblock: None, | ||
| dynamicContracts: [], | ||
| } | ||
| }) | ||
|
|
There was a problem hiding this comment.
Chain id parsing should not default to 0 on invalid keys.
Line 201 falls back to 0, which can mask malformed process configs and potentially produce confusing “wrong chain” behavior. Prefer throwing when Int.fromString fails.
Proposed fix
- let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0)
+ let chainId = switch chainIdStr->Int.fromString {
+ | Some(v) => v
+ | None => Js.Exn.raiseError(`Invalid chain id key: ${chainIdStr}`)
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let makeInitialState = ( | |
| ~config: Config.t, | |
| ~processConfigChains: Js.Dict.t<chainConfig>, | |
| ): Persistence.initialState => { | |
| let chainKeys = processConfigChains->Js.Dict.keys | |
| let chains = chainKeys->Array.map(chainIdStr => { | |
| let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0) | |
| let chain = ChainMap.Chain.makeUnsafe(~chainId) | |
| if !(config.chainMap->ChainMap.has(chain)) { | |
| Js.Exn.raiseError(`Chain ${chainIdStr} is not configured in config.yaml`) | |
| } | |
| let processChainConfig = processConfigChains->Js.Dict.unsafeGet(chainIdStr) | |
| { | |
| Persistence.id: chainId, | |
| startBlock: processChainConfig.startBlock, | |
| endBlock: Some(processChainConfig.endBlock), | |
| maxReorgDepth: 0, // No reorg support in test indexer | |
| progressBlockNumber: -1, | |
| numEventsProcessed: 0, | |
| firstEventBlockNumber: None, | |
| timestampCaughtUpToHeadOrEndblock: None, | |
| dynamicContracts: [], | |
| } | |
| }) | |
| let makeInitialState = ( | |
| ~config: Config.t, | |
| ~processConfigChains: Js.Dict.t<chainConfig>, | |
| ): Persistence.initialState => { | |
| let chainKeys = processConfigChains->Js.Dict.keys | |
| let chains = chainKeys->Array.map(chainIdStr => { | |
| let chainId = switch chainIdStr->Int.fromString { | |
| | Some(v) => v | |
| | None => Js.Exn.raiseError(`Invalid chain id key: ${chainIdStr}`) | |
| } | |
| let chain = ChainMap.Chain.makeUnsafe(~chainId) | |
| if !(config.chainMap->ChainMap.has(chain)) { | |
| Js.Exn.raiseError(`Chain ${chainIdStr} is not configured in config.yaml`) | |
| } | |
| let processChainConfig = processConfigChains->Js.Dict.unsafeGet(chainIdStr) | |
| { | |
| Persistence.id: chainId, | |
| startBlock: processChainConfig.startBlock, | |
| endBlock: Some(processChainConfig.endBlock), | |
| maxReorgDepth: 0, // No reorg support in test indexer | |
| progressBlockNumber: -1, | |
| numEventsProcessed: 0, | |
| firstEventBlockNumber: None, | |
| timestampCaughtUpToHeadOrEndblock: None, | |
| dynamicContracts: [], | |
| } | |
| }) |
🤖 Prompt for AI Agents
In @codegenerator/cli/npm/envio/src/TestIndexer.res around lines 195 - 221, The
code in makeInitialState currently parses chainIdStr with
Int.fromString->Option.getWithDefault(0), which silently converts invalid keys
to 0; instead, detect parse failure and raise a clear error. Replace the
getWithDefault(0) usage by explicitly handling the Option from Int.fromString
(e.g., pattern-match or use an Option.getExn) and throw a descriptive exception
referencing chainIdStr when parsing fails so malformed processConfigChains keys
do not become chainId 0; keep the subsequent use of ChainMap.Chain.makeUnsafe
and the existing validation that the chain exists in config.
| // Handle messages from worker | ||
| worker->NodeJs.WorkerThreads.onMessage((msg: TestIndexerProxyStorage.workerMessage) => { | ||
| let respond = data => | ||
| worker->NodeJs.WorkerThreads.workerPostMessage( | ||
| { | ||
| TestIndexerProxyStorage.id: msg.id, | ||
| payload: TestIndexerProxyStorage.Response({data: data}), | ||
| }->Utils.magic, | ||
| ) | ||
|
|
||
| switch msg.payload { | ||
| | LoadByIds({tableName, ids}) => store->handleLoadByIds(~tableName, ~ids)->respond | ||
|
|
||
| | LoadByField({tableName, fieldName, fieldValue, operator}) => | ||
| store->handleLoadByField(~tableName, ~fieldName, ~fieldValue, ~operator)->respond | ||
|
|
||
| | WriteBatch({ | ||
| updatedEntities, | ||
| checkpointIds, | ||
| checkpointChainIds, | ||
| checkpointBlockNumbers, | ||
| checkpointBlockHashes, | ||
| checkpointEventsProcessed, | ||
| }) => | ||
| store->handleWriteBatch( | ||
| ~updatedEntities, | ||
| ~checkpointIds, | ||
| ~checkpointChainIds, | ||
| ~checkpointBlockNumbers, | ||
| ~checkpointBlockHashes, | ||
| ~checkpointEventsProcessed, | ||
| ) | ||
| Js.Json.null->respond | ||
| } | ||
| }) |
There was a problem hiding this comment.
Main-thread message handler should return Error payloads on exceptions (avoid deadlocks).
If handleLoadByIds / handleLoadByField / handleWriteBatch throws, the worker-side sendRequest promise never resolves/rejects, and the test run can hang. Wrap handler execution and respond with TestIndexerProxyStorage.Error.
Proposed fix (try/catch + Error response)
// Handle messages from worker
worker->NodeJs.WorkerThreads.onMessage((msg: TestIndexerProxyStorage.workerMessage) => {
let respond = data =>
worker->NodeJs.WorkerThreads.workerPostMessage(
{
TestIndexerProxyStorage.id: msg.id,
payload: TestIndexerProxyStorage.Response({data: data}),
}->Utils.magic,
)
+ let respondError = (exn: exn) =>
+ worker->NodeJs.WorkerThreads.workerPostMessage(
+ {
+ TestIndexerProxyStorage.id: msg.id,
+ payload: TestIndexerProxyStorage.Error({
+ message: exn->Js.Exn.message->Option.getWithDefault("Unknown error"),
+ }),
+ }->Utils.magic,
+ )
- switch msg.payload {
- | LoadByIds({tableName, ids}) => store->handleLoadByIds(~tableName, ~ids)->respond
+ try {
+ switch msg.payload {
+ | LoadByIds({tableName, ids}) =>
+ store->handleLoadByIds(~tableName, ~ids)->respond
- | LoadByField({tableName, fieldName, fieldValue, operator}) =>
- store->handleLoadByField(~tableName, ~fieldName, ~fieldValue, ~operator)->respond
+ | LoadByField({tableName, fieldName, fieldValue, operator}) =>
+ store->handleLoadByField(~tableName, ~fieldName, ~fieldValue, ~operator)->respond
- | WriteBatch({
+ | WriteBatch({
updatedEntities,
checkpointIds,
checkpointChainIds,
checkpointBlockNumbers,
checkpointBlockHashes,
checkpointEventsProcessed,
}) =>
store->handleWriteBatch(
~updatedEntities,
~checkpointIds,
~checkpointChainIds,
~checkpointBlockNumbers,
~checkpointBlockHashes,
~checkpointEventsProcessed,
)
Js.Json.null->respond
+ }
+ } catch {
+ | exn => respondError(exn)
}
})🤖 Prompt for AI Agents
In @codegenerator/cli/npm/envio/src/TestIndexer.res around lines 284 - 318, The
message handler in worker->NodeJs.WorkerThreads.onMessage currently calls store
methods (handleLoadByIds, handleLoadByField, handleWriteBatch) directly so
exceptions never send a response; wrap each handler invocation in a try/catch,
call the existing respond function in both success and failure paths, and on
exception send TestIndexerProxyStorage.Error({message: Js.Exn.message(exception)
|> Belt.Option.getWithDefault("unknown")}) (or equivalent) as the payload so the
worker-side sendRequest promise always resolves/rejects; apply this to the
LoadByIds, LoadByField branches and the WriteBatch branch (ensure WriteBatch
still responds with Js.Json.null on success and an Error payload on exception).
| let nextRequestId = (proxy: t): requestId => { | ||
| proxy.requestCounter = proxy.requestCounter + 1 | ||
| proxy.requestCounter | ||
| } | ||
|
|
||
| let sendRequest = (proxy: t, ~payload: workerPayload): promise<Js.Json.t> => { | ||
| Promise.make((resolve, reject) => { | ||
| let id = proxy->nextRequestId | ||
| proxy.pendingRequests->Js.Dict.set(id->Int.toString, {resolve, reject}) | ||
| proxy.parentPort->NodeJs.WorkerThreads.postMessage({id, payload}) | ||
| }) | ||
| } |
There was a problem hiding this comment.
sendRequest can leak pendingRequests forever (no timeout / cancellation).
If the main thread never responds (worker crash, logic bug, port closed), the promise never settles and pendingRequests grows unbounded. Consider a per-request timeout that rejects + deletes the entry.
🤖 Prompt for AI Agents
In @codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res around lines 96
- 107, sendRequest currently creates a never-settling Promise and leaves entries
in pendingRequests if the worker never responds; update sendRequest (and if
needed nextRequestId) to start a per-request timeout when creating the promise
that will call reject with a timeout error and remove the pendingRequests entry
(Js.Dict.delete) when the timer fires or when the response resolves, and ensure
the timer is cleared on resolve/reject; keep using Promise.make and postMessage
to parentPort but add the timeout logic tied to the same request id so
pendingRequests cannot leak forever.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In @codegenerator/cli/npm/envio/src/TestIndexer.res:
- Around line 380-397: The onExit handler uses Js.Exn.raiseError which throws
immediately, preventing reject from being invoked; instead create and pass an
Error object to reject (e.g., build a message string using code->Int.toString
and call reject(new Error(message)) or use Js.Exn.raiseErrorToJs if you prefer a
non-throwing conversion), leaving state.processInProgress assignment intact and
keeping the same success branch that resolves with { changes:
state.processChanges } and the loop that updates state.progressBlockByChain.
🧹 Nitpick comments (3)
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.ts (1)
88-96: Consider defensive array access instead of non-null assertions.The non-null assertions (
!) onmockAddresses[0]andmockAddresses[1]assume the array has at least 2 elements. While this is likely always true for the mock helpers, explicit handling would be more robust.🔧 Suggested improvement
- const userAddress1 = Addresses.mockAddresses[0]!; - const userAddress2 = Addresses.mockAddresses[1]!; + const userAddress1 = Addresses.mockAddresses[0]; + const userAddress2 = Addresses.mockAddresses[1]; + if (!userAddress1 || !userAddress2) { + throw new Error("Mock addresses not available"); + }Alternatively, if
mockAddressesis guaranteed to have sufficient elements by design, this can be left as-is.scenarios/test_codegen/test/EventHandler_test.ts (1)
15-15: Duplicate import from "generated".
createTestIndexeris imported separately but could be consolidated with the existing import from "generated" on lines 3-12.Suggested consolidation
import { TestHelpers, indexer, type User, type Indexer, type EvmChainId, type EvmChainName, type FuelChainId, type SvmChainId, + createTestIndexer, } from "generated"; import { type Address } from "envio"; import { expectType, type TypeEqual } from "ts-expect"; -import { createTestIndexer } from "generated";codegenerator/cli/npm/envio/src/TestIndexer.res (1)
327-333: Error handling in worker creation catch block may cause unexpected behavior.The catch block calls
reject(exn->Utils.magic)and thenraise(exn). Sinceraisethrows synchronously, the code after the try-catch block will not execute, but the promise will still be pending (reject was called but the Promise.make callback exits abnormally via exception).This may work in practice since reject was called, but the pattern is unusual.
Consider returning after reject to avoid the re-throw
let worker = try { NodeJs.WorkerThreads.makeWorker(workerPath, {workerData: workerData}) } catch { | exn => reject(exn->Utils.magic) - raise(exn) + // Early return - reject handles the error propagation + %raw(`return`) }Alternatively, if the intention is to exit the Promise.make callback after rejection, the current pattern does work (the exception bubbles up but the promise is already rejected).
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (11)
codegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/Env.rescodegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/PgStorage.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/npm/envio/src/bindings/Pino.rescodegenerator/cli/templates/static/erc20_template/typescript/config.yamlcodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tsscenarios/test_codegen/src/handlers/EventHandlers.tsscenarios/test_codegen/test/EventHandler_test.tsscenarios/test_codegen/test/LoadLinkedEntities.res
💤 Files with no reviewable changes (1)
- scenarios/test_codegen/src/handlers/EventHandlers.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- codegenerator/cli/templates/static/erc20_template/typescript/config.yaml
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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:
scenarios/test_codegen/test/LoadLinkedEntities.rescodegenerator/cli/npm/envio/src/bindings/Pino.rescodegenerator/cli/npm/envio/src/PgStorage.rescodegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/Env.rescodegenerator/cli/npm/envio/src/TestIndexer.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript
.resmodules directly; ignore compiled.jsartifacts
Files:
scenarios/test_codegen/test/LoadLinkedEntities.rescodegenerator/cli/npm/envio/src/bindings/Pino.rescodegenerator/cli/npm/envio/src/PgStorage.rescodegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/Env.rescodegenerator/cli/npm/envio/src/TestIndexer.res
**/*.{test,spec}.{ts,tsx,js,jsx,res}
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
**/*.{test,spec}.{ts,tsx,js,jsx,res}: Always use single assert to check the whole value instead of multiple asserts for every field
Prefer Public module API for testing
Use_onlyto specify which tests to run during test development
Files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.ts
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Verify tests pass by running compiler `pnpm rescript` and tests `pnpm mocha`
Learnt from: nikbhintade
Repo: enviodev/hyperindex PR: 822
File: codegenerator/cli/templates/static/multichain_indexer_template/typescript/src/EventHandlers.ts:10-18
Timestamp: 2025-11-19T05:36:33.975Z
Learning: The multichain_indexer_template in codegenerator/cli/templates/static/ is designed to demonstrate multichain indexing features. It intentionally uses minimal event parameters (e.g., only capturing the `pool` address from Uniswap V3 PoolCreated events) to keep the focus on multichain functionality rather than comprehensive event indexing.
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Import entity types from `generated/src/db/Entities.gen` for type annotations (e.g., `Pair_t`, `Token_t`), NOT from `generated` which exports contract handlers. Use the correct entity type imports to prevent TypeScript errors like 'refers to a value, but is being used as a type'
Applied to files:
scenarios/test_codegen/test/LoadLinkedEntities.rescodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tsscenarios/test_codegen/test/EventHandler_test.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : In Envio HyperIndex, use `entity_id` fields (e.g., `token_id: string`) instead of direct object references for entity relationships
Applied to files:
scenarios/test_codegen/test/LoadLinkedEntities.rescodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-11-19T05:36:33.975Z
Learnt from: nikbhintade
Repo: enviodev/hyperindex PR: 822
File: codegenerator/cli/templates/static/multichain_indexer_template/typescript/src/EventHandlers.ts:10-18
Timestamp: 2025-11-19T05:36:33.975Z
Learning: The multichain_indexer_template in codegenerator/cli/templates/static/ is designed to demonstrate multichain indexing features. It intentionally uses minimal event parameters (e.g., only capturing the `pool` address from Uniswap V3 PoolCreated events) to keep the focus on multichain functionality rather than comprehensive event indexing.
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tsscenarios/test_codegen/test/EventHandler_test.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : ALWAYS normalize amounts when adding tokens with different decimal places in HyperIndex handlers, creating helper functions to convert to standard decimals (e.g., 18 decimals)
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tsscenarios/test_codegen/test/EventHandler_test.tscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Always verify entity type field names match exactly with the generated entity types. For example, use `token0_id` not `token0`, and `transaction_id` not `transaction`. Run `pnpm tsc --noEmit` to catch type mismatches
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For Step 6 - Final Migration Verification: Go through each handler and helper function systematically, comparing the logic line-by-line to the original subgraph implementation. Iterate multiple times until logic is completely correct, as first pass often misses subtle differences
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : When updating existing entities in HyperIndex handlers, always use the spread operator for immutability since returned objects are read-only
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 3 - Refactor file structure to mirror the original subgraph EXACTLY using the same filenames, create separate handler files by contract (e.g., contract1.ts, contract2.ts) instead of a single EventHandlers.ts file, and move handlers from EventHandlers.ts to contract-specific files
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/npm/envio/index.d.tsscenarios/test_codegen/test/EventHandler_test.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Always cast timestamps to BigInt using `BigInt(event.block.timestamp)` instead of using raw timestamps from events
Applied to files:
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tsscenarios/test_codegen/test/EventHandler_test.ts
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to **/*.{test,spec}.{ts,tsx,js,jsx,res} : Prefer Public module API for testing
Applied to files:
codegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Use `string | undefined` for optional string fields in Envio types, not `string | null`, as generated types are strict about null vs undefined
Applied to files:
codegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Import and use the Effect API (`S`, `createEffect`) from 'envio' package for external calls in HyperIndex handlers
Applied to files:
codegenerator/cli/npm/envio/index.d.tsscenarios/test_codegen/test/EventHandler_test.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/{src/handlers,src/**}/*.ts : ALL external calls (RPC calls, API calls, blockchain state fetching) MUST use the Effect API with `context.effect()` to enable preload optimization and parallelization. Create Effect API functions in `src/effects/` folder for better organization
Applied to files:
codegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/effects/**/*.ts : When making external RPC calls, use viem with createPublicClient and batching for efficiency. Define Effect functions with proper schemas using the S module from 'envio': S.object(), S.string, S.number, etc.
Applied to files:
codegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Entry module for generated runtime is `Index.res` which starts HTTP server, loads `Config.res`, calls `RegisterHandlers.res`, spins up `GlobalStateManager.res`
Applied to files:
codegenerator/cli/npm/envio/src/Main.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/EventHandlers.ts : For Step 1 - Clear all boilerplate code from EventHandlers.ts and replace with empty handlers containing TODO comments referencing the original subgraph implementation
Applied to files:
scenarios/test_codegen/test/EventHandler_test.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 4 - Implement contract registration for factory events using `contractRegister` above the handler to track dynamically created contracts: `Factory.EventName.contractRegister(({ event, context }) => { context.addContractName(event.params.contractAddress); });`
Applied to files:
scenarios/test_codegen/test/EventHandler_test.ts
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.{res,resi} : Always use ReScript 11 documentation
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/{**/*.ts,**/schema.graphql} : Ensure database schema compatibility: verify that the types you're setting in code match the schema entity property types exactly. Compare with schema.graphql - for example, `Int!` in schema requires `number` in code, `BigInt!` requires `BigInt`, `BigDecimal!` requires `BigDecimal`
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: For multichain indexing, prefix all entity IDs with `event.chainId`: `${event.chainId}-${originalId}`, never hardcode `chainId = 1`, always use `event.chainId`, and use chain-specific Bundle IDs like `${chainId}-1` for accurate pricing per network
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
🧬 Code graph analysis (1)
codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.ts (1)
codegenerator/cli/npm/envio/src/bindings/Ethers.res.d.mts (1)
Addresses(5-5)
⏰ 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 (19)
scenarios/test_codegen/test/LoadLinkedEntities.res (1)
167-189: LGTM! Type references correctly updated to use public entity module paths.The migration from
Types.c,Types.b,Types.atoEntities.C.t,Entities.B.t,Entities.A.taligns with the PR's goal of unifying type paths across the codebase. The test logic remains unchanged.codegenerator/cli/npm/envio/src/bindings/Pino.res (1)
1-9: LGTM! Adding#silentlog level is appropriate.The
#silentvariant is a valid Pino log level that suppresses all logging output. This is particularly useful for test scenarios where log noise should be minimized.codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.ts (3)
1-6: LGTM! Good test setup with Vitest and generated helpers.The imports are well-organized, separating the test framework (vitest), types (Account), and test utilities (TestHelpers, createTestIndexer).
7-81: LGTM! Comprehensive end-to-end indexer test.The test effectively validates:
- Initial mint event processing at block 10,861,674
- Balance updates on subsequent transfers at block 10,861,766
Using inline snapshots for complex state verification is appropriate here as it captures the full expected output structure including block hashes and chain IDs.
98-137: LGTM! Well-structured unit test for Transfer event handling.The test clearly demonstrates:
- MockDb setup with initial entity state
- Creating mock events with specific parameters
- Processing events and verifying resulting state changes
- Good use of descriptive assertion messages
The comments explaining MockDb immutability are helpful for template users.
codegenerator/cli/npm/envio/src/Env.res (2)
28-43: LGTM! Well-structured log level schema with optional handling.The
logLevelSchemaenum covers all standard Pino levels plus custom user levels and the new#silentoption. MakinguserLogLeveloptional with explicit defaulting provides clearer semantics for distinguishing "not configured" from explicit configuration.
127-134: LGTM! Clean logger initialization with explicit default.Using
Belt.Option.getWithDefault(#info)clearly shows the fallback behavior whenLOG_LEVELis not set.codegenerator/cli/npm/envio/src/PgStorage.res (1)
16-20: LGTM! Correctly adapted to optionaluserLogLeveltype.The comparison against
Some(#warn)andSome(#error)properly handles the updated option type fromEnv.res. The logic remains the same: suppress Postgres notices for high-severity log levels.scenarios/test_codegen/test/EventHandler_test.ts (1)
638-756: LGTM! Comprehensive test coverage for createTestIndexer.The tests thoroughly cover:
- Basic happy path returning
{ changes: [] }- Validation for exactly one chain requirement
- Mutual exclusion (only one process at a time)
- Block range validation against config and previously processed blocks
The synchronous vs async error handling is correctly distinguished using
assert.throwsvsassert.rejects.codegenerator/cli/npm/envio/index.d.ts (2)
18-19: LGTM! Useful utility type for IDE display.The
Prettify<T>type is a well-known pattern that expands complex intersection types for better IDE tooltips and error messages.
476-529: LGTM! Well-designed test indexer type surface.The types correctly model the test indexer constraints:
TestIndexerChainConfigrequires bothstartBlockandendBlock(no open-ended ranges in tests)TestIndexerChainIdsextracts chain IDs from whichever ecosystem is configuredTestIndexerProcessConfigusesPartial<Record<...>>appropriately - runtime validation inTestIndexer.resenforces exactly one chainThe JSDoc comments provide clear documentation for the public API.
codegenerator/cli/npm/envio/src/Main.res (2)
249-264: LGTM! Clean test mode integration.The
~isTestparameter correctly:
- Disables TUI for clean test output
- Forces
isDevelopmentModeto false to ensure proper process exit behavior- Disables rollback on reorg (not needed for deterministic test runs)
The default value of
falseensures backward compatibility.
275-327: LGTM! Server startup correctly gated by test mode.Skipping the HTTP server in test mode is appropriate - tests don't need the metrics/console endpoints and this avoids port conflicts when running multiple test processes.
codegenerator/cli/npm/envio/src/TestIndexer.res (6)
25-39: LGTM!Clean implementation for ID-based entity lookups with appropriate handling of missing tables/entities.
59-63: JSON value comparison may produce unexpected results for non-primitive types.The operators
>and<onJs.Json.tvalues work correctly for numbers but may produce unexpected results for strings (lexicographic comparison) or objects/arrays (reference comparison, typically always false).If field queries are expected to work only with numeric fields, consider documenting this limitation. Otherwise, type-aware comparison logic may be needed.
Is this intentional behavior? If only numeric/primitive comparisons are expected, consider adding a comment or runtime validation.
77-189: LGTM! Well-structured batch write handling.The function correctly:
- Updates the in-memory entity store for subsequent load operations
- Tracks changes per checkpoint for test inspection
- Handles both Set and Delete operations appropriately
The use of
Js.Dict.unsafeGeton line 122 is safe sinceentityConfigsis populated fromallEntitiesduring initialization, and the worker would have failed earlier if an unknown entity was referenced.
191-225: LGTM!Correctly initializes state for test runs with appropriate defaults:
maxReorgDepth: 0- no reorg handling needed in testscleanRun: true- fresh state per test indexer instance- Validates chains exist in config before proceeding
227-260: LGTM! Thorough block range validation.The validation covers all edge cases:
- Prevents starting before config's start block
- Prevents ending after config's end block
- Prevents re-processing already processed blocks
The error messages are clear and provide actionable guidance.
409-442: LGTM! Proper worker initialization with appropriate guards.The function correctly:
- Validates it's running in a worker thread
- Handles missing parentPort/workerData gracefully
- Configures log level appropriately for test mode
- Starts the indexer in test mode
The
->ignoreonMain.startis fine since the worker's lifetime is managed by the main thread via the exit handler.
| Self::Single(gql_scalar) => gql_scalar.to_rescript_type(schema)?, | ||
| Self::ListType(field_type) => { | ||
| RescriptTypeIdent::Array(Box::new(field_type.to_rescript_type(schema)?)) | ||
| TypeIdent::Array(Box::new(field_type.to_rescript_type(schema)?)) |
There was a problem hiding this comment.
Nice api at some point
| TypeIdent::Array(Box::new(field_type.to_rescript_type(schema)?)) | |
| TypeIdent::array(field_type.to_rescript_type(schema)?) |
| //Re-exporting types for backwards compatability | ||
| {{#each entities as | entity |}} | ||
| @genType.as("{{entity.name.original}}") | ||
| type {{entity.name.uncapitalized}} = Entities.{{entity.name.capitalized}}.t | ||
| {{/each}} | ||
|
|
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
codegenerator/cli/src/hbs_templating/codegen_templates.rs (1)
2372-2385: Tests reference non-existent fieldinternal_config_ts_code.Lines 2376 and 2383 access
project_template.internal_config_ts_code, but this field does not exist in theProjectTemplatestruct. The actual field is namedinternal_config_json_code. These tests will fail to compile.Change
project_template.internal_config_ts_codetoproject_template.internal_config_json_codeon both lines.
🤖 Fix all issues with AI agents
In @codegenerator/cli/npm/envio/src/TestIndexer.res:
- Around line 196-198: The current mapping silently defaults invalid chainIdStr
to 0 (chainKeys->Array.map ... chainIdStr ->
Int.fromString->Option.getWithDefault(0)), which can mask bad config; change the
logic to explicitly handle parse failures by raising a clear error or returning
a Result instead of defaulting to 0: replace the getWithDefault(0) usage with an
explicit Option match or getExn that throws a descriptive exception when
Int.fromString returns None (include chainIdStr in the message), then pass the
validated chainId into ChainMap.Chain.makeUnsafe; this ensures invalid IDs are
surfaced rather than treated as chain 0.
In @codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res:
- Around line 188-192: The functions executeUnsafe and setChainMeta in
TestIndexerProxyStorage.res currently return Obj.magic(), which yields undefined
at runtime; replace these with explicit failures or proper typed returns like
the other rollback helpers: throw a clear Error (e.g., "executeUnsafe not
implemented" and "setChainMeta not implemented") or implement/return the correct
expected types for executeUnsafe and setChainMeta so callers cannot receive
unexpected undefined values; locate the functions by name (executeUnsafe,
setChainMeta) and make their behavior consistent with the other methods that
throw on unsupported operations.
In @codegenerator/cli/templates/static/greeter_template/typescript/README.md:
- Line 21: Decide whether the project target is Node.js v20 or v22+ and make the
versions consistent: if moving to v22+/v24, update the cursor rule in
hyperindex.mdc (the Node.js version constraint there) to allow v22+ (or
specifically v24 if preferred); if sticking with v20, revert the README entry
"[Node.js v22+ (v24 recommended)]" in greeter_template README.md (and the
identical lines in blank_template, erc20_template, factory_template,
greeteronfuel_template, svmblock_template) back to "Node.js v20" so the
templates and the .cursor/rules/hyperindex.mdc agree.
🧹 Nitpick comments (5)
adr/why-workers-for-test-indexer.md (1)
1-46: Well-structured ADR with clear rationale.The document effectively explains the decision to use worker threads for test indexer isolation. The context, alternatives, decision, and consequences are all well-documented and follow ADR best practices.
Optional: Consider adding debugging and memory implications
While the document is comprehensive, you could optionally enhance the "Negative" consequences section by mentioning:
- Debugging complexity: Debugging across worker boundaries can be more challenging than debugging in a single process
- Memory implications: Multiple workers running in parallel may increase memory usage compared to sequential execution
These additions would provide a more complete picture of the trade-offs, though the current documentation is already sufficient.
Additionally, the phrase on Line 20 about "handler registration is a global singleton that would conflict with top-level await" could be clarified. The connection between global singleton registration and top-level await isn't immediately clear and might benefit from a brief explanation.
CONTRIBUTING.md (1)
21-21: Optional: Consider using a markdown link to avoid bare URL.The URL on this line triggers a markdown linting rule (MD034). While functional, wrapping it in markdown link syntax improves consistency.
♻️ Proposed fix
-1. Node.js v22+ (v24 recommended) https://nodejs.org/en +1. [Node.js v22+ (v24 recommended)](https://nodejs.org/en)codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res (1)
96-107: Consider adding a timeout to prevent hanging tests.The
sendRequestfunction correctly stores the pending request before posting the message to avoid race conditions. However, there's no timeout mechanism - if the main thread doesn't respond (e.g., due to a crash), the promise will hang indefinitely. This could cause tests to hang rather than fail cleanly.💡 Optional: Add timeout to sendRequest
let sendRequest = (proxy: t, ~payload: workerPayload): promise<Js.Json.t> => { - Promise.make((resolve, reject) => { - let id = proxy->nextRequestId - proxy.pendingRequests->Js.Dict.set(id->Int.toString, {resolve, reject}) - proxy.parentPort->NodeJs.WorkerThreads.postMessage({id, payload}) - }) + Promise.make((resolve, reject) => { + let id = proxy->nextRequestId + let idStr = id->Int.toString + proxy.pendingRequests->Js.Dict.set(idStr, {resolve, reject}) + proxy.parentPort->NodeJs.WorkerThreads.postMessage({id, payload}) + // Optional: Add timeout for debugging hung tests + // let _ = Js.Global.setTimeout(() => { + // switch proxy.pendingRequests->Utils.Dict.dangerouslyGetNonOption(idStr) { + // | Some(_) => reject(Utils.Error.make(`Request ${idStr} timed out`)) + // | None => () + // } + // }, 30000) + }) }codegenerator/cli/npm/envio/src/TestIndexer.res (2)
328-334: Double error handling on worker creation failure.When worker creation fails, both
reject(exn)andraise(exn)are called. Therejectwill properly fail the promise, butraisewill also throw synchronously. SincePromise.makecatches synchronous exceptions, this should still work, but the dual handling is redundant.💡 Simplify error handling
let worker = try { NodeJs.WorkerThreads.makeWorker(workerPath, {workerData: workerData}) } catch { | exn => reject(exn->Utils.magic) - raise(exn) + // Return early from Promise.make callback - the rejection is handled + %raw(`return`) }Alternatively, just let the exception propagate since
Promise.makewill catch it and reject:- let worker = try { - NodeJs.WorkerThreads.makeWorker(workerPath, {workerData: workerData}) - } catch { - | exn => - reject(exn->Utils.magic) - raise(exn) - } + let worker = NodeJs.WorkerThreads.makeWorker(workerPath, {workerData: workerData})
59-63: Use type-aware comparison forJs.Json.tvalues instead of direct operators.The comparison operators (
>,<) onJs.Json.trely on JavaScript's loose comparison semantics, which can produce unexpected results when comparing different JSON types. While the current schema-based conversion ensures both values undergo the same type mapping, this approach is fragile and error-prone. Consider deserializing both values to their proper types before comparison, or implementing explicit type-aware comparison logic that validates type consistency before applying operators.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (10)
codegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__envio_dts_code_generated_for_evm.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__envio_dts_code_generated_for_fuel.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__indexer_code_generates_correct_types_and_values.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__indexer_code_multiple_chains.snapis excluded by!**/*.snapcodegenerator/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_ts_code_omits_default_values.snapis excluded by!**/*.snapcodegenerator/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__internal_config_ts_code_with_all_options.snapis excluded by!**/*.snap
📒 Files selected for processing (24)
CONTRIBUTING.mdadr/why-workers-for-test-indexer.mdcodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/PgStorage.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/npm/envio/src/TestIndexerProxyStorage.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.rescodegenerator/cli/npm/envio/src/bindings/Pino.rescodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/templates/dynamic/codegen/envio.d.ts.hbscodegenerator/cli/templates/dynamic/codegen/internal.config.json.hbscodegenerator/cli/templates/dynamic/codegen/internal.config.ts.hbscodegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/templates/static/blank_template/shared/README.mdcodegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.tscodegenerator/cli/templates/static/factory_template/shared/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/integration_tests/tests/test_indexers/wildcard-uni-factory/README.md
💤 Files with no reviewable changes (1)
- codegenerator/cli/templates/dynamic/codegen/internal.config.ts.hbs
✅ Files skipped from review due to trivial changes (2)
- codegenerator/cli/templates/dynamic/codegen/internal.config.json.hbs
- codegenerator/cli/templates/dynamic/codegen/envio.d.ts.hbs
🚧 Files skipped from review as they are similar to previous changes (4)
- codegenerator/cli/templates/static/erc20_template/typescript/src/indexer.test.ts
- codegenerator/cli/npm/envio/src/PgStorage.res
- codegenerator/cli/templates/dynamic/codegen/package.json.hbs
- codegenerator/cli/npm/envio/src/bindings/Pino.res
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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/Main.rescodegenerator/cli/npm/envio/src/TestIndexerProxyStorage.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.rescodegenerator/cli/npm/envio/src/TestIndexer.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript
.resmodules directly; ignore compiled.jsartifacts
Files:
codegenerator/cli/npm/envio/src/Main.rescodegenerator/cli/npm/envio/src/TestIndexerProxyStorage.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.rescodegenerator/cli/npm/envio/src/TestIndexer.res
codegenerator/cli/templates/dynamic/**/*.hbs
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Templates in Handlebars format (.hbs) live under
codegenerator/cli/templates/dynamic/
Files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs
🧠 Learnings (41)
📓 Common learnings
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Verify tests pass by running compiler `pnpm rescript` and tests `pnpm mocha`
Learnt from: nikbhintade
Repo: enviodev/hyperindex PR: 822
File: codegenerator/cli/templates/static/multichain_indexer_template/typescript/src/EventHandlers.ts:10-18
Timestamp: 2025-11-19T05:36:33.975Z
Learning: The multichain_indexer_template in codegenerator/cli/templates/static/ is designed to demonstrate multichain indexing features. It intentionally uses minimal event parameters (e.g., only capturing the `pool` address from Uniswap V3 PoolCreated events) to keep the focus on multichain functionality rather than comprehensive event indexing.
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Use pnpm as the package manager
Applied to files:
CONTRIBUTING.mdcodegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/blank_template/shared/README.mdcodegenerator/integration_tests/tests/test_indexers/wildcard-uni-factory/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.md
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Use `pnpm` over `npm`/`npx`
Applied to files:
CONTRIBUTING.mdcodegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/blank_template/shared/README.mdcodegenerator/integration_tests/tests/test_indexers/wildcard-uni-factory/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.md
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Always use Node.js v20 only (no higher or lower versions)
Applied to files:
CONTRIBUTING.mdcodegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/blank_template/shared/README.mdcodegenerator/integration_tests/tests/test_indexers/wildcard-uni-factory/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.md
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Once compilation is successful, run `TUI_OFF=true pnpm dev` to catch runtime errors in HyperIndex indexers
Applied to files:
CONTRIBUTING.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/factory_template/shared/README.md
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Verify tests pass by running compiler `pnpm rescript` and tests `pnpm mocha`
Applied to files:
CONTRIBUTING.md
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: After any change to TypeScript files, run `pnpm tsc --noEmit` to ensure successful compilation
Applied to files:
CONTRIBUTING.md
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Whitelist the following commands for HyperIndex development: `pnpm codegen` and `pnpm tsc --noEmit`
Applied to files:
CONTRIBUTING.md
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Never add raw amounts from different tokens without normalization using helper functions like `normalizeAmountToUSD()`
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.md
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : In Envio HyperIndex, use `entity_id` fields (e.g., `token_id: string`) instead of direct object references for entity relationships
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/factory_template/shared/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/static/blank_template/shared/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Always verify entity type field names match exactly with the generated entity types. For example, use `token0_id` not `token0`, and `transaction_id` not `transaction`. Run `pnpm tsc --noEmit` to catch type mismatches
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : ALWAYS normalize amounts when adding tokens with different decimal places in HyperIndex handlers, creating helper functions to convert to standard decimals (e.g., 18 decimals)
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For Step 6 - Final Migration Verification: Go through each handler and helper function systematically, comparing the logic line-by-line to the original subgraph implementation. Iterate multiple times until logic is completely correct, as first pass often misses subtle differences
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/static/blank_template/shared/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : When updating existing entities in HyperIndex handlers, always use the spread operator for immutability since returned objects are read-only
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/static/blank_template/shared/README.mdcodegenerator/integration_tests/tests/test_indexers/wildcard-uni-factory/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/EventHandlers.ts : For Step 1 - Clear all boilerplate code from EventHandlers.ts and replace with empty handlers containing TODO comments referencing the original subgraph implementation
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/blank_template/shared/README.md
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Import entity types from `generated/src/db/Entities.gen` for type annotations (e.g., `Pair_t`, `Token_t`), NOT from `generated` which exports contract handlers. Use the correct entity type imports to prevent TypeScript errors like 'refers to a value, but is being used as a type'
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For entity creation patterns, always include all required fields in a single object literal and use `context.Entity.set(entity)` (without await). Update patterns should spread existing entity data and update only changed fields: `const updated = { ...existing, field: newValue }; context.Entity.set(updated);`
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/factory_template/shared/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Never hardcode contract addresses or configuration values - always use constants defined in the original subgraph or utility files. Reference original subgraph patterns for constants like FACTORY_ADDRESS, ADDRESS_ZERO, etc.
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.md
📚 Learning: 2025-11-19T05:36:33.975Z
Learnt from: nikbhintade
Repo: enviodev/hyperindex PR: 822
File: codegenerator/cli/templates/static/multichain_indexer_template/typescript/src/EventHandlers.ts:10-18
Timestamp: 2025-11-19T05:36:33.975Z
Learning: The multichain_indexer_template in codegenerator/cli/templates/static/ is designed to demonstrate multichain indexing features. It intentionally uses minimal event parameters (e.g., only capturing the `pool` address from Uniswap V3 PoolCreated events) to keep the focus on multichain functionality rather than comprehensive event indexing.
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Ensure docker is installed
Applied to files:
codegenerator/cli/templates/static/erc20_template/shared/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/blank_template/shared/README.mdcodegenerator/integration_tests/tests/test_indexers/wildcard-uni-factory/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.md
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Entry module for generated runtime is `Index.res` which starts HTTP server, loads `Config.res`, calls `RegisterHandlers.res`, spins up `GlobalStateManager.res`
Applied to files:
codegenerator/cli/npm/envio/src/Main.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/{**/*.ts,**/schema.graphql} : Ensure database schema compatibility: verify that the types you're setting in code match the schema entity property types exactly. Compare with schema.graphql - for example, `Int!` in schema requires `number` in code, `BigInt!` requires `BigInt`, `BigDecimal!` requires `BigDecimal`
Applied to files:
codegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/factory_template/shared/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Always cast timestamps to BigInt using `BigInt(event.block.timestamp)` instead of using raw timestamps from events
Applied to files:
codegenerator/cli/templates/static/svmblock_template/typescript/README.md
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Use `string | undefined` for optional string fields in Envio types, not `string | null`, as generated types are strict about null vs undefined
Applied to files:
codegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Applied to files:
codegenerator/cli/templates/static/svmblock_template/typescript/README.mdcodegenerator/cli/templates/static/factory_template/shared/README.mdcodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/npm/envio/index.d.tscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/utils/**/*.ts : When implementing helper functions with no entity or handler dependencies, implement the COMPLETE business logic from the original subgraph immediately, not just placeholder TODO comments
Applied to files:
codegenerator/cli/templates/static/greeteronfuel_template/typescript/README.mdcodegenerator/cli/templates/static/greeter_template/typescript/README.md
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to codegenerator/cli/templates/static/**/*.res : Static ReScript template files live under `codegenerator/cli/templates/static/` and are copied verbatim
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to codegenerator/cli/templates/dynamic/**/*.hbs : Templates in Handlebars format (.hbs) live under `codegenerator/cli/templates/dynamic/`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Config parsing flows: `human_config.rs` → `system_config.rs` → `hbs_templating/codegen_templates.rs`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 3 - Refactor file structure to mirror the original subgraph EXACTLY using the same filenames, create separate handler files by contract (e.g., contract1.ts, contract2.ts) instead of a single EventHandlers.ts file, and move handlers from EventHandlers.ts to contract-specific files
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/src/hbs_templating/codegen_templates.rscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 4 - Implement contract registration for factory events using `contractRegister` above the handler to track dynamically created contracts: `Factory.EventName.contractRegister(({ event, context }) => { context.addContractName(event.params.contractAddress); });`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Import and use the Effect API (`S`, `createEffect`) from 'envio' package for external calls in HyperIndex handlers
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbscodegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : All TypeScript handler and utility files must have proper async/await for database operations. Use `await` for `context.Entity.get()`, `context.Entity.getWhere().field.eq()` calls. Note: `context.Entity.set()` does NOT need `await` - it's synchronous
Applied to files:
codegenerator/cli/templates/static/greeter_template/typescript/README.md
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/schema.graphql : For Step 2 - Migrate GraphQL schema from TheGraph format to Envio format: remove `entity` decorators, convert `Bytes!` to `String!`, convert `ID!` to `ID!` (keep as is), and ensure ALL entity arrays have `derivedFrom(field: "fieldName")` directives to prevent 'EE211: Arrays of entities is unsupported' error
Applied to files:
codegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.graphql : Do not add the entity decorator to GraphQL schema types in HyperIndex
Applied to files:
codegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.graphql : Use `entity_id` fields for relationships in GraphQL schemas (e.g., `user_id: String!`) instead of direct entity references or entity arrays
Applied to files:
codegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{yaml,yml} : Use the Envio EVM schema file for YAML validation in config.yaml: `yaml-language-server: $schema=./node_modules/envio/evm.schema.json`
Applied to files:
codegenerator/cli/src/hbs_templating/codegen_templates.rs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/{src/handlers,src/**}/*.ts : ALL external calls (RPC calls, API calls, blockchain state fetching) MUST use the Effect API with `context.effect()` to enable preload optimization and parallelization. Create Effect API functions in `src/effects/` folder for better organization
Applied to files:
codegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/effects/**/*.ts : When making external RPC calls, use viem with createPublicClient and batching for efficiency. Define Effect functions with proper schemas using the S module from 'envio': S.object(), S.string, S.number, etc.
Applied to files:
codegenerator/cli/npm/envio/index.d.ts
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.{res,resi} : Always use ReScript 11 documentation
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: For multichain indexing, prefix all entity IDs with `event.chainId`: `${event.chainId}-${originalId}`, never hardcode `chainId = 1`, always use `event.chainId`, and use chain-specific Bundle IDs like `${chainId}-1` for accurate pricing per network
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
🪛 markdownlint-cli2 (0.18.1)
CONTRIBUTING.md
21-21: Bare URL used
(MD034, no-bare-urls)
🔇 Additional comments (36)
codegenerator/integration_tests/tests/test_indexers/wildcard-uni-factory/README.md (1)
21-21: No action needed. The Node.js v22+ (v24 recommended) specification in this README is correct and aligns with the project's established standards. The repository has already standardized on Node.js >=22.0.0 across all package.json files and runs v22.10.0 in all CI/CD workflows.Likely an incorrect or invalid review comment.
codegenerator/cli/templates/static/blank_template/shared/README.md (1)
21-21: No changes needed. The Node.js v22+ (v24 recommended) requirement is correct and consistent throughout the codebase. All package.json files specify">=22.0.0", and all template README files document this same requirement. The change aligns with the actual project constraints.Likely an incorrect or invalid review comment.
CONTRIBUTING.md (1)
21-21: Update the template file hyperindex.mdc to reflect the project's actual Node.js requirement.The CONTRIBUTING.md change to Node.js v22+ is correct and aligns with the project's package.json (
"node": ">=22.0.0") and all CI/CD workflows (using 22.10.0). However, the template file at./codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdcstill specifies "Node.js v20 only (no higher or lower versions)". This template should be updated to match the actual project requirement of v22+ to avoid misleading generated guidance.Likely an incorrect or invalid review comment.
codegenerator/cli/templates/static/factory_template/shared/README.md (1)
36-36: LGTM!The Node.js prerequisite update to "v22+ (v24 recommended)" is consistent with other template READMEs updated in this PR.
codegenerator/cli/templates/static/erc20_template/shared/README.md (2)
3-3: LGTM!Formatting change from bold to italic is consistent with other template documentation.
21-21: LGTM!Node.js prerequisite update aligns with the project-wide version requirement change.
codegenerator/cli/npm/envio/src/Main.res (2)
249-264: LGTM!The test mode parameter cleanly integrates into the start function:
- Disables TUI and development mode appropriately
- Disables rollback on reorg for deterministic test behavior
- Uses idiomatic ReScript spread operator for config modification
275-327: LGTM!Server startup and state retrieval logic are correctly guarded by
!isTest, ensuring test isolation. The getState callback logic is preserved for production use while being skipped entirely in test mode.codegenerator/cli/npm/envio/src/bindings/NodeJs.res (2)
39-39: LGTM!Adding
execArgvtoProcess.tenables passing execution arguments to worker threads, which is necessary for the test indexer infrastructure.
84-109: Excellent FFI bindings for worker_threadsThe WorkerThreads module provides accurate bindings to the Node.js worker_threads API:
isMainThreadandworkerDatacorrectly useJs.Nullable.tfor nullable values@sendannotations properly map instance methods (postMessage, on, terminate)workerOptionscorrectly exposes common options (workerData,execArgv) as a record with optional fields- Array syntax follows ReScript 11 conventions (
array<string>not[| |])- Event handling via
@as("message"),@as("error"),@as("exit")correctly maps to Node.js EventEmitter APIcodegenerator/cli/npm/envio/index.d.ts (3)
18-19: LGTM!The
Prettify<T>utility type is a well-known TypeScript pattern that expands complex intersection types for better IDE tooltips and error messages.
343-354: LGTM!
IndexerConfigTypesprovides a minimal constraint that allowsIndexerFromConfigand related types to work without requiring the fullIndexerConfigstructure, improving ergonomics for type inference.
492-546: LGTM!The TestIndexer type system is well-designed:
TestIndexerChainConfigclearly defines the block range interfaceTestIndexerChainIdscorrectly extracts chain IDs from the first configured ecosystemTestIndexerProcessConfiguses mapped types with optional chainsTestIndexerFromConfigexposes a cleanprocessmethod returning the result typecodegenerator/cli/templates/dynamic/codegen/src/Types.ts.hbs (4)
9-10: LGTM!The
IsEmptyObject<T>utility type correctly useskeyof T extends neverto detect empty object types, enabling conditional type exports based on ecosystem configuration.
52-67: LGTM!The
Configtype correctly constructs a composite type from all configured ecosystems using conditional intersection types. This enablesIndexerFromConfigto derive the correct indexer shape.
82-87: LGTM!The
TestIndexertype is correctly imported fromenvioand parameterized with the generatedConfig, providing type-safe access to the test indexer API.
150-151: LGTM!Exporting per-entity type aliases (e.g.,
export type Gravatar = Entities.Gravatar_t) improves developer experience by providing cleaner imports without the_tsuffix.codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs (3)
1-1: LGTM!The
@@directivesyntax for JSON imports withwith { type: 'json' }is the correct approach for importing JSON files in ReScript with ES modules.
26-30: LGTM!Filtering out test and spec files prevents them from being auto-loaded as handlers:
.test.- Jest/Vitest convention.spec.- Jasmine/Mocha convention_test.- ReScript conventionThis ensures only production handlers are registered.
89-89: LGTM!Using
%raw(\internalConfigJson`)correctly references the directive-imported JSON value, passing it toConfig.fromPublic` for configuration initialization.codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res (3)
1-66: Well-structured type definitions for worker-main thread messaging.The use of
@tagfor discriminated unions andJs.Json.tfor cross-worker serialization is appropriate. The type hierarchy clearly separates worker-to-main (workerPayload) and main-to-worker (mainPayload) message types.
68-94: LGTM - Proper request/response correlation with cleanup.The message listener correctly correlates responses by ID, removes pending requests after handling, and throws clear errors for unexpected response IDs. The pattern of using
Obj.magicwithJs.Dict.unsafeDeleteKeyis idiomatic for dict mutation in ReScript.
143-187: WriteBatch implementation correctly serializes entities for cross-worker messaging.The entity serialization logic properly handles both
SetandDeletechange types, encoding entities to JSON using the entity schema before sending to the main thread. The checkpoint metadata is correctly forwarded.codegenerator/cli/npm/envio/src/TestIndexer.res (5)
1-24: LGTM - Type definitions appropriately model test indexer state.The use of
unknownforchangesandsetsprovides flexibility for heterogeneous entity types. ThetestIndexerStatecorrectly usesmutablefor fields that need mutation during processing.
77-189: Complex but well-structured batch write handling.The function correctly:
- Groups changes by checkpoint ID for proper ordering
- Updates in-memory entity state for subsequent load operations
- Parses entities with their schemas before storing in the changes array
- Handles null
blockHashvalues appropriatelyOne consideration:
S.parseOrThrowat line 123 could throw if there's a schema mismatch. Ensure upstream error handling catches this.
228-261: Thorough block range validation with clear error messages.The validation correctly enforces:
startBlock >= config.startBlockendBlock <= config.endBlock(if configured)startBlock > progressBlock(for sequential test runs)Error messages helpfully suggest using
createTestIndexer()for a fresh state.
263-403: Well-designed test indexer factory with proper lifecycle management.The implementation correctly:
- Prevents concurrent process calls
- Enforces single-chain restriction (with clear error message about multichain limitation)
- Validates block ranges before starting
- Manages worker lifecycle with proper error/exit handlers
- Tracks progress for sequential test runs
410-443: Proper worker initialization with good defaults.The function correctly:
- Guards against being called from the main thread
- Validates required parentPort and workerData
- Defaults to silent logging for clean test output (while respecting explicit
LOG_LEVEL)- Exits cleanly with error code on missing worker data
codegenerator/cli/src/hbs_templating/codegen_templates.rs (8)
39-114: Well-structured internal config types with appropriate serde annotations.The design correctly:
- Uses
skip_serializing_ifto omit default values, keeping output minimal- Separates ecosystem-specific config into optional fields
- Uses
Box<RawValue>for ABI to preserve exact JSON format without re-parsing overhead- Applies
rename_all = "camelCase"consistently for JavaScript interop
151-186: Type-safe refactor fromStringtoTypeIdent.The change to use
TypeIdentdirectly instead of converting toStringimmediately improves type safety and enables richer type comparisons throughout the codebase.
219-243: Consistent type refactoring in EntityRecordTypeTemplate.The changes from
RescriptRecordFieldtoRecordFieldandRescriptSchemaModetoSchemaModeare consistent naming simplifications that improve code clarity without changing functionality.
616-711: EventTemplate properly updated to use new type system.Key improvements:
TypeIdent::Addresscomparison (line 631) is more type-safe than string comparisonTypeExpr::Identifier(TypeIdent::Unit)(line 637) correctly represents empty event paramsRecordField::newandto_valid_rescript_nameprovide consistent field handling
1539-1624: Internal config JSON generation with proper ecosystem handling.The implementation correctly:
- Parses and re-serializes ABIs to ensure compact JSON format
- Creates ecosystem-specific config structures (EVM includes
addressFormat/eventDecoder, Fuel has contracts, SVM is chains-only)- Omits
multichainwhen "unordered" (the default)- Uses
to_string_prettyfor readable output
1626-1743: TypeScript declaration generation for ecosystem types.The implementation correctly generates all ecosystem types (
EvmChains,EvmContracts,FuelChains,FuelContracts,SvmChains) regardless of which ecosystem is active. Non-active ecosystems get empty{}types, providing a consistent interface for consumers.
2023-2038: Test constants properly updated to use TypeIdent.The test helper
EventParamTypeTemplate::newcorrectly usesTypeIdentfor type-safe comparisons and value generation.
1494-1517: Test indexer integration code generation is correct.The generated code properly:
- Creates per-chain optional config fields using
@asannotation for numeric keys- Constructs the worker path using ESM-compatible
import.meta.url- References
TestIndexerWorker.res.mjs, which is automatically compiled fromTestIndexerWorker.resvia ReScript's.res.mjssuffix configuration- Integrates with
Generated.configWithoutRegistrationsandGenerated.codegenPersistence, both properly defined in the generatedGenerated.resmodule
| let chains = chainKeys->Array.map(chainIdStr => { | ||
| let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0) | ||
| let chain = ChainMap.Chain.makeUnsafe(~chainId) |
There was a problem hiding this comment.
Silently defaulting invalid chain ID to 0 could hide configuration errors.
If chainIdStr is not a valid integer, it defaults to 0 which may inadvertently match a valid Fuel chain (chain ID 0). Consider raising an error for invalid chain IDs.
💡 Suggested fix
let chains = chainKeys->Array.map(chainIdStr => {
- let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0)
+ let chainId = switch chainIdStr->Int.fromString {
+ | Some(id) => id
+ | None => Js.Exn.raiseError(`Invalid chain ID: ${chainIdStr} is not a valid integer`)
+ }
let chain = ChainMap.Chain.makeUnsafe(~chainId)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| let chains = chainKeys->Array.map(chainIdStr => { | |
| let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0) | |
| let chain = ChainMap.Chain.makeUnsafe(~chainId) | |
| let chains = chainKeys->Array.map(chainIdStr => { | |
| let chainId = switch chainIdStr->Int.fromString { | |
| | Some(id) => id | |
| | None => Js.Exn.raiseError(`Invalid chain ID: ${chainIdStr} is not a valid integer`) | |
| } | |
| let chain = ChainMap.Chain.makeUnsafe(~chainId) |
🤖 Prompt for AI Agents
In @codegenerator/cli/npm/envio/src/TestIndexer.res around lines 196 - 198, The
current mapping silently defaults invalid chainIdStr to 0 (chainKeys->Array.map
... chainIdStr -> Int.fromString->Option.getWithDefault(0)), which can mask bad
config; change the logic to explicitly handle parse failures by raising a clear
error or returning a Result instead of defaulting to 0: replace the
getWithDefault(0) usage with an explicit Option match or getExn that throws a
descriptive exception when Int.fromString returns None (include chainIdStr in
the message), then pass the validated chainId into ChainMap.Chain.makeUnsafe;
this ensures invalid IDs are surfaced rather than treated as chain 0.
| setEffectCacheOrThrow: async (~effect as _, ~items as _, ~initialize as _) => (), | ||
| dumpEffectCache: async () => (), | ||
| executeUnsafe: async _ => Obj.magic(), | ||
| setChainMeta: async _ => Obj.magic(), | ||
| pruneStaleCheckpoints: async (~safeCheckpointId as _) => (), |
There was a problem hiding this comment.
Potential runtime issues with Obj.magic() returns.
executeUnsafe and setChainMeta return Obj.magic() which is essentially undefined. If these functions are called and their return values are used, this could cause subtle runtime errors. Consider throwing explicit errors (like the rollback functions) or documenting that these are intentional no-ops.
💡 Suggested fix: throw explicit errors or return proper types
- executeUnsafe: async _ => Obj.magic(),
- setChainMeta: async _ => Obj.magic(),
+ executeUnsafe: async _ => {
+ Js.Exn.raiseError("TestIndexer: executeUnsafe is not supported in test mode")
+ },
+ setChainMeta: async _ => {
+ // No-op: chain metadata updates are not persisted in test mode
+ ()
+ },📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| setEffectCacheOrThrow: async (~effect as _, ~items as _, ~initialize as _) => (), | |
| dumpEffectCache: async () => (), | |
| executeUnsafe: async _ => Obj.magic(), | |
| setChainMeta: async _ => Obj.magic(), | |
| pruneStaleCheckpoints: async (~safeCheckpointId as _) => (), | |
| setEffectCacheOrThrow: async (~effect as _, ~items as _, ~initialize as _) => (), | |
| dumpEffectCache: async () => (), | |
| executeUnsafe: async _ => { | |
| Js.Exn.raiseError("TestIndexer: executeUnsafe is not supported in test mode") | |
| }, | |
| setChainMeta: async _ => { | |
| // No-op: chain metadata updates are not persisted in test mode | |
| () | |
| }, | |
| pruneStaleCheckpoints: async (~safeCheckpointId as _) => (), |
🤖 Prompt for AI Agents
In @codegenerator/cli/npm/envio/src/TestIndexerProxyStorage.res around lines 188
- 192, The functions executeUnsafe and setChainMeta in
TestIndexerProxyStorage.res currently return Obj.magic(), which yields undefined
at runtime; replace these with explicit failures or proper typed returns like
the other rollback helpers: throw a clear Error (e.g., "executeUnsafe not
implemented" and "setChainMeta not implemented") or implement/return the correct
expected types for executeUnsafe and setChainMeta so callers cannot receive
unexpected undefined values; locate the functions by name (executeUnsafe,
setChainMeta) and make their behavior consistent with the other methods that
throw on unsupported operations.
* Fix test indexer field comparison for bigint and BigDecimal Store decoded entities instead of JSON to enable proper comparison. The previous implementation stored JSON values and compared them directly, which fails for bigint and BigDecimal since they serialize as strings. Now entities are parsed when received from the worker thread, and comparisons use the TableIndices.FieldValue logic that properly handles numeric type comparisons. * Simplify field comparison using schema-based conversion Use entityConfig.table field schema with S.convertOrThrow to parse JSON field values instead of manual type-based parsing. This reuses the existing schema infrastructure and follows the same pattern as InMemoryTable for field value comparison. --------- Co-authored-by: Claude <noreply@anthropic.com>
Instead of scanning from block 0, set startBlock to match endBlock (10_861_674) for more efficient targeted block testing. Co-authored-by: Claude <noreply@anthropic.com>
…erindex into dz/test-indexer-with-vitest
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@codegenerator/cli/templates/dynamic/codegen/package.json.hbs`:
- Around line 15-20: The "start" script in the package.json.hbs template
currently hardcodes a nested tsx path (node_modules/envio/node_modules/tsx/...),
which breaks under pnpm/other package managers; update the "start" script to set
NODE_OPTIONS='--import tsx' on the node invocation instead of importing the
nested tsx path, preserving the existing tsc step when {{is_typescript}} is true
and keeping the same {{relative_path_to_root_from_generated}} and
{{relative_path_to_generated_from_root}} usages so the command becomes: run tsc
--noEmit when needed, then run node with NODE_OPTIONS='--import tsx' and the
entry {{relative_path_to_generated_from_root}}/src/Index.res.mjs.
♻️ Duplicate comments (6)
codegenerator/cli/npm/envio/src/TestIndexer.res (6)
26-44:handleLoadByIdssilently drops missing IDs, diverging from "OrThrow" semantics.The function filters out missing IDs rather than throwing when an ID is not found. If
Persistence.storage.loadByIdsOrThrowis expected to error on missing IDs (or preserve positional alignment), this will produce different behavior in tests vs production, potentially hiding bugs.Consider either:
- Throwing when any ID is missing, or
- Returning results in the same order as input IDs (with
nullfor missing entries) to maintain positional alignment
116-167:handleWriteBatchonly processeslatestChange, ignoringupdate.history.Line 117 only handles
update.latestChange. Ifupdate.historycontains earlier changes that should be applied/tracked, this could result in:
- Incorrect store state for subsequent loads
- Incomplete checkpoint change output
If historical changes need to be preserved for accurate test behavior, iterate through
update.historybefore applyinglatestChange.
169-206: Add length validation beforegetUnsafeon checkpoint arrays.The loop at lines 170-206 uses
Array.getUnsafeon multiple arrays (checkpointIds,checkpointBlockNumbers,checkpointBlockHashes,checkpointChainIds,checkpointEventsProcessed) assuming they all have identical lengths. Any mismatch would cause a runtime exception that's hard to debug.💡 Suggested invariant check
// Add before the for loop at line 170 let len = checkpointIds->Array.length if checkpointBlockNumbers->Array.length !== len || checkpointBlockHashes->Array.length !== len || checkpointChainIds->Array.length !== len || checkpointEventsProcessed->Array.length !== len { Js.Exn.raiseError("Checkpoint metadata arrays have mismatched lengths") }
214-215: Silently defaulting invalid chain ID to 0 could hide configuration errors.Line 215 defaults to
0whenInt.fromStringfails. Chain ID 0 may be a valid chain (e.g., Fuel), so this could mask malformed process configs and produce confusing "wrong chain" behavior.🐛 Proposed fix
- let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0) + let chainId = switch chainIdStr->Int.fromString { + | Some(id) => id + | None => Js.Exn.raiseError(`Invalid chain ID: ${chainIdStr} is not a valid integer`) + }
323-324: Same chain ID parsing issue exists here.Line 324 also defaults invalid chain IDs to 0. Apply the same fix as suggested for line 215.
365-399: Main-thread message handler should catch exceptions to avoid deadlocks.If
handleLoadByIds,handleLoadByField, orhandleWriteBatchthrows, the worker-sidesendRequestpromise never resolves/rejects, and the test run can hang indefinitely. Wrap handler execution in try/catch and respond withTestIndexerProxyStorage.Erroron failure.🐛 Proposed fix sketch
worker->NodeJs.WorkerThreads.onMessage((msg: TestIndexerProxyStorage.workerMessage) => { let respond = data => worker->NodeJs.WorkerThreads.workerPostMessage( { TestIndexerProxyStorage.id: msg.id, payload: TestIndexerProxyStorage.Response({data: data}), }->Utils.magic, ) + let respondError = message => + worker->NodeJs.WorkerThreads.workerPostMessage( + { + TestIndexerProxyStorage.id: msg.id, + payload: TestIndexerProxyStorage.Error({message: message}), + }->Utils.magic, + ) - switch msg.payload { + try { + switch msg.payload { | LoadByIds({tableName, ids}) => state->handleLoadByIds(~tableName, ~ids)->respond ... - } + } + } catch { + | exn => respondError(exn->Js.Exn.message->Option.getWithDefault("Unknown error")) + } })
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
codegenerator/cli/npm/envio/pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlscenarios/test_codegen/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (6)
codegenerator/cli/npm/envio/package.jsoncodegenerator/cli/npm/envio/package.json.tmplcodegenerator/cli/npm/envio/src/Benchmark.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.rescodegenerator/cli/templates/dynamic/codegen/package.json.hbs
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{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/Benchmark.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript
.resmodules directly; ignore compiled.jsartifacts
Files:
codegenerator/cli/npm/envio/src/Benchmark.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/npm/envio/src/bindings/NodeJs.res
codegenerator/cli/templates/dynamic/**/*.hbs
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Templates in Handlebars format (.hbs) live under
codegenerator/cli/templates/dynamic/
Files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
🧠 Learnings (22)
📓 Common learnings
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : In Envio HyperIndex, use `entity_id` fields (e.g., `token_id: string`) instead of direct object references for entity relationships
Applied to files:
codegenerator/cli/npm/envio/package.jsoncodegenerator/cli/npm/envio/package.json.tmplcodegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Import and use the Effect API (`S`, `createEffect`) from 'envio' package for external calls in HyperIndex handlers
Applied to files:
codegenerator/cli/npm/envio/package.jsoncodegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/{**/*.ts,**/schema.graphql} : Ensure database schema compatibility: verify that the types you're setting in code match the schema entity property types exactly. Compare with schema.graphql - for example, `Int!` in schema requires `number` in code, `BigInt!` requires `BigInt`, `BigDecimal!` requires `BigDecimal`
Applied to files:
codegenerator/cli/npm/envio/package.jsoncodegenerator/cli/npm/envio/package.json.tmplcodegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: After any change to TypeScript files, run `pnpm tsc --noEmit` to ensure successful compilation
Applied to files:
codegenerator/cli/npm/envio/package.jsoncodegenerator/cli/npm/envio/package.json.tmpl
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Always verify entity type field names match exactly with the generated entity types. For example, use `token0_id` not `token0`, and `transaction_id` not `transaction`. Run `pnpm tsc --noEmit` to catch type mismatches
Applied to files:
codegenerator/cli/npm/envio/package.jsoncodegenerator/cli/npm/envio/package.json.tmplcodegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : When updating existing entities in HyperIndex handlers, always use the spread operator for immutability since returned objects are read-only
Applied to files:
codegenerator/cli/npm/envio/package.json.tmplcodegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For entity creation patterns, always include all required fields in a single object literal and use `context.Entity.set(entity)` (without await). Update patterns should spread existing entity data and update only changed fields: `const updated = { ...existing, field: newValue }; context.Entity.set(updated);`
Applied to files:
codegenerator/cli/npm/envio/package.json.tmpl
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Import entity types from `generated/src/db/Entities.gen` for type annotations (e.g., `Pair_t`, `Token_t`), NOT from `generated` which exports contract handlers. Use the correct entity type imports to prevent TypeScript errors like 'refers to a value, but is being used as a type'
Applied to files:
codegenerator/cli/npm/envio/package.json.tmplcodegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Use `string | undefined` for optional string fields in Envio types, not `string | null`, as generated types are strict about null vs undefined
Applied to files:
codegenerator/cli/npm/envio/package.json.tmpl
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Always cast timestamps to BigInt using `BigInt(event.block.timestamp)` instead of using raw timestamps from events
Applied to files:
codegenerator/cli/npm/envio/package.json.tmpl
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For Step 6 - Final Migration Verification: Go through each handler and helper function systematically, comparing the logic line-by-line to the original subgraph implementation. Iterate multiple times until logic is completely correct, as first pass often misses subtle differences
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 3 - Refactor file structure to mirror the original subgraph EXACTLY using the same filenames, create separate handler files by contract (e.g., contract1.ts, contract2.ts) instead of a single EventHandlers.ts file, and move handlers from EventHandlers.ts to contract-specific files
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : All TypeScript handler and utility files must have proper async/await for database operations. Use `await` for `context.Entity.get()`, `context.Entity.getWhere().field.eq()` calls. Note: `context.Entity.set()` does NOT need `await` - it's synchronous
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/utils/**/*.ts : When implementing helper functions with no entity or handler dependencies, implement the COMPLETE business logic from the original subgraph immediately, not just placeholder TODO comments
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to codegenerator/cli/templates/static/**/*.res : Static ReScript template files live under `codegenerator/cli/templates/static/` and are copied verbatim
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to **/*.res : Prefer reading ReScript `.res` modules directly; ignore compiled `.js` artifacts
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Verify tests pass by running compiler `pnpm rescript` and tests `pnpm mocha`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbs
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.{res,resi} : Always use ReScript 11 documentation
Applied to files:
codegenerator/cli/templates/dynamic/codegen/package.json.hbscodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-11-19T05:36:33.975Z
Learnt from: nikbhintade
Repo: enviodev/hyperindex PR: 822
File: codegenerator/cli/templates/static/multichain_indexer_template/typescript/src/EventHandlers.ts:10-18
Timestamp: 2025-11-19T05:36:33.975Z
Learning: The multichain_indexer_template in codegenerator/cli/templates/static/ is designed to demonstrate multichain indexing features. It intentionally uses minimal event parameters (e.g., only capturing the `pool` address from Uniswap V3 PoolCreated events) to keep the focus on multichain functionality rather than comprehensive event indexing.
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: For multichain indexing, prefix all entity IDs with `event.chainId`: `${event.chainId}-${originalId}`, never hardcode `chainId = 1`, always use `event.chainId`, and use chain-specific Bundle IDs like `${chainId}-1` for accurate pricing per network
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
⏰ 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 (7)
codegenerator/cli/npm/envio/package.json (1)
48-49: LGTM - Consistent with template.The tsx dependency addition is consistent with
package.json.tmpl, ensuring the development and release configurations remain in sync.codegenerator/cli/npm/envio/package.json.tmpl (1)
59-60: LGTM - tsx dependency for TestIndexer worker thread support.The addition of
tsxas a runtime dependency aligns with the PR objective to "Apply tsx for TestIndexer worker thread." This enables running TypeScript files directly in worker threads without pre-compilation. The version 4.21.0 is current and has no known security advisories.codegenerator/cli/npm/envio/src/Benchmark.res (1)
219-219: LGTM! ESM-compatible dirname resolution.This correctly switches from the CommonJS
__dirnameto the ESM-compatible pattern usingimport.meta.url, which is necessary for ES modules.codegenerator/cli/npm/envio/src/bindings/NodeJs.res (1)
83-112: LGTM! Well-structured WorkerThreads bindings.The bindings correctly expose the Node.js
worker_threadsAPI surface needed for the test indexer worker communication. ThegetDirnamehelper provides a clean ESM-compatible replacement for__dirname.One minor note: the polymorphic types on
workerDataand message handlers ('a) rely on consistent type usage at call sites. This is acceptable for internal use but requires care to ensure type safety.codegenerator/cli/npm/envio/src/TestIndexer.res (3)
46-91: Good fix for JSON comparisons using TableIndices.FieldValue.The implementation now properly handles type-aware comparisons for bigint and BigDecimal by parsing the JSON field value using the field's schema and using
TableIndices.FieldValuecomparison methods. This addresses the previous concern about unsafe JSON comparisons.
407-424: Good fix for worker exit error handling.The
onExithandler now correctly usesUtils.Error.makeinstead ofJs.Exn.raiseError, ensuring the promise is properly rejected on non-zero exit codes.
436-468: LGTM! Worker initialization is well-structured.The
initTestWorkerfunction properly:
- Validates it's running in a worker thread
- Handles missing parent port gracefully
- Sets up the proxy storage for main-thread communication
- Respects user log level preferences while defaulting to silent
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| "db-up": "cd {{relative_path_to_root_from_generated}} && node -e 'import(\"{{relative_path_to_generated_from_root}}/src/db/Migrations.res.mjs\").then(m => m.runUpMigrations(true))'", | ||
| "db-down": "cd {{relative_path_to_root_from_generated}} && node -e 'import(\"{{relative_path_to_generated_from_root}}/src/db/Migrations.res.mjs\").then(m => m.runDownMigrations(true))'", | ||
| "db-setup": "cd {{relative_path_to_root_from_generated}} && node -e 'import(\"{{relative_path_to_generated_from_root}}/src/db/Migrations.res.mjs\").then(m => m.runUpMigrations(true, true))'", | ||
| "print-benchmark-summary": "cd {{relative_path_to_root_from_generated}} && node -e 'import(\"{{relative_path_to_generated_from_root}}/src/Benchmark.res.mjs\").then(m => m.Summary.printSummary())'", | ||
| {{!-- tsx is needed for start script to support TypeScript handlers --}} | ||
| "start": "cd {{relative_path_to_root_from_generated}}{{#if is_typescript}} && tsc --noEmit{{/if}} && node --no-warnings --import {{relative_path_to_generated_from_root}}/node_modules/envio/node_modules/tsx/dist/esm/index.mjs {{relative_path_to_generated_from_root}}/src/Index.res.mjs" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Locate and check the envio package.json for tsx dependency
find . -path "*/node_modules/envio/package.json" -o -path "*/envio/package.json" | head -5Repository: enviodev/hyperindex
Length of output: 105
🏁 Script executed:
#!/bin/bash
# Check multiple possible locations for envio's package.json
if [ -f "codegenerator/cli/npm/envio/package.json" ]; then
echo "=== Found at codegenerator/cli/npm/envio/package.json ==="
cat codegenerator/cli/npm/envio/package.json | jq '.dependencies.tsx // .devDependencies.tsx // .optionalDependencies.tsx // "NOT_FOUND"'
fi
# Also try to find it elsewhere
find . -type f -name "package.json" -path "*/envio/*" 2>/dev/null | grep -v node_modules | head -5Repository: enviodev/hyperindex
Length of output: 172
🏁 Script executed:
#!/bin/bash
# List the structure to understand the layout
ls -la codegenerator/cli/npm/envio/ 2>/dev/null || echo "Path not found at expected location"Repository: enviodev/hyperindex
Length of output: 992
🏁 Script executed:
#!/bin/bash
# View the full envio package.json to understand tsx dependency declaration
cat codegenerator/cli/npm/envio/package.jsonRepository: enviodev/hyperindex
Length of output: 1550
🏁 Script executed:
#!/bin/bash
# Check if tsx is also in the package.json.tmpl (template)
if [ -f "codegenerator/cli/npm/envio/package.json.tmpl" ]; then
echo "=== package.json.tmpl ==="
cat codegenerator/cli/npm/envio/package.json.tmpl
fiRepository: enviodev/hyperindex
Length of output: 1799
🏁 Script executed:
#!/bin/bash
# Search for other references to tsx in templates/dynamic to see if there are patterns
rg "tsx" codegenerator/cli/templates/dynamic/ -A 2 -B 2Repository: enviodev/hyperindex
Length of output: 1213
🏁 Script executed:
#!/bin/bash
# Check if there's a pnpm-lock.yaml at the root (indicating pnpm usage)
if [ -f "pnpm-lock.yaml" ]; then
echo "Project uses pnpm"
ls -la pnpm-lock.yaml
fiRepository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check what package manager the project uses
if [ -f "package-lock.json" ]; then
echo "Uses npm"
elif [ -f "pnpm-lock.yaml" ]; then
echo "Uses pnpm"
elif [ -f "yarn.lock" ]; then
echo "Uses yarn"
else
echo "No lock file found at root"
fi
# Check the package.json at root for package manager clues
if [ -f "package.json" ]; then
echo ""
echo "=== Root package.json ==="
head -20 package.json
fiRepository: enviodev/hyperindex
Length of output: 89
🏁 Script executed:
#!/bin/bash
# Check if the nested tsx path actually resolves when installed via npm
# by looking at how tsx is actually referenced elsewhere in the codebase
rg "import.*tsx" codegenerator/cli/templates/ -t ts -t js -t mjs 2>/dev/null | head -10Repository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/antml:bash
# Check if there's documentation or examples showing how tsx is used in generated projects
find codegenerator/cli/templates/dynamic -name "*.hbs" -o -name "*.ts" | xargs grep -l "tsx" 2>/dev/nullRepository: enviodev/hyperindex
Length of output: 123
🏁 Script executed:
#!/bin/bash
# Check if generated projects have tsx as a dependency
# Look for templates that show what dependencies are generated
rg "dependencies" codegenerator/cli/templates/dynamic/ -A 10 | grep -A 5 "tsx"Repository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check if there's any tooling that tells us what the default package manager is
# Look in package.json or other config files
rg "packageManager" . --type json 2>/dev/null | head -5Repository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Verify the tsx path by checking what the dist/esm/index.mjs file actually is
# in case it's something special or if there's an alternative
if [ -d "codegenerator/cli/npm/envio/node_modules/tsx" ]; then
ls -la codegenerator/cli/npm/envio/node_modules/tsx/dist/esm/index.mjs 2>/dev/null && echo "Path exists in dev environment"
elif [ -d "node_modules/tsx" ]; then
echo "tsx found at root node_modules"
ls -la node_modules/tsx/dist/esm/index.mjs 2>/dev/null
fiRepository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check the generated package.json template to see what dependencies are included
# Look for the main package.json.hbs or package.json generation logic
find codegenerator/cli/templates/dynamic -name "*.hbs" -exec grep -l '"dependencies"' {} \;Repository: enviodev/hyperindex
Length of output: 198
🏁 Script executed:
#!/bin/bash
# Check if there's documentation about generated project structure
find . -name "README*" -o -name "GUIDE*" | xargs grep -l "package.json" 2>/dev/null | head -3Repository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Look more carefully at what dependencies the generated projects are supposed to have
# by examining all package.json related templates
find codegenerator/cli/templates -name "*package.json*" -type f | while read f; do
echo "=== $f ==="
head -50 "$f"
doneRepository: enviodev/hyperindex
Length of output: 3285
🏁 Script executed:
#!/bin/bash
# Check the Node.js version requirement to see if import.meta.resolve is available
# Node 18.19.0+ and 20.10.0+ support import.meta.resolve()
rg "engines" codegenerator/cli/templates/dynamic/codegen/package.json.hbs -A 2Repository: enviodev/hyperindex
Length of output: 105
🏁 Script executed:
#!/antml:bash
# Search for how tsx is actually used in the generated code
# Look for any tests or documentation about tsx usage
rg "tsx" codegenerator/cli/templates/ -B 5 -A 5 --type hbsRepository: enviodev/hyperindex
Length of output: 2051
🏁 Script executed:
#!/bin/bash
# Check if there's any alternative tsx resolution or if it's consistently nested
rg "node_modules" codegenerator/cli/templates/dynamic/codegen/package.json.hbsRepository: enviodev/hyperindex
Length of output: 351
🏁 Script executed:
#!/bin/bash
# Check if there's any pnpm configuration that would affect node_modules structure
if [ -f "pnpm-workspace.yaml" ] || [ -f ".npmrc" ] || [ -f "pnpm-lock.yaml" ]; then
echo "Project uses pnpm"
fi
# Also check what the actual recommended package manager is
rg "pnpm" . --type json 2>/dev/null | head -5Repository: enviodev/hyperindex
Length of output: 496
🏁 Script executed:
#!/an/bash
# Look for any existing generated projects or test fixtures that show how the nested path works
find . -path "*/generated/package.json" -type f 2>/dev/null | head -3 | xargs cat 2>/dev/null | grep -A 5 -B 5 "tsx\|envio"Repository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check if there are any integration tests or examples showing the actual generated output
find . -name "*.test.*" -o -name "*.spec.*" | xargs grep -l "start.*script\|tsx" 2>/dev/null | head -3Repository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check if there are any known issues or TODOs about the tsx path
rg "tsx.*path\|tsx.*nested\|tsx.*hoisting" . --type hbs --type ts --type js 2>/dev/nullRepository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Look for how tsx is actually referenced in generated projects
# by checking if there are any build/config files that might reference it
find scenarios -name "package.json" -exec grep -l "tsx" {} \; 2>/dev/nullRepository: enviodev/hyperindex
Length of output: 243
🏁 Script executed:
#!/bin/bash
# Check the actual structure: does the nested tsx path exist when envio is installed?
# Let's look at what the start script would resolve to with pnpm
if [ -f "pnpm-lock.yaml" ]; then
echo "Project uses pnpm - checking how tsx is resolved"
# Check if tsx appears in the lock file
grep "tsx" pnpm-lock.yaml | head -5
fiRepository: enviodev/hyperindex
Length of output: 45
🏁 Script executed:
#!/bin/bash
# Check one of the scenario package.json files that mentions tsx to see if they have the nested path
echo "=== scenarios/test_codegen/package.json ==="
cat scenarios/test_codegen/package.json | grep -A 50 '"scripts"'Repository: enviodev/hyperindex
Length of output: 1745
🏁 Script executed:
#!/bin/bash
# Check if any of the scenario generated projects have the tsx nested path in their start script
for f in scenarios/*/package.json scenarios/*/generated/package.json; do
if [ -f "$f" ]; then
if grep -q "node_modules/envio/node_modules/tsx" "$f"; then
echo "=== Found nested tsx path in $f ==="
grep "start" "$f"
fi
fi
doneRepository: enviodev/hyperindex
Length of output: 45
Use NODE_OPTIONS='--import tsx' instead of nested tsx path for better package manager compatibility.
The start script references a nested path node_modules/envio/node_modules/tsx/dist/esm/index.mjs, which assumes npm's dependency tree structure. This breaks with pnpm (which flattens node_modules via symlinks) and may vary across package managers.
The test scenarios in this repository use a more portable pattern: NODE_OPTIONS='--import tsx'. Consider using this approach instead, which works consistently across npm, pnpm, and yarn without relying on nested dependency paths.
🤖 Prompt for AI Agents
In `@codegenerator/cli/templates/dynamic/codegen/package.json.hbs` around lines 15
- 20, The "start" script in the package.json.hbs template currently hardcodes a
nested tsx path (node_modules/envio/node_modules/tsx/...), which breaks under
pnpm/other package managers; update the "start" script to set
NODE_OPTIONS='--import tsx' on the node invocation instead of importing the
nested tsx path, preserving the existing tsc step when {{is_typescript}} is true
and keeping the same {{relative_path_to_root_from_generated}} and
{{relative_path_to_generated_from_root}} usages so the command becomes: run tsc
--noEmit when needed, then run node with NODE_OPTIONS='--import tsx' and the
entry {{relative_path_to_generated_from_root}}/src/Index.res.mjs.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@codegenerator/cli/npm/envio/src/TestIndexer.res`:
- Around line 116-167: handleWriteBatch in TestIndexer.res currently only
inspects update.latestChange, skipping earlier entries in update.history; change
it to iterate over update.history (each change) and apply the same logic used
for the Set/Delete branches (parse entity via S.parseOrThrow, update entityDict,
compute checkpointKey from checkpointId, get/create entityChanges and
entityChange, push to sets or deleted) for each history item so every historical
change is recorded in changesByCheckpoint; reuse the existing logic inside the
switch on update.latestChange but run it for each change in update.history (and
still include latestChange if history doesn't contain it) to mirror
PgStorage.res behavior.
♻️ Duplicate comments (4)
codegenerator/cli/npm/envio/src/TestIndexer.res (4)
214-216: Chain ID parsing silently defaults to 0 on invalid keys.
Int.fromString->Option.getWithDefault(0)masks malformed config keys. Chain ID 0 may be valid (Fuel), causing confusing "wrong chain" behavior instead of a clear error.💡 Proposed fix
let chains = chainKeys->Array.map(chainIdStr => { - let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0) + let chainId = switch chainIdStr->Int.fromString { + | Some(id) => id + | None => Js.Exn.raiseError(`Invalid chain ID: ${chainIdStr} is not a valid integer`) + } let chain = ChainMap.Chain.makeUnsafe(~chainId)
323-325: Same chain ID parsing issue repeated here.Line 324 has the same
getWithDefault(0)pattern that silently masks invalid chain IDs.💡 Proposed fix
chainKeys->Array.forEach(chainIdStr => { - let chainId = chainIdStr->Int.fromString->Option.getWithDefault(0) + let chainId = switch chainIdStr->Int.fromString { + | Some(id) => id + | None => Js.Exn.raiseError(`Invalid chain ID in process config: ${chainIdStr}`) + } let chain = ChainMap.Chain.makeUnsafe(~chainId)
169-206: Add length validation beforegetUnsafecalls on checkpoint arrays.Lines 170-184 use
Array.getUnsafeon multiple parallel arrays (checkpointIds,checkpointBlockNumbers,checkpointBlockHashes,checkpointChainIds,checkpointEventsProcessed) assuming identical lengths. A mismatch would cause a silent out-of-bounds access.💡 Proposed fix: Add invariant check
let handleWriteBatch = ( ... ): unit => { + // Validate checkpoint arrays have matching lengths + let checkpointCount = checkpointIds->Array.length + if checkpointBlockNumbers->Array.length !== checkpointCount || + checkpointBlockHashes->Array.length !== checkpointCount || + checkpointChainIds->Array.length !== checkpointCount || + checkpointEventsProcessed->Array.length !== checkpointCount { + Js.Exn.raiseError("Checkpoint metadata arrays have mismatched lengths") + } + // Group entity changes by checkpointId ...
362-396: Unhandled exceptions in message handler will cause deadlocks.If
handleLoadByIds,handleLoadByField, orhandleWriteBatchthrows (e.g., viaraiseErrorwhen a field is not found), no response is sent to the worker. The worker-sidesendRequestpromise never resolves/rejects, causing the test run to hang indefinitely.Wrap the switch statement in try/catch:
Proposed fix
worker->NodeJs.WorkerThreads.onMessage((msg: TestIndexerProxyStorage.workerMessage) => { let respond = data => worker->NodeJs.WorkerThreads.workerPostMessage( { TestIndexerProxyStorage.id: msg.id, payload: TestIndexerProxyStorage.Response({data: data}), }->Utils.magic, ) + let respondError = message => + worker->NodeJs.WorkerThreads.workerPostMessage( + { + TestIndexerProxyStorage.id: msg.id, + payload: TestIndexerProxyStorage.Error({message: message}), + }->Utils.magic, + ) - switch msg.payload { - | LoadByIds({tableName, ids}) => state->handleLoadByIds(~tableName, ~ids)->respond - | LoadByField({tableName, fieldName, fieldValue, operator}) => - state->handleLoadByField(~tableName, ~fieldName, ~fieldValue, ~operator)->respond - | WriteBatch({...}) => - state->handleWriteBatch(...) - Js.Json.null->respond - } + try { + switch msg.payload { + | LoadByIds({tableName, ids}) => state->handleLoadByIds(~tableName, ~ids)->respond + | LoadByField({tableName, fieldName, fieldValue, operator}) => + state->handleLoadByField(~tableName, ~fieldName, ~fieldValue, ~operator)->respond + | WriteBatch({...}) => + state->handleWriteBatch(...) + Js.Json.null->respond + } + } catch { + | exn => respondError(exn->Utils.prettifyExn) + } })
🧹 Nitpick comments (1)
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs (1)
26-30: Test file filtering looks good, but verify pattern coverage.The filter excludes files containing
.test.,.spec., or_test.which covers common conventions. However, files likefoo_spec.tsorfoo.tests.ts(plural) would not be filtered.Consider extending patterns for completeness
- files->Js.Array2.filter(file => { - !(file->Js.String2.includes(".test.") || file->Js.String2.includes(".spec.") || file->Js.String2.includes("_test.")) - }) + files->Js.Array2.filter(file => { + !(file->Js.String2.includes(".test.") || file->Js.String2.includes(".spec.") || file->Js.String2.includes("_test.") || file->Js.String2.includes("_spec.")) + })
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
.cursor/rules/navigation.mdcAGENTS.mdCLAUDE.mdcodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbscodegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res
💤 Files with no reviewable changes (1)
- .cursor/rules/navigation.mdc
✅ Files skipped from review due to trivial changes (1)
- CLAUDE.md
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{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/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/npm/envio/src/TestIndexer.res
codegenerator/cli/templates/static/**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Static ReScript template files live under
codegenerator/cli/templates/static/and are copied verbatim
Files:
codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res
**/*.res
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Prefer reading ReScript
.resmodules directly; ignore compiled.jsartifacts
Files:
codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/npm/envio/src/TestIndexer.res
codegenerator/cli/templates/dynamic/**/*.hbs
📄 CodeRabbit inference engine (.cursor/rules/navigation.mdc)
Templates in Handlebars format (.hbs) live under
codegenerator/cli/templates/dynamic/
Files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
🧠 Learnings (18)
📓 Common learnings
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Verify tests pass by running compiler `pnpm rescript` and tests `pnpm mocha`
📚 Learning: 2025-11-19T05:36:33.975Z
Learnt from: nikbhintade
Repo: enviodev/hyperindex PR: 822
File: codegenerator/cli/templates/static/multichain_indexer_template/typescript/src/EventHandlers.ts:10-18
Timestamp: 2025-11-19T05:36:33.975Z
Learning: The multichain_indexer_template in codegenerator/cli/templates/static/ is designed to demonstrate multichain indexing features. It intentionally uses minimal event parameters (e.g., only capturing the `pool` address from Uniswap V3 PoolCreated events) to keep the focus on multichain functionality rather than comprehensive event indexing.
Applied to files:
codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : In Envio HyperIndex, use `entity_id` fields (e.g., `token_id: string`) instead of direct object references for entity relationships
Applied to files:
codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: AFTER EVERY SINGLE CODE CHANGE, you MUST test the indexer with `TUI_OFF=true pnpm dev` to catch runtime errors early, as TypeScript compilation only catches syntax and type errors while runtime errors (database issues, missing entities, logic errors) only appear when running the indexer
Applied to files:
codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Use `!context.isPreload` check to prevent logic from running during preload in HyperIndex handlers
Applied to files:
codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : Import and use the Effect API (`S`, `createEffect`) from 'envio' package for external calls in HyperIndex handlers
Applied to files:
codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.rescodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-11-25T12:40:26.435Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/rescript.mdc:0-0
Timestamp: 2025-11-25T12:40:26.435Z
Learning: Applies to **/*.{res,resi} : Always use ReScript 11 documentation
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.rescodegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/{**/*.ts,**/schema.graphql} : Ensure database schema compatibility: verify that the types you're setting in code match the schema entity property types exactly. Compare with schema.graphql - for example, `Int!` in schema requires `number` in code, `BigInt!` requires `BigInt`, `BigDecimal!` requires `BigDecimal`
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Always verify entity type field names match exactly with the generated entity types. For example, use `token0_id` not `token0`, and `transaction_id` not `transaction`. Run `pnpm tsc --noEmit` to catch type mismatches
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:12:49.547Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/hyperindex.mdc:0-0
Timestamp: 2025-12-04T12:12:49.547Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.{ts,js} : When updating existing entities in HyperIndex handlers, always use the spread operator for immutability since returned objects are read-only
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2025-12-04T12:13:23.245Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.245Z
Learning: For multichain indexing, prefix all entity IDs with `event.chainId`: `${event.chainId}-${originalId}`, never hardcode `chainId = 1`, always use `event.chainId`, and use chain-specific Bundle IDs like `${chainId}-1` for accurate pricing per network
Applied to files:
codegenerator/cli/npm/envio/src/TestIndexer.res
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to codegenerator/cli/templates/static/**/*.res : Static ReScript template files live under `codegenerator/cli/templates/static/` and are copied verbatim
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 3 - Refactor file structure to mirror the original subgraph EXACTLY using the same filenames, create separate handler files by contract (e.g., contract1.ts, contract2.ts) instead of a single EventHandlers.ts file, and move handlers from EventHandlers.ts to contract-specific files
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Applies to codegenerator/cli/templates/dynamic/**/*.hbs : Templates in Handlebars format (.hbs) live under `codegenerator/cli/templates/dynamic/`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2026-01-05T11:20:07.222Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: .cursor/rules/navigation.mdc:0-0
Timestamp: 2026-01-05T11:20:07.222Z
Learning: Config parsing flows: `human_config.rs` → `system_config.rs` → `hbs_templating/codegen_templates.rs`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : For Step 6 - Final Migration Verification: Go through each handler and helper function systematically, comparing the logic line-by-line to the original subgraph implementation. Iterate multiple times until logic is completely correct, as first pass often misses subtle differences
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/*.ts : Import entity types from `generated/src/db/Entities.gen` for type annotations (e.g., `Pair_t`, `Token_t`), NOT from `generated` which exports contract handlers. Use the correct entity type imports to prevent TypeScript errors like 'refers to a value, but is being used as a type'
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
📚 Learning: 2025-12-04T12:13:23.246Z
Learnt from: CR
Repo: enviodev/hyperindex PR: 0
File: codegenerator/cli/templates/static/shared/.cursor/rules/subgraph-migration.mdc:0-0
Timestamp: 2025-12-04T12:13:23.246Z
Learning: Applies to codegenerator/cli/templates/static/shared/**/src/**/*.ts : For Step 4 - Implement contract registration for factory events using `contractRegister` above the handler to track dynamically created contracts: `Factory.EventName.contractRegister(({ event, context }) => { context.addContractName(event.params.contractAddress); });`
Applied to files:
codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs
⏰ 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 (9)
AGENTS.md (1)
1-5: Verify this file belongs in this PR.This file appears unrelated to the PR objectives (TestIndexer framework, Vitest migration) and is not mentioned in the commit message. No references to AGENTS.md were found in the codebase. If this was included unintentionally, it should be removed from this PR.
Note:
.cursor/rules/exists but contains.mdcfiles. CLAUDE.md is similarly placed at the repository root, suggesting root-level placement may be intentional for agent/AI guidance files.codegenerator/cli/templates/dynamic/codegen/src/Generated.res.hbs (2)
1-1: LGTM! Inline JSON import directive.Using the
@@directiveto import JSON withwith { type: 'json' }is the correct approach for ES module JSON imports in ReScript, replacing the previous external binding pattern.
88-92: Verify%rawaccess to directive-imported value.Using
%raw(internalConfigJson)to reference the@@directive-imported JSON is necessary since the directive creates a runtime binding not visible to ReScript's type system. This is the expected pattern.codegenerator/cli/npm/envio/src/TestIndexer.res (5)
1-24: LGTM! Type definitions are well-structured.The type declarations for
chainConfig,processResult,t<'processConfig>,entityChange, andtestIndexerStateprovide a clean public API surface for the test indexer.
46-91: Field comparison logic correctly uses typed comparisons viaTableIndices.FieldValue.The implementation properly parses JSON to typed values using the field schema and delegates comparisons to
TableIndices.FieldValue.eq/gt/lt, which handles bigint and BigDecimal correctly. This addresses the previous concern about raw JSON comparisons.
246-279: LGTM! Block range validation is comprehensive.The
validateBlockRangefunction provides clear, actionable error messages for invalid configurations, checking startBlock/endBlock bounds and preventing overlap with previously processed ranges.
433-466: LGTM! Worker initialization is well-structured.The
initTestWorkerfunction properly validates it's running in a worker thread, extracts parent port, handles missing worker data gracefully, and silences logs by default in test mode while respecting explicitLOG_LEVELsettings.
26-44: > Likely an incorrect or invalid review comment.codegenerator/cli/templates/static/codegen/src/TestIndexerWorker.res (1)
1-17: LGTM! Worker entry point is cleanly structured.The worker bootstrap correctly:
- Registers the tsx loader before any TypeScript imports
- Wires up the generated handlers and config
- Constructs persistence with the required entity and enum configurations
The inline
~makePersistencefunction avoids circular dependencies by constructingPersistence.makeat runtime.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
Co-authored-by: Claude <noreply@anthropic.com>
Previously, handleWriteBatch only inspected update.latestChange, skipping earlier entries in update.history. This change mirrors PgStorage.res behavior by iterating over all history entries and applying Set/Delete logic for each. Includes a fallback to process latestChange when history is empty for backwards compatibility. Co-authored-by: Claude <noreply@anthropic.com>
Based on #884
And #802
Summary by CodeRabbit
New Features
Tests
Documentation
Breaking Changes
✏️ Tip: You can customize this high-level summary in your review settings.