Skip to content

feat: auto-register ESM loader hooks in TuskDrift.initialize()#146

Merged
sohankshirsagar merged 2 commits intomainfrom
sohan/better-esm-dx
Mar 25, 2026
Merged

feat: auto-register ESM loader hooks in TuskDrift.initialize()#146
sohankshirsagar merged 2 commits intomainfrom
sohan/better-esm-dx

Conversation

@sohankshirsagar
Copy link
Contributor

@sohankshirsagar sohankshirsagar commented Mar 25, 2026

  • update cli setup agent prompts
  • update main docs
    • init params, tuskDriftInit.ts

Summary

ESM users previously had to manually call register('@use-tusk/drift-node-sdk/hook.mjs', pathToFileURL('./')) in their init file before importing the SDK. This was an extra step that CJS users didn't need, and was easy to forget.

This PR auto-registers ESM loader hooks inside TuskDrift.initialize(), matching. The ESM init file is now identical to CJS. The --import flag is still required for ESM applications. With CJS we can control the import order in the application code, but in ESM imports are evaluated before import module's code runs so calling TuskDrift.initialize() doesn't always guarantee it runs before the rest of the import graph

Changes

  • New file src/core/esmLoader.ts: initializeEsmLoader() uses createAddHookMessageChannel() from import-in-the-middle and module.register() to set up ESM loader hooks automatically. Guarded by CJS detection, Node version check (>= 18.19 / >= 20.6), and a global flag to prevent double-registration.
  • New registerEsmLoaderHooks option in InitParams: Defaults to true. Users can set to false to disable auto-registration if import-in-the-middle causes issues with specific packages.
  • TuskDrift.initialize() calls initializeEsmLoader() early, before registerDefaultInstrumentations(), gated on registerEsmLoaderHooks !== false.
  • Extracted isCommonJS() to src/core/utils/runtimeDetectionUtils.ts: Shared between TuskDrift.ts and esmLoader.ts instead of duplicated. Removed the private method from TuskDriftCore.
  • Simplified all 13 ESM E2E test tdInit.ts files: Removed manual register() calls — they are now identical to their CJS counterparts.
  • Updated docs/initialization.md: Collapsed ESM/CJS init file examples into one, moved "Determining Your Module System" to the entry point section (still needed for --import), added registerEsmLoaderHooks to the params table, added "Troubleshooting ESM" section documenting the opt-out and common failure modes.
  • hook.mjs kept for backward compatibility: Existing users with manual register() calls will continue to work.

Notes

  • CJS users are unaffected: isCommonJS() returns early, no ESM hooks are registered.

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 17 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/core/esmLoader.ts">

<violation number="1" location="src/core/esmLoader.ts:44">
P1: Set the `__tuskDriftEsmLoaderRegistered` flag only after successful registration (or reset it in `catch`), otherwise one transient failure permanently disables future registration attempts.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@tusk-dev
Copy link

tusk-dev bot commented Mar 25, 2026

Generated 14 tests - 14 passed

Commit tests View tests

Tip

New to Tusk Unit Tests? Learn more here.

Test Summary

  • TuskDrift.initialize - 6 ✓
  • initializeEsmLoader - 4 ✓
  • isCommonJS - 4 ✓

Results

Tusk's tests all pass cleanly. The test suite validates the core changes: TuskDrift.initialize() now safely handles the new registerEsmLoaderHooks parameter (defaults to true, respects opt-out via false), the extracted initializeEsmLoader() function gracefully exits in CommonJS and prevents double-registration via a global flag, and the shared isCommonJS() utility correctly detects the runtime environment. The tests confirm backward compatibility—existing users who omit the parameter won't break—and that the feature integrates cleanly with other initialization options. No edge cases are left exposed: disabled mode, multiple calls, and error handling all pass.

View check history

Commit Status Output Created (UTC)
f3f0776 Generated 14 tests - 14 passed Tests Mar 25, 2026 1:40AM
efa0768 Generated 14 tests - 14 passed Tests Mar 25, 2026 6:06PM

Was Tusk helpful? Give feedback by reacting with 👍 or 👎

@sohankshirsagar sohankshirsagar merged commit 617d49a into main Mar 25, 2026
19 checks passed
@sohankshirsagar sohankshirsagar deleted the sohan/better-esm-dx branch March 25, 2026 18:54
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