fix(js): handle ${configDir} in tsconfig files when inferring tasks (#31098)
## Current Behavior
The `${configDir}` template variable in tsconfig files is incorrectly
handled when inferring tasks with the `@nx/js/typescript` plugin.
## Expected Behavior
The `${configDir}` template variable in tsconfig files should be
correctly handled when inferring tasks with the `@nx/js/typescript`
plugin.
## Related Issue(s)
Fixes #30883
This commit is contained in:
parent
30a7709d71
commit
e6a3d77db3
@ -796,6 +796,73 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should add the config file and the `include` and `exclude` patterns using the "${configDir}" template', async () => {
|
||||||
|
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||||
|
'libs/my-lib/tsconfig.json': JSON.stringify({
|
||||||
|
include: ['${configDir}/src/**/*.ts'],
|
||||||
|
exclude: ['${configDir}/src/**/foo.ts'],
|
||||||
|
// set this to keep outputs smaller
|
||||||
|
compilerOptions: { outDir: 'dist' },
|
||||||
|
}),
|
||||||
|
'libs/my-lib/package.json': `{}`,
|
||||||
|
});
|
||||||
|
expect(await invokeCreateNodesOnMatchingFiles(context, {}))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"libs/my-lib": {
|
||||||
|
"projectType": "library",
|
||||||
|
"targets": {
|
||||||
|
"typecheck": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "tsc --build --emitDeclarationOnly",
|
||||||
|
"dependsOn": [
|
||||||
|
"^typecheck",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/package.json",
|
||||||
|
"{projectRoot}/tsconfig.json",
|
||||||
|
"{projectRoot}/src/**/*.ts",
|
||||||
|
"!{projectRoot}/src/**/foo.ts",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"typescript",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs type-checking for the project.",
|
||||||
|
"help": {
|
||||||
|
"command": "npx tsc --build --help",
|
||||||
|
"example": {
|
||||||
|
"args": [
|
||||||
|
"--force",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"typescript",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "libs/my-lib",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/dist/**/*.d.ts",
|
||||||
|
"{projectRoot}/dist/tsconfig.tsbuildinfo",
|
||||||
|
],
|
||||||
|
"syncGenerators": [
|
||||||
|
"@nx/js:typescript-sync",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should normalize and add directories in `include` with the ts extensions', async () => {
|
it('should normalize and add directories in `include` with the ts extensions', async () => {
|
||||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||||
'libs/my-lib/tsconfig.json': JSON.stringify({
|
'libs/my-lib/tsconfig.json': JSON.stringify({
|
||||||
@ -2608,6 +2675,68 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support the "${configDir}" template', async () => {
|
||||||
|
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||||
|
'libs/my-lib/tsconfig.json': JSON.stringify({
|
||||||
|
compilerOptions: { outDir: '${configDir}/dist' },
|
||||||
|
files: ['main.ts'],
|
||||||
|
}),
|
||||||
|
'libs/my-lib/package.json': `{}`,
|
||||||
|
});
|
||||||
|
expect(await invokeCreateNodesOnMatchingFiles(context, {}))
|
||||||
|
.toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"libs/my-lib": {
|
||||||
|
"projectType": "library",
|
||||||
|
"targets": {
|
||||||
|
"typecheck": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "tsc --build --emitDeclarationOnly",
|
||||||
|
"dependsOn": [
|
||||||
|
"^typecheck",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"typescript",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Runs type-checking for the project.",
|
||||||
|
"help": {
|
||||||
|
"command": "npx tsc --build --help",
|
||||||
|
"example": {
|
||||||
|
"args": [
|
||||||
|
"--force",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"typescript",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "libs/my-lib",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/dist/**/*.d.ts",
|
||||||
|
"{projectRoot}/dist/tsconfig.tsbuildinfo",
|
||||||
|
],
|
||||||
|
"syncGenerators": [
|
||||||
|
"@nx/js:typescript-sync",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -3351,6 +3480,78 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
|||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should add the config file and the `include` and `exclude` patterns using the "${configDir}" template', async () => {
|
||||||
|
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||||
|
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||||
|
compilerOptions: {
|
||||||
|
outDir: 'dist',
|
||||||
|
},
|
||||||
|
include: ['${configDir}/src/**/*.ts'],
|
||||||
|
exclude: ['${configDir}/src/**/*.spec.ts'],
|
||||||
|
}),
|
||||||
|
'libs/my-lib/tsconfig.json': `{}`,
|
||||||
|
'libs/my-lib/package.json': `{"main": "./dist/index.js"}`,
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
await invokeCreateNodesOnMatchingFiles(context, {
|
||||||
|
typecheck: false,
|
||||||
|
build: true,
|
||||||
|
})
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"libs/my-lib": {
|
||||||
|
"projectType": "library",
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "tsc --build tsconfig.lib.json",
|
||||||
|
"dependsOn": [
|
||||||
|
"^build",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"{projectRoot}/package.json",
|
||||||
|
"{projectRoot}/tsconfig.lib.json",
|
||||||
|
"{projectRoot}/src/**/*.ts",
|
||||||
|
"!{projectRoot}/src/**/*.spec.ts",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"typescript",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Builds the project with \`tsc\`.",
|
||||||
|
"help": {
|
||||||
|
"command": "npx tsc --build --help",
|
||||||
|
"example": {
|
||||||
|
"args": [
|
||||||
|
"--force",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"typescript",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "libs/my-lib",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/dist",
|
||||||
|
],
|
||||||
|
"syncGenerators": [
|
||||||
|
"@nx/js:typescript-sync",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it('should normalize and add directories in `include` with the ts extensions', async () => {
|
it('should normalize and add directories in `include` with the ts extensions', async () => {
|
||||||
await applyFilesToTempFsAndContext(tempFs, context, {
|
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||||
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||||
@ -4948,6 +5149,74 @@ describe(`Plugin: ${PLUGIN_NAME}`, () => {
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should support the "${configDir}" template', async () => {
|
||||||
|
await applyFilesToTempFsAndContext(tempFs, context, {
|
||||||
|
'libs/my-lib/tsconfig.lib.json': JSON.stringify({
|
||||||
|
compilerOptions: {
|
||||||
|
outDir: '${configDir}/dist',
|
||||||
|
},
|
||||||
|
files: ['main.ts'],
|
||||||
|
}),
|
||||||
|
'libs/my-lib/tsconfig.json': `{}`,
|
||||||
|
'libs/my-lib/package.json': `{"main": "./dist/index.js"}`,
|
||||||
|
});
|
||||||
|
expect(
|
||||||
|
await invokeCreateNodesOnMatchingFiles(context, {
|
||||||
|
typecheck: false,
|
||||||
|
build: true,
|
||||||
|
})
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"projects": {
|
||||||
|
"libs/my-lib": {
|
||||||
|
"projectType": "library",
|
||||||
|
"targets": {
|
||||||
|
"build": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "tsc --build tsconfig.lib.json",
|
||||||
|
"dependsOn": [
|
||||||
|
"^build",
|
||||||
|
],
|
||||||
|
"inputs": [
|
||||||
|
"production",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"typescript",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Builds the project with \`tsc\`.",
|
||||||
|
"help": {
|
||||||
|
"command": "npx tsc --build --help",
|
||||||
|
"example": {
|
||||||
|
"args": [
|
||||||
|
"--force",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"technologies": [
|
||||||
|
"typescript",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "libs/my-lib",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{projectRoot}/dist",
|
||||||
|
],
|
||||||
|
"syncGenerators": [
|
||||||
|
"@nx/js:typescript-sync",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -344,7 +344,7 @@ async function getConfigFileHash(
|
|||||||
...(packageJson ? [hashObject(packageJson)] : []),
|
...(packageJson ? [hashObject(packageJson)] : []),
|
||||||
// change this to bust the cache when making changes that would yield
|
// change this to bust the cache when making changes that would yield
|
||||||
// different results for the same hash
|
// different results for the same hash
|
||||||
hashObject({ bust: 2 }),
|
hashObject({ bust: 3 }),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,11 +636,18 @@ function getInputs(
|
|||||||
return [input];
|
return [input];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const configDirTemplate = '${configDir}';
|
||||||
|
const substituteConfigDir = (p: string) =>
|
||||||
|
p.startsWith(configDirTemplate) ? p.replace(configDirTemplate, './') : p;
|
||||||
|
|
||||||
projectTsConfigFiles.forEach(([configPath, config]) => {
|
projectTsConfigFiles.forEach(([configPath, config]) => {
|
||||||
configFiles.add(configPath);
|
configFiles.add(configPath);
|
||||||
const offset = relative(absoluteProjectRoot, dirname(configPath));
|
const offset = relative(absoluteProjectRoot, dirname(configPath));
|
||||||
(config.raw?.include ?? []).forEach((p: string) => {
|
(config.raw?.include ?? []).forEach((p: string) => {
|
||||||
const normalized = normalizeInput(join(offset, p), config);
|
const normalized = normalizeInput(
|
||||||
|
join(offset, substituteConfigDir(p)),
|
||||||
|
config
|
||||||
|
);
|
||||||
normalized.forEach((input) => includePaths.add(input));
|
normalized.forEach((input) => includePaths.add(input));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -653,11 +660,14 @@ function getInputs(
|
|||||||
const otherFilesInclude: string[] = [];
|
const otherFilesInclude: string[] = [];
|
||||||
projectTsConfigFiles.forEach(([path, c]) => {
|
projectTsConfigFiles.forEach(([path, c]) => {
|
||||||
if (path !== configPath) {
|
if (path !== configPath) {
|
||||||
otherFilesInclude.push(...(c.raw?.include ?? []));
|
otherFilesInclude.push(
|
||||||
|
...(c.raw?.include ?? []).map(substituteConfigDir)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
const normalize = (p: string) => (p.startsWith('./') ? p.slice(2) : p);
|
const normalize = (p: string) => (p.startsWith('./') ? p.slice(2) : p);
|
||||||
config.raw.exclude.forEach((excludePath: string) => {
|
config.raw.exclude.forEach((e: string) => {
|
||||||
|
const excludePath = substituteConfigDir(e);
|
||||||
if (
|
if (
|
||||||
!otherFilesInclude.some(
|
!otherFilesInclude.some(
|
||||||
(includePath) =>
|
(includePath) =>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user