diff --git a/src/loaders.ts b/src/loaders.ts index ec534f9..56986ac 100644 --- a/src/loaders.ts +++ b/src/loaders.ts @@ -35,7 +35,36 @@ type resolve = ( recursiveCall?: boolean, ) => MaybePromise; -const extensions = ['.js', '.json', '.ts', '.tsx', '.jsx'] as const; +const mappedExtensions: Record = { + '.js': ['.ts', '.tsx'], + '.jsx': ['.ts', '.tsx'], + '.cjs': ['.cts'], + '.mjs': ['.mts'], + '': ['.ts', '.js', '.json', '.tsx', '.jsx'], +}; + +function resolveTsAlternativeSpecifiers(specifier: string) { + const alternativePaths = mappedExtensions[''].map(alternativeExtension => ({ + specifier, + specifierExtension: '', + alternativeExtension, + })); + const specifierExtension = path.extname(specifier); + if (!specifierExtension) { + return alternativePaths; + } + const extensionsToTry = mappedExtensions[specifierExtension] ?? []; + specifier = specifier.slice(0, specifier.length - specifierExtension.length); + return [ + // Try using subextension first + ...alternativePaths, + ...extensionsToTry.map(alternativeExtension => ({ + specifier, + specifierExtension, + alternativeExtension, + })), + ]; +} async function tryExtensions( specifier: string, @@ -43,10 +72,15 @@ async function tryExtensions( defaultResolve: resolve, ) { let error; - for (const extension of extensions) { + for (const alternativePath of resolveTsAlternativeSpecifiers(specifier)) { + const { + specifier: alternativeSpecifier, + specifierExtension, + alternativeExtension, + } = alternativePath; try { return await resolve( - specifier + extension, + `${alternativeSpecifier}${alternativeExtension}`, context, defaultResolve, true, @@ -54,7 +88,7 @@ async function tryExtensions( } catch (_error: any) { if (error === undefined) { const { message } = _error; - _error.message = _error.message.replace(`${extension}'`, "'"); + _error.message = _error.message.replace(`${alternativeExtension}'`, `${specifierExtension}'`); _error.stack = _error.stack.replace(message, _error.message); error = _error; } diff --git a/tests/specs/typescript/cts.ts b/tests/specs/typescript/cts.ts index ea4061a..9a3059f 100644 --- a/tests/specs/typescript/cts.ts +++ b/tests/specs/typescript/cts.ts @@ -28,9 +28,9 @@ export default testSuite(async ({ describe }, node: NodeApis) => { describe('full path via .cjs', ({ test }) => { const importPath = './lib/ts-ext-cts/index.cjs'; - test('Load - should not work', async () => { + test('Load', async () => { const nodeProcess = await node.load(importPath); - expect(nodeProcess.stderr).toMatch('Cannot find module'); + expect(nodeProcess.stderr).toMatch('SyntaxError: Unexpected token \':\''); }); test('Import', async () => { diff --git a/tests/specs/typescript/mts.ts b/tests/specs/typescript/mts.ts index d4e0e0a..747e604 100644 --- a/tests/specs/typescript/mts.ts +++ b/tests/specs/typescript/mts.ts @@ -39,9 +39,9 @@ export default testSuite(async ({ describe }, node: NodeApis) => { describe('full path via .mjs', ({ test }) => { const importPath = './lib/ts-ext-mts/index.mjs'; - test('Load - should not work', async () => { + test('Load', async () => { const nodeProcess = await node.load(importPath); - expect(nodeProcess.stderr).toMatch('Cannot find module'); + assertResults(nodeProcess.stdout); }); test('Import', async () => { diff --git a/tests/specs/typescript/ts.ts b/tests/specs/typescript/ts.ts index 420b217..baaf6e2 100644 --- a/tests/specs/typescript/ts.ts +++ b/tests/specs/typescript/ts.ts @@ -47,9 +47,9 @@ export default testSuite(async ({ describe }, node: NodeApis) => { describe('full path via .js', ({ test }) => { const importPath = './lib/ts-ext-ts/index.js'; - test('Load - should not work', async () => { + test('Load', async () => { const nodeProcess = await node.load(importPath); - expect(nodeProcess.stderr).toMatch('Cannot find module'); + assertResults(nodeProcess.stdout, 'ts-ext-ts/index.ts'); }); test('Import', async () => {