fix(misc): handle outputs with globs when normalizing tsconfig path mappings for buidable libraries (#30506)
## Current Behavior If a buildable library depends on another buildable library that has `outputs` using globs the build fails when using an executor that remaps the dependency TypeScript path mappings to the build outputs. ## Expected Behavior Building a buildable library using an executor that remaps the dependency TypeScript path mappings to the build outputs should succeed. The remapping logic should identify and replace the glob patterns and keep the fixed part of the pattern (no segment with wildcards). Note: additionally, an obsolete check was removed from the `@nx/angular:package` and `@nx/angular:delegate-build`. ## Related Issue(s) Fixes #30041
This commit is contained in:
parent
e4e9973db3
commit
bae3acd48e
@ -2,7 +2,6 @@ import type { ExecutorContext } from '@nx/devkit';
|
|||||||
import { joinPathFragments, parseTargetString, runExecutor } from '@nx/devkit';
|
import { joinPathFragments, parseTargetString, runExecutor } from '@nx/devkit';
|
||||||
import {
|
import {
|
||||||
calculateProjectBuildableDependencies,
|
calculateProjectBuildableDependencies,
|
||||||
checkDependentProjectsHaveBeenBuilt,
|
|
||||||
createTmpTsConfig,
|
createTmpTsConfig,
|
||||||
} from '@nx/js/src/utils/buildable-libs-utils';
|
} from '@nx/js/src/utils/buildable-libs-utils';
|
||||||
import type { DelegateBuildExecutorSchema } from './schema';
|
import type { DelegateBuildExecutorSchema } from './schema';
|
||||||
@ -27,17 +26,6 @@ export async function* delegateBuildExecutor(
|
|||||||
dependencies
|
dependencies
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
|
||||||
!checkDependentProjectsHaveBeenBuilt(
|
|
||||||
context.root,
|
|
||||||
context.projectName,
|
|
||||||
context.targetName,
|
|
||||||
dependencies
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return { success: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
const { buildTarget, ...targetOptions } = options;
|
const { buildTarget, ...targetOptions } = options;
|
||||||
const delegateTarget = parseTargetString(buildTarget, context);
|
const delegateTarget = parseTargetString(buildTarget, context);
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import type { ExecutorContext } from '@nx/devkit';
|
|||||||
import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await';
|
import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await';
|
||||||
import {
|
import {
|
||||||
calculateProjectBuildableDependencies,
|
calculateProjectBuildableDependencies,
|
||||||
checkDependentProjectsHaveBeenBuilt,
|
|
||||||
createTmpTsConfig,
|
createTmpTsConfig,
|
||||||
type DependentBuildableProjectNode,
|
type DependentBuildableProjectNode,
|
||||||
} from '@nx/js/src/utils/buildable-libs-utils';
|
} from '@nx/js/src/utils/buildable-libs-utils';
|
||||||
@ -65,8 +64,7 @@ export function createLibraryExecutor(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { target, dependencies, topLevelDependencies } =
|
const { dependencies } = calculateProjectBuildableDependencies(
|
||||||
calculateProjectBuildableDependencies(
|
|
||||||
context.taskGraph,
|
context.taskGraph,
|
||||||
context.projectGraph,
|
context.projectGraph,
|
||||||
context.root,
|
context.root,
|
||||||
@ -74,16 +72,6 @@ export function createLibraryExecutor(
|
|||||||
context.targetName,
|
context.targetName,
|
||||||
context.configurationName
|
context.configurationName
|
||||||
);
|
);
|
||||||
if (
|
|
||||||
!checkDependentProjectsHaveBeenBuilt(
|
|
||||||
context.root,
|
|
||||||
context.projectName,
|
|
||||||
context.targetName,
|
|
||||||
dependencies
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
return Promise.resolve({ success: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.watch) {
|
if (options.watch) {
|
||||||
return yield* eachValueFrom(
|
return yield* eachValueFrom(
|
||||||
|
|||||||
@ -45,6 +45,41 @@ describe('updatePaths', () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle outputs with glob patterns', () => {
|
||||||
|
const paths: Record<string, string[]> = {
|
||||||
|
'@proj/lib1': ['libs/lib1/src/index.ts'],
|
||||||
|
'@proj/lib2': ['libs/lib2/src/index.ts'],
|
||||||
|
'@proj/lib3': ['libs/lib3/src/index.ts'],
|
||||||
|
};
|
||||||
|
|
||||||
|
updatePaths(
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: '@proj/lib1',
|
||||||
|
node: { name: 'lib1', type: 'lib', data: { root: 'libs/lib1' } },
|
||||||
|
outputs: ['dist/libs/lib1/**/*.js'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '@proj/lib2',
|
||||||
|
node: { name: 'lib2', type: 'lib', data: { root: 'libs/lib2' } },
|
||||||
|
outputs: ['dist/libs/lib2/*.js'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '@proj/lib3',
|
||||||
|
node: { name: 'lib3', type: 'lib', data: { root: 'libs/lib3' } },
|
||||||
|
outputs: ['dist/libs/lib3/foo-*/*.js'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
paths
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(paths).toEqual({
|
||||||
|
'@proj/lib1': ['dist/libs/lib1'],
|
||||||
|
'@proj/lib2': ['dist/libs/lib2'],
|
||||||
|
'@proj/lib3': ['dist/libs/lib3'],
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('calculateProjectDependencies', () => {
|
describe('calculateProjectDependencies', () => {
|
||||||
|
|||||||
@ -8,12 +8,11 @@ import {
|
|||||||
getOutputsForTargetAndConfiguration,
|
getOutputsForTargetAndConfiguration,
|
||||||
parseTargetString,
|
parseTargetString,
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
stripIndents,
|
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { unlinkSync } from 'fs';
|
import { unlinkSync } from 'fs';
|
||||||
import { isNpmProject } from 'nx/src/project-graph/operators';
|
import { isNpmProject } from 'nx/src/project-graph/operators';
|
||||||
import { directoryExists, fileExists } from 'nx/src/utils/fileutils';
|
import { fileExists } from 'nx/src/utils/fileutils';
|
||||||
import { output } from 'nx/src/utils/output';
|
import { output } from 'nx/src/utils/output';
|
||||||
import { dirname, join, relative, extname, resolve } from 'path';
|
import { dirname, join, relative, extname, resolve } from 'path';
|
||||||
import type * as ts from 'typescript';
|
import type * as ts from 'typescript';
|
||||||
@ -477,56 +476,6 @@ function cleanupTmpTsConfigFile(tmpTsConfigPath) {
|
|||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function checkDependentProjectsHaveBeenBuilt(
|
|
||||||
root: string,
|
|
||||||
projectName: string,
|
|
||||||
targetName: string,
|
|
||||||
projectDependencies: DependentBuildableProjectNode[]
|
|
||||||
): boolean {
|
|
||||||
const missing = findMissingBuildDependencies(
|
|
||||||
root,
|
|
||||||
projectName,
|
|
||||||
targetName,
|
|
||||||
projectDependencies
|
|
||||||
);
|
|
||||||
if (missing.length > 0) {
|
|
||||||
console.error(stripIndents`
|
|
||||||
It looks like all of ${projectName}'s dependencies have not been built yet:
|
|
||||||
${missing.map((x) => ` - ${x.node.name}`).join('\n')}
|
|
||||||
|
|
||||||
You might be missing a "targetDefaults" configuration in your root nx.json (https://nx.dev/reference/project-configuration#target-defaults),
|
|
||||||
or "dependsOn" configured in ${projectName}'s project.json (https://nx.dev/reference/project-configuration#dependson)
|
|
||||||
`);
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function findMissingBuildDependencies(
|
|
||||||
root: string,
|
|
||||||
projectName: string,
|
|
||||||
targetName: string,
|
|
||||||
projectDependencies: DependentBuildableProjectNode[]
|
|
||||||
): DependentBuildableProjectNode[] {
|
|
||||||
const depLibsToBuildFirst: DependentBuildableProjectNode[] = [];
|
|
||||||
|
|
||||||
// verify whether all dependent libraries have been built
|
|
||||||
projectDependencies.forEach((dep) => {
|
|
||||||
if (dep.node.type !== 'lib') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const paths = dep.outputs.map((p) => join(root, p));
|
|
||||||
|
|
||||||
if (!paths.some(directoryExists)) {
|
|
||||||
depLibsToBuildFirst.push(dep);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return depLibsToBuildFirst;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updatePaths(
|
export function updatePaths(
|
||||||
dependencies: DependentBuildableProjectNode[],
|
dependencies: DependentBuildableProjectNode[],
|
||||||
paths: Record<string, string[]>
|
paths: Record<string, string[]>
|
||||||
@ -539,7 +488,9 @@ export function updatePaths(
|
|||||||
// If there are outputs
|
// If there are outputs
|
||||||
if (dep.outputs && dep.outputs.length > 0) {
|
if (dep.outputs && dep.outputs.length > 0) {
|
||||||
// Directly map the dependency name to the output paths (dist/packages/..., etc.)
|
// Directly map the dependency name to the output paths (dist/packages/..., etc.)
|
||||||
paths[dep.name] = dep.outputs;
|
paths[dep.name] = dep.outputs.map((output) =>
|
||||||
|
output.replace(/(\*|\/[^\/]*\*).*$/, '')
|
||||||
|
);
|
||||||
|
|
||||||
// check for secondary entrypoints
|
// check for secondary entrypoints
|
||||||
// For each registered path
|
// For each registered path
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user