Skip to content

Migrate from Js.* to modern ReScript APIs - #1104

Merged
DZakh merged 4 commits into
mainfrom
claude/remove-warning-flag-SVTy5
Apr 14, 2026
Merged

Migrate from Js.* to modern ReScript APIs#1104
DZakh merged 4 commits into
mainfrom
claude/remove-warning-flag-SVTy5

Conversation

@DZakh

@DZakh DZakh commented Apr 14, 2026

Copy link
Copy Markdown
Member

Summary

This PR modernizes the codebase by migrating from deprecated Js.* APIs to their modern ReScript equivalents. This includes updates to exception handling, dictionary operations, array methods, date handling, and JSON types.

Key Changes

  • Exception Handling: Replaced Js.Exn.raiseError() with JsError.throwWithMessage() for more idiomatic error throwing
  • Dictionary Operations: Migrated from Js.Dict to Dict module (e.g., Js.Dict.get()Dict.get(), Js.Dict.empty()Dict.make(), Js.Dict.fromArray()Dict.fromArray())
  • Array Methods: Updated Js.Array2.map() to Array.map() for consistency with modern ReScript stdlib
  • Date Handling: Changed Js.Date.fromString() to Date.fromString()
  • JSON Types: Updated Js.Json.t to JSON.t in type definitions
  • Option Methods: Replaced Option.getExn with Option.getOrThrow for better semantics
  • Console Logging: Changed Js.log() to Console.log()
  • Configuration: Removed deprecated warnings configuration from rescript.json files and cleaned up bs-dependencies configuration

Notable Implementation Details

  • All changes maintain backward compatibility in functionality while using modern APIs
  • Test files were reformatted with improved code organization (better line breaks and indentation)
  • The migration is comprehensive across test files, source code, and configuration files
  • No functional behavior changes - this is purely an API modernization effort

https://claude.ai/code/session_01YCbJaSa8Vpi5tSgU8WRWcS

Summary by CodeRabbit

  • Refactor
    • Switched many internals to use native ReScript/stdlib primitives and native JSON/Date types for more consistent runtime behavior.
  • Chores
    • Removed obsolete compiler warnings configuration from project templates.
  • Tests
    • Reformatted and modernized test code, replacing JS interop with stdlib equivalents and standardizing error handling for clearer, more consistent test behavior.

Continues the Js.* → ReScript stdlib migration from #1103 for the
places where the -3 warning suppression was still left:

- scenarios/test_codegen and scenarios/fuel_test: ran rescript-tools
  migrate-all, plus manual fixes for Array.sort (now returns unit —
  switched to Array.toSorted) with Int.compare comparators, and
  string_of_int/float_of_int → Int.toString/Int.toFloat.

- packages/cli/templates/static/{codegen,blank_template}/rescript.json:
  dropped "warnings": -3. Templates regenerate indexer code, so also
  updated the Rust codegen:
    - type_schema.rs: Js.Json.t → JSON.t, Js.Date.t → Date.t,
      Js.Date.fromFloat → Date.fromTime.
    - codegen_templates.rs: SingleOrMultiple now uses Array.isArray
      instead of Js.Json.decodeArray, with JSON.t aliases.
    - Regenerated insta snapshots.

https://claude.ai/code/session_01YCbJaSa8Vpi5tSgU8WRWcS
@coderabbitai

coderabbitai Bot commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a2cd462f-91b3-4b41-ad59-4c1725db4657

📥 Commits

Reviewing files that changed from the base of the PR and between 0c0c4ff and fbaf235.

⛔ Files ignored due to path filters (2)
  • packages/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__indexer_code_generates_correct_types_and_values.snap is excluded by !**/*.snap
  • packages/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__indexer_code_multiple_chains.snap is excluded by !**/*.snap
📒 Files selected for processing (2)
  • packages/cli/src/hbs_templating/codegen_templates.rs
  • scenarios/test_codegen/test/rollback/Rollback_test.res

📝 Walkthrough

Walkthrough

Migrates ReScript code and tests from JS interop to ReScript stdlib: Js.Json.tJSON.t, Js.DateDate, Js.Dict/Js.Array2Dict/Array, replaces Js.Exn.raiseError with JsError.throwWithMessage, and updates generated SingleOrMultiple.isMultiple to use Array.isArray + Utils.magic.

Changes

Cohort / File(s) Summary
Generated code & type mappings
packages/cli/src/hbs_templating/codegen_templates.rs, packages/cli/src/type_schema.rs
Updated generated type mappings: Js.Json.tJSON.t, Js.Date.tDate.t, default Js.Date.fromFloat(0.)Date.fromTime(0.). Reworked SingleOrMultiple.isMultiple to use Array.isArray + Utils.magic and adjusted recursive depth handling.
Rescript config templates
packages/cli/templates/static/blank_template/rescript/rescript.json, packages/cli/templates/static/codegen/rescript.json, scenarios/fuel_test/rescript.json, scenarios/test_codegen/rescript.json
Removed "warnings": { "number": "-3" } entries from rescript.json templates.
Mocks & indexer surface
scenarios/test_codegen/test/__mocks__/MockConfig.res, scenarios/test_codegen/test/__mocks__/MockEvents.res, scenarios/test_codegen/test/helpers/MockIndexer.res
Replaced Js.Dict/Js.Array2 with Dict/Array, switched Js.Exn.raiseErrorJsError.throwWithMessage, changed exported queryEffectCache/other JSON types to JSON.t, and reformatted type annotations.
Core tests — event/config/handlers
scenarios/test_codegen/test/EventHandlers.res, scenarios/test_codegen/test/Config_test.res, scenarios/test_codegen/test/EventFilters_test.res, scenarios/test_codegen/test/EventOrigin_test.res
Migrated JS interop APIs to stdlib equivalents (JsError, Dict, Array, JSON/Nullable), changed pattern-match error variants (Js.Exn.ErrorJsExn), and compacted assertion formatting.
Core tests — sources, sync, RPC
scenarios/test_codegen/test/HyperSyncSource_test.res, scenarios/test_codegen/test/HyperSync_test.res, scenarios/test_codegen/test/RpcSource_test.res, scenarios/test_codegen/test/BlockLag_test.res
Replaced collection and option APIs with stdlib (Dict.make/fromArray, Array.*, Option.getOrThrow), standardized error throws to JsError.throwWithMessage, and simplified many assertions/formatting.
Core tests — chain/entity management
scenarios/test_codegen/test/ChainManager_test.res, scenarios/test_codegen/test/E2E_test.res, scenarios/test_codegen/test/EntityColumnTypes_test.res, scenarios/test_codegen/test/LoadLayer_test.res
Switched time/random to Date.now()/Math.random(), arrays/dicts to Array/Dict, Js.Global.setTimeoutsetTimeout, nullable types to Nullable, and compacted assertions.
Core tests — blocks & I/O
scenarios/test_codegen/test/OptionalBlockParams_test.res, scenarios/test_codegen/test/RawEventsTableMigration_test.res, scenarios/test_codegen/test/ReorgDetection_test.res, scenarios/test_codegen/test/WriteRead_test.res
Replaced Js.Date.*, Js.Array2.*, and Js.Exn.raiseError with stdlib equivalents and JsError; reformatted SQL/expectation calls but retained semantics.
Library tests & helpers
scenarios/test_codegen/test/lib_tests/*, scenarios/test_codegen/test/fixtures/LogTesting.res
Systematic replacement of Js.* interop (dates, arrays, dicts, exceptions, string includes) with stdlib (Date, Array, Dict, JsError, String.includes), plus assertion formatting changes.
Rollback & schema/unit tests
scenarios/test_codegen/test/rollback/*, scenarios/test_codegen/test/schema_types/*
Switched Js.Array2.findArray.find and Option.getExnOption.getOrThrow, replaced Js.Exn.raiseError with JsError.throwWithMessage, and moved Js.DateDate.
Miscellaneous tests & formatting-only updates
Many test files under scenarios/test_codegen/test/* and scenarios/fuel_test/*
Predominantly formatting and API surface updates from Js.* to stdlib counterparts, collapsing multi-line assertions to single-line forms without behavior changes.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • JasoonS
  • JonoPrest

"🐰
JSON and Dates now take the stage,
Dicts and Arrays turn a page.
Errors hopped from Js to new,
Tests refreshed—so neat and true.
A tiny rabbit cheers: hooray!"

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objective: migrating deprecated Js.* APIs to modern ReScript stdlib equivalents. It is concise, specific, and directly reflects the primary focus of the changeset.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/remove-warning-flag-SVTy5

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

❤️ Share

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

…-flag-SVTy5

# Conflicts:
#	scenarios/test_codegen/test/rollback/Rollback_test.res

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

🧹 Nitpick comments (3)
scenarios/test_codegen/test/lib_tests/Persistence_test.res (1)

17-19: Fix typo in assertion message text.

Intial should be Initial to keep failure output clear.

Proposed patch
-    t.expect(persistence.storageStatus, ~message=`Intial storage status should be unknown`).toEqual(
+    t.expect(persistence.storageStatus, ~message=`Initial storage status should be unknown`).toEqual(
       Persistence.Unknown,
     )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scenarios/test_codegen/test/lib_tests/Persistence_test.res` around lines 17 -
19, Update the assertion message string for the test using
t.expect(persistence.storageStatus, ~message=`Intial storage status should be
unknown`) to correct the typo: replace "Intial" with "Initial" so the message
reads "Initial storage status should be unknown" in the Persistence_test.res
assertion.
scenarios/test_codegen/test/lib_tests/PgStorage_test.res (1)

118-129: Consolidate this into one assertion for the whole outcome.

At Line 118-Line 129, these checks are tightly related and can be expressed as a single assertion to keep failures clearer and align with test style conventions.

♻️ Proposed refactor
-        t.expect(
-          queryAsc,
-          ~message="Same fields with different directions must produce different index names",
-        ).not.toBe(queryDesc)
-        t.expect(
-          queryAsc->String.includes("\"t_a_b\""),
-          ~message="ASC index name has no suffix",
-        ).toBeTruthy()
-        t.expect(
-          queryDesc->String.includes("\"t_a_desc_b_desc\""),
-          ~message="DESC index name encodes direction",
-        ).toBeTruthy()
+        t.expect(
+          {
+            differentQueries: queryAsc !== queryDesc,
+            ascNameOk: queryAsc->String.includes("\"t_a_b\""),
+            descNameOk: queryDesc->String.includes("\"t_a_desc_b_desc\""),
+          },
+          ~message="Index names must differ and encode direction correctly",
+        ).toEqual({
+          differentQueries: true,
+          ascNameOk: true,
+          descNameOk: true,
+        })

Based on learnings: Applies to **/*.{test.res,test.js,test.ts,test.tsx,spec.res,spec.js,spec.ts,spec.tsx} : Always use single assert to check the whole value instead of multiple asserts for every field.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scenarios/test_codegen/test/lib_tests/PgStorage_test.res` around lines 118 -
129, The three related assertions around queryAsc and queryDesc should be
consolidated into a single assertion that verifies the entire outcome at once:
build an expected combined check (e.g., a single string/regex or composed
object) that ensures queryAsc !== queryDesc, that queryAsc contains "\"t_a_b\"",
and that queryDesc contains "\"t_a_desc_b_desc\"", then replace the three
t.expect calls with one t.expect(...).toBeTruthy() (or equivalent) that
evaluates that combined condition; refer to the existing symbols queryAsc,
queryDesc and their String.includes checks to locate and combine the checks into
one assertion.
packages/cli/src/hbs_templating/codegen_templates.rs (1)

1658-1681: Prefer JSON.Decode.array here instead of Array.isArray + Utils.magic.

JSON.t already exposes arrays directly in ReScript 12, and JSON.Decode.array returns option<array<t>>. Switching to that would remove the unchecked cast from the generated helper and make future refactors safer. (rescript-lang.org)

♻️ Proposed fix
-  let rec isMultiple = (t: t<'a>, ~nestedArrayDepth): bool =>
-    if !Array.isArray(t) {{
-      false
-    }} else {{
-      let arr = t->(Utils.magic: t<'a> => array<t<'a>>)
-      if nestedArrayDepth == 0 {{
-        true
-      }} else if arr->Array.length == 0 {{
-        AmbiguousEmptyNestedArray->ErrorHandling.mkLogAndRaise(
-          ~msg="The given empty array could be interperated as a flat array (value) or nested array. Since it's ambiguous,
-          please pass in a nested empty array if the intention is to provide an empty array as a value",
-        )
-      }} else {{
-        arr->Utils.Array.firstUnsafe->isMultiple(~nestedArrayDepth=nestedArrayDepth - 1)
-      }}
-    }}
+  let rec isMultiple = (t: t<'a>, ~nestedArrayDepth): bool =>
+    switch t->JSON.Decode.array {{
+    | None => false
+    | Some(arr) =>
+      if nestedArrayDepth == 0 {{
+        true
+      }} else if arr->Array.length == 0 {{
+        AmbiguousEmptyNestedArray->ErrorHandling.mkLogAndRaise(
+          ~msg="The given empty array could be interperated as a flat array (value) or nested array. Since it's ambiguous,
+          please pass in a nested empty array if the intention is to provide an empty array as a value",
+        )
+      }} else {{
+        arr->Utils.Array.firstUnsafe->isMultiple(~nestedArrayDepth=nestedArrayDepth - 1)
+      }}
+    }}
Based on learnings: Always use ReScript 12 documentation. Never suggest ReasonML syntax
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/hbs_templating/codegen_templates.rs` around lines 1658 -
1681, The isMultiple helper currently checks arrays using Array.isArray plus an
unchecked cast via Utils.magic and should be changed to use JSON.Decode.array to
safely decode t as an option<array<t>>; replace the Array.isArray branch with a
JSON.Decode.array(t) match (None -> false | Some(arr) -> ...), keep the existing
nestedArrayDepth logic and error raise via
AmbiguousEmptyNestedArray->ErrorHandling.mkLogAndRaise when arr is empty at
deeper depth, and remove the Utils.magic cast to eliminate unsafe casting and
rely on JSON.Decode.array for safe extraction.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/hbs_templating/codegen_templates.rs`:
- Around line 1675-1677: Update the error message string in
AmbiguousEmptyNestedArray->ErrorHandling.mkLogAndRaise to correct the typo:
replace "interperated" with "interpreted" in the ~msg text so the raised message
reads "...could be interpreted as a flat array (value) or nested array..."
ensuring the rest of the message stays unchanged.

In `@scenarios/test_codegen/test/ChainManager_test.res`:
- Line 61: The event string uses an un-annotated magic cast; change the
expression `...->Utils.magic` to include an explicit ReScript cast signature
like `...->(Utils.magic: string => eventType)` (replace eventType with the
appropriate target type), referencing the `Utils.magic` usage on the `event`
field so the cast is explicit (i.e., annotate the input as string and the
desired output type).

In `@scenarios/test_codegen/test/Config_test.res`:
- Line 189: Update the unannotated uses of Utils.magic by adding explicit cast
signatures of the form (Utils.magic: inputType => outputType) for each modified
test param; specifically replace {"from": "0xabc", "to": "0xdef", "value":
100n}->Utils.magic with {"from": "0xabc", "to": "0xdef", "value":
100n}->(Utils.magic: {from:string,to:string,value:int} => <expectedOutputType>),
{"id": 1n, "details": ("hello","world")}->Utils.magic with ->(Utils.magic:
{id:int,details:(string,string)} => <expectedOutputType>), {"data":
(1n,(2n,"hello"))}->Utils.magic with ->(Utils.magic: {data:(int,(int,string))}
=> <expectedOutputType>), and {"ids":[1n,2n,3n]}->Utils.magic with
->(Utils.magic: {ids: list<int>} => <expectedOutputType>); also check and
annotate the empty-tuple case `()->Utils.magic` similarly. Replace
<expectedOutputType> with the actual expected return types for each test.

In `@scenarios/test_codegen/test/HyperSync_test.res`:
- Line 39: The test currently uses Console.log(page) which doesn't verify
behavior; replace that log with ReScript assertions using the Assert module to
validate the expected shape or error for the `page` value (e.g., check specific
fields like `page.id`, `page.status`, or that `page` is an error/empty shape).
Locate the `Console.log(page)` call in the test (in HyperSync_test.res) and swap
it for one or more Assert.* checks (e.g., Assert.equal, Assert.assert, or
Assert.exceptions) that express the contract for broken-transaction handling so
the test fails when the actual `page` value deviates from expectations.

In `@scenarios/test_codegen/test/HyperSyncSource_test.res`:
- Line 188: The topic1 entry uses Utils.magic without an explicit cast; update
the topic1 value (the mockAddress0->Utils.magic usage) to use the explicit
typed-cast form required by our ReScript guideline: wrap the Utils.magic use
with an explicit type annotation showing the input and output types (i.e.,
convert mockAddress0->Utils.magic into mockAddress0->(Utils.magic: inputType =>
outputType)), so the conversion boundary on topic1 is explicit and typed.

In `@scenarios/test_codegen/test/lib_tests/PgStorage_test.res`:
- Around line 693-695: The assertion message incorrectly says "Should return
empty string when no chain configs provided" while the test asserts that query
is None; update the expectation message for the t.expect(...).toBe(None)
assertion (the one referencing variable `query` in PgStorage_test.res) to
accurately describe the asserted value (e.g., "Should return None when no chain
configs provided") so test failures report the correct expectation.

In `@scenarios/test_codegen/test/LoadLayer_test.res`:
- Line 362: Replace all untyped Utils.magic casts of the form "fieldValue":
"123"->Utils.magic (and the other similar occurrences) with explicit annotated
casts using the ReScript pattern value->(Utils.magic: inputType => outputType);
update each instance to use the correct inputType and outputType for that field
(for example "123"->(Utils.magic: string => int) if converting string to int) so
each "fieldValue": ... entry uses the explicit cast form; search for the same
untyped ->Utils.magic token in the file and apply the same transformation to
each occurrence.

---

Nitpick comments:
In `@packages/cli/src/hbs_templating/codegen_templates.rs`:
- Around line 1658-1681: The isMultiple helper currently checks arrays using
Array.isArray plus an unchecked cast via Utils.magic and should be changed to
use JSON.Decode.array to safely decode t as an option<array<t>>; replace the
Array.isArray branch with a JSON.Decode.array(t) match (None -> false |
Some(arr) -> ...), keep the existing nestedArrayDepth logic and error raise via
AmbiguousEmptyNestedArray->ErrorHandling.mkLogAndRaise when arr is empty at
deeper depth, and remove the Utils.magic cast to eliminate unsafe casting and
rely on JSON.Decode.array for safe extraction.

In `@scenarios/test_codegen/test/lib_tests/Persistence_test.res`:
- Around line 17-19: Update the assertion message string for the test using
t.expect(persistence.storageStatus, ~message=`Intial storage status should be
unknown`) to correct the typo: replace "Intial" with "Initial" so the message
reads "Initial storage status should be unknown" in the Persistence_test.res
assertion.

In `@scenarios/test_codegen/test/lib_tests/PgStorage_test.res`:
- Around line 118-129: The three related assertions around queryAsc and
queryDesc should be consolidated into a single assertion that verifies the
entire outcome at once: build an expected combined check (e.g., a single
string/regex or composed object) that ensures queryAsc !== queryDesc, that
queryAsc contains "\"t_a_b\"", and that queryDesc contains
"\"t_a_desc_b_desc\"", then replace the three t.expect calls with one
t.expect(...).toBeTruthy() (or equivalent) that evaluates that combined
condition; refer to the existing symbols queryAsc, queryDesc and their
String.includes checks to locate and combine the checks into one assertion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f2266f01-28c5-4c5d-b192-5f7bf9c89379

📥 Commits

Reviewing files that changed from the base of the PR and between 2418466 and 63fc65d.

⛔ Files ignored due to path filters (2)
  • packages/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__indexer_code_generates_correct_types_and_values.snap is excluded by !**/*.snap
  • packages/cli/src/hbs_templating/snapshots/envio__hbs_templating__codegen_templates__test__indexer_code_multiple_chains.snap is excluded by !**/*.snap
📒 Files selected for processing (46)
  • packages/cli/src/hbs_templating/codegen_templates.rs
  • packages/cli/src/type_schema.rs
  • packages/cli/templates/static/blank_template/rescript/rescript.json
  • packages/cli/templates/static/codegen/rescript.json
  • scenarios/fuel_test/rescript.json
  • scenarios/fuel_test/test/HyperFuelSource_test.res
  • scenarios/test_codegen/rescript.json
  • scenarios/test_codegen/src/handlers/EventHandlers.res
  • scenarios/test_codegen/test/BlockLag_test.res
  • scenarios/test_codegen/test/ChainManager_test.res
  • scenarios/test_codegen/test/Config_test.res
  • scenarios/test_codegen/test/E2E_test.res
  • scenarios/test_codegen/test/EntityColumnTypes_test.res
  • scenarios/test_codegen/test/EventFilters_test.res
  • scenarios/test_codegen/test/EventOrigin_test.res
  • scenarios/test_codegen/test/HandlerTypes_test.res
  • scenarios/test_codegen/test/HyperSyncSource_test.res
  • scenarios/test_codegen/test/HyperSync_test.res
  • scenarios/test_codegen/test/Indexer_test.res
  • scenarios/test_codegen/test/LoadLayer_test.res
  • scenarios/test_codegen/test/OptionalBlockParams_test.res
  • scenarios/test_codegen/test/RawEventsTableMigration_test.res
  • scenarios/test_codegen/test/ReorgDetection_test.res
  • scenarios/test_codegen/test/RpcSource_test.res
  • scenarios/test_codegen/test/Utils_test.res
  • scenarios/test_codegen/test/Viem_test.res
  • scenarios/test_codegen/test/WriteRead_test.res
  • scenarios/test_codegen/test/__mocks__/MockConfig.res
  • scenarios/test_codegen/test/__mocks__/MockEvents.res
  • scenarios/test_codegen/test/fixtures/LogTesting.res
  • scenarios/test_codegen/test/helpers/MockIndexer.res
  • scenarios/test_codegen/test/lib_tests/ClickHouse_test.res
  • scenarios/test_codegen/test/lib_tests/EventRouter_test.res
  • scenarios/test_codegen/test/lib_tests/FetchState_onBlock_test.res
  • scenarios/test_codegen/test/lib_tests/FetchState_test.res
  • scenarios/test_codegen/test/lib_tests/Persistence_test.res
  • scenarios/test_codegen/test/lib_tests/PgStorage_test.res
  • scenarios/test_codegen/test/lib_tests/Rpc_Test.res
  • scenarios/test_codegen/test/lib_tests/SingleOrMultiple_test.res
  • scenarios/test_codegen/test/lib_tests/SourceManager_test.res
  • scenarios/test_codegen/test/lib_tests/Throttler_test.res
  • scenarios/test_codegen/test/rollback/ChainDataHelpers.res
  • scenarios/test_codegen/test/rollback/MockChainData_test.res
  • scenarios/test_codegen/test/rollback/Rollback_test.res
  • scenarios/test_codegen/test/schema_types/BigDecimal_test.res
  • scenarios/test_codegen/test/schema_types/Timestamp_test.res
💤 Files with no reviewable changes (1)
  • packages/cli/templates/static/codegen/rescript.json

Comment thread packages/cli/src/hbs_templating/codegen_templates.rs
logIndex,
eventConfig: Utils.magic("Mock eventConfig in ChainManager test"),
event: `mock event (chainId)${id->Int.toString} - (blockNumber)${currentBlockNumber.contents->string_of_int} - (logIndex)${logIndex->string_of_int} - (timestamp)${currentTime.contents->string_of_int}`->Utils.magic,
event: `mock event (chainId)${id->Int.toString} - (blockNumber)${currentBlockNumber.contents->Int.toString} - (logIndex)${logIndex->Int.toString} - (timestamp)${currentTime.contents->Int.toString}`->Utils.magic,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Add an explicit type annotation to this Utils.magic cast.

Line 61 uses ->Utils.magic without a cast signature. Please annotate it inline as value->(Utils.magic: inputType => outputType).

As per coding guidelines **/*.res: “When using Utils.magic for type casting in ReScript, always add explicit type annotations: value->(Utils.magic: inputType => outputType)”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scenarios/test_codegen/test/ChainManager_test.res` at line 61, The event
string uses an un-annotated magic cast; change the expression `...->Utils.magic`
to include an explicit ReScript cast signature like `...->(Utils.magic: string
=> eventType)` (replace eventType with the appropriate target type), referencing
the `Utils.magic` usage on the `event` field so the cast is explicit (i.e.,
annotate the input as string and the desired output type).

// Serialize a params object to JSON via the schema
let testParams: Internal.eventParams = {"from": "0xabc", "to": "0xdef", "value": 100n}->Utils.magic
let testParams: Internal.eventParams =
{"from": "0xabc", "to": "0xdef", "value": 100n}->Utils.magic

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Unannotated Utils.magic calls:"
rg -nP '\->\s*Utils\.magic\b' scenarios/test_codegen/test/Config_test.res || true

echo
echo "Annotated Utils.magic calls:"
rg -nP '\->\s*\(Utils\.magic\s*:' scenarios/test_codegen/test/Config_test.res || true

Repository: enviodev/hyperindex

Length of output: 859


🏁 Script executed:

sed -n '185,235p' scenarios/test_codegen/test/Config_test.res

Repository: enviodev/hyperindex

Length of output: 2457


🏁 Script executed:

git diff HEAD -- scenarios/test_codegen/test/Config_test.res | head -100

Repository: enviodev/hyperindex

Length of output: 45


🏁 Script executed:

git status

Repository: enviodev/hyperindex

Length of output: 262


🏁 Script executed:

sed -n '240,270p' scenarios/test_codegen/test/Config_test.res

Repository: enviodev/hyperindex

Length of output: 1311


🏁 Script executed:

rg -nP '->Utils\.magic' scenarios/test_codegen/test/Config_test.res | head -20

Repository: enviodev/hyperindex

Length of output: 467


🏁 Script executed:

rg -n '\->Utils\.magic' scenarios/test_codegen/test/Config_test.res | head -20

Repository: enviodev/hyperindex

Length of output: 798


🏁 Script executed:

sed -n '194,204p' scenarios/test_codegen/test/Config_test.res

Repository: enviodev/hyperindex

Length of output: 581


Add explicit type annotations for Utils.magic on modified test params.

The following testParams assignments lack explicit cast signatures, which weakens type safety:

  • Line 189: {"from": "0xabc", "to": "0xdef", "value": 100n}->Utils.magic
  • Line 207: {"id": 1n, "details": ("hello", "world")}->Utils.magic
  • Line 217: {"data": (1n, (2n, "hello"))}->Utils.magic
  • Line 227: {"ids": [1n, 2n, 3n]}->Utils.magic
Proposed fix
-    let testParams: Internal.eventParams =
-      {"from": "0xabc", "to": "0xdef", "value": 100n}->Utils.magic
+    let testParams: Internal.eventParams =
+      ({"from": "0xabc", "to": "0xdef", "value": 100n}: {"from": string, "to": string, "value": bigint})->(Utils.magic: {"from": string, "to": string, "value": bigint} => Internal.eventParams)

-    let testParams: Internal.eventParams = {"id": 1n, "details": ("hello", "world")}->Utils.magic
+    let testParams: Internal.eventParams = ({"id": 1n, "details": ("hello", "world")}: {"id": bigint, "details": (string, string)})->(Utils.magic: {"id": bigint, "details": (string, string)} => Internal.eventParams)

-    let testParams: Internal.eventParams = {"data": (1n, (2n, "hello"))}->Utils.magic
+    let testParams: Internal.eventParams = ({"data": (1n, (2n, "hello"))}: {"data": (bigint, (bigint, string))})->(Utils.magic: {"data": (bigint, (bigint, string))} => Internal.eventParams)

-    let testParams: Internal.eventParams = {"ids": [1n, 2n, 3n]}->Utils.magic
+    let testParams: Internal.eventParams = ({"ids": [1n, 2n, 3n]}: {"ids": array<bigint>})->(Utils.magic: {"ids": array<bigint>} => Internal.eventParams)

Per the guideline: **/*.res requires explicit type annotations when using Utils.magic: value->(Utils.magic: inputType => outputType).

Note: Line 196 also contains an unannotated Utils.magic testParams assignment with an empty tuple ()->Utils.magic and may need the same treatment if it is within the scope of changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scenarios/test_codegen/test/Config_test.res` at line 189, Update the
unannotated uses of Utils.magic by adding explicit cast signatures of the form
(Utils.magic: inputType => outputType) for each modified test param;
specifically replace {"from": "0xabc", "to": "0xdef", "value":
100n}->Utils.magic with {"from": "0xabc", "to": "0xdef", "value":
100n}->(Utils.magic: {from:string,to:string,value:int} => <expectedOutputType>),
{"id": 1n, "details": ("hello","world")}->Utils.magic with ->(Utils.magic:
{id:int,details:(string,string)} => <expectedOutputType>), {"data":
(1n,(2n,"hello"))}->Utils.magic with ->(Utils.magic: {data:(int,(int,string))}
=> <expectedOutputType>), and {"ids":[1n,2n,3n]}->Utils.magic with
->(Utils.magic: {ids: list<int>} => <expectedOutputType>); also check and
annotate the empty-tuple case `()->Utils.magic` similarly. Replace
<expectedOutputType> with the actual expected return types for each test.

)

Js.log(page)
Console.log(page)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace logging with assertions in this test.

Console.log(page) does not verify behavior, so this test can pass without checking the broken-transaction handling contract. Please assert on expected page fields (or expected error/empty shape) using Assert instead of logging.

Suggested change
-    Console.log(page)
+    Assert.isTrue(Array.length(page.data.logs) >= 0)
+    Assert.equal(page.nextBlock, Some(12403140))

Based on learnings: “In ReScript tests, never log — use Assert module for all verifications.”

📝 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.

Suggested change
Console.log(page)
Assert.isTrue(Array.length(page.data.logs) >= 0)
Assert.equal(page.nextBlock, Some(12403140))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scenarios/test_codegen/test/HyperSync_test.res` at line 39, The test
currently uses Console.log(page) which doesn't verify behavior; replace that log
with ReScript assertions using the Assert module to validate the expected shape
or error for the `page` value (e.g., check specific fields like `page.id`,
`page.status`, or that `page` is an error/empty shape). Locate the
`Console.log(page)` call in the test (in HyperSync_test.res) and swap it for one
or more Assert.* checks (e.g., Assert.equal, Assert.assert, or
Assert.exceptions) that express the contract for broken-transaction handling so
the test fails when the actual `page` value deviates from expectations.

topicSelections: [
{
topic0: ["event 2"->EvmTypes.Hex.fromStringUnsafe],
topic1: [mockAddress0->Utils.magic],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Make the Utils.magic cast explicit at this topic field.

Line 188 should use a typed cast form to keep the conversion boundary explicit.

Suggested change
-              topic1: [mockAddress0->Utils.magic],
+              topic1: [mockAddress0->(Utils.magic: Address.t => EvmTypes.Hex.t)],

As per coding guidelines **/*.res: “When using Utils.magic for type casting in ReScript, always add explicit type annotations: value->(Utils.magic: inputType => outputType)”.

📝 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.

Suggested change
topic1: [mockAddress0->Utils.magic],
topic1: [mockAddress0->(Utils.magic: Address.t => EvmTypes.Hex.t)],
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scenarios/test_codegen/test/HyperSyncSource_test.res` at line 188, The topic1
entry uses Utils.magic without an explicit cast; update the topic1 value (the
mockAddress0->Utils.magic usage) to use the explicit typed-cast form required by
our ReScript guideline: wrap the Utils.magic use with an explicit type
annotation showing the input and output types (i.e., convert
mockAddress0->Utils.magic into mockAddress0->(Utils.magic: inputType =>
outputType)), so the conversion boundary on topic1 is explicit and typed.

Comment on lines +693 to +695
t.expect(query, ~message="Should return empty string when no chain configs provided").toBe(
None,
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the assertion message to match the asserted value type.

At Line 693, the message says “empty string” but the assertion checks None. This can mislead test failure triage.

📝 Proposed fix
-        t.expect(query, ~message="Should return empty string when no chain configs provided").toBe(
+        t.expect(query, ~message="Should return None when no chain configs are provided").toBe(
           None,
         )
📝 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.

Suggested change
t.expect(query, ~message="Should return empty string when no chain configs provided").toBe(
None,
)
t.expect(query, ~message="Should return None when no chain configs are provided").toBe(
None,
)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scenarios/test_codegen/test/lib_tests/PgStorage_test.res` around lines 693 -
695, The assertion message incorrectly says "Should return empty string when no
chain configs provided" while the test asserts that query is None; update the
expectation message for the t.expect(...).toBe(None) assertion (the one
referencing variable `query` in PgStorage_test.res) to accurately describe the
asserted value (e.g., "Should return None when no chain configs provided") so
test failures report the correct expectation.

t.expect(storageMock.loadByFieldOrThrowCalls).toEqual([
{
"fieldName": "id",
"fieldValue": "123"->Utils.magic,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Use explicit Utils.magic annotations for these field-value casts.

Lines 362, 368, 398, 467, and 473 currently use untyped ->Utils.magic. Please switch each to the explicit cast form value->(Utils.magic: inputType => outputType).

As per coding guidelines **/*.res: “When using Utils.magic for type casting in ReScript, always add explicit type annotations: value->(Utils.magic: inputType => outputType)”.

Also applies to: 368-368, 398-398, 467-467, 473-473

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scenarios/test_codegen/test/LoadLayer_test.res` at line 362, Replace all
untyped Utils.magic casts of the form "fieldValue": "123"->Utils.magic (and the
other similar occurrences) with explicit annotated casts using the ReScript
pattern value->(Utils.magic: inputType => outputType); update each instance to
use the correct inputType and outputType for that field (for example
"123"->(Utils.magic: string => int) if converting string to int) so each
"fieldValue": ... entry uses the explicit cast form; search for the same untyped
->Utils.magic token in the file and apply the same transformation to each
occurrence.

claude added 2 commits April 14, 2026 14:52
The migration from Array.sort with subtraction to Array.toSorted with
Int.compare changed the runtime behaviour: the old a - b on Obj.magic
strings relied on JS numeric coercion, so "137" - "1337" = -1200 sorted
numerically. Int.compare uses the < primitive which compares strings
lexicographically, so "1337" < "137" and the metric rows came out in
the wrong order, breaking the multichain rollback test.

Parse the chainId/value strings with Int.fromString before comparing so
the sort keeps its original numeric semantics.

https://claude.ai/code/session_01YCbJaSa8Vpi5tSgU8WRWcS
Typo was pre-existing in the template (from #1071) but my previous
commit moved the string, so address the CodeRabbit review comment
while it is still topical.

https://claude.ai/code/session_01YCbJaSa8Vpi5tSgU8WRWcS
@DZakh
DZakh merged commit 814b87f into main Apr 14, 2026
9 checks passed
@DZakh
DZakh deleted the claude/remove-warning-flag-SVTy5 branch April 14, 2026 15:03
DZakh pushed a commit that referenced this pull request Apr 15, 2026
Conflicts resolved:
- EventConfigBuilder.res (top): main's #1104 dropped `open Belt` and removed
  the empty-component-type stub. Kept the `eventParamComponent` /
  `eventParam.components` definitions from this PR (the feature) and dropped
  `open Belt` to follow main's modern-API migration. Migrated the
  component helpers (`componentsToSimulateSchema`,
  `componentsToDefaultValue`, `componentsToRemapper`, `paramsToRemap`)
  from `Js.String2.*`, `Js.Array2.*`, `Js.Dict.*` to the modern `String.*`
  / `Array.*` / `Dict.*` APIs to match main's style; flipped
  `Array.forEachWithIndex` argument order from `(i, c)` to `(c, i)` to
  match the modern signature.
- EventConfigBuilder.res (buildSimulateParamsSchema): kept this PR's
  component-aware schema/default selection but used main's `Dict.set`
  (was `Js.Dict.set`).
- EventHandlers.ts: both sides added independent registrations near the
  bottom of the file. Kept both — this PR's `#538` Solidity-struct
  regression handler and main's #1105 `indexer.onBlock` test
  registrations.
- codegen_templates.rs (test): main's #1106 added a third `&CapitalizedOptions`
  contract_name argument to `EventTemplate::from_config_event`. Updated
  the new `event_template_named_struct_rescript_snapshot` test to pass a
  `SablierLockup` contract name.
- snapshot regenerated for `event_template_named_struct_rescript_snapshot`
  to capture main's #1106 `onEventWhere` API refactor (chain-object
  callback rather than flat args).

https://claude.ai/code/session_01QHeJe9qkDbozn6YP8uxdeg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants