Skip to content

fix: bundle every package's JS output instead of emitting raw tsc - #42

Merged
ChristoPy merged 1 commit into
mainfrom
fix/esm-bundling-broken-subpath-exports
Jul 27, 2026
Merged

fix: bundle every package's JS output instead of emitting raw tsc#42
ChristoPy merged 1 commit into
mainfrom
fix/esm-bundling-broken-subpath-exports

Conversation

@ChristoPy

Copy link
Copy Markdown
Contributor

Summary

Every published package except rest and sdk built with bare tsc against a tsconfig set to "moduleResolution": "bundler" -- a setting that deliberately emits extension-less relative import specifiers (e.g. from './resources/checkout') on the assumption a bundler runs afterward. None did. Under real Node.js ESM resolution (what every actual npm/Node consumer uses, not Bun's more lenient resolver, which is why local workspace testing never caught this) that produces ERR_MODULE_NOT_FOUND on import, immediately.

Confirmed by packing and installing the real tarballs in an isolated directory: types, zod, and typebox all failed on their own internal multi-file imports; adapters failed transitively (imports zod at runtime, not just for types); express/fastify/hono/elysia/supabase all failed transitively through adapters. eslint-plugin and better-auth failed too. Only rest and sdk worked, because they already bundled with bun build instead of plain tsc.

Fix, applied uniformly: bun build <entrypoints> --outdir dist --target node for JS (matching each package's actual exports map, including the v1/v2 subpaths on types/zod/typebox/sdk that were being silently promised but never produced), then tsc --emitDeclarationOnly for types only -- the same pattern rest/sdk already used successfully. Also fixed sdk's build, which only ever bundled the root entrypoint despite declaring /v1 and /v2 subpath exports (so @abacatepay/sdk/v1 has never actually resolved under Node, even before this rewrite). Also fixed eslint-plugin's build/types scripts, which had swapped bodies -- types called bun run types recursively (infinite loop) and was never invoked by prepublishOnly anyway.

Verified with npm pack + a fresh isolated install of all 11 tarballs together (not the workspace symlinks), running an end-to-end script that imports every package, hits the real API, and exercises the zod -> adapters -> express dispatch chain. All pass.

Patch-bumped every affected package (types 3.0.1, sdk/zod/typebox/adapters/ express/fastify/hono/elysia/supabase 2.0.1, eslint-plugin 0.1.3, better-auth 1.0.1) -- this restores intended behavior, 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.

Every published package except rest and sdk built with bare `tsc` against a
tsconfig set to "moduleResolution": "bundler" -- a setting that deliberately
emits extension-less relative import specifiers (e.g. `from
'./resources/checkout'`) on the assumption a bundler runs afterward. None
did. Under real Node.js ESM resolution (what every actual npm/Node consumer
uses, not Bun's more lenient resolver, which is why local workspace testing
never caught this) that produces ERR_MODULE_NOT_FOUND on import, immediately.

Confirmed by packing and installing the real tarballs in an isolated
directory: types, zod, and typebox all failed on their own internal
multi-file imports; adapters failed transitively (imports zod at runtime,
not just for types); express/fastify/hono/elysia/supabase all failed
transitively through adapters. eslint-plugin and better-auth failed too.
Only rest and sdk worked, because they already bundled with `bun build`
instead of plain `tsc`.

Fix, applied uniformly: `bun build <entrypoints> --outdir dist --target
node` for JS (matching each package's actual `exports` map, including the
v1/v2 subpaths on types/zod/typebox/sdk that were being silently promised
but never produced), then `tsc --emitDeclarationOnly` for types only -- the
same pattern rest/sdk already used successfully. Also fixed sdk's build,
which only ever bundled the root entrypoint despite declaring `/v1` and
`/v2` subpath exports (so `@abacatepay/sdk/v1` has never actually resolved
under Node, even before this rewrite). Also fixed eslint-plugin's build/types
scripts, which had swapped bodies -- `types` called `bun run types`
recursively (infinite loop) and was never invoked by `prepublishOnly` anyway.

Verified with `npm pack` + a fresh isolated install of all 11 tarballs
together (not the workspace symlinks), running an end-to-end script that
imports every package, hits the real API, and exercises the
zod -> adapters -> express dispatch chain. All pass.

Patch-bumped every affected package (types 3.0.1, sdk/zod/typebox/adapters/
express/fastify/hono/elysia/supabase 2.0.1, eslint-plugin 0.1.3, better-auth
1.0.1) -- this restores intended behavior, 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
@ChristoPy
ChristoPy merged commit ff4bbae 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