mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-09 03:17:54 +00:00
fix: apply ESM .js extension fallback to tsconfig path alias resolution
Path alias imports (e.g. `@/utils.js` via tsconfig paths) now correctly strip JS-family extensions and retry with TS equivalents when the literal .js file does not exist. This applies the same stripJsExtension fallback already used for relative imports to the alias resolution branch. Fixes #1528
This commit is contained in:
parent
a2f1b07700
commit
f3350696c8
2 changed files with 71 additions and 3 deletions
|
|
@ -72,6 +72,13 @@ export const resolveImportPath = (
|
|||
const resolved = tryResolveWithExtensions(rewritten, allFiles);
|
||||
if (resolved) return cache(resolved);
|
||||
|
||||
// ESM fallback: strip .js/.jsx/.mjs/.cjs and retry with TS equivalents
|
||||
const strippedAlias = stripJsExtension(rewritten);
|
||||
if (strippedAlias !== null) {
|
||||
const esmResolved = tryResolveWithExtensions(strippedAlias, allFiles);
|
||||
if (esmResolved) return cache(esmResolved);
|
||||
}
|
||||
|
||||
// Try suffix matching as fallback
|
||||
const parts = rewritten.split('/').filter(Boolean);
|
||||
const suffixResult = suffixResolve(parts, normalizedFileList, allFileList, index);
|
||||
|
|
@ -132,9 +139,6 @@ export const resolveImportPath = (
|
|||
|
||||
// TypeScript ESM: imports use .js/.jsx/.mjs/.cjs but source files are
|
||||
// .ts/.tsx/.mts/.cts. Strip the JS-family extension and re-resolve.
|
||||
// NOTE: This fallback only applies to relative imports. Path alias imports
|
||||
// (e.g. @/utils.js via tsconfig paths) do not yet strip .js extensions —
|
||||
// that is a known limitation tracked for follow-up.
|
||||
if (language === SupportedLanguages.TypeScript || language === SupportedLanguages.JavaScript) {
|
||||
const stripped = stripJsExtension(basePath);
|
||||
if (stripped !== null) {
|
||||
|
|
|
|||
|
|
@ -151,3 +151,67 @@ describe('stripJsExtension', () => {
|
|||
it('returns null for .ts', () => expect(stripJsExtension('foo/bar.ts')).toBeNull());
|
||||
it('returns null for no extension', () => expect(stripJsExtension('foo/bar')).toBeNull());
|
||||
});
|
||||
|
||||
describe('ESM extension resolution — path aliases with .js extensions', () => {
|
||||
function resolveWithAlias(
|
||||
currentFile: string,
|
||||
importPath: string,
|
||||
ctx: ReturnType<typeof makeCtx>,
|
||||
aliases: [string, string][],
|
||||
baseUrl = '.',
|
||||
): string | null {
|
||||
return resolveImportPath(
|
||||
currentFile,
|
||||
importPath,
|
||||
ctx.allFilesSet,
|
||||
ctx.files,
|
||||
ctx.normalized,
|
||||
ctx.cache,
|
||||
SupportedLanguages.TypeScript,
|
||||
{ aliases, baseUrl },
|
||||
ctx.index,
|
||||
);
|
||||
}
|
||||
|
||||
it('resolves @/utils.js to src/utils.ts via alias', () => {
|
||||
const ctx = makeCtx(['src/index.ts', 'src/utils.ts']);
|
||||
const result = resolveWithAlias('src/index.ts', '@/utils.js', ctx, [['@/', 'src/']], '.');
|
||||
expect(result).toBe('src/utils.ts');
|
||||
});
|
||||
|
||||
it('resolves @/component.jsx to src/component.tsx via alias', () => {
|
||||
const ctx = makeCtx(['src/index.ts', 'src/component.tsx']);
|
||||
const result = resolveWithAlias(
|
||||
'src/index.ts',
|
||||
'@/component.jsx',
|
||||
ctx,
|
||||
[['@/', 'src/']],
|
||||
'.',
|
||||
);
|
||||
expect(result).toBe('src/component.tsx');
|
||||
});
|
||||
|
||||
it('prefers actual .js file over TS fallback in alias resolution', () => {
|
||||
const ctx = makeCtx(['src/index.ts', 'src/utils.js', 'src/utils.ts']);
|
||||
const result = resolveWithAlias('src/index.ts', '@/utils.js', ctx, [['@/', 'src/']], '.');
|
||||
expect(result).toBe('src/utils.js');
|
||||
});
|
||||
|
||||
it('resolves alias with baseUrl prefix', () => {
|
||||
const ctx = makeCtx(['app/src/index.ts', 'app/src/helpers/token.ts']);
|
||||
const result = resolveWithAlias(
|
||||
'app/src/index.ts',
|
||||
'~/helpers/token.js',
|
||||
ctx,
|
||||
[['~/', 'src/']],
|
||||
'app',
|
||||
);
|
||||
expect(result).toBe('app/src/helpers/token.ts');
|
||||
});
|
||||
|
||||
it('returns null when alias .js import has no matching source', () => {
|
||||
const ctx = makeCtx(['src/index.ts']);
|
||||
const result = resolveWithAlias('src/index.ts', '@/missing.js', ctx, [['@/', 'src/']], '.');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue