diff --git a/README.md b/README.md index fa9c7d7b0..95d45d732 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,9 @@ - Blazing fast on-demand TypeScript & ESM compilation - Works in both [CommonJS and ESM packages](https://nodejs.org/api/packages.html#type) - Supports next-gen TypeScript extensions (`.cts` & `.mts`) -- Supports `node:` import prefixes - Hides experimental feature warnings - TypeScript REPL - Resolves `tsconfig.json` [`paths`](https://www.typescriptlang.org/tsconfig#paths) -- Tested on Linux & Windows with Node.js v12~20 > **💡 Protip: Looking to bundle your TypeScript project?** > @@ -45,7 +43,7 @@ How does it compare to [ts-node](https://github.com/TypeStrong/ts-node)? Checkou tsx strives to: 1. Enhance Node.js with TypeScript compatibility 2. Improve ESM <-> CJS interoperability -3. Support the latest major version of Node.js v12 and up _(likely to change in the future)_ +3. Support the [LTS versions of Node.js](https://endoflife.date/nodejs) ## Install diff --git a/package.json b/package.json index dae629516..7521db615 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,9 @@ "lint-staged": { "*.{js,ts,mjs,mts,cjs,cts,json}": "pnpm lint" }, + "engines": { + "node": ">=18.0.0" + }, "dependencies": { "esbuild": "~0.18.20", "get-tsconfig": "^4.7.2", diff --git a/src/cjs/index.ts b/src/cjs/index.ts index 936ceb9c3..b351c2d26 100644 --- a/src/cjs/index.ts +++ b/src/cjs/index.ts @@ -11,7 +11,6 @@ import type { TransformOptions } from 'esbuild'; import { installSourceMapSupport } from '../source-map'; import { transformSync, transformDynamicImport } from '../utils/transform'; import { resolveTsPath } from '../utils/resolve-ts-path'; -import { nodeSupportsImport, supportsNodePrefix } from '../utils/node-features'; const isRelativePathPattern = /^\.{1,2}\//; const isTsFilePatten = /\.[cm]?tsx?$/; @@ -66,7 +65,7 @@ const transformer = ( let code = fs.readFileSync(filePath, 'utf8'); - if (filePath.endsWith('.cjs') && nodeSupportsImport) { + if (filePath.endsWith('.cjs')) { const transformed = transformDynamicImport(filePath, code); if (transformed) { code = applySourceMap(transformed, filePath); @@ -126,15 +125,8 @@ Object.defineProperty(extensions, '.mjs', { enumerable: false, }); -// Add support for "node:" protocol const defaultResolveFilename = Module._resolveFilename.bind(Module); Module._resolveFilename = (request, parent, isMain, options) => { - // Added in v12.20.0 - // https://nodejs.org/api/esm.html#esm_node_imports - if (!supportsNodePrefix && request.startsWith('node:')) { - request = request.slice(5); - } - if ( tsconfigPathsMatcher diff --git a/src/esm/index.ts b/src/esm/index.ts index 09e116e4c..f31120979 100644 --- a/src/esm/index.ts +++ b/src/esm/index.ts @@ -11,4 +11,3 @@ if ( } export * from './loaders.js'; -export * from './loaders-deprecated.js'; diff --git a/src/esm/loaders-deprecated.ts b/src/esm/loaders-deprecated.ts deleted file mode 100644 index 0ac52b34f..000000000 --- a/src/esm/loaders-deprecated.ts +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Deprecated ESM loaders used in Node v12 & 14 - * https://nodejs.org/docs/latest-v12.x/api/esm.html#esm_hooks - * https://nodejs.org/docs/latest-v14.x/api/esm.html#esm_hooks - */ -import { fileURLToPath } from 'url'; -import type { ModuleFormat } from 'module'; -import type { TransformOptions } from 'esbuild'; -import { transform, transformDynamicImport } from '../utils/transform'; -import { nodeSupportsDeprecatedLoaders } from '../utils/node-features'; -import { - applySourceMap, - fileMatcher, - tsExtensionsPattern, - getFormatFromFileUrl, - fileProtocol, - isJsonPattern, - type MaybePromise, - type NodeError, -} from './utils.js'; - -type getFormat = ( - url: string, - context: Record, - defaultGetFormat: getFormat, -) => MaybePromise<{ format: ModuleFormat }>; - -const _getFormat: getFormat = async function ( - url, - context, - defaultGetFormat, -) { - if (isJsonPattern.test(url)) { - return { format: 'module' }; - } - - try { - return await defaultGetFormat(url, context, defaultGetFormat); - } catch (error) { - if ( - (error as NodeError).code === 'ERR_UNKNOWN_FILE_EXTENSION' - && url.startsWith(fileProtocol) - ) { - const format = await getFormatFromFileUrl(url); - if (format) { - return { format }; - } - } - - throw error; - } -}; - -type Source = string | SharedArrayBuffer | Uint8Array; - -type transformSource = ( - source: Source, - context: { - url: string; - format: ModuleFormat; - }, - defaultTransformSource: transformSource, -) => MaybePromise<{ source: Source }> - -const _transformSource: transformSource = async function ( - source, - context, - defaultTransformSource, -) { - const { url } = context; - const filePath = url.startsWith('file://') ? fileURLToPath(url) : url; - - if (process.send) { - process.send({ - type: 'dependency', - path: url, - }); - } - - if ( - isJsonPattern.test(url) - || tsExtensionsPattern.test(url) - ) { - const transformed = await transform( - source.toString(), - filePath, - { - tsconfigRaw: fileMatcher?.(filePath) as TransformOptions['tsconfigRaw'], - }, - ); - - return { - source: applySourceMap(transformed, url), - }; - } - - const result = await defaultTransformSource(source, context, defaultTransformSource); - - if (context.format === 'module') { - const dynamicImportTransformed = transformDynamicImport(filePath, result.source.toString()); - if (dynamicImportTransformed) { - result.source = applySourceMap( - dynamicImportTransformed, - url, - ); - } - } - - return result; -}; - -export const getFormat = nodeSupportsDeprecatedLoaders ? _getFormat : undefined; -export const transformSource = nodeSupportsDeprecatedLoaders ? _transformSource : undefined; diff --git a/src/esm/loaders.ts b/src/esm/loaders.ts index 4f105e88e..6bde3ea38 100644 --- a/src/esm/loaders.ts +++ b/src/esm/loaders.ts @@ -7,9 +7,6 @@ import type { import type { TransformOptions } from 'esbuild'; import { transform, transformDynamicImport } from '../utils/transform'; import { resolveTsPath } from '../utils/resolve-ts-path'; -import { - supportsNodePrefix, -} from '../utils/node-features'; import { applySourceMap, tsconfigPathsMatcher, @@ -164,12 +161,6 @@ export const resolve: resolve = async function ( defaultResolve, recursiveCall, ) { - // Added in v12.20.0 - // https://nodejs.org/api/esm.html#esm_node_imports - if (!supportsNodePrefix && specifier.startsWith('node:')) { - specifier = specifier.slice(5); - } - // If directory, can be index.js, index.ts, etc. if (isDirectoryPattern.test(specifier)) { return await tryDirectory(specifier, context, defaultResolve); diff --git a/src/utils/node-features.ts b/src/utils/node-features.ts index d9c23b14d..825017182 100644 --- a/src/utils/node-features.ts +++ b/src/utils/node-features.ts @@ -8,24 +8,6 @@ const compareNodeVersion = (version: Version) => ( || nodeVersion[2] - version[2] ); -export const nodeSupportsImport = ( - // v13.2.0 and higher - compareNodeVersion([13, 2, 0]) >= 0 - - // 12.20.0 ~ 13.0.0 - || ( - compareNodeVersion([12, 20, 0]) >= 0 - && compareNodeVersion([13, 0, 0]) < 0 - ) -); - -export const supportsNodePrefix = ( - compareNodeVersion([16, 0, 0]) >= 0 - || compareNodeVersion([14, 18, 0]) >= 0 -); - -export const nodeSupportsDeprecatedLoaders = compareNodeVersion([16, 12, 0]) < 0; - /** * Node.js loaders are isolated from v20 * https://github.com/nodejs/node/issues/49455#issuecomment-1703812193 diff --git a/tests/utils/node-versions.ts b/tests/utils/node-versions.ts index 707b8aac3..0d757a8b2 100644 --- a/tests/utils/node-versions.ts +++ b/tests/utils/node-versions.ts @@ -1,5 +1,4 @@ export const nodeVersions = [ - '18', '20', ...( ( @@ -7,11 +6,7 @@ export const nodeVersions = [ && process.platform !== 'win32' ) ? [ - '12.20.0', // CJS named export detection added - '12', - '14', - '16', - '17', + '18', ] as const : [] as const ),