Skip to content

Commit bae3acd

Browse files
authored
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
1 parent e4e9973 commit bae3acd

File tree

4 files changed

+47
-85
lines changed

4 files changed

+47
-85
lines changed

packages/angular/src/executors/delegate-build/delegate-build.impl.ts

-12
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import type { ExecutorContext } from '@nx/devkit';
22
import { joinPathFragments, parseTargetString, runExecutor } from '@nx/devkit';
33
import {
44
calculateProjectBuildableDependencies,
5-
checkDependentProjectsHaveBeenBuilt,
65
createTmpTsConfig,
76
} from '@nx/js/src/utils/buildable-libs-utils';
87
import type { DelegateBuildExecutorSchema } from './schema';
@@ -27,17 +26,6 @@ export async function* delegateBuildExecutor(
2726
dependencies
2827
);
2928

30-
if (
31-
!checkDependentProjectsHaveBeenBuilt(
32-
context.root,
33-
context.projectName,
34-
context.targetName,
35-
dependencies
36-
)
37-
) {
38-
return { success: false };
39-
}
40-
4129
const { buildTarget, ...targetOptions } = options;
4230
const delegateTarget = parseTargetString(buildTarget, context);
4331

packages/angular/src/executors/package/package.impl.ts

+8-20
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import type { ExecutorContext } from '@nx/devkit';
22
import { eachValueFrom } from '@nx/devkit/src/utils/rxjs-for-await';
33
import {
44
calculateProjectBuildableDependencies,
5-
checkDependentProjectsHaveBeenBuilt,
65
createTmpTsConfig,
76
type DependentBuildableProjectNode,
87
} from '@nx/js/src/utils/buildable-libs-utils';
@@ -65,25 +64,14 @@ export function createLibraryExecutor(
6564
);
6665
}
6766

68-
const { target, dependencies, topLevelDependencies } =
69-
calculateProjectBuildableDependencies(
70-
context.taskGraph,
71-
context.projectGraph,
72-
context.root,
73-
context.projectName,
74-
context.targetName,
75-
context.configurationName
76-
);
77-
if (
78-
!checkDependentProjectsHaveBeenBuilt(
79-
context.root,
80-
context.projectName,
81-
context.targetName,
82-
dependencies
83-
)
84-
) {
85-
return Promise.resolve({ success: false });
86-
}
67+
const { dependencies } = calculateProjectBuildableDependencies(
68+
context.taskGraph,
69+
context.projectGraph,
70+
context.root,
71+
context.projectName,
72+
context.targetName,
73+
context.configurationName
74+
);
8775

8876
if (options.watch) {
8977
return yield* eachValueFrom(

packages/js/src/utils/buildable-libs-utils.spec.ts

+35
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,41 @@ describe('updatePaths', () => {
4545
],
4646
});
4747
});
48+
49+
it('should handle outputs with glob patterns', () => {
50+
const paths: Record<string, string[]> = {
51+
'@proj/lib1': ['libs/lib1/src/index.ts'],
52+
'@proj/lib2': ['libs/lib2/src/index.ts'],
53+
'@proj/lib3': ['libs/lib3/src/index.ts'],
54+
};
55+
56+
updatePaths(
57+
[
58+
{
59+
name: '@proj/lib1',
60+
node: { name: 'lib1', type: 'lib', data: { root: 'libs/lib1' } },
61+
outputs: ['dist/libs/lib1/**/*.js'],
62+
},
63+
{
64+
name: '@proj/lib2',
65+
node: { name: 'lib2', type: 'lib', data: { root: 'libs/lib2' } },
66+
outputs: ['dist/libs/lib2/*.js'],
67+
},
68+
{
69+
name: '@proj/lib3',
70+
node: { name: 'lib3', type: 'lib', data: { root: 'libs/lib3' } },
71+
outputs: ['dist/libs/lib3/foo-*/*.js'],
72+
},
73+
],
74+
paths
75+
);
76+
77+
expect(paths).toEqual({
78+
'@proj/lib1': ['dist/libs/lib1'],
79+
'@proj/lib2': ['dist/libs/lib2'],
80+
'@proj/lib3': ['dist/libs/lib3'],
81+
});
82+
});
4883
});
4984

5085
describe('calculateProjectDependencies', () => {

packages/js/src/utils/buildable-libs-utils.ts

+4-53
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@ import {
88
getOutputsForTargetAndConfiguration,
99
parseTargetString,
1010
readJsonFile,
11-
stripIndents,
1211
writeJsonFile,
1312
} from '@nx/devkit';
1413
import { unlinkSync } from 'fs';
1514
import { isNpmProject } from 'nx/src/project-graph/operators';
16-
import { directoryExists, fileExists } from 'nx/src/utils/fileutils';
15+
import { fileExists } from 'nx/src/utils/fileutils';
1716
import { output } from 'nx/src/utils/output';
1817
import { dirname, join, relative, extname, resolve } from 'path';
1918
import type * as ts from 'typescript';
@@ -477,56 +476,6 @@ function cleanupTmpTsConfigFile(tmpTsConfigPath) {
477476
} catch (e) {}
478477
}
479478

480-
export function checkDependentProjectsHaveBeenBuilt(
481-
root: string,
482-
projectName: string,
483-
targetName: string,
484-
projectDependencies: DependentBuildableProjectNode[]
485-
): boolean {
486-
const missing = findMissingBuildDependencies(
487-
root,
488-
projectName,
489-
targetName,
490-
projectDependencies
491-
);
492-
if (missing.length > 0) {
493-
console.error(stripIndents`
494-
It looks like all of ${projectName}'s dependencies have not been built yet:
495-
${missing.map((x) => ` - ${x.node.name}`).join('\n')}
496-
497-
You might be missing a "targetDefaults" configuration in your root nx.json (https://nx.dev/reference/project-configuration#target-defaults),
498-
or "dependsOn" configured in ${projectName}'s project.json (https://nx.dev/reference/project-configuration#dependson)
499-
`);
500-
return false;
501-
} else {
502-
return true;
503-
}
504-
}
505-
506-
export function findMissingBuildDependencies(
507-
root: string,
508-
projectName: string,
509-
targetName: string,
510-
projectDependencies: DependentBuildableProjectNode[]
511-
): DependentBuildableProjectNode[] {
512-
const depLibsToBuildFirst: DependentBuildableProjectNode[] = [];
513-
514-
// verify whether all dependent libraries have been built
515-
projectDependencies.forEach((dep) => {
516-
if (dep.node.type !== 'lib') {
517-
return;
518-
}
519-
520-
const paths = dep.outputs.map((p) => join(root, p));
521-
522-
if (!paths.some(directoryExists)) {
523-
depLibsToBuildFirst.push(dep);
524-
}
525-
});
526-
527-
return depLibsToBuildFirst;
528-
}
529-
530479
export function updatePaths(
531480
dependencies: DependentBuildableProjectNode[],
532481
paths: Record<string, string[]>
@@ -539,7 +488,9 @@ export function updatePaths(
539488
// If there are outputs
540489
if (dep.outputs && dep.outputs.length > 0) {
541490
// Directly map the dependency name to the output paths (dist/packages/..., etc.)
542-
paths[dep.name] = dep.outputs;
491+
paths[dep.name] = dep.outputs.map((output) =>
492+
output.replace(/(\*|\/[^\/]*\*).*$/, '')
493+
);
543494

544495
// check for secondary entrypoints
545496
// For each registered path

0 commit comments

Comments
 (0)