nx 19.2.0-beta.2 → 19.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -12
- package/src/devkit-exports.d.ts +3 -1
- package/src/devkit-exports.js +5 -1
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +14 -3
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +63 -15
- package/src/plugins/js/utils/resolve-relative-to-dir.d.ts +5 -0
- package/src/plugins/js/utils/resolve-relative-to-dir.js +18 -0
- package/src/project-graph/error-types.d.ts +37 -19
- package/src/project-graph/error-types.js +31 -19
- package/src/project-graph/plugins/index.d.ts +1 -0
- package/src/project-graph/plugins/index.js +3 -1
- package/src/project-graph/plugins/internal-api.d.ts +2 -2
- package/src/project-graph/plugins/internal-api.js +33 -3
- package/src/project-graph/plugins/public-api.d.ts +34 -3
- package/src/project-graph/plugins/utils.d.ts +4 -3
- package/src/project-graph/plugins/utils.js +13 -26
- package/src/project-graph/utils/project-configuration-utils.js +89 -74
- package/src/plugins/js/utils/find-external-package-json-path.d.ts +0 -10
- package/src/plugins/js/utils/find-external-package-json-path.js +0 -42
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "nx",
|
3
|
-
"version": "19.2.0-beta.
|
3
|
+
"version": "19.2.0-beta.4",
|
4
4
|
"private": false,
|
5
5
|
"description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
|
6
6
|
"repository": {
|
@@ -69,7 +69,7 @@
|
|
69
69
|
"yargs-parser": "21.1.1",
|
70
70
|
"node-machine-id": "1.1.12",
|
71
71
|
"ora": "5.3.0",
|
72
|
-
"@nrwl/tao": "19.2.0-beta.
|
72
|
+
"@nrwl/tao": "19.2.0-beta.4"
|
73
73
|
},
|
74
74
|
"peerDependencies": {
|
75
75
|
"@swc-node/register": "^1.8.0",
|
@@ -84,16 +84,16 @@
|
|
84
84
|
}
|
85
85
|
},
|
86
86
|
"optionalDependencies": {
|
87
|
-
"@nx/nx-darwin-x64": "19.2.0-beta.
|
88
|
-
"@nx/nx-darwin-arm64": "19.2.0-beta.
|
89
|
-
"@nx/nx-linux-x64-gnu": "19.2.0-beta.
|
90
|
-
"@nx/nx-linux-x64-musl": "19.2.0-beta.
|
91
|
-
"@nx/nx-win32-x64-msvc": "19.2.0-beta.
|
92
|
-
"@nx/nx-linux-arm64-gnu": "19.2.0-beta.
|
93
|
-
"@nx/nx-linux-arm64-musl": "19.2.0-beta.
|
94
|
-
"@nx/nx-linux-arm-gnueabihf": "19.2.0-beta.
|
95
|
-
"@nx/nx-win32-arm64-msvc": "19.2.0-beta.
|
96
|
-
"@nx/nx-freebsd-x64": "19.2.0-beta.
|
87
|
+
"@nx/nx-darwin-x64": "19.2.0-beta.4",
|
88
|
+
"@nx/nx-darwin-arm64": "19.2.0-beta.4",
|
89
|
+
"@nx/nx-linux-x64-gnu": "19.2.0-beta.4",
|
90
|
+
"@nx/nx-linux-x64-musl": "19.2.0-beta.4",
|
91
|
+
"@nx/nx-win32-x64-msvc": "19.2.0-beta.4",
|
92
|
+
"@nx/nx-linux-arm64-gnu": "19.2.0-beta.4",
|
93
|
+
"@nx/nx-linux-arm64-musl": "19.2.0-beta.4",
|
94
|
+
"@nx/nx-linux-arm-gnueabihf": "19.2.0-beta.4",
|
95
|
+
"@nx/nx-win32-arm64-msvc": "19.2.0-beta.4",
|
96
|
+
"@nx/nx-freebsd-x64": "19.2.0-beta.4"
|
97
97
|
},
|
98
98
|
"nx-migrations": {
|
99
99
|
"migrations": "./migrations.json",
|
package/src/devkit-exports.d.ts
CHANGED
@@ -15,7 +15,9 @@ export type { WorkspaceJsonConfiguration, ProjectsConfigurations, TargetDependen
|
|
15
15
|
*/
|
16
16
|
export type { Generator, GeneratorCallback, Executor, ExecutorContext, TaskGraphExecutor, GeneratorsJson, ExecutorsJson, MigrationsJson, CustomHasher, HasherContext, } from './config/misc-interfaces';
|
17
17
|
export { workspaceLayout } from './config/configuration';
|
18
|
-
export type { NxPlugin, NxPluginV2, CreateNodes, CreateNodesFunction, CreateNodesResult, CreateNodesContext, CreateDependencies, CreateDependenciesContext, CreateMetadata, CreateMetadataContext, ProjectsMetadata, } from './project-graph/plugins';
|
18
|
+
export type { NxPlugin, NxPluginV2, CreateNodes, CreateNodesFunction, CreateNodesResult, CreateNodesContext, CreateNodesContextV2, CreateNodesFunctionV2, CreateNodesResultV2, CreateNodesV2, CreateDependencies, CreateDependenciesContext, CreateMetadata, CreateMetadataContext, ProjectsMetadata, } from './project-graph/plugins';
|
19
|
+
export { AggregateCreateNodesError } from './project-graph/error-types';
|
20
|
+
export { createNodesFromFiles } from './project-graph/plugins';
|
19
21
|
export type { NxPluginV1, ProjectTargetConfigurator, } from './utils/nx-plugin.deprecated';
|
20
22
|
/**
|
21
23
|
* @category Workspace
|
package/src/devkit-exports.js
CHANGED
@@ -4,9 +4,13 @@
|
|
4
4
|
* Try hard to not add to this API to reduce the surface area we need to maintain.
|
5
5
|
*/
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
7
|
-
exports.createProjectFileMapUsingProjectGraph = exports.cacheDir = exports.hashArray = exports.defaultTasksRunner = exports.getOutputsForTargetAndConfiguration = exports.readProjectsConfigurationFromProjectGraph = exports.readCachedProjectGraph = exports.createProjectGraphAsync = exports.reverse = exports.appRootPath = exports.workspaceRoot = exports.normalizePath = exports.joinPathFragments = exports.stripIndents = exports.writeJsonFile = exports.readJsonFile = exports.stripJsonComments = exports.serializeJson = exports.parseJson = exports.updateJson = exports.writeJson = exports.readJson = exports.validateDependency = exports.ProjectGraphBuilder = exports.DependencyType = exports.updateNxJson = exports.readNxJson = exports.glob = exports.getProjects = exports.updateProjectConfiguration = exports.removeProjectConfiguration = exports.readProjectConfiguration = exports.addProjectConfiguration = exports.runExecutor = exports.isWorkspacesEnabled = exports.getPackageManagerVersion = exports.detectPackageManager = exports.getPackageManagerCommand = exports.output = exports.logger = exports.workspaceLayout = void 0;
|
7
|
+
exports.createProjectFileMapUsingProjectGraph = exports.cacheDir = exports.hashArray = exports.defaultTasksRunner = exports.getOutputsForTargetAndConfiguration = exports.readProjectsConfigurationFromProjectGraph = exports.readCachedProjectGraph = exports.createProjectGraphAsync = exports.reverse = exports.appRootPath = exports.workspaceRoot = exports.normalizePath = exports.joinPathFragments = exports.stripIndents = exports.writeJsonFile = exports.readJsonFile = exports.stripJsonComments = exports.serializeJson = exports.parseJson = exports.updateJson = exports.writeJson = exports.readJson = exports.validateDependency = exports.ProjectGraphBuilder = exports.DependencyType = exports.updateNxJson = exports.readNxJson = exports.glob = exports.getProjects = exports.updateProjectConfiguration = exports.removeProjectConfiguration = exports.readProjectConfiguration = exports.addProjectConfiguration = exports.runExecutor = exports.isWorkspacesEnabled = exports.getPackageManagerVersion = exports.detectPackageManager = exports.getPackageManagerCommand = exports.output = exports.logger = exports.createNodesFromFiles = exports.AggregateCreateNodesError = exports.workspaceLayout = void 0;
|
8
8
|
var configuration_1 = require("./config/configuration");
|
9
9
|
Object.defineProperty(exports, "workspaceLayout", { enumerable: true, get: function () { return configuration_1.workspaceLayout; } });
|
10
|
+
var error_types_1 = require("./project-graph/error-types");
|
11
|
+
Object.defineProperty(exports, "AggregateCreateNodesError", { enumerable: true, get: function () { return error_types_1.AggregateCreateNodesError; } });
|
12
|
+
var plugins_1 = require("./project-graph/plugins");
|
13
|
+
Object.defineProperty(exports, "createNodesFromFiles", { enumerable: true, get: function () { return plugins_1.createNodesFromFiles; } });
|
10
14
|
/**
|
11
15
|
* @category Logger
|
12
16
|
*/
|
@@ -4,11 +4,11 @@ import { ProjectGraphExternalNode, ProjectGraphProjectNode } from '../../../../c
|
|
4
4
|
* containing the file importing it e.g. `lodash__packages/my-lib`, the value is the
|
5
5
|
* resolved external node name from the project graph.
|
6
6
|
*/
|
7
|
-
type NpmResolutionCache = Map<string, string>;
|
7
|
+
type NpmResolutionCache = Map<string, string | null>;
|
8
8
|
export declare function isBuiltinModuleImport(importExpr: string): boolean;
|
9
9
|
export declare class TargetProjectLocator {
|
10
10
|
private readonly nodes;
|
11
|
-
readonly externalNodes
|
11
|
+
private readonly externalNodes;
|
12
12
|
private readonly npmResolutionCache;
|
13
13
|
private projectRootMappings;
|
14
14
|
private npmProjects;
|
@@ -31,7 +31,7 @@ export declare class TargetProjectLocator {
|
|
31
31
|
* @param importExpr
|
32
32
|
* @param projectRoot
|
33
33
|
*/
|
34
|
-
findNpmProjectFromImport(importExpr: string, fromFilePath: string): string |
|
34
|
+
findNpmProjectFromImport(importExpr: string, fromFilePath: string): string | null;
|
35
35
|
/**
|
36
36
|
* Return file paths matching the import relative to the repo root
|
37
37
|
* @param normalizedImportExpr
|
@@ -44,5 +44,16 @@ export declare class TargetProjectLocator {
|
|
44
44
|
private getAbsolutePath;
|
45
45
|
private getRootTsConfig;
|
46
46
|
private findMatchingProjectFiles;
|
47
|
+
/**
|
48
|
+
* In many cases the package.json will be directly resolvable, so we try that first.
|
49
|
+
* If, however, package exports are used and the package.json is not defined, we will
|
50
|
+
* need to resolve the main entry point of the package and traverse upwards to find the
|
51
|
+
* package.json.
|
52
|
+
*
|
53
|
+
* In some cases, such as when multiple module formats are published, the resolved package.json
|
54
|
+
* might only contain the "type" field - no "name" or "version", so in such cases we keep traversing
|
55
|
+
* until we find a package.json that contains the "name" and "version" fields.
|
56
|
+
*/
|
57
|
+
private readPackageJson;
|
47
58
|
}
|
48
59
|
export {};
|
@@ -6,7 +6,7 @@ const node_path_1 = require("node:path");
|
|
6
6
|
const find_project_for_path_1 = require("../../../../project-graph/utils/find-project-for-path");
|
7
7
|
const fileutils_1 = require("../../../../utils/fileutils");
|
8
8
|
const workspace_root_1 = require("../../../../utils/workspace-root");
|
9
|
-
const
|
9
|
+
const resolve_relative_to_dir_1 = require("../../utils/resolve-relative-to-dir");
|
10
10
|
const typescript_1 = require("../../utils/typescript");
|
11
11
|
/**
|
12
12
|
* Use a shared cache to avoid repeated npm package resolution work within the TargetProjectLocator.
|
@@ -30,17 +30,22 @@ class TargetProjectLocator {
|
|
30
30
|
this.tsConfig = this.getRootTsConfig();
|
31
31
|
this.paths = this.tsConfig.config?.compilerOptions?.paths;
|
32
32
|
this.typescriptResolutionCache = new Map();
|
33
|
-
this.npmProjects = externalNodes;
|
34
33
|
/**
|
35
34
|
* Only the npm external nodes should be included.
|
36
35
|
*
|
37
|
-
* Unlike the raw externalNodes, ensure that
|
38
|
-
* for optimal lookup.
|
36
|
+
* Unlike the raw externalNodes, ensure that there is always copy of the node where the version
|
37
|
+
* is set in the key for optimal lookup.
|
39
38
|
*/
|
40
|
-
this.npmProjects = Object.values(externalNodes).reduce((acc, node) => {
|
39
|
+
this.npmProjects = Object.values(this.externalNodes).reduce((acc, node) => {
|
41
40
|
if (node.type === 'npm') {
|
42
|
-
const
|
43
|
-
acc[
|
41
|
+
const keyWithVersion = `npm:${node.data.packageName}@${node.data.version}`;
|
42
|
+
if (!acc[node.name]) {
|
43
|
+
acc[node.name] = node;
|
44
|
+
}
|
45
|
+
// The node.name may have already contained the version
|
46
|
+
if (!acc[keyWithVersion]) {
|
47
|
+
acc[keyWithVersion] = node;
|
48
|
+
}
|
44
49
|
}
|
45
50
|
return acc;
|
46
51
|
}, {});
|
@@ -123,17 +128,20 @@ class TargetProjectLocator {
|
|
123
128
|
}
|
124
129
|
try {
|
125
130
|
// package.json refers to an external package, we do not match against the version found in there, we instead try and resolve the relevant package how node would
|
126
|
-
const
|
131
|
+
const externalPackageJson = this.readPackageJson(packageName, fullDirPath);
|
127
132
|
// The external package.json path might be not be resolvable, e.g. if a reference has been added to a project package.json, but the install command has not been run yet.
|
128
|
-
if (!
|
129
|
-
|
133
|
+
if (!externalPackageJson) {
|
134
|
+
// Try and fall back to resolving an external node from the graph by name
|
135
|
+
const externalNode = this.npmProjects[`npm:${packageName}`];
|
136
|
+
const externalNodeName = externalNode?.name || null;
|
137
|
+
this.npmResolutionCache.set(npmImportForProject, externalNodeName);
|
138
|
+
return externalNodeName;
|
130
139
|
}
|
131
|
-
const externalPackageJson = (0, fileutils_1.readJsonFile)(externalPackageJsonPath);
|
132
140
|
const npmProjectKey = `npm:${externalPackageJson.name}@${externalPackageJson.version}`;
|
133
|
-
if (!this.npmProjects[npmProjectKey]) {
|
134
|
-
return undefined;
|
135
|
-
}
|
136
141
|
const matchingExternalNode = this.npmProjects[npmProjectKey];
|
142
|
+
if (!matchingExternalNode) {
|
143
|
+
return null;
|
144
|
+
}
|
137
145
|
this.npmResolutionCache.set(npmImportForProject, matchingExternalNode.name);
|
138
146
|
return matchingExternalNode.name;
|
139
147
|
}
|
@@ -141,7 +149,7 @@ class TargetProjectLocator {
|
|
141
149
|
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
142
150
|
console.error(e);
|
143
151
|
}
|
144
|
-
return
|
152
|
+
return null;
|
145
153
|
}
|
146
154
|
}
|
147
155
|
/**
|
@@ -221,6 +229,46 @@ class TargetProjectLocator {
|
|
221
229
|
const project = (0, find_project_for_path_1.findProjectForPath)(file, this.projectRootMappings);
|
222
230
|
return this.nodes[project];
|
223
231
|
}
|
232
|
+
/**
|
233
|
+
* In many cases the package.json will be directly resolvable, so we try that first.
|
234
|
+
* If, however, package exports are used and the package.json is not defined, we will
|
235
|
+
* need to resolve the main entry point of the package and traverse upwards to find the
|
236
|
+
* package.json.
|
237
|
+
*
|
238
|
+
* In some cases, such as when multiple module formats are published, the resolved package.json
|
239
|
+
* might only contain the "type" field - no "name" or "version", so in such cases we keep traversing
|
240
|
+
* until we find a package.json that contains the "name" and "version" fields.
|
241
|
+
*/
|
242
|
+
readPackageJson(packageName, relativeToDir) {
|
243
|
+
// The package.json is directly resolvable
|
244
|
+
const packageJsonPath = (0, resolve_relative_to_dir_1.resolveRelativeToDir)((0, node_path_1.join)(packageName, 'package.json'), relativeToDir);
|
245
|
+
if (packageJsonPath) {
|
246
|
+
return (0, fileutils_1.readJsonFile)(packageJsonPath);
|
247
|
+
}
|
248
|
+
try {
|
249
|
+
// Resolve the main entry point of the package
|
250
|
+
const mainPath = (0, resolve_relative_to_dir_1.resolveRelativeToDir)(packageName, relativeToDir);
|
251
|
+
let dir = (0, node_path_1.dirname)(mainPath);
|
252
|
+
while (dir !== (0, node_path_1.parse)(dir).root) {
|
253
|
+
const packageJsonPath = (0, node_path_1.join)(dir, 'package.json');
|
254
|
+
try {
|
255
|
+
const parsedPackageJson = (0, fileutils_1.readJsonFile)(packageJsonPath);
|
256
|
+
// Ensure the package.json contains the "name" and "version" fields
|
257
|
+
if (parsedPackageJson.name && parsedPackageJson.version) {
|
258
|
+
return parsedPackageJson;
|
259
|
+
}
|
260
|
+
}
|
261
|
+
catch {
|
262
|
+
// Package.json doesn't exist, keep traversing
|
263
|
+
}
|
264
|
+
dir = (0, node_path_1.dirname)(dir);
|
265
|
+
}
|
266
|
+
return null;
|
267
|
+
}
|
268
|
+
catch {
|
269
|
+
return null;
|
270
|
+
}
|
271
|
+
}
|
224
272
|
}
|
225
273
|
exports.TargetProjectLocator = TargetProjectLocator;
|
226
274
|
function parsePackageNameFromImportExpression(importExpression) {
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.resolveRelativeToDir = void 0;
|
4
|
+
/**
|
5
|
+
* NOTE: This function is in its own file because it is not possible to mock
|
6
|
+
* require.resolve directly in jest https://github.com/jestjs/jest/issues/9543
|
7
|
+
*/
|
8
|
+
function resolveRelativeToDir(path, relativeToDir) {
|
9
|
+
try {
|
10
|
+
return require.resolve(path, {
|
11
|
+
paths: [relativeToDir],
|
12
|
+
});
|
13
|
+
}
|
14
|
+
catch {
|
15
|
+
return null;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
exports.resolveRelativeToDir = resolveRelativeToDir;
|
@@ -1,10 +1,10 @@
|
|
1
|
-
import { CreateNodesResultWithContext } from './plugins/internal-api';
|
2
1
|
import { ConfigurationResult, ConfigurationSourceMaps } from './utils/project-configuration-utils';
|
3
2
|
import { ProjectConfiguration } from '../config/workspace-json-project-json';
|
4
3
|
import { ProjectGraph } from '../config/project-graph';
|
4
|
+
import { CreateNodesFunctionV2 } from './plugins';
|
5
5
|
export declare class ProjectGraphError extends Error {
|
6
6
|
#private;
|
7
|
-
constructor(errors: Array<
|
7
|
+
constructor(errors: Array<AggregateCreateNodesError | MergeNodesError | ProjectsWithNoNameError | MultipleProjectsWithSameNameError | ProcessDependenciesError | ProcessProjectGraphError | CreateMetadataError | WorkspaceValidityError>, partialProjectGraph: ProjectGraph, partialSourceMaps: ConfigurationSourceMaps);
|
8
8
|
/**
|
9
9
|
* The daemon cannot throw errors which contain methods as they are not serializable.
|
10
10
|
*
|
@@ -18,7 +18,7 @@ export declare class ProjectGraphError extends Error {
|
|
18
18
|
*/
|
19
19
|
getPartialProjectGraph(): ProjectGraph;
|
20
20
|
getPartialSourcemaps(): ConfigurationSourceMaps;
|
21
|
-
getErrors(): (
|
21
|
+
getErrors(): (AggregateCreateNodesError | MergeNodesError | CreateMetadataError | ProjectsWithNoNameError | MultipleProjectsWithSameNameError | ProcessDependenciesError | ProcessProjectGraphError | WorkspaceValidityError)[];
|
22
22
|
}
|
23
23
|
export declare class MultipleProjectsWithSameNameError extends Error {
|
24
24
|
conflicts: Map<string, string[]>;
|
@@ -44,25 +44,44 @@ export declare class ProjectWithNoNameError extends Error {
|
|
44
44
|
}
|
45
45
|
export declare function isProjectWithNoNameError(e: unknown): e is ProjectWithNoNameError;
|
46
46
|
export declare class ProjectConfigurationsError extends Error {
|
47
|
-
readonly errors: Array<MergeNodesError |
|
47
|
+
readonly errors: Array<MergeNodesError | AggregateCreateNodesError | ProjectsWithNoNameError | MultipleProjectsWithSameNameError>;
|
48
48
|
readonly partialProjectConfigurationsResult: ConfigurationResult;
|
49
|
-
constructor(errors: Array<MergeNodesError |
|
49
|
+
constructor(errors: Array<MergeNodesError | AggregateCreateNodesError | ProjectsWithNoNameError | MultipleProjectsWithSameNameError>, partialProjectConfigurationsResult: ConfigurationResult);
|
50
50
|
}
|
51
51
|
export declare function isProjectConfigurationsError(e: unknown): e is ProjectConfigurationsError;
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
file: string;
|
57
|
-
pluginName: string;
|
58
|
-
error: Error;
|
59
|
-
});
|
60
|
-
}
|
52
|
+
/**
|
53
|
+
* This error should be thrown when a `createNodesV2` function hits a recoverable error.
|
54
|
+
* It allows Nx to recieve partial results and continue processing for better UX.
|
55
|
+
*/
|
61
56
|
export declare class AggregateCreateNodesError extends Error {
|
62
|
-
readonly
|
63
|
-
readonly
|
64
|
-
|
65
|
-
|
57
|
+
readonly errors: Array<[file: string | null, error: Error]>;
|
58
|
+
readonly partialResults: Awaited<ReturnType<CreateNodesFunctionV2>>;
|
59
|
+
/**
|
60
|
+
* Throwing this error from a `createNodesV2` function will allow Nx to continue processing and recieve partial results from your plugin.
|
61
|
+
* @example
|
62
|
+
* export async function createNodesV2(
|
63
|
+
* files: string[],
|
64
|
+
* ) {
|
65
|
+
* const partialResults = [];
|
66
|
+
* const errors = [];
|
67
|
+
* await Promise.all(files.map(async (file) => {
|
68
|
+
* try {
|
69
|
+
* const result = await createNodes(file);
|
70
|
+
* partialResults.push(result);
|
71
|
+
* } catch (e) {
|
72
|
+
* errors.push([file, e]);
|
73
|
+
* }
|
74
|
+
* }));
|
75
|
+
* if (errors.length > 0) {
|
76
|
+
* throw new AggregateCreateNodesError(errors, partialResults);
|
77
|
+
* }
|
78
|
+
* return partialResults;
|
79
|
+
* }
|
80
|
+
*
|
81
|
+
* @param errors An array of tuples that represent errors encountered when processing a given file. An example entry might look like ['path/to/project.json', [Error: 'Invalid JSON. Unexpected token 'a' in JSON at position 0]]
|
82
|
+
* @param partialResults The partial results of the `createNodesV2` function. This should be the results for each file that didn't encounter an issue.
|
83
|
+
*/
|
84
|
+
constructor(errors: Array<[file: string | null, error: Error]>, partialResults: Awaited<ReturnType<CreateNodesFunctionV2>>);
|
66
85
|
}
|
67
86
|
export declare class MergeNodesError extends Error {
|
68
87
|
file: string;
|
@@ -102,7 +121,6 @@ export declare class AggregateProjectGraphError extends Error {
|
|
102
121
|
}
|
103
122
|
export declare function isAggregateProjectGraphError(e: unknown): e is AggregateProjectGraphError;
|
104
123
|
export declare function isCreateMetadataError(e: unknown): e is CreateMetadataError;
|
105
|
-
export declare function isCreateNodesError(e: unknown): e is CreateNodesError;
|
106
124
|
export declare function isAggregateCreateNodesError(e: unknown): e is AggregateCreateNodesError;
|
107
125
|
export declare function isMergeNodesError(e: unknown): e is MergeNodesError;
|
108
126
|
export declare class DaemonProjectGraphError extends Error {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
var _ProjectGraphError_errors, _ProjectGraphError_partialProjectGraph, _ProjectGraphError_partialSourceMaps;
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
4
|
-
exports.LoadPluginError = exports.DaemonProjectGraphError = exports.isMergeNodesError = exports.isAggregateCreateNodesError = exports.
|
4
|
+
exports.LoadPluginError = exports.DaemonProjectGraphError = exports.isMergeNodesError = exports.isAggregateCreateNodesError = exports.isCreateMetadataError = exports.isAggregateProjectGraphError = exports.AggregateProjectGraphError = exports.ProcessProjectGraphError = exports.isWorkspaceValidityError = exports.WorkspaceValidityError = exports.ProcessDependenciesError = exports.CreateMetadataError = exports.MergeNodesError = exports.AggregateCreateNodesError = exports.isProjectConfigurationsError = exports.ProjectConfigurationsError = exports.isProjectWithNoNameError = exports.ProjectWithNoNameError = exports.isProjectsWithNoNameError = exports.ProjectsWithNoNameError = exports.isMultipleProjectsWithSameNameError = exports.isProjectWithExistingNameError = exports.ProjectWithExistingNameError = exports.MultipleProjectsWithSameNameError = exports.ProjectGraphError = void 0;
|
5
5
|
const tslib_1 = require("tslib");
|
6
6
|
class ProjectGraphError extends Error {
|
7
7
|
constructor(errors, partialProjectGraph, partialSourceMaps) {
|
@@ -126,21 +126,38 @@ function isProjectConfigurationsError(e) {
|
|
126
126
|
e?.name === ProjectConfigurationsError.name));
|
127
127
|
}
|
128
128
|
exports.isProjectConfigurationsError = isProjectConfigurationsError;
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
this.name = this.constructor.name;
|
134
|
-
this.file = file;
|
135
|
-
this.pluginName = pluginName;
|
136
|
-
this.stack = `${this.message}\n ${error.stack.split('\n').join('\n ')}`;
|
137
|
-
}
|
138
|
-
}
|
139
|
-
exports.CreateNodesError = CreateNodesError;
|
129
|
+
/**
|
130
|
+
* This error should be thrown when a `createNodesV2` function hits a recoverable error.
|
131
|
+
* It allows Nx to recieve partial results and continue processing for better UX.
|
132
|
+
*/
|
140
133
|
class AggregateCreateNodesError extends Error {
|
141
|
-
|
134
|
+
/**
|
135
|
+
* Throwing this error from a `createNodesV2` function will allow Nx to continue processing and recieve partial results from your plugin.
|
136
|
+
* @example
|
137
|
+
* export async function createNodesV2(
|
138
|
+
* files: string[],
|
139
|
+
* ) {
|
140
|
+
* const partialResults = [];
|
141
|
+
* const errors = [];
|
142
|
+
* await Promise.all(files.map(async (file) => {
|
143
|
+
* try {
|
144
|
+
* const result = await createNodes(file);
|
145
|
+
* partialResults.push(result);
|
146
|
+
* } catch (e) {
|
147
|
+
* errors.push([file, e]);
|
148
|
+
* }
|
149
|
+
* }));
|
150
|
+
* if (errors.length > 0) {
|
151
|
+
* throw new AggregateCreateNodesError(errors, partialResults);
|
152
|
+
* }
|
153
|
+
* return partialResults;
|
154
|
+
* }
|
155
|
+
*
|
156
|
+
* @param errors An array of tuples that represent errors encountered when processing a given file. An example entry might look like ['path/to/project.json', [Error: 'Invalid JSON. Unexpected token 'a' in JSON at position 0]]
|
157
|
+
* @param partialResults The partial results of the `createNodesV2` function. This should be the results for each file that didn't encounter an issue.
|
158
|
+
*/
|
159
|
+
constructor(errors, partialResults) {
|
142
160
|
super('Failed to create nodes');
|
143
|
-
this.pluginName = pluginName;
|
144
161
|
this.errors = errors;
|
145
162
|
this.partialResults = partialResults;
|
146
163
|
this.name = this.constructor.name;
|
@@ -230,11 +247,6 @@ function isCreateMetadataError(e) {
|
|
230
247
|
e?.name === CreateMetadataError.name));
|
231
248
|
}
|
232
249
|
exports.isCreateMetadataError = isCreateMetadataError;
|
233
|
-
function isCreateNodesError(e) {
|
234
|
-
return (e instanceof CreateNodesError ||
|
235
|
-
(typeof e === 'object' && 'name' in e && e?.name === CreateNodesError.name));
|
236
|
-
}
|
237
|
-
exports.isCreateNodesError = isCreateNodesError;
|
238
250
|
function isAggregateCreateNodesError(e) {
|
239
251
|
return (e instanceof AggregateCreateNodesError ||
|
240
252
|
(typeof e === 'object' &&
|
@@ -1,8 +1,10 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.registerPluginTSTranspiler = exports.readPluginPackageJson = void 0;
|
3
|
+
exports.createNodesFromFiles = exports.registerPluginTSTranspiler = exports.readPluginPackageJson = void 0;
|
4
4
|
const tslib_1 = require("tslib");
|
5
5
|
tslib_1.__exportStar(require("./public-api"), exports);
|
6
6
|
var loader_1 = require("./loader");
|
7
7
|
Object.defineProperty(exports, "readPluginPackageJson", { enumerable: true, get: function () { return loader_1.readPluginPackageJson; } });
|
8
8
|
Object.defineProperty(exports, "registerPluginTSTranspiler", { enumerable: true, get: function () { return loader_1.registerPluginTSTranspiler; } });
|
9
|
+
var utils_1 = require("./utils");
|
10
|
+
Object.defineProperty(exports, "createNodesFromFiles", { enumerable: true, get: function () { return utils_1.createNodesFromFiles; } });
|
@@ -1,12 +1,12 @@
|
|
1
1
|
import { PluginConfiguration } from '../../config/nx-json';
|
2
2
|
import { NxPluginV1 } from '../../utils/nx-plugin.deprecated';
|
3
|
-
import { CreateDependencies, CreateDependenciesContext, CreateMetadata, CreateMetadataContext,
|
3
|
+
import { CreateDependencies, CreateDependenciesContext, CreateMetadata, CreateMetadataContext, CreateNodesContextV2, CreateNodesResult, NxPluginV2 } from './public-api';
|
4
4
|
import { ProjectGraph, ProjectGraphProcessor } from '../../config/project-graph';
|
5
5
|
export declare class LoadedNxPlugin {
|
6
6
|
readonly name: string;
|
7
7
|
readonly createNodes?: [
|
8
8
|
filePattern: string,
|
9
|
-
fn: (matchedFiles: string[], context:
|
9
|
+
fn: (matchedFiles: string[], context: CreateNodesContextV2) => Promise<Array<readonly [plugin: string, file: string, result: CreateNodesResult]>>
|
10
10
|
];
|
11
11
|
readonly createDependencies?: (context: CreateDependenciesContext) => ReturnType<CreateDependencies>;
|
12
12
|
readonly createMetadata?: (graph: ProjectGraph, context: CreateMetadataContext) => ReturnType<CreateMetadata>;
|
@@ -6,9 +6,10 @@ exports.getDefaultPlugins = exports.loadNxPlugins = exports.nxPluginCache = expo
|
|
6
6
|
const path_1 = require("path");
|
7
7
|
const workspace_root_1 = require("../../utils/workspace-root");
|
8
8
|
const angular_json_1 = require("../../adapter/angular-json");
|
9
|
-
const utils_1 = require("./utils");
|
10
9
|
const isolation_1 = require("./isolation");
|
11
10
|
const loader_1 = require("./loader");
|
11
|
+
const utils_1 = require("./utils");
|
12
|
+
const error_types_1 = require("../error-types");
|
12
13
|
class LoadedNxPlugin {
|
13
14
|
constructor(plugin, pluginDefinition) {
|
14
15
|
this.name = plugin.name;
|
@@ -17,12 +18,41 @@ class LoadedNxPlugin {
|
|
17
18
|
this.include = pluginDefinition.include;
|
18
19
|
this.exclude = pluginDefinition.exclude;
|
19
20
|
}
|
20
|
-
if (plugin.createNodes) {
|
21
|
+
if (plugin.createNodes && !plugin.createNodesV2) {
|
21
22
|
this.createNodes = [
|
22
23
|
plugin.createNodes[0],
|
23
|
-
(
|
24
|
+
(configFiles, context) => (0, utils_1.createNodesFromFiles)(plugin.createNodes[1], configFiles, this.options, context).then((results) => results.map((r) => [this.name, r[0], r[1]])),
|
25
|
+
];
|
26
|
+
}
|
27
|
+
if (plugin.createNodesV2) {
|
28
|
+
this.createNodes = [
|
29
|
+
plugin.createNodesV2[0],
|
30
|
+
async (configFiles, context) => {
|
31
|
+
const result = await plugin.createNodesV2[1](configFiles, this.options, context);
|
32
|
+
return result.map((r) => [this.name, r[0], r[1]]);
|
33
|
+
},
|
24
34
|
];
|
25
35
|
}
|
36
|
+
if (this.createNodes) {
|
37
|
+
const inner = this.createNodes[1];
|
38
|
+
this.createNodes[1] = async (...args) => {
|
39
|
+
performance.mark(`${plugin.name}:createNodes - start`);
|
40
|
+
try {
|
41
|
+
return await inner(...args);
|
42
|
+
}
|
43
|
+
catch (e) {
|
44
|
+
if ((0, error_types_1.isAggregateCreateNodesError)(e)) {
|
45
|
+
throw e;
|
46
|
+
}
|
47
|
+
// The underlying plugin errored out. We can't know any partial results.
|
48
|
+
throw new error_types_1.AggregateCreateNodesError([null, e], []);
|
49
|
+
}
|
50
|
+
finally {
|
51
|
+
performance.mark(`${plugin.name}:createNodes - end`);
|
52
|
+
performance.measure(`${plugin.name}:createNodes`, `${plugin.name}:createNodes - start`, `${plugin.name}:createNodes - end`);
|
53
|
+
}
|
54
|
+
};
|
55
|
+
}
|
26
56
|
if (plugin.createDependencies) {
|
27
57
|
this.createDependencies = (context) => plugin.createDependencies(this.options, context);
|
28
58
|
}
|
@@ -6,19 +6,23 @@ import { RawProjectGraphDependency } from '../project-graph-builder';
|
|
6
6
|
/**
|
7
7
|
* Context for {@link CreateNodesFunction}
|
8
8
|
*/
|
9
|
-
export interface CreateNodesContext {
|
10
|
-
readonly nxJsonConfiguration: NxJsonConfiguration;
|
11
|
-
readonly workspaceRoot: string;
|
9
|
+
export interface CreateNodesContext extends CreateNodesContextV2 {
|
12
10
|
/**
|
13
11
|
* The subset of configuration files which match the createNodes pattern
|
14
12
|
*/
|
15
13
|
readonly configFiles: readonly string[];
|
16
14
|
}
|
15
|
+
export interface CreateNodesContextV2 {
|
16
|
+
readonly nxJsonConfiguration: NxJsonConfiguration;
|
17
|
+
readonly workspaceRoot: string;
|
18
|
+
}
|
17
19
|
/**
|
18
20
|
* A function which parses a configuration file into a set of nodes.
|
19
21
|
* Used for creating nodes for the {@link ProjectGraph}
|
20
22
|
*/
|
21
23
|
export type CreateNodesFunction<T = unknown> = (projectConfigurationFile: string, options: T | undefined, context: CreateNodesContext) => CreateNodesResult | Promise<CreateNodesResult>;
|
24
|
+
export type CreateNodesResultV2 = Array<readonly [configFileSource: string, result: CreateNodesResult]>;
|
25
|
+
export type CreateNodesFunctionV2<T = unknown> = (projectConfigurationFiles: readonly string[], options: T | undefined, context: CreateNodesContextV2) => CreateNodesResultV2 | Promise<CreateNodesResultV2>;
|
22
26
|
export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
23
27
|
export interface CreateNodesResult {
|
24
28
|
/**
|
@@ -32,11 +36,29 @@ export interface CreateNodesResult {
|
|
32
36
|
}
|
33
37
|
/**
|
34
38
|
* A pair of file patterns and {@link CreateNodesFunction}
|
39
|
+
*
|
40
|
+
* Nx 19.2+: Both original `CreateNodes` and `CreateNodesV2` are supported. Nx will only invoke `CreateNodesV2` if it is present.
|
41
|
+
* Nx 20.X : The `CreateNodesV2` will be the only supported API. This typing will still exist, but be identical to `CreateNodesV2`.
|
42
|
+
Nx **will not** invoke the original `plugin.createNodes` callback. This should give plugin authors a window to transition.
|
43
|
+
Plugin authors should update their plugin's `createNodes` function to align with `CreateNodesV2` / the updated `CreateNodes`.
|
44
|
+
The plugin should contain something like: `export createNodes = createNodesV2;` during this period. This will allow the plugin
|
45
|
+
to maintain compatibility with Nx 19.2 and up.
|
46
|
+
* Nx 21.X : The `CreateNodesV2` typing will be removed, as it has replaced `CreateNodes`.
|
47
|
+
*
|
48
|
+
* @deprecated Use {@link CreateNodesV2} instead. CreateNodesV2 will replace this API. Read more about the transition above.
|
35
49
|
*/
|
36
50
|
export type CreateNodes<T = unknown> = readonly [
|
37
51
|
projectFilePattern: string,
|
38
52
|
createNodesFunction: CreateNodesFunction<T>
|
39
53
|
];
|
54
|
+
/**
|
55
|
+
* A pair of file patterns and {@link CreateNodesFunctionV2}
|
56
|
+
* In Nx 20 {@link CreateNodes} will be replaced with this type. In Nx 21, this type will be removed.
|
57
|
+
*/
|
58
|
+
export type CreateNodesV2<T = unknown> = readonly [
|
59
|
+
projectFilePattern: string,
|
60
|
+
createNodesFunction: CreateNodesFunctionV2<T>
|
61
|
+
];
|
40
62
|
/**
|
41
63
|
* Context for {@link CreateDependencies}
|
42
64
|
*/
|
@@ -82,8 +104,17 @@ export type NxPluginV2<TOptions = unknown> = {
|
|
82
104
|
/**
|
83
105
|
* Provides a file pattern and function that retrieves configuration info from
|
84
106
|
* those files. e.g. { '**\/*.csproj': buildProjectsFromCsProjFile }
|
107
|
+
*
|
108
|
+
* @deprecated Use {@link createNodesV2} instead. In Nx 20 support for calling createNodes with a single file for the first argument will be removed.
|
85
109
|
*/
|
86
110
|
createNodes?: CreateNodes<TOptions>;
|
111
|
+
/**
|
112
|
+
* Provides a file pattern and function that retrieves configuration info from
|
113
|
+
* those files. e.g. { '**\/*.csproj': buildProjectsFromCsProjFiles }
|
114
|
+
*
|
115
|
+
* In Nx 20 {@link createNodes} will be replaced with this property. In Nx 21, this property will be removed.
|
116
|
+
*/
|
117
|
+
createNodesV2?: CreateNodesV2<TOptions>;
|
87
118
|
/**
|
88
119
|
* Provides a function to analyze files to create dependencies for the {@link ProjectGraph}
|
89
120
|
*/
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import type { NxPluginV1 } from '../../utils/nx-plugin.deprecated';
|
2
|
-
import type {
|
3
|
-
import {
|
2
|
+
import type { LoadedNxPlugin, NormalizedPlugin } from './internal-api';
|
3
|
+
import { CreateNodesContextV2, CreateNodesFunction, CreateNodesResult, type NxPlugin, type NxPluginV2 } from './public-api';
|
4
4
|
export declare function isNxPluginV2(plugin: NxPlugin): plugin is NxPluginV2;
|
5
5
|
export declare function isNxPluginV1(plugin: NxPlugin | LoadedNxPlugin): plugin is NxPluginV1;
|
6
6
|
export declare function normalizeNxPlugin(plugin: NxPlugin): NormalizedPlugin;
|
7
|
-
export
|
7
|
+
export type AsyncFn<T extends Function> = T extends (...args: infer A) => infer R ? (...args: A) => Promise<Awaited<R>> : never;
|
8
|
+
export declare function createNodesFromFiles<T = unknown>(createNodes: CreateNodesFunction, configFiles: readonly string[], options: T, context: CreateNodesContextV2): Promise<[file: string, value: CreateNodesResult][]>;
|
@@ -1,11 +1,10 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.createNodesFromFiles = exports.normalizeNxPlugin = exports.isNxPluginV1 = exports.isNxPluginV2 = void 0;
|
4
4
|
const node_path_1 = require("node:path");
|
5
5
|
const to_project_name_1 = require("../../config/to-project-name");
|
6
6
|
const globs_1 = require("../../utils/globs");
|
7
7
|
const error_types_1 = require("../error-types");
|
8
|
-
const perf_hooks_1 = require("perf_hooks");
|
9
8
|
function isNxPluginV2(plugin) {
|
10
9
|
return 'createNodes' in plugin || 'createDependencies' in plugin;
|
11
10
|
}
|
@@ -40,36 +39,24 @@ function normalizeNxPlugin(plugin) {
|
|
40
39
|
return plugin;
|
41
40
|
}
|
42
41
|
exports.normalizeNxPlugin = normalizeNxPlugin;
|
43
|
-
async function
|
44
|
-
perf_hooks_1.performance.mark(`${plugin.name}:createNodes - start`);
|
45
|
-
const errors = [];
|
42
|
+
async function createNodesFromFiles(createNodes, configFiles, options, context) {
|
46
43
|
const results = [];
|
47
|
-
const
|
44
|
+
const errors = [];
|
45
|
+
await Promise.all(configFiles.map(async (file) => {
|
48
46
|
try {
|
49
|
-
const value = await
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
pluginName: plugin.name,
|
55
|
-
});
|
56
|
-
}
|
47
|
+
const value = await createNodes(file, options, {
|
48
|
+
...context,
|
49
|
+
configFiles,
|
50
|
+
});
|
51
|
+
results.push([file, value]);
|
57
52
|
}
|
58
53
|
catch (e) {
|
59
|
-
errors.push(
|
60
|
-
error: e,
|
61
|
-
pluginName: plugin.name,
|
62
|
-
file,
|
63
|
-
}));
|
54
|
+
errors.push([file, e]);
|
64
55
|
}
|
65
|
-
});
|
66
|
-
await Promise.all(promises).then(() => {
|
67
|
-
perf_hooks_1.performance.mark(`${plugin.name}:createNodes - end`);
|
68
|
-
perf_hooks_1.performance.measure(`${plugin.name}:createNodes`, `${plugin.name}:createNodes - start`, `${plugin.name}:createNodes - end`);
|
69
|
-
});
|
56
|
+
}));
|
70
57
|
if (errors.length > 0) {
|
71
|
-
throw new error_types_1.AggregateCreateNodesError(
|
58
|
+
throw new error_types_1.AggregateCreateNodesError(errors, results);
|
72
59
|
}
|
73
60
|
return results;
|
74
61
|
}
|
75
|
-
exports.
|
62
|
+
exports.createNodesFromFiles = createNodesFromFiles;
|
@@ -227,92 +227,35 @@ plugins) {
|
|
227
227
|
const results = [];
|
228
228
|
const errors = [];
|
229
229
|
// We iterate over plugins first - this ensures that plugins specified first take precedence.
|
230
|
-
for (const {
|
230
|
+
for (const { createNodes: createNodesTuple, include, exclude, name: pluginName, } of plugins) {
|
231
231
|
const [pattern, createNodes] = createNodesTuple ?? [];
|
232
232
|
if (!pattern) {
|
233
233
|
continue;
|
234
234
|
}
|
235
|
-
const matchingConfigFiles =
|
236
|
-
for (const file of projectFiles) {
|
237
|
-
if ((0, minimatch_1.minimatch)(file, pattern, { dot: true })) {
|
238
|
-
if (include) {
|
239
|
-
const included = include.some((includedPattern) => (0, minimatch_1.minimatch)(file, includedPattern, { dot: true }));
|
240
|
-
if (!included) {
|
241
|
-
continue;
|
242
|
-
}
|
243
|
-
}
|
244
|
-
if (exclude) {
|
245
|
-
const excluded = exclude.some((excludedPattern) => (0, minimatch_1.minimatch)(file, excludedPattern, { dot: true }));
|
246
|
-
if (excluded) {
|
247
|
-
continue;
|
248
|
-
}
|
249
|
-
}
|
250
|
-
matchingConfigFiles.push(file);
|
251
|
-
}
|
252
|
-
}
|
235
|
+
const matchingConfigFiles = findMatchingConfigFiles(projectFiles, pattern, include, exclude);
|
253
236
|
let r = createNodes(matchingConfigFiles, {
|
254
237
|
nxJsonConfiguration: nxJson,
|
255
238
|
workspaceRoot: root,
|
256
|
-
configFiles: matchingConfigFiles,
|
257
239
|
}).catch((e) => {
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
240
|
+
const errorBodyLines = [
|
241
|
+
`An error occurred while processing files for the ${pluginName} plugin.`,
|
242
|
+
];
|
243
|
+
const error = (0, error_types_1.isAggregateCreateNodesError)(e)
|
244
|
+
? // This is an expected error if something goes wrong while processing files.
|
245
|
+
e
|
246
|
+
: // This represents a single plugin erroring out with a hard error.
|
247
|
+
new error_types_1.AggregateCreateNodesError([[null, e]], []);
|
248
|
+
errorBodyLines.push(...error.errors.map(([file, e]) => ` - ${file}: ${e.message}`));
|
249
|
+
error.message = errorBodyLines.join('\n');
|
250
|
+
// This represents a single plugin erroring out with a hard error.
|
251
|
+
errors.push(error);
|
252
|
+
// The plugin didn't return partial results, so we return an empty array.
|
253
|
+
return error.partialResults.map((r) => [pluginName, r[0], r[1]]);
|
265
254
|
});
|
266
255
|
results.push(r);
|
267
256
|
}
|
268
257
|
return Promise.all(results).then((results) => {
|
269
|
-
|
270
|
-
const projectRootMap = {};
|
271
|
-
const externalNodes = {};
|
272
|
-
const configurationSourceMaps = {};
|
273
|
-
for (const result of results.flat()) {
|
274
|
-
const { projects: projectNodes, externalNodes: pluginExternalNodes, file, pluginName, } = result;
|
275
|
-
const sourceInfo = [file, pluginName];
|
276
|
-
if (result[symbols_1.OVERRIDE_SOURCE_FILE]) {
|
277
|
-
sourceInfo[0] = result[symbols_1.OVERRIDE_SOURCE_FILE];
|
278
|
-
}
|
279
|
-
for (const node in projectNodes) {
|
280
|
-
// Handles `{projects: {'libs/foo': undefined}}`.
|
281
|
-
if (!projectNodes[node]) {
|
282
|
-
continue;
|
283
|
-
}
|
284
|
-
const project = {
|
285
|
-
root: node,
|
286
|
-
...projectNodes[node],
|
287
|
-
};
|
288
|
-
try {
|
289
|
-
mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, sourceInfo);
|
290
|
-
}
|
291
|
-
catch (error) {
|
292
|
-
errors.push(new error_types_1.MergeNodesError({
|
293
|
-
file,
|
294
|
-
pluginName,
|
295
|
-
error,
|
296
|
-
}));
|
297
|
-
}
|
298
|
-
}
|
299
|
-
Object.assign(externalNodes, pluginExternalNodes);
|
300
|
-
}
|
301
|
-
try {
|
302
|
-
validateAndNormalizeProjectRootMap(projectRootMap);
|
303
|
-
}
|
304
|
-
catch (e) {
|
305
|
-
if ((0, error_types_1.isProjectsWithNoNameError)(e) ||
|
306
|
-
(0, error_types_1.isMultipleProjectsWithSameNameError)(e)) {
|
307
|
-
errors.push(e);
|
308
|
-
}
|
309
|
-
else {
|
310
|
-
throw e;
|
311
|
-
}
|
312
|
-
}
|
313
|
-
const rootMap = createRootMap(projectRootMap);
|
314
|
-
perf_hooks_1.performance.mark('createNodes:merge - end');
|
315
|
-
perf_hooks_1.performance.measure('createNodes:merge', 'createNodes:merge - start', 'createNodes:merge - end');
|
258
|
+
const { projectRootMap, externalNodes, rootMap, configurationSourceMaps } = mergeCreateNodesResults(results, errors);
|
316
259
|
perf_hooks_1.performance.mark('build-project-configs:end');
|
317
260
|
perf_hooks_1.performance.measure('build-project-configs', 'build-project-configs:start', 'build-project-configs:end');
|
318
261
|
if (errors.length === 0) {
|
@@ -336,6 +279,78 @@ plugins) {
|
|
336
279
|
});
|
337
280
|
}
|
338
281
|
exports.createProjectConfigurations = createProjectConfigurations;
|
282
|
+
function mergeCreateNodesResults(results, errors) {
|
283
|
+
perf_hooks_1.performance.mark('createNodes:merge - start');
|
284
|
+
const projectRootMap = {};
|
285
|
+
const externalNodes = {};
|
286
|
+
const configurationSourceMaps = {};
|
287
|
+
for (const result of results.flat()) {
|
288
|
+
const [file, pluginName, nodes] = result;
|
289
|
+
const { projects: projectNodes, externalNodes: pluginExternalNodes } = nodes;
|
290
|
+
const sourceInfo = [file, pluginName];
|
291
|
+
if (result[symbols_1.OVERRIDE_SOURCE_FILE]) {
|
292
|
+
sourceInfo[0] = result[symbols_1.OVERRIDE_SOURCE_FILE];
|
293
|
+
}
|
294
|
+
for (const node in projectNodes) {
|
295
|
+
// Handles `{projects: {'libs/foo': undefined}}`.
|
296
|
+
if (!projectNodes[node]) {
|
297
|
+
continue;
|
298
|
+
}
|
299
|
+
const project = {
|
300
|
+
root: node,
|
301
|
+
...projectNodes[node],
|
302
|
+
};
|
303
|
+
try {
|
304
|
+
mergeProjectConfigurationIntoRootMap(projectRootMap, project, configurationSourceMaps, sourceInfo);
|
305
|
+
}
|
306
|
+
catch (error) {
|
307
|
+
errors.push(new error_types_1.MergeNodesError({
|
308
|
+
file,
|
309
|
+
pluginName,
|
310
|
+
error,
|
311
|
+
}));
|
312
|
+
}
|
313
|
+
}
|
314
|
+
Object.assign(externalNodes, pluginExternalNodes);
|
315
|
+
}
|
316
|
+
try {
|
317
|
+
validateAndNormalizeProjectRootMap(projectRootMap);
|
318
|
+
}
|
319
|
+
catch (e) {
|
320
|
+
if ((0, error_types_1.isProjectsWithNoNameError)(e) ||
|
321
|
+
(0, error_types_1.isMultipleProjectsWithSameNameError)(e)) {
|
322
|
+
errors.push(e);
|
323
|
+
}
|
324
|
+
else {
|
325
|
+
throw e;
|
326
|
+
}
|
327
|
+
}
|
328
|
+
const rootMap = createRootMap(projectRootMap);
|
329
|
+
perf_hooks_1.performance.mark('createNodes:merge - end');
|
330
|
+
perf_hooks_1.performance.measure('createNodes:merge', 'createNodes:merge - start', 'createNodes:merge - end');
|
331
|
+
return { projectRootMap, externalNodes, rootMap, configurationSourceMaps };
|
332
|
+
}
|
333
|
+
function findMatchingConfigFiles(projectFiles, pattern, include, exclude) {
|
334
|
+
const matchingConfigFiles = [];
|
335
|
+
for (const file of projectFiles) {
|
336
|
+
if ((0, minimatch_1.minimatch)(file, pattern, { dot: true })) {
|
337
|
+
if (include) {
|
338
|
+
const included = include.some((includedPattern) => (0, minimatch_1.minimatch)(file, includedPattern, { dot: true }));
|
339
|
+
if (!included) {
|
340
|
+
continue;
|
341
|
+
}
|
342
|
+
}
|
343
|
+
if (exclude) {
|
344
|
+
const excluded = exclude.some((excludedPattern) => (0, minimatch_1.minimatch)(file, excludedPattern, { dot: true }));
|
345
|
+
if (excluded) {
|
346
|
+
continue;
|
347
|
+
}
|
348
|
+
}
|
349
|
+
matchingConfigFiles.push(file);
|
350
|
+
}
|
351
|
+
}
|
352
|
+
return matchingConfigFiles;
|
353
|
+
}
|
339
354
|
function readProjectConfigurationsFromRootMap(projectRootMap) {
|
340
355
|
const projects = {};
|
341
356
|
// If there are projects that have the same name, that is an error.
|
@@ -1,10 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* In many cases the package.json will be directly resolvable, so we try that first.
|
3
|
-
* If, however, package exports are used and the package.json is not defined, we will
|
4
|
-
* need to resolve the main entry point of the package and traverse upwards to find the
|
5
|
-
* package.json.
|
6
|
-
*
|
7
|
-
* NOTE: Unit testing this code is currently impractical as it is not possible to mock
|
8
|
-
* require.resolve in jest https://github.com/jestjs/jest/issues/9543
|
9
|
-
*/
|
10
|
-
export declare function findExternalPackageJsonPath(packageName: string, relativeToDir: string): string | null;
|
@@ -1,42 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.findExternalPackageJsonPath = void 0;
|
4
|
-
const node_fs_1 = require("node:fs");
|
5
|
-
const node_path_1 = require("node:path");
|
6
|
-
/**
|
7
|
-
* In many cases the package.json will be directly resolvable, so we try that first.
|
8
|
-
* If, however, package exports are used and the package.json is not defined, we will
|
9
|
-
* need to resolve the main entry point of the package and traverse upwards to find the
|
10
|
-
* package.json.
|
11
|
-
*
|
12
|
-
* NOTE: Unit testing this code is currently impractical as it is not possible to mock
|
13
|
-
* require.resolve in jest https://github.com/jestjs/jest/issues/9543
|
14
|
-
*/
|
15
|
-
function findExternalPackageJsonPath(packageName, relativeToDir) {
|
16
|
-
try {
|
17
|
-
return require.resolve((0, node_path_1.join)(packageName, 'package.json'), {
|
18
|
-
paths: [relativeToDir],
|
19
|
-
});
|
20
|
-
}
|
21
|
-
catch {
|
22
|
-
try {
|
23
|
-
// Resolve the main entry point of the package
|
24
|
-
const mainPath = require.resolve(packageName, {
|
25
|
-
paths: [relativeToDir],
|
26
|
-
});
|
27
|
-
let dir = (0, node_path_1.dirname)(mainPath);
|
28
|
-
while (dir !== (0, node_path_1.parse)(dir).root) {
|
29
|
-
const packageJsonPath = (0, node_path_1.join)(dir, 'package.json');
|
30
|
-
if ((0, node_fs_1.existsSync)(packageJsonPath)) {
|
31
|
-
return packageJsonPath;
|
32
|
-
}
|
33
|
-
dir = (0, node_path_1.dirname)(dir);
|
34
|
-
}
|
35
|
-
throw new Error(`Could not find package.json for ${packageName}`);
|
36
|
-
}
|
37
|
-
catch {
|
38
|
-
return null;
|
39
|
-
}
|
40
|
-
}
|
41
|
-
}
|
42
|
-
exports.findExternalPackageJsonPath = findExternalPackageJsonPath;
|