Skip to content

fix(packaging): use conditional type exports for dual packages#750

Open
hassiebbot wants to merge 2 commits intomainfrom
hassieb/lfe-8846-cjs-type-mismatch-when-using-langfuselangchain-with
Open

fix(packaging): use conditional type exports for dual packages#750
hassiebbot wants to merge 2 commits intomainfrom
hassieb/lfe-8846-cjs-type-mismatch-when-using-langfuselangchain-with

Conversation

@hassiebbot
Copy link
Copy Markdown
Collaborator

@hassiebbot hassiebbot commented Mar 16, 2026

Problem

TypeScript nodenext CommonJS consumers could resolve @langfuse/* packages through their ESM declaration entrypoints because each package exported sibling types / import / require conditions. That caused mixed ESM/CJS type graphs and errors like CallbackHandler not being assignable to BaseCallbackHandler.

Changes

  • nest types under import and require in all dual-format package export maps
  • point require types at ./dist/index.d.cts
  • add scripts/check-package-exports.mjs
  • run the new check from precommit:check and ci

Release info Sub-libraries affected

Bump level

  • Major
  • Minor
  • Patch

Libraries affected

  • All of them
  • langfuse
  • langfuse-node

Changelog notes

  • Fixed dual-package type resolution for CommonJS nodenext consumers by using conditional declaration exports.

Verification

  • pnpm check:exports
  • prettier --check package.json packages/*/package.json scripts/check-package-exports.mjs
  • git diff --check

Disclaimer: Experimental PR review

Greptile Summary

Fixes dual-package TypeScript type resolution for CommonJS nodenext consumers by nesting types conditions under import and require in all 6 package export maps. Previously, a top-level types condition caused CJS consumers to resolve ESM declaration files, leading to mixed type graphs and assignability errors. The CJS require.types now correctly points to ./dist/index.d.cts (generated by tsup's dts: true for type: "module" packages).

  • All 6 sub-packages (client, core, langchain, openai, otel, tracing) updated with identical conditional export structure
  • New scripts/check-package-exports.mjs validation script enforces the export map structure
  • Validation integrated into both precommit:check and ci pipelines

Confidence Score: 5/5

  • This PR is safe to merge — it correctly fixes a well-known dual-package TypeScript resolution issue with a standard pattern.
  • The changes are mechanical and consistent across all 6 packages. The conditional export structure is the recommended pattern for type: "module" packages with CJS support. tsup v8 with dts: true and format: ["cjs", "esm"] generates both .d.ts and .d.cts files for type: "module" packages, so the referenced declaration files will exist at build time. A new validation script enforces the structure going forward, and it's integrated into both pre-commit and CI.
  • No files require special attention. All changes follow a consistent, well-understood pattern.

Important Files Changed

Filename Overview
package.json Adds check:exports script and integrates it into precommit:check and ci pipelines.
scripts/check-package-exports.mjs New validation script that asserts all 6 packages use the correct conditional type exports structure. Hardcodes the package list which could drift if new packages are added.
packages/client/package.json Nests types under import/require conditions, pointing CJS types to .d.cts. Correct for type: "module" + tsup dts: true.
packages/core/package.json Same conditional type exports restructuring as other packages. Consistent and correct.
packages/langchain/package.json Same conditional type exports restructuring. Consistent with all other packages.
packages/openai/package.json Same conditional type exports restructuring. Consistent with all other packages.
packages/otel/package.json Same conditional type exports restructuring. Consistent with all other packages.
packages/tracing/package.json Same conditional type exports restructuring. Consistent with all other packages.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["TypeScript consumer<br/>moduleResolution: nodenext"] --> B{Module system?}
    B -->|"import"| C["exports['.'].import"]
    B -->|"require"| D["exports['.'].require"]
    C --> E["types → ./dist/index.d.ts<br/>(ESM declarations)"]
    C --> F["default → ./dist/index.mjs"]
    D --> G["types → ./dist/index.d.cts<br/>(CJS declarations)"]
    D --> H["default → ./dist/index.cjs"]
    E --> I["✅ Correct ESM type graph"]
    G --> J["✅ Correct CJS type graph"]
Loading

Last reviewed commit: 8d5ec5e

@vercel
Copy link
Copy Markdown

vercel bot commented Mar 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
langfuse-js Ready Ready Preview Mar 16, 2026 6:16pm

Request Review

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