{"id":14986,"library":"ts-dual-module","title":"TypeScript Dual Module Builder","description":"ts-dual-module is a command-line tool designed to simplify the creation of dual-module (ESM + CommonJS) packages using TypeScript. It targets projects that define `\"type\": \"module\"` in their `package.json` and automatically builds both module formats from TypeScript sources, typically located in a `./src` directory and outputting to `./dist`. The tool handles the complexities of `package.json` `exports` and `typesVersions` fields to ensure correct module resolution and type declarations for both environments, specifically addressing CommonJS subpath export issues where TypeScript's default `moduleResolution` might fall short. The current stable version is 0.6.3, indicating it's actively maintained but still in a pre-1.0 development phase, which implies a focus on adding features and refining functionality, potentially with breaking changes between minor versions. Its key differentiator is the automation of dual-module bundling and `package.json` configuration, saving developers from complex manual setup or reliance on multiple build steps with different TypeScript configurations.","status":"active","version":"0.6.3","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/bstefanescu/ts-dual-module","tags":["javascript","typescript","build","exports","tsc","esm","cjs","dual-module"],"install":[{"cmd":"npm install ts-dual-module","lang":"bash","label":"npm"},{"cmd":"yarn add ts-dual-module","lang":"bash","label":"yarn"},{"cmd":"pnpm add ts-dual-module","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Executes the main dual-module build process, compiling TypeScript sources into both ESM and CommonJS formats and updating `package.json`.","symbol":"tsmod build","correct":"npx tsmod build"},{"note":"Interactively initializes the project by creating a basic `tsconfig.json` and configuring the output directory, or creating specific `tsconfig.esm.json` and `tsconfig.cjs.json` files.","symbol":"tsmod init","correct":"npx tsmod init"},{"note":"Adds a subpath export entry to `package.json`, including the necessary `typesVersions` mapping to ensure correct type resolution for CommonJS builds.","symbol":"tsmod export","correct":"npx tsmod export <subpath> <target_file>"}],"quickstart":{"code":"mkdir my-dual-package\ncd my-dual-package\n\nnpm init -y\n# Add \"type\": \"module\" to package.json\nnode -e \"const pkg = require('./package.json'); pkg.type = 'module'; require('fs').writeFileSync('./package.json', JSON.stringify(pkg, null, 2));\"\n\nnpm install -D typescript ts-dual-module\n\nmkdir src\necho 'export const greet = (name: string) => `Hello, ${name} from ESM!`;' > src/index.ts\necho 'export const farewell = (name: string) => `Goodbye, ${name} from CJS!`;' > src/cjs.ts\n\nnpx tsmod init # Follow prompts, e.g., default 'dist' output directory\nnpx tsmod build\n\n# Verify output\ncat dist/index.d.ts\ncat dist/index.mjs\ncat dist/index.js\ncat package.json # Check for updated exports and typesVersions\n\nnode -e \"import { greet } from './dist/index.mjs'; console.log(greet('ESM User'));\"\nnode -e \"require('./dist/index.js').greet ? console.log(require('./dist/index.js').greet('CJS User')) : console.log(require('./dist/index.js').farewell('CJS User - CJS path'));\"","lang":"typescript","description":"Sets up a new TypeScript project with `type: \"module\"`, installs `ts-dual-module`, initializes it, builds dual ESM/CJS outputs, and demonstrates usage."},"warnings":[{"fix":"Ensure your `package.json` includes `\"type\": \"module\"`. If you are building a CommonJS-first package that also needs ESM, consider alternatives or carefully manage `tsconfig.json` settings.","message":"The tool assumes your project is an ESM package, meaning your root `package.json` must contain `\"type\": \"module\"`. Projects without this declaration may not build correctly or exhibit unexpected module resolution behavior.","severity":"breaking","affected_versions":">=0.1.0"},{"fix":"Rely on `tsmod export` for managing subpath exports and avoid manual modifications to the `exports` and `typesVersions` fields in `package.json` to prevent conflicts.","message":"The `ts-dual-module` tool automatically modifies your `package.json` to include `exports` and `typesVersions` fields. Manual edits to these fields may be overwritten or conflict with the tool's output.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Always use `npx tsmod export <subpath> <target_file>` to add subpath exports. This ensures the necessary `typesVersions` mapping is generated, fixing type resolution for CommonJS consumers.","message":"For subpath exports to work correctly with CommonJS builds, `ts-dual-module` adds a `typesVersions` entry. Without this, TypeScript's default `moduleResolution` (especially below `Node16`) might not resolve types for subpath imports in CJS environments.","severity":"gotcha","affected_versions":">=0.1.0"},{"fix":"Run `npx tsmod init` to generate a base `tsconfig.json`. Review and customize it, or create `tsconfig.esm.json` and `tsconfig.cjs.json` for fine-grained control, ensuring `moduleResolution` and `target` settings are appropriate for your project.","message":"A `tsconfig.json` file is required in the project root as the base configuration for TypeScript compilation. The tool will prompt to create one via `npx tsmod init` if missing, but incorrect configurations can lead to build failures or unexpected output.","severity":"gotcha","affected_versions":">=0.1.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Use `npx tsmod export <subpath> <target_file>` to add the subpath export. This command automatically sets up the `exports` and `typesVersions` fields in `package.json` to correctly map types for both ESM and CJS.","cause":"Subpath exports are not correctly configured in `package.json` for CommonJS consumers, leading to type resolution failures.","error":"Cannot find module 'your-package/subpath' or its corresponding type declarations."},{"fix":"Allow `ts-dual-module` to manage your `exports` field. If you have custom exports, ensure they align with Node.js's dual package hazard guidelines, explicitly defining `import`, `require`, and `default` conditions.","cause":"Your `package.json` `exports` field is misconfigured or conflicts with how Node.js is trying to resolve the module. This often happens if `import` and `require` conditions are not correctly defined, or if `default` is not set up properly.","error":"Error: The 'exports' field in package.json does not allow imports of 'your-package/dist/index.js' (or similar errors related to exports condition)."},{"fix":"Ensure `tsconfig.json` exists and is correctly configured (run `npx tsmod init` if unsure). Verify `compilerOptions.moduleResolution` is set to `node` or `nodenext`. Install any missing type declaration packages (e.g., `npm install -D @types/node`).","cause":"This is a general TypeScript compilation error indicating that types or modules are not being resolved. It could be due to a missing `tsconfig.json`, incorrect `moduleResolution` settings, or uninstalled `@types/` packages.","error":"TS2304: Cannot find name 'SomeType' / TS2307: Cannot find module 'some-module'."}],"ecosystem":"npm"}