Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

tsc-esm-fix

antongolub78.2kMIT3.1.2TypeScript support: included

Make tsc-compiled es2020/esnext bundles compatible with esm/mjs requirements

tsc, esm, mjs, es2020, esnext, tsc-esm-fix, tsc-es2020-fix

readme

tsc-esm-fix

Make TS projects compatible with esm/mjs requirements

CI Maintainability Test Coverage npm (tag)

Problem

This workaround is aimed to bypass a bunch of tsc, ts-jest and esbuild issues right here and right now.

moduleResolution: nodenext

Nightly build TypeScript 4.7 provides experimental esm support. But it still forces to add extensions by hand (tested on 4.7.0-dev.20220408).

src/main/ts/q/u/x/index.ts:1:21 - error TS2835: Relative import paths need explicit file extensions in EcmaScript imports when '--moduleResolution' is 'node12' or 'nodenext'. Did you mean '../../../foo.js'?

1 import { foo } from '../../../foo'

Moreover, if understand TS/49271 correctly, nodenext + pkg.json type: module requires .js extension to be added to all .d.ts files of external ESM packages too. Well, good luck with that.

Solutions

  1. Post-process tsc-compiled outputs each time after build.
  2. Patch project sources once as Sindre recommends in the ESM migration guide
  3. Use ttypescript with transformer-append-js-ext plugin

This lib covers options 1 and 2.

Features

  • Injects extensions to imports/re-exports statements.
    • import {foo} from './foo'import {foo} from './foo.js'
    • import {baz} from 'external/baz'import {baz} from 'external/baz.js'
    • Note, including the file extension is only necessary for packages without an "exports" field. So in this case all the external refs remain as are.
    • Pays attention to index files: import {bar} from './bar'import {bar} from './bar/index.js'
    • Handles . and .. shortcuts
      • export * from '.'export * from './index.js'
      • export * from '..'export * from '../index.js'
    • Injects .js extensions into .d.ts libdef files
    • Does not affect string literals and comments: depseek
  • Handles conditional exports (https://nodejs.org/api/packages.html#conditional-exports)
  • Follows outDir found in tsconfig.json.
  • Searches and replaces __dirname and __filename refs with import.meta.
  • Fills blank files with export {} (esbuild issue 1043)
  • Patches source map files to point to the updated files.
  • Patches require statements with new file refs if ext changes (hybrid/dual pkg)
  • Changes file extensions (applied to local deps only).
  • Supports Windows-based runtimes.

Getting started

Requirements

Node.js >=16.0.0

Install

npm i -dev tsc-esm-fix
yarn add -D tsc-esm-fix

# or w/o saving to package.json
npx tsc-esm-fix [options]

Usage examples

tsc-esm-fix [options]

# to post-process outputs each time
tsc-esm-fix --target='target/es6'

# to patch ts sources once
tsc-esm-fix --src='src/main/ts' --ext='.js'
import { fix } from 'tsc-esm-fix'
await fix({
  dirnameVar: true,
  filenameVar: true,
  ext: true
})

Input
code ref

import { foo } from './foo';
import './bar';

// external cjs module
import * as e1def from 'e1/a/b/c';
import * as e1root from 'e1';
const { e1 } = e1def;
const { e1: e1x } = e1root;
export { e1, e1x };

// external esm module with `main` in pkg.json
export { m1 } from 'm1';
export { m1 as m1x } from 'm1/index';

// external esm module with `exports` in pkg.json
export { e2 } from 'e2';
export { e2 as es3 } from 'e2/index';
export { e2 as es4 } from 'e2/alias';
export { e2foo } from 'e2/foo';
export { e2bar } from 'e2/bar-bundle';

export * from './foo';
export * from './baz';
export * from './q/u/x';
export const foobaz = foo + 'baz';
export { foo as foo1 } from './foo.js';

// Dir with index.js file inside: ./qux.js/index.js
export { qux } from './qux.js';

export const dirname = __dirname;
export const filename = __filename;

console.log(foobaz);

Output

import { foo } from './foo.js';
import './bar.js';

import * as e1def from 'e1/a/b/c/index.js';
import * as e1root from 'e1';
const { e1 } = e1def;
const { e1: e1x } = e1root;
export { e1, e1x };

export { m1 } from 'm1';
export { m1 as m1x } from 'm1/index.js';

export { e2 } from 'e2';
export { e2 as es3 } from 'e2/index';
export { e2 as es4 } from 'e2/alias';
export { e2foo } from 'e2/foo';
export { e2bar } from 'e2/bar-bundle';

export * from './foo.js';
export * from './baz/index.js';
export * from './q/u/x/index.js';
export const foobaz = foo + 'baz';
export { foo as foo1 } from './foo.js';

export { qux } from './qux.js/index.js';

export const dirname = /file:\\\\/\\\\/(.+)\\\\/[^/]/.exec(import.meta.url)[1];
export const filename = /file:\\\\/\\\\/(.+)/.exec(import.meta.url)[1];

CLI

tsc-esm-fix [opts]
Option Description Default
--tsconfig Path to project's ts-config(s) tsconfig.json
--src Entry points where the ts-source files are placed. If defined src option suppresses target
--target tsc-compiled output directory If not specified inherited from tsconfig.json compilerOptions.outDir
--dirnameVar Replace __dirname usages with import.meta true
--filenameVar Replace __filename var references with import.meta statements true
--ext Append extension to relative imports/re-exports .js
--ts-ext Known TS extensions .ts,.tsx,.mts,.mtsx,.cts,.ctsx
--js-ext Known JS extensions .js,.jsx,.mjs,.mjsx,.cjs,.cjsx
--unlink Remove original files if ext changes true
--fillBlank Fill blank files with export {} false
--forceDefaultExport Injects export default undefined if not present false
--sourceMap Patch source map files to point to the updated files. false
--cwd cwd process.cwd()
--out Output dir. Defaults to cwd, so files would be overwritten process.cwd()
--debug Prints debug notes

--target vs --src

When --src option is used, the util just modifies file contents in place. --target also renames files to change their extension. You may prevent deletion original of files by using --no-unlink.

glob patterns

By default, the util looks for ts/tsx files in src directory and js/d.ts files in target. But you can specify custom patterns via corresponding options. For example: --src='src/main/ts/**/*.ts'.

const patterns =
  sources.length > 0
    ? sources.map((src) => src.includes('*') ? src : `${src}/**/*.{ts,tsx}`)
    : targets.map((target) => target.includes('*') ? target : `${target}/**/*.{js,d.ts}`)

JS/TS API

import { fix, IFixOptions } from 'tsc-esm-fix'

const fixOptions: IFixOptions = {
  tsconfig: 'tsconfig.build.json',
  dirnameVar: true,
  filenameVar: true,
  ext: true
}

await fix(fixOptions)
export interface IFixOptions {
  cwd: string
  src?: string | string[]
  target?: string | string[]
  out?: string
  tsconfig?: string | string[]
  dirnameVar: boolean
  filenameVar: boolean
  fillBlank?: boolean
  forceDefaultExport?: boolean
  sourceMap?: boolean
  ext: boolean | string
  tsExt: string | string[]
  jsExt: string | string[]
  unlink?: boolean,
  debug?: boolean | IFunction
}

Alternatives

Contributing

Feel free to open any issues: bug reports, feature requests or questions. You're always welcome to suggest a PR. Just fork this repo, write some code, add some tests and push your changes. Any feedback is appreciated.

References

License

MIT

changelog

3.1.2 (2024-11-01)

Fixes & improvements

  • fix: reenable json5 parser (4dadb65)

3.1.1 (2024-10-31)

Fixes & improvements

  • fix: replace custom tsConfig resolver with xtends (9ef4877)

3.1.0 (2024-10-05)

Fixes & improvements

  • docs: mention jsExt and tsExt options (b0fd156)

Features

  • feat: allow configure js and ts extensions lists (938320f)

3.0.2 (2024-08-05)

Fixes & improvements

  • fix: target opt should override tsconfig specified defaults (b365c46)

3.0.1 (2024-07-20)

Fixes & improvements

  • fix(cli): omit empty opts (a76f044)

3.0.0 (2024-07-13)

Features

  • feat: update node engine range, require v18 (5881b67)

BREAKING CHANGES

  • following deps, require Node.js >= 18 (5881b67)

Fixes & improvements

  • refactor: update bin entry point (320a756)
  • refactor: replace meow → type-flag, microbundle → esbuild (1cc1a1a)
  • refactor: replace globby with fast-glob (2c3b91a)

2.20.27 (2024-04-23)

Fixes & improvements

  • fix: handle malformed exports map (f845eee)

2.20.26 (2024-02-20)

Fixes & improvements

  • fix(deps): update dependency depseek to ^0.4.0 (a024fb9)

2.20.25 (2024-02-20)

Fixes & improvements

  • fix(deps): update dependency depseek to ^0.3.0 (e30d1e2)

2.20.24 (2024-02-11)

Fixes & improvements

  • perf: up dev deps, repack (a5c9e18)

2.20.23 (2024-02-05)

Fixes & improvements

  • perf: tech release to fix readme on npm (2372dad)

2.20.22 (2024-01-28)

Fixes & improvements

  • refactor: use depseek patchRefs api (96c826a)

2.20.21 (2023-12-31)

Fixes & improvements

2.20.20 (2023-12-31)

Fixes & improvements

  • fix: use depseek to avoid comments and string literals affects (6f843ca)

2.20.19 (2023-12-30)

Fixes & improvements

  • refactor: separate fix into resolve and patch stages (925346a)
  • refactor: decompose fix.ts (9bebde8)

2.20.18 (2023-12-02)

Fixes & improvements

  • docs: fix CLI usage example (#142) (43b77f3)

2.20.17 (2023-09-19)

Fixes & improvements

  • fix: tech release to push the prev d.ts fix (88e071d)

2.20.16 (2023-09-18)

Fixes & improvements

  • perf: up deps (b69d862)
  • fix: provide support for shortened import syntax (53e493b)

2.20.15 (2023-08-12)

Fixes & improvements

  • fix: fix nodejs requirement (4d965ba)
  • fix: let cjs pkg be referenced by its name as a module (30a7978)

2.20.14 (2023-05-09)

Performance Improvements

2.20.13 (2023-05-02)

Bug Fixes

  • deps: update dependency meow to v12 (96906a9)

2.20.5 (2022-10-11)

Bug Fixes

  • deps: update dependency meow to v11 (1db4e85)

2.20.4 (2022-08-16)

Bug Fixes

  • handle require in arrays (d818d5d)

2.20.3 (2022-08-15)

Performance Improvements

  • improve __dirname and __filename subs for ts sources as input (73c719e), closes #90

2.20.2 (2022-08-14)

Performance Improvements

  • make stricter __dirname and __filename subtitutions (8459f27), closes #90

2.20.1 (2022-08-14)

Bug Fixes

  • patch __dirname subs for windows paths (8950b3b), closes #89

2.20.0 (2022-07-21)

Features

  • provide sourcemaps processing (239929c), closes #86

2.19.1 (2022-07-21)

Bug Fixes

  • handle trailing slash refs (1d9a03e), closes #87

2.19.0 (2022-07-19)

Features

  • introdude forceDefaultExport directive (c81b274)

2.18.0 (2022-06-06)

Features

  • support custom glob patterns (eb2905b)

2.17.3 (2022-06-05)

2.17.2 (2022-06-05)

Bug Fixes

2.17.1 (2022-06-05)

Bug Fixes

2.17.0 (2022-06-05)

Features

2.16.0 (2022-06-03)

Features

  • add .js ext to libdef files (fb03b28)

2.15.1 (2022-05-31)

Bug Fixes

2.15.0 (2022-05-18)

Features

2.14.1 (2022-05-13)

Bug Fixes

  • add missing src option to CLI (1890f2e)

2.13.0 (2022-04-22)

Features

2.12.4 (2022-04-08)

2.12.3 (2022-04-08)

2.12.2 (2022-04-08)

2.12.1 (2022-04-07)

2.12.0 (2022-04-07)

Features

  • push warning if tsconfig is incompatible (7641729)

2.11.0 (2022-04-07)

Bug Fixes

  • search variants in local deps before node_modules (c42fd55)

Features

  • patch require statements (a43b311)

2.10.0 (2022-04-07)

Bug Fixes

Features

  • add support for es2021 and es2022 modules (7e3384b)

2.9.1 (2022-04-06)

2.9.0 (2022-04-01)

Features

  • add default export to empty files (33aeb5c)

2.8.0 (2022-03-31)

Features

  • introduce fillBlank options (bfe2cb7)

2.7.8 (2022-03-09)

Bug Fixes

2.7.7 (2022-01-24)

Bug Fixes

  • deps: update dependency globby to v13 (bf73503)

2.7.6 (2021-12-30)

Bug Fixes

  • move coverals to actions, fix vuls (7889771)

2.7.5 (2021-12-11)

Bug Fixes

  • do not follow node_modules/.cache (d9e01c7), closes #48

2.7.4 (2021-11-12)

2.7.3 (2021-10-02)

2.7.2 (2021-09-12)

2.7.1 (2021-09-07)

2.7.0 (2021-09-07)

Features

  • add Node.js ^12.20.0 to supported engines (b213f1c)
  • support custom debug function (5eed5c0)

Performance Improvements

  • pkg: update globby to v12.0.2, update jest to v27.1.0, rm patch-package (2ed6880)

2.6.0 (2021-08-18)

Features

  • provide ts-sources patching (8bc4ab0)

2.5.1 (2021-08-18)

2.5.0 (2021-08-18)

Bug Fixes

  • handle directories with file-like names (8c60d3f)

Features

  • introduce unlink CLI flag (af31516)

2.4.4 (2021-08-17)

2.4.3 (2021-08-15)

2.4.2 (2021-08-15)

Bug Fixes

  • update fast-glob, fix vuls (cc2f898)

2.4.1 (2021-08-15)

2.4.0 (2021-08-15)

Bug Fixes

  • dont add ext prefix for modules that use exports pkg.json directive (31fdb35), closes #24

Features

  • support json5-formatted tsconfigs (625a9cb), closes #17

2.3.3 (2021-08-15)

2.3.2 (2021-08-14)

2.3.1 (2021-08-11)

Bug Fixes

  • deps: update dependency globby to v12 (3801cc2)

2.3.0 (2021-07-28)

Features

  • handle import with no vars, downgrade globby to v11 (b934041)

2.2.2 (2021-06-10)

Bug Fixes

2.2.1 (2021-06-10)

Bug Fixes

  • tweak up tsconfig resolver (b5829f8), closes #13

2.2.0 (2021-06-10)

Features

2.1.0 (2021-06-10)

Bug Fixes

Features

  • handle external modules relative paths (82f287a), closes #5

2.0.1 (2021-06-07)

Performance Improvements

  • mention requirements, deps revision (8d0f0d8)

2.0.0 (2021-06-07)

Bug Fixes

  • pkg: add missed @types/fs-extra (71e704c)

Performance Improvements

  • update deps, migrate to mjs modules (c9f6c4e)

BREAKING CHANGES

  • repack as mjs, require Node.js >= 14

1.1.2 (2021-06-07)

Bug Fixes

  • add upper relative paths for repl regex (#9) (3e2c476)

1.1.1 (2021-05-11)

1.1.0 (2021-05-11)

Features

  • pkg: provide dual export (1257ca0)

1.0.0 (2021-05-11)

Bug Fixes

  • add missed backslash escapes (965ec35)

Features

  • add __filename and __dirname replacers (65ca6e0)
  • add impl drafts (4b0d359)
  • add relativeModuleExt fix (502231e)
  • add unixify to support win-based runtime (2a7d424)
  • provide CLI (d2cfc48)
  • rm original files on patch (ebd547c)