Skip to content

fix: bundle declaration files, fixing nodenext/node16 TypeScript cons… - #45

Merged
ChristoPy merged 1 commit into
mainfrom
fix/bundle-declaration-files
Jul 27, 2026
Merged

fix: bundle declaration files, fixing nodenext/node16 TypeScript cons…#45
ChristoPy merged 1 commit into
mainfrom
fix/bundle-declaration-files

Conversation

@ChristoPy

Copy link
Copy Markdown
Contributor

Summary

Fixing the .js bundling two rounds ago didn't touch declaration emission at all. tsc --emitDeclarationOnly walks the original unbundled source tree regardless of what bun build did to the JS, so e.g. sdk's dist/index.d.ts still said export * from './v2' -- extension-less, same as the .js had before. Confirmed with a real strict TypeScript consumer project (moduleResolution: "nodenext", an increasingly common/recommended setting): error TS2834: Relative import paths need explicit file extensions, cascading into TS2305: Module has no exported member for everything re-exported through the broken chain. Affects every package with more than one internal source file -- which turned out to be all 13, since even the "single-file" framework packages have a second version.ts file re-exported from index.ts.

Two different fixes depending on the package:

  • types, rest, zod, typebox, sdk, adapters (genuine multi-file internal structure): added dts-bundle-generator, flattening each entrypoint's declarations into one self-contained file, same shape as the already- bundled .js. Had to explicitly pass --disable-symlinks-following, since bun's workspace symlinks resolve outside node_modules and the tool was treating @abacatepay/* as local source to inline rather than an external package to import -- which would have silently duplicated enum declarations (PaymentStatus, PaymentMethod, etc.) into nominally incompatible copies for any consumer mixing e.g. @abacatepay/sdk with @abacatepay/types directly.

  • express, fastify, hono, elysia, supabase, better-auth, eslint-plugin (exactly one relative import each, ./version or ./rules/no-secret-key): dts-bundle-generator choked trying to fully resolve their peer dependencies' complex ambient types (express-serve-static-core, fastify's node:http references, elysia's TSchema, eslint's estree) -- errors that don't exist in the actual bug, just the tool's resolution depth. Simpler, more robust fix for a single import: add the .js extension directly in source and keep plain tsc --emitDeclarationOnly.

Verified with npm pack + a fresh isolated install of all 13 tarballs, first confirming the runtime verify.mjs script still passes (21/21, no regression), then a real TypeScript consumer project with moduleResolution: "nodenext" and skipLibCheck: true (the realistic default -- skipLibCheck: false additionally flagged unrelated internal type-soundness issues inside elysia's own published types, which no real consumer checks) importing every package/subpath and mixing sdk-returned values with directly-imported types. Clean.

Patch-bumped every package: types 3.0.3, rest 1.0.2, sdk/zod/typebox/ adapters/express/fastify/hono/elysia/supabase 2.0.3, eslint-plugin 0.1.5, better-auth 1.0.3. No public API changed.

Related Issue

Closes (N/A)

Why

What problem does this solve?

What changed

Breaking changes

  • Yes
  • No

Checklist

  • Docs updated
  • CI passing
  • I followed the CONTRIBUTING guidelines
  • I added or updated tests (if applicable)

Additional context

Add any other context or screenshots here.

…umers

Fixing the .js bundling two rounds ago didn't touch declaration emission at
all. `tsc --emitDeclarationOnly` walks the original unbundled source tree
regardless of what bun build did to the JS, so e.g. sdk's dist/index.d.ts
still said `export * from './v2'` -- extension-less, same as the .js had
before. Confirmed with a real strict TypeScript consumer project
(moduleResolution: "nodenext", an increasingly common/recommended setting):
`error TS2834: Relative import paths need explicit file extensions`,
cascading into `TS2305: Module has no exported member` for everything
re-exported through the broken chain. Affects every package with more than
one internal source file -- which turned out to be all 13, since even the
"single-file" framework packages have a second `version.ts` file re-exported
from `index.ts`.

Two different fixes depending on the package:

- types, rest, zod, typebox, sdk, adapters (genuine multi-file internal
  structure): added dts-bundle-generator, flattening each entrypoint's
  declarations into one self-contained file, same shape as the already-
  bundled .js. Had to explicitly pass --disable-symlinks-following, since
  bun's workspace symlinks resolve outside node_modules and the tool was
  treating @abacatepay/* as local source to inline rather than an external
  package to import -- which would have silently duplicated `enum`
  declarations (PaymentStatus, PaymentMethod, etc.) into nominally
  incompatible copies for any consumer mixing e.g. @abacatepay/sdk with
  @abacatepay/types directly.

- express, fastify, hono, elysia, supabase, better-auth, eslint-plugin
  (exactly one relative import each, `./version` or `./rules/no-secret-key`):
  dts-bundle-generator choked trying to fully resolve their peer
  dependencies' complex ambient types (express-serve-static-core, fastify's
  node:http references, elysia's TSchema, eslint's estree) -- errors that
  don't exist in the actual bug, just the tool's resolution depth. Simpler,
  more robust fix for a single import: add the .js extension directly in
  source and keep plain `tsc --emitDeclarationOnly`.

Verified with `npm pack` + a fresh isolated install of all 13 tarballs,
first confirming the runtime verify.mjs script still passes (21/21, no
regression), then a real TypeScript consumer project with `moduleResolution:
"nodenext"` and `skipLibCheck: true` (the realistic default -- skipLibCheck:
false additionally flagged unrelated internal type-soundness issues inside
elysia's own published types, which no real consumer checks) importing every
package/subpath and mixing sdk-returned values with directly-imported types.
Clean.

Patch-bumped every package: types 3.0.3, rest 1.0.2, sdk/zod/typebox/
adapters/express/fastify/hono/elysia/supabase 2.0.3, eslint-plugin 0.1.5,
better-auth 1.0.3. No public API changed.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01EqaJ2TCZoyMCFjK4WcKxBR
@ChristoPy ChristoPy self-assigned this Jul 27, 2026
@socket-security

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addeddts-bundle-generator@​9.5.110010010080100

View full report

@ChristoPy
ChristoPy merged commit 5c10083 into main Jul 27, 2026
2 of 3 checks passed
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.

1 participant