Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,80 @@ describe('TargetProjectLocator', () => {

expect(result).toEqual('child-pm-workspaces');
});

it('should convert relative file paths to absolute paths before TypeScript module resolution', () => {
const typescriptModule = require('nx/src/plugins/js/utils/typescript');
const resolveModuleByImportSpy = jest
.spyOn(typescriptModule, 'resolveModuleByImport')
.mockReturnValue('/root/libs/proj/some-module.ts');

// Create a simple locator to test TypeScript resolution path
const simpleProjects: Record<string, ProjectGraphProjectNode> = {
proj: {
name: 'proj',
type: 'lib',
data: { root: 'libs/proj' },
},
};

const testLocator = new TargetProjectLocator(
simpleProjects,
{},
new Map()
);

// Test with a relative path - the method should convert it to absolute
// We use a unique package name that won't be found via npm resolution
(testLocator as any).resolveImportWithTypescript(
'package-that-is-installed-in-workspace-root',
'libs/proj/index.ts'
);

// Verify that resolveModuleByImport was called with an absolute path
// We only care that the second parameter (filePath) was converted to absolute
expect(resolveModuleByImportSpy).toHaveBeenCalled();
const [[importExpr, filePath]] = resolveModuleByImportSpy.mock.calls;
expect(importExpr).toBe('package-that-is-installed-in-workspace-root');
expect(filePath).toBe('/root/libs/proj/index.ts'); // relative path should be converted to absolute

resolveModuleByImportSpy.mockRestore();
});

it('should keep absolute file paths as-is for TypeScript module resolution', () => {
const typescriptModule = require('nx/src/plugins/js/utils/typescript');
const resolveModuleByImportSpy = jest
.spyOn(typescriptModule, 'resolveModuleByImport')
.mockReturnValue('/root/libs/proj/some-module.ts');

const simpleProjects: Record<string, ProjectGraphProjectNode> = {
proj: {
name: 'proj',
type: 'lib',
data: { root: 'libs/proj' },
},
};

const testLocator = new TargetProjectLocator(
simpleProjects,
{},
new Map()
);

// Test with an absolute path - it should remain absolute
(testLocator as any).resolveImportWithTypescript(
'package-that-is-installed-in-workspace-root',
'/root/libs/proj/index.ts'
);

// Verify that resolveModuleByImport was called with the same absolute path
// We only care that the second parameter (filePath) remained absolute
expect(resolveModuleByImportSpy).toHaveBeenCalled();
const [[importExpr, filePath]] = resolveModuleByImportSpy.mock.calls;
expect(importExpr).toBe('package-that-is-installed-in-workspace-root');
expect(filePath).toBe('/root/libs/proj/index.ts');

resolveModuleByImportSpy.mockRestore();
});
});

describe('findTargetProjectWithImport (without tsconfig.json)', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { isBuiltin } from 'node:module';
import { dirname, join, posix, relative } from 'node:path';
import { dirname, join, posix, relative, isAbsolute } from 'node:path';
import { clean, satisfies } from 'semver';
import type {
ProjectGraphExternalNode,
Expand Down Expand Up @@ -417,6 +417,11 @@ export class TargetProjectLocator {
filePath: string
): string | undefined {
let resolvedModule: string;
if (!isAbsolute(filePath)) {
// Convert to an absolute file path because TypeScript's module resolution won't
// properly walk up the directory tree (toward the workspace root) when given a relative path.
filePath = this.getAbsolutePath(filePath);
}
const projectName = findProjectForPath(filePath, this.projectRootMappings);
const cacheScope = projectName
? // fall back to the project name if the project root can't be determined
Expand Down
Loading