fix: add .js to relative imports so the ESM build loads in node - #4
Merged
Conversation
Verifying the published 0.4.0-pre.3 against a pristine monaco 0.56 turned up a bug that predates this branch. Importing the package as native ESM throws: Error [ERR_MODULE_NOT_FOUND]: Cannot find module .../lib/esm/pgsql/pgsql imported from .../lib/esm/timescale/timescale.js `src/timescale/timescale.ts` imported `../pgsql/pgsql` without an extension. TypeScript emits relative specifiers verbatim, so the ESM output carried an extensionless import, which Node cannot resolve -- and our exports map points the `import` condition straight at that output. Reproduced identically on 0.3.2, so every ESM consumer without a bundler to paper over it has been broken; the bundler-based consumers we happen to have are why nobody noticed. `index.ts` already used `.js` throughout, so this makes the rest of the package consistent with it. The `../types` imports in the contribution files get the same treatment: those are `import type` and erase at compile time, so they were never part of the bug, but leaving them inconsistent invites the next one. Tried enforcing this with the compiler instead of by hand. `module: node16` on the ESM build does flag extensionless relative imports, but only when the package is `"type": "module"` -- which this is not, so it silently emitted CommonJS into lib/esm instead. Reverted; the linter is a better home for this rule than a tsconfig that changes the output format as a side effect. Verified against a real registry install of the prerelease with the rebuilt lib dropped in: ESM now loads (pgsql 657 builtins, timescale 825, correctly layering), CJS is unchanged and still emits CommonJS, and a consumer typechecks under `moduleResolution: bundler`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Found while verifying the published
0.4.0-pre.3against a pristine monaco 0.56: importing this package as native ESM throws.src/timescale/timescale.tsimported../pgsql/pgsqlwithout an extension. TypeScript emits relative specifiers verbatim, so the ESM output carries an extensionless import that Node can't resolve — and our exports map points theimportcondition straight at that output.This predates the 0.56 work — reproduced identically on
0.3.2. Every ESM consumer without a bundler to paper over it has been broken; the bundler-based consumers we happen to have (webpack, rolldown) are why nobody noticed.index.tsalready used.jsthroughout, so this just makes the rest of the package consistent. The../typesimports in the contribution files get the same treatment — those areimport typeand erase at compile time, so they were never part of the bug, but leaving them inconsistent invites the next one.A dead end worth recording
I tried enforcing this with the compiler rather than by hand.
module: node16on the ESM build does flag extensionless relative imports — but only when the package is"type": "module", which this isn't. Instead it silently emitted CommonJS intolib/esm, which would have been a much worse bug than the one I was fixing. Caught it by checking the emitted output; reverted.A lint rule (
import/extensions) is the right home for this, but it's currently'off'in.eslintrc.jsand turning it on is its own change. Noting it as a follow-up rather than smuggling it in here.Verification
Against a real registry install of
0.4.0-pre.3with the rebuiltlibdropped in:import)ERR_MODULE_NOT_FOUNDrequire)tsc(bundler)Also confirmed
lib/cjsstill emits real CommonJS andlib/esmstill emits real ESM, since that was the failure mode of the approach I backed out of.Lint, 228 tests, and both build targets pass on Node 24.
Please re-cut the prerelease
0.4.0-pre.3has this bug. Worth a0.4.0-pre.4before the final0.4.0— happy to re-verify against it.