Security News
Fluent Assertions Faces Backlash After Abandoning Open Source Licensing
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
tsc-esm-fix
Advanced tools
Make tsc-compiled `es2020/esnext` bundles compatible with esm/mjs requirements
Make TS projects compatible with esm/mjs requirements
This workaround is aimed to bypass a bunch of tsc, ts-jest and esbuild issues right here and right now.
.js
extensions for relative module paths if compiled as es2020/esnext
.import.meta
is not allowed.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 the .js
extension in .d.ts
files of external ESM packages too. Well, good luck with that.
This lib covers options 1 and 2.
import {foo} from './foo'
→ import {foo} from './foo.js'
import {baz} from 'external/baz'
→ import {baz} from 'external/baz.js'
import {bar} from './bar'
→ import {bar} from './bar/index.js'
.
and ..
shortcuts
export * from '.'
→ export * from './index.js'
export * from '..'
→ export * from '../index.js'
.js
extensions into .d.ts
libdef filesoutDir
found in tsconfig.json.__dirname
and __filename
refs with import.meta
.export {}
(esbuild issue 1043)require
statements with new file refs if ext changes (hybrid/dual pkg)Node.js ^12.20.0 || ^14.13.1 || >=16.0.0
npm i -dev tsc-esm-fix
yarn add -D tsc-esm-fix
# or w/o saving to package.json
npx tsc-esm-fix [options]
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];
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 |
--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 |
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
.
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}`)
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
unlink?: boolean,
debug?: boolean | IFunction
}
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.
type="module"
{ default: {} }
FAQs
Make tsc-compiled `es2020/esnext` bundles compatible with esm/mjs requirements
The npm package tsc-esm-fix receives a total of 19,803 weekly downloads. As such, tsc-esm-fix popularity was classified as popular.
We found that tsc-esm-fix demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Fluent Assertions is facing backlash after dropping the Apache license for a commercial model, leaving users blindsided and questioning contributor rights.
Research
Security News
Socket researchers uncover the risks of a malicious Python package targeting Discord developers.
Security News
The UK is proposing a bold ban on ransomware payments by public entities to disrupt cybercrime, protect critical services, and lead global cybersecurity efforts.