Skip to content

Commit

Permalink
fix(vite): resolves files with dot suffixes correctly
Browse files Browse the repository at this point in the history
concat `ext` with `filename` for parse in `findFile` function from `nx-tsconfig-paths.plugin` that previously led to an unresolved error for files with dot suffixes e.g.`/dir/file.suffix.ext`

Closes nrwl#27852
  • Loading branch information
KonstantinKai authored and Coly010 committed Dec 12, 2024
1 parent 22cec78 commit c5b51f0
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 24 deletions.
28 changes: 4 additions & 24 deletions packages/vite/plugins/nx-tsconfig-paths.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
workspaceRoot,
} from '@nx/devkit';
import { copyFileSync, existsSync } from 'node:fs';
import { join, parse, relative, resolve } from 'node:path';
import { join, relative, resolve } from 'node:path';
import {
loadConfig,
createMatchPath,
Expand All @@ -18,6 +18,7 @@ import {
} from '@nx/js/src/utils/buildable-libs-utils';
import { Plugin } from 'vite';
import { nxViteBuildCoordinationPlugin } from './nx-vite-build-coordination.plugin';
import { findFile } from '../src/utils/nx-tsconfig-paths-find-file';
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';

export interface nxViteTsPathsOptions {
Expand Down Expand Up @@ -243,33 +244,12 @@ There should at least be a tsconfig.base.json or tsconfig.json in the root of th
);

resolvedFile = findFile(
importPath.replace(normalizedImport, joinedPath)
importPath.replace(normalizedImport, joinedPath),
options.extensions
);
}
}

return resolvedFile;
}

function findFile(path: string): string {
for (const ext of options.extensions) {
// Support file with "." in the name.
let resolvedPath = resolve(path + ext);
if (existsSync(resolvedPath)) {
return resolvedPath;
}

// Support file extensions such as .css and .js in the import path.
const { dir, name } = parse(path);
resolvedPath = resolve(dir, name + ext);
if (existsSync(resolvedPath)) {
return resolvedPath;
}

const resolvedIndexPath = resolve(path, `index${ext}`);
if (existsSync(resolvedIndexPath)) {
return resolvedIndexPath;
}
}
}
}
95 changes: 95 additions & 0 deletions packages/vite/src/utils/nx-tsconfig-paths-find-file.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import { findFile as findFileMain } from './nx-tsconfig-paths-find-file';

describe('@nx/vite nx-tsconfig-paths-find-file', () => {
const extensions = ['.ts', '.js'];
const fs = new Set<string>();
const existsSyncImpl = (path: string) => fs.has(path);
const findFile = (path: string): string =>
findFileMain(path, extensions, existsSyncImpl);

beforeAll(() => {
[
'/dir1/file.ts',
'/dir1/file.suffix.ts',
'/dir2/inner/index.ts',
'/dir2/inner/index.js',
'/dir3/file.js',
'/dir4/file.css',
'/dir5/file.suffix.ts.js',
'/dir6/inner.suffix/index.ts',
].forEach((item) => fs.add(item));
});

afterAll(() => {
fs.clear();
});

const cases: Array<{
title: string;
path: string;
expected: string | undefined;
}> = [
{
title: 'Should return undefined for missing file',
path: '/dir10/file',
expected: undefined,
},
{
title: 'Should return undefined for missing index file',
path: '/dir10/inner',
expected: undefined,
},
{
title: 'Should return existing file path with extension',
path: '/dir1/file',
expected: '/dir1/file.ts',
},
{
title:
'Should return correct file in case with same filename but one with suffix',
path: '/dir1/file.suffix',
expected: '/dir1/file.suffix.ts',
},
{
title: 'Should return existing file with dir request',
path: '/dir2/inner',
expected: '/dir2/inner/index.ts',
},
{
title: 'Should return existing file with index request',
path: '/dir2/inner/index',
expected: '/dir2/inner/index.ts',
},
{
title: 'Should return existing file with js extension',
path: '/dir3/file',
expected: '/dir3/file.js',
},
{
title: 'Should return undefined for non presented extension',
path: '/dir4/file',
expected: undefined,
},
{
title: 'Should return undefined for unknown file',
path: '/dir5/file.suffix',
expected: undefined,
},
{
title: 'Should return js file with strange suffix filename',
path: '/dir5/file.suffix.ts',
expected: '/dir5/file.suffix.ts.js',
},
{
title: 'Should return index file for dir with suffixed name',
path: '/dir6/inner.suffix',
expected: '/dir6/inner.suffix/index.ts',
},
];

cases.forEach(({ title, path, expected }) => {
it(title, () => {
expect(findFile(path)).toEqual(expected);
});
});
});
29 changes: 29 additions & 0 deletions packages/vite/src/utils/nx-tsconfig-paths-find-file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { existsSync } from 'node:fs';
import { parse, resolve } from 'node:path';

export function findFile(
/**
* File path without extension
*/
path: string,
extensions: string[],
existsSyncImpl: typeof existsSync = existsSync
): string {
for (const ext of extensions) {
/**
* Support file extensions such as .css and .js in the import path.
*
* NOTE: We should concatenate the `path` with `ext` because filenames with dot suffixes, e.g., `filename.suffix`, resolve incorrectly.
*/
const { dir, name } = parse(path + ext);
const resolvedPath = resolve(dir, name + ext);
if (existsSyncImpl(resolvedPath)) {
return resolvedPath;
}

const resolvedIndexPath = resolve(path, `index${ext}`);
if (existsSyncImpl(resolvedIndexPath)) {
return resolvedIndexPath;
}
}
}

0 comments on commit c5b51f0

Please sign in to comment.