Skip to content

Commit

Permalink
fix(esm): implicit resolution with tsconfig paths
Browse files Browse the repository at this point in the history
fixes #607
  • Loading branch information
privatenumber committed Jul 3, 2024
1 parent 1603c66 commit a74aa58
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 29 deletions.
67 changes: 38 additions & 29 deletions src/esm/hook/resolve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,28 +92,6 @@ const resolveBase: ResolveHook = async (
context,
nextResolve,
) => {
// If directory, can be index.js, index.ts, etc.

// Resolve TS alias
// Bare specifier
if (
!requestAcceptsQuery(specifier)
// TS path alias
&& tsconfigPathsMatcher
&& !context.parentURL?.includes('/node_modules/')
) {
const possiblePaths = tsconfigPathsMatcher(specifier);
for (const possiblePath of possiblePaths) {
try {
return await resolveBase(
pathToFileURL(possiblePath).toString(),
context,
nextResolve,
);
} catch {}
}
}

const isBarePackageName = isBarePackageNamePattern.test(specifier);

// Typescript gives .ts, .cts, or .mts priority over actual .js, .cjs, or .mjs extensions
Expand Down Expand Up @@ -160,11 +138,10 @@ const resolveDirectory: ResolveHook = async (
context,
nextResolve,
) => {
const [specifierWithoutQuery, query] = specifier.split('?');

if (isDirectoryPattern.test(specifier)) {
// If directory, can be index.js, index.ts, etc.
return (await resolveExtensions(
`${specifierWithoutQuery}index${query ? `?${query}` : ''}`,
`${specifier}index`,
context,
nextResolve,
true,
Expand All @@ -181,7 +158,7 @@ const resolveDirectory: ResolveHook = async (
if (errorPath) {
try {
return (await resolveExtensions(
`${errorPath}/index${query ? `?${query}` : ''}`,
`${errorPath}/index`,
context,
nextResolve,
true,
Expand All @@ -201,6 +178,33 @@ const resolveDirectory: ResolveHook = async (
}
};

const resolveTsPaths: ResolveHook = async (
specifier,
context,
nextResolve,
) => {
if (
// Bare specifier
!requestAcceptsQuery(specifier)
// TS path alias
&& tsconfigPathsMatcher
&& !context.parentURL?.includes('/node_modules/')
) {
const possiblePaths = tsconfigPathsMatcher(specifier);
for (const possiblePath of possiblePaths) {
try {
return await resolveDirectory(
pathToFileURL(possiblePath).toString(),
context,
nextResolve,
);
} catch {}
}
}

return resolveDirectory(specifier, context, nextResolve);
};

export const resolve: ResolveHook = async (
specifier,
context,
Expand All @@ -219,8 +223,10 @@ export const resolve: ResolveHook = async (
return nextResolve(specifier, context);
}

const resolved = await resolveDirectory(
specifier,
const [cleanSpecifier, query] = specifier.split('?');

const resolved = await resolveTsPaths(
cleanSpecifier,
context,
nextResolve,
);
Expand All @@ -237,11 +243,14 @@ export const resolve: ResolveHook = async (
resolved.format = await getFormatFromFileUrl(resolved.url);
}

if (query) {
resolved.url += `?${query}`;
}

// Inherit namespace
if (
requestNamespace
&& !resolved.url.includes(namespaceQuery)
&& requestAcceptsQuery(resolved.url)
) {
resolved.url += (resolved.url.includes('?') ? '&' : '?') + namespaceQuery + requestNamespace;
}
Expand Down
8 changes: 8 additions & 0 deletions tests/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,14 @@ export const files = {
${sourcemap.test('cts')}
`,

'tsconfig.json': createTsconfig({
compilerOptions: {
paths: {
'@/*': ['./*'],
},
},
}),

'file.txt': 'hello',

'broken-syntax.ts': 'if',
Expand Down
18 changes: 18 additions & 0 deletions tests/specs/smoke.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,11 @@ export default testSuite(async ({ describe }, { tsx, supports, version }: NodeAp
// .js in esm syntax
import * as js from './js/index.js';
import './js/index.js?query=123';
import '@/js/index.js?query=123';
import './js/index';
import '@/js/index';
import './js/';
import '@/js/';
// No double .default.default in Dynamic Import
import/* comment */('./js/index.js').then(m => {
Expand All @@ -63,7 +66,9 @@ export default testSuite(async ({ describe }, { tsx, supports, version }: NodeAp
// .json
import * as json from './json/index.json';
import './json/index';
import '@/json/index';
import './json/';
import '@/json/';
// .cjs
import * as cjs from './cjs/index.cjs';
Expand Down Expand Up @@ -202,6 +207,7 @@ export default testSuite(async ({ describe }, { tsx, supports, version }: NodeAp
// .js in esm syntax
import * as js from './js/index.js';
import './js/index.js?query=123';
import '@/js/index.js?query=123';
import './js/index';
import './js/';
Expand Down Expand Up @@ -265,26 +271,37 @@ export default testSuite(async ({ describe }, { tsx, supports, version }: NodeAp
// .ts
import './ts/index.ts';
import './ts/index.js';
import '@/ts/index.js';
import './ts/index.jsx';
import './ts/index';
import '@/ts/index';
import './ts/';
import '@/ts/';
import './ts/period.in.name';
import '@/ts/period.in.name';
// .jsx
import * as jsx from './jsx/index.jsx';
import './jsx/index.js';
import '@/jsx/index.js';
import './jsx/index';
import '@/jsx/index';
import './jsx/';
import '@/jsx/';
// .tsx
import './tsx/index.tsx';
import './tsx/index.js';
import './tsx/index.jsx';
import '@/tsx/index.jsx';
import './tsx/index';
import '@/tsx/index';
import './tsx/';
import '@/tsx/';
// .cts
import './cts/index.cjs';
import '@/cts/index.cjs';
expectErrors(
// TODO:
// [() => import ('./cts/index.cts'), 'Cannot find module'],
Expand All @@ -303,6 +320,7 @@ export default testSuite(async ({ describe }, { tsx, supports, version }: NodeAp
// .mts
import './mts/index.mjs';
import '@/mts/index.mjs';
expectErrors(
// TODO:
// [() => import ('./mts/index.mts'), 'Cannot find module'],
Expand Down

0 comments on commit a74aa58

Please sign in to comment.