nx 19.2.0-beta.0 → 19.2.0-beta.2
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-internals.d.ts +1 -0
- package/src/devkit-internals.js +3 -1
- package/src/plugins/js/lock-file/pnpm-parser.js +1 -1
- package/src/plugins/js/project-graph/build-dependencies/build-dependencies.js +16 -3
- package/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.d.ts +2 -1
- package/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.js +40 -27
- package/src/plugins/js/project-graph/build-dependencies/explicit-project-dependencies.d.ts +2 -1
- package/src/plugins/js/project-graph/build-dependencies/explicit-project-dependencies.js +14 -19
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +22 -6
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +98 -47
- package/src/plugins/js/utils/find-external-package-json-path.d.ts +10 -0
- package/src/plugins/js/utils/find-external-package-json-path.js +42 -0
- package/src/tasks-runner/utils.js +18 -4
- package/src/utils/print-help.js +1 -1
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.2",
|
|
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.2"
|
|
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.2",
|
|
88
|
+
"@nx/nx-darwin-arm64": "19.2.0-beta.2",
|
|
89
|
+
"@nx/nx-linux-x64-gnu": "19.2.0-beta.2",
|
|
90
|
+
"@nx/nx-linux-x64-musl": "19.2.0-beta.2",
|
|
91
|
+
"@nx/nx-win32-x64-msvc": "19.2.0-beta.2",
|
|
92
|
+
"@nx/nx-linux-arm64-gnu": "19.2.0-beta.2",
|
|
93
|
+
"@nx/nx-linux-arm64-musl": "19.2.0-beta.2",
|
|
94
|
+
"@nx/nx-linux-arm-gnueabihf": "19.2.0-beta.2",
|
|
95
|
+
"@nx/nx-win32-arm64-msvc": "19.2.0-beta.2",
|
|
96
|
+
"@nx/nx-freebsd-x64": "19.2.0-beta.2"
|
|
97
97
|
},
|
|
98
98
|
"nx-migrations": {
|
|
99
99
|
"migrations": "./migrations.json",
|
|
@@ -23,3 +23,4 @@ export { retrieveProjectConfigurations } from './project-graph/utils/retrieve-wo
|
|
|
23
23
|
export { LoadedNxPlugin } from './project-graph/plugins/internal-api';
|
|
24
24
|
export * from './project-graph/error-types';
|
|
25
25
|
export { registerTsProject } from './plugins/js/utils/register';
|
|
26
|
+
export { interpolate } from './tasks-runner/utils';
|
package/src/devkit-internals.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerTsProject = exports.LoadedNxPlugin = exports.retrieveProjectConfigurations = exports.findProjectForPath = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.splitTarget = exports.readProjectConfigurationsFromRootMap = exports.mergeTargetConfigurations = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.getExecutorInformation = exports.createTempNpmDirectory = void 0;
|
|
3
|
+
exports.interpolate = exports.registerTsProject = exports.LoadedNxPlugin = exports.retrieveProjectConfigurations = exports.findProjectForPath = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.splitTarget = exports.readProjectConfigurationsFromRootMap = exports.mergeTargetConfigurations = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.getExecutorInformation = exports.createTempNpmDirectory = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
/**
|
|
6
6
|
* Note to developers: STOP! These exports are available via requireNx in @nx/devkit.
|
|
@@ -47,3 +47,5 @@ Object.defineProperty(exports, "LoadedNxPlugin", { enumerable: true, get: functi
|
|
|
47
47
|
tslib_1.__exportStar(require("./project-graph/error-types"), exports);
|
|
48
48
|
var register_1 = require("./plugins/js/utils/register");
|
|
49
49
|
Object.defineProperty(exports, "registerTsProject", { enumerable: true, get: function () { return register_1.registerTsProject; } });
|
|
50
|
+
var utils_1 = require("./tasks-runner/utils");
|
|
51
|
+
Object.defineProperty(exports, "interpolate", { enumerable: true, get: function () { return utils_1.interpolate; } });
|
|
@@ -233,7 +233,7 @@ function getNodes(data, keyMap, isV5) {
|
|
|
233
233
|
function getHoistedVersion(hoistedDependencies, packageName, isV5) {
|
|
234
234
|
let version = (0, package_json_1.getHoistedPackageVersion)(packageName);
|
|
235
235
|
if (!version) {
|
|
236
|
-
const key = Object.keys(hoistedDependencies).find((k) => k.startsWith(
|
|
236
|
+
const key = Object.keys(hoistedDependencies).find((k) => k.startsWith(`/${packageName}/`));
|
|
237
237
|
if (key) {
|
|
238
238
|
version = parseBaseVersion(getVersion(key.slice(1), packageName), isV5);
|
|
239
239
|
}
|
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildExplicitDependencies = void 0;
|
|
4
|
-
const explicit_project_dependencies_1 = require("./explicit-project-dependencies");
|
|
5
4
|
const explicit_package_json_dependencies_1 = require("./explicit-package-json-dependencies");
|
|
5
|
+
const explicit_project_dependencies_1 = require("./explicit-project-dependencies");
|
|
6
|
+
const target_project_locator_1 = require("./target-project-locator");
|
|
6
7
|
function buildExplicitDependencies(jsPluginConfig, ctx) {
|
|
7
8
|
if (totalNumberOfFilesToProcess(ctx) === 0)
|
|
8
9
|
return [];
|
|
9
10
|
let dependencies = [];
|
|
11
|
+
// TODO: TargetProjectLocator is a public API, so we can't change the shape of it
|
|
12
|
+
// We should eventually let it accept Record<string, ProjectConfiguration> s.t. we
|
|
13
|
+
// don't have to reshape the CreateDependenciesContext here.
|
|
14
|
+
const nodes = Object.fromEntries(Object.entries(ctx.projects).map(([key, config]) => [
|
|
15
|
+
key,
|
|
16
|
+
{
|
|
17
|
+
name: key,
|
|
18
|
+
type: null,
|
|
19
|
+
data: config,
|
|
20
|
+
},
|
|
21
|
+
]));
|
|
22
|
+
const targetProjectLocator = new target_project_locator_1.TargetProjectLocator(nodes, ctx.externalNodes);
|
|
10
23
|
if (jsPluginConfig.analyzeSourceFiles === undefined ||
|
|
11
24
|
jsPluginConfig.analyzeSourceFiles === true) {
|
|
12
25
|
let tsExists = false;
|
|
@@ -16,12 +29,12 @@ function buildExplicitDependencies(jsPluginConfig, ctx) {
|
|
|
16
29
|
}
|
|
17
30
|
catch { }
|
|
18
31
|
if (tsExists) {
|
|
19
|
-
dependencies = dependencies.concat((0, explicit_project_dependencies_1.buildExplicitTypeScriptDependencies)(ctx));
|
|
32
|
+
dependencies = dependencies.concat((0, explicit_project_dependencies_1.buildExplicitTypeScriptDependencies)(ctx, targetProjectLocator));
|
|
20
33
|
}
|
|
21
34
|
}
|
|
22
35
|
if (jsPluginConfig.analyzePackageJson === undefined ||
|
|
23
36
|
jsPluginConfig.analyzePackageJson === true) {
|
|
24
|
-
dependencies = dependencies.concat((0, explicit_package_json_dependencies_1.buildExplicitPackageJsonDependencies)(ctx));
|
|
37
|
+
dependencies = dependencies.concat((0, explicit_package_json_dependencies_1.buildExplicitPackageJsonDependencies)(ctx, targetProjectLocator));
|
|
25
38
|
}
|
|
26
39
|
return dependencies;
|
|
27
40
|
}
|
package/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { CreateDependenciesContext } from '../../../../project-graph/plugins';
|
|
2
2
|
import { RawProjectGraphDependency } from '../../../../project-graph/project-graph-builder';
|
|
3
|
-
|
|
3
|
+
import { TargetProjectLocator } from './target-project-locator';
|
|
4
|
+
export declare function buildExplicitPackageJsonDependencies(ctx: CreateDependenciesContext, targetProjectLocator: TargetProjectLocator): RawProjectGraphDependency[];
|
package/src/plugins/js/project-graph/build-dependencies/explicit-package-json-dependencies.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildExplicitPackageJsonDependencies = void 0;
|
|
4
|
-
const
|
|
5
|
-
const path_1 = require("path");
|
|
4
|
+
const node_path_1 = require("node:path");
|
|
6
5
|
const project_graph_1 = require("../../../../config/project-graph");
|
|
7
|
-
const
|
|
8
|
-
const path_2 = require("../../../../utils/path");
|
|
6
|
+
const file_utils_1 = require("../../../../project-graph/file-utils");
|
|
9
7
|
const project_graph_builder_1 = require("../../../../project-graph/project-graph-builder");
|
|
10
|
-
|
|
8
|
+
const json_1 = require("../../../../utils/json");
|
|
9
|
+
const path_1 = require("../../../../utils/path");
|
|
10
|
+
function buildExplicitPackageJsonDependencies(ctx, targetProjectLocator) {
|
|
11
11
|
const res = [];
|
|
12
12
|
let packageNameMap = undefined;
|
|
13
13
|
const nodes = Object.values(ctx.projects);
|
|
@@ -16,7 +16,7 @@ function buildExplicitPackageJsonDependencies(ctx) {
|
|
|
16
16
|
if (isPackageJsonAtProjectRoot(nodes, f.file)) {
|
|
17
17
|
// we only create the package name map once and only if a package.json file changes
|
|
18
18
|
packageNameMap = packageNameMap || createPackageNameMap(ctx.projects);
|
|
19
|
-
processPackageJson(source, f.file, ctx, res, packageNameMap);
|
|
19
|
+
processPackageJson(source, f.file, ctx, targetProjectLocator, res, packageNameMap);
|
|
20
20
|
}
|
|
21
21
|
});
|
|
22
22
|
});
|
|
@@ -27,7 +27,7 @@ function createPackageNameMap(projects) {
|
|
|
27
27
|
const res = {};
|
|
28
28
|
for (let projectName of Object.keys(projects)) {
|
|
29
29
|
try {
|
|
30
|
-
const packageJson = (0, json_1.parseJson)((0, file_utils_1.defaultFileRead)((0,
|
|
30
|
+
const packageJson = (0, json_1.parseJson)((0, file_utils_1.defaultFileRead)((0, node_path_1.join)(projects[projectName].root, 'package.json')));
|
|
31
31
|
res[packageJson.name ?? projectName] = projectName;
|
|
32
32
|
}
|
|
33
33
|
catch (e) { }
|
|
@@ -36,13 +36,12 @@ function createPackageNameMap(projects) {
|
|
|
36
36
|
}
|
|
37
37
|
function isPackageJsonAtProjectRoot(nodes, fileName) {
|
|
38
38
|
return (fileName.endsWith('package.json') &&
|
|
39
|
-
nodes.find((projectNode) => (0,
|
|
39
|
+
nodes.find((projectNode) => (0, path_1.joinPathFragments)(projectNode.root, 'package.json') === fileName));
|
|
40
40
|
}
|
|
41
|
-
function processPackageJson(sourceProject, fileName, ctx, collectedDeps, packageNameMap) {
|
|
41
|
+
function processPackageJson(sourceProject, fileName, ctx, targetProjectLocator, collectedDeps, packageNameMap) {
|
|
42
42
|
try {
|
|
43
43
|
const deps = readDeps((0, json_1.parseJson)((0, file_utils_1.defaultFileRead)(fileName)));
|
|
44
|
-
|
|
45
|
-
deps.forEach((d) => {
|
|
44
|
+
for (const d of Object.keys(deps)) {
|
|
46
45
|
// package.json refers to another project in the monorepo
|
|
47
46
|
if (packageNameMap[d]) {
|
|
48
47
|
const dependency = {
|
|
@@ -53,30 +52,44 @@ function processPackageJson(sourceProject, fileName, ctx, collectedDeps, package
|
|
|
53
52
|
};
|
|
54
53
|
(0, project_graph_builder_1.validateDependency)(dependency, ctx);
|
|
55
54
|
collectedDeps.push(dependency);
|
|
55
|
+
continue;
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
target: `npm:${d}`,
|
|
61
|
-
sourceFile: fileName,
|
|
62
|
-
type: project_graph_1.DependencyType.static,
|
|
63
|
-
};
|
|
64
|
-
(0, project_graph_builder_1.validateDependency)(dependency, ctx);
|
|
65
|
-
collectedDeps.push(dependency);
|
|
57
|
+
const externalNodeName = targetProjectLocator.findNpmProjectFromImport(d, fileName);
|
|
58
|
+
if (!externalNodeName) {
|
|
59
|
+
continue;
|
|
66
60
|
}
|
|
67
|
-
|
|
61
|
+
const dependency = {
|
|
62
|
+
source: sourceProject,
|
|
63
|
+
target: externalNodeName,
|
|
64
|
+
sourceFile: fileName,
|
|
65
|
+
type: project_graph_1.DependencyType.static,
|
|
66
|
+
};
|
|
67
|
+
(0, project_graph_builder_1.validateDependency)(dependency, ctx);
|
|
68
|
+
collectedDeps.push(dependency);
|
|
69
|
+
}
|
|
68
70
|
}
|
|
69
71
|
catch (e) {
|
|
70
72
|
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
|
71
|
-
console.
|
|
73
|
+
console.error(e);
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
}
|
|
75
77
|
function readDeps(packageJson) {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
const deps = {};
|
|
79
|
+
/**
|
|
80
|
+
* We process dependencies in a rough order of increasing importance such that if a dependency is listed in multiple
|
|
81
|
+
* sections, the version listed under the "most important" one wins, with production dependencies being the most important.
|
|
82
|
+
*/
|
|
83
|
+
const depType = [
|
|
84
|
+
'optionalDependencies',
|
|
85
|
+
'peerDependencies',
|
|
86
|
+
'devDependencies',
|
|
87
|
+
'dependencies',
|
|
81
88
|
];
|
|
89
|
+
for (const type of depType) {
|
|
90
|
+
for (const [depName, depVersion] of Object.entries(packageJson[type] || {})) {
|
|
91
|
+
deps[depName] = depVersion;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return deps;
|
|
82
95
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { CreateDependenciesContext } from '../../../../project-graph/plugins';
|
|
2
2
|
import { RawProjectGraphDependency } from '../../../../project-graph/project-graph-builder';
|
|
3
|
-
|
|
3
|
+
import { TargetProjectLocator } from './target-project-locator';
|
|
4
|
+
export declare function buildExplicitTypeScriptDependencies(ctx: CreateDependenciesContext, targetProjectLocator: TargetProjectLocator): RawProjectGraphDependency[];
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildExplicitTypeScriptDependencies = void 0;
|
|
4
|
-
const target_project_locator_1 = require("./target-project-locator");
|
|
5
|
-
const project_graph_1 = require("../../../../config/project-graph");
|
|
6
4
|
const path_1 = require("path");
|
|
7
|
-
const
|
|
8
|
-
const path_2 = require("../../../../utils/path");
|
|
5
|
+
const project_graph_1 = require("../../../../config/project-graph");
|
|
9
6
|
const project_graph_builder_1 = require("../../../../project-graph/project-graph-builder");
|
|
7
|
+
const path_2 = require("../../../../utils/path");
|
|
8
|
+
const workspace_root_1 = require("../../../../utils/workspace-root");
|
|
10
9
|
function isRoot(projects, projectName) {
|
|
11
10
|
return projects[projectName]?.root === '.';
|
|
12
11
|
}
|
|
13
12
|
function convertImportToDependency(importExpr, sourceFile, source, type, targetProjectLocator) {
|
|
14
|
-
const target = targetProjectLocator.
|
|
15
|
-
|
|
13
|
+
const target = targetProjectLocator.findProjectFromImport(importExpr, sourceFile);
|
|
14
|
+
if (!target) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
16
17
|
return {
|
|
17
18
|
source,
|
|
18
19
|
target,
|
|
@@ -20,19 +21,7 @@ function convertImportToDependency(importExpr, sourceFile, source, type, targetP
|
|
|
20
21
|
type,
|
|
21
22
|
};
|
|
22
23
|
}
|
|
23
|
-
function buildExplicitTypeScriptDependencies(ctx) {
|
|
24
|
-
// TODO: TargetProjectLocator is a public API, so we can't change the shape of it
|
|
25
|
-
// We should eventually let it accept Record<string, ProjectConfiguration> s.t. we
|
|
26
|
-
// don't have to reshape the CreateDependenciesContext here.
|
|
27
|
-
const nodes = Object.fromEntries(Object.entries(ctx.projects).map(([key, config]) => [
|
|
28
|
-
key,
|
|
29
|
-
{
|
|
30
|
-
name: key,
|
|
31
|
-
type: null,
|
|
32
|
-
data: config,
|
|
33
|
-
},
|
|
34
|
-
]));
|
|
35
|
-
const targetProjectLocator = new target_project_locator_1.TargetProjectLocator(nodes, ctx.externalNodes);
|
|
24
|
+
function buildExplicitTypeScriptDependencies(ctx, targetProjectLocator) {
|
|
36
25
|
const res = [];
|
|
37
26
|
const filesToProcess = {};
|
|
38
27
|
const moduleExtensions = [
|
|
@@ -63,6 +52,9 @@ function buildExplicitTypeScriptDependencies(ctx) {
|
|
|
63
52
|
const normalizedFilePath = (0, path_2.normalizePath)((0, path_1.relative)(workspace_root_1.workspaceRoot, file));
|
|
64
53
|
for (const importExpr of staticImportExpressions) {
|
|
65
54
|
const dependency = convertImportToDependency(importExpr, normalizedFilePath, sourceProject, project_graph_1.DependencyType.static, targetProjectLocator);
|
|
55
|
+
if (!dependency) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
66
58
|
// TODO: These edges technically should be allowed but we need to figure out how to separate config files out from root
|
|
67
59
|
if (isRoot(ctx.projects, dependency.source) ||
|
|
68
60
|
!isRoot(ctx.projects, dependency.target)) {
|
|
@@ -71,6 +63,9 @@ function buildExplicitTypeScriptDependencies(ctx) {
|
|
|
71
63
|
}
|
|
72
64
|
for (const importExpr of dynamicImportExpressions) {
|
|
73
65
|
const dependency = convertImportToDependency(importExpr, normalizedFilePath, sourceProject, project_graph_1.DependencyType.dynamic, targetProjectLocator);
|
|
66
|
+
if (!dependency) {
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
74
69
|
// TODO: These edges technically should be allowed but we need to figure out how to separate config files out from root
|
|
75
70
|
if (isRoot(ctx.projects, dependency.source) ||
|
|
76
71
|
!isRoot(ctx.projects, dependency.target)) {
|
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
import { ProjectGraphExternalNode, ProjectGraphProjectNode } from '../../../../config/project-graph';
|
|
2
|
+
/**
|
|
3
|
+
* The key is a combination of the package name and the workspace relative directory
|
|
4
|
+
* containing the file importing it e.g. `lodash__packages/my-lib`, the value is the
|
|
5
|
+
* resolved external node name from the project graph.
|
|
6
|
+
*/
|
|
7
|
+
type NpmResolutionCache = Map<string, string>;
|
|
8
|
+
export declare function isBuiltinModuleImport(importExpr: string): boolean;
|
|
2
9
|
export declare class TargetProjectLocator {
|
|
3
10
|
private readonly nodes;
|
|
4
|
-
|
|
11
|
+
readonly externalNodes: Record<string, ProjectGraphExternalNode>;
|
|
12
|
+
private readonly npmResolutionCache;
|
|
5
13
|
private projectRootMappings;
|
|
6
14
|
private npmProjects;
|
|
7
15
|
private tsConfig;
|
|
8
16
|
private paths;
|
|
9
17
|
private typescriptResolutionCache;
|
|
10
|
-
|
|
11
|
-
constructor(nodes: Record<string, ProjectGraphProjectNode>, externalNodes: Record<string, ProjectGraphExternalNode>);
|
|
18
|
+
constructor(nodes: Record<string, ProjectGraphProjectNode>, externalNodes?: Record<string, ProjectGraphExternalNode>, npmResolutionCache?: NpmResolutionCache);
|
|
12
19
|
/**
|
|
13
|
-
*
|
|
20
|
+
* Resolve any workspace or external project that matches the given import expression,
|
|
21
|
+
* originating from the given filePath.
|
|
14
22
|
*
|
|
15
23
|
* @param importExpr
|
|
16
24
|
* @param filePath
|
|
17
25
|
*/
|
|
18
|
-
|
|
26
|
+
findProjectFromImport(importExpr: string, filePath: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve any external project that matches the given import expression,
|
|
29
|
+
* relative to the given file path.
|
|
30
|
+
*
|
|
31
|
+
* @param importExpr
|
|
32
|
+
* @param projectRoot
|
|
33
|
+
*/
|
|
34
|
+
findNpmProjectFromImport(importExpr: string, fromFilePath: string): string | undefined;
|
|
19
35
|
/**
|
|
20
36
|
* Return file paths matching the import relative to the repo root
|
|
21
37
|
* @param normalizedImportExpr
|
|
@@ -24,9 +40,9 @@ export declare class TargetProjectLocator {
|
|
|
24
40
|
findPaths(normalizedImportExpr: string): string[] | undefined;
|
|
25
41
|
private resolveImportWithTypescript;
|
|
26
42
|
private resolveImportWithRequire;
|
|
27
|
-
private findNpmPackage;
|
|
28
43
|
private findProjectOfResolvedModule;
|
|
29
44
|
private getAbsolutePath;
|
|
30
45
|
private getRootTsConfig;
|
|
31
46
|
private findMatchingProjectFiles;
|
|
32
47
|
}
|
|
48
|
+
export {};
|
|
@@ -1,36 +1,60 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.TargetProjectLocator = void 0;
|
|
4
|
-
const
|
|
3
|
+
exports.TargetProjectLocator = exports.isBuiltinModuleImport = void 0;
|
|
4
|
+
const node_module_1 = require("node:module");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const find_project_for_path_1 = require("../../../../project-graph/utils/find-project-for-path");
|
|
5
7
|
const fileutils_1 = require("../../../../utils/fileutils");
|
|
6
|
-
const path_1 = require("path");
|
|
7
8
|
const workspace_root_1 = require("../../../../utils/workspace-root");
|
|
8
|
-
const
|
|
9
|
-
const
|
|
9
|
+
const find_external_package_json_path_1 = require("../../utils/find-external-package-json-path");
|
|
10
|
+
const typescript_1 = require("../../utils/typescript");
|
|
11
|
+
/**
|
|
12
|
+
* Use a shared cache to avoid repeated npm package resolution work within the TargetProjectLocator.
|
|
13
|
+
*/
|
|
14
|
+
const defaultNpmResolutionCache = new Map();
|
|
10
15
|
const builtInModuleSet = new Set([
|
|
11
|
-
...
|
|
12
|
-
...
|
|
16
|
+
...node_module_1.builtinModules,
|
|
17
|
+
...node_module_1.builtinModules.map((x) => `node:${x}`),
|
|
13
18
|
]);
|
|
19
|
+
function isBuiltinModuleImport(importExpr) {
|
|
20
|
+
const packageName = parsePackageNameFromImportExpression(importExpr);
|
|
21
|
+
return builtInModuleSet.has(packageName);
|
|
22
|
+
}
|
|
23
|
+
exports.isBuiltinModuleImport = isBuiltinModuleImport;
|
|
14
24
|
class TargetProjectLocator {
|
|
15
|
-
constructor(nodes, externalNodes) {
|
|
25
|
+
constructor(nodes, externalNodes = {}, npmResolutionCache = defaultNpmResolutionCache) {
|
|
16
26
|
this.nodes = nodes;
|
|
17
27
|
this.externalNodes = externalNodes;
|
|
28
|
+
this.npmResolutionCache = npmResolutionCache;
|
|
18
29
|
this.projectRootMappings = (0, find_project_for_path_1.createProjectRootMappings)(this.nodes);
|
|
19
|
-
this.npmProjects = filterRootExternalDependencies(this.externalNodes);
|
|
20
30
|
this.tsConfig = this.getRootTsConfig();
|
|
21
31
|
this.paths = this.tsConfig.config?.compilerOptions?.paths;
|
|
22
32
|
this.typescriptResolutionCache = new Map();
|
|
23
|
-
this.
|
|
33
|
+
this.npmProjects = externalNodes;
|
|
34
|
+
/**
|
|
35
|
+
* Only the npm external nodes should be included.
|
|
36
|
+
*
|
|
37
|
+
* Unlike the raw externalNodes, ensure that the version is always set in the key
|
|
38
|
+
* for optimal lookup.
|
|
39
|
+
*/
|
|
40
|
+
this.npmProjects = Object.values(externalNodes).reduce((acc, node) => {
|
|
41
|
+
if (node.type === 'npm') {
|
|
42
|
+
const key = `npm:${node.data.packageName}@${node.data.version}`;
|
|
43
|
+
acc[key] = node;
|
|
44
|
+
}
|
|
45
|
+
return acc;
|
|
46
|
+
}, {});
|
|
24
47
|
}
|
|
25
48
|
/**
|
|
26
|
-
*
|
|
49
|
+
* Resolve any workspace or external project that matches the given import expression,
|
|
50
|
+
* originating from the given filePath.
|
|
27
51
|
*
|
|
28
52
|
* @param importExpr
|
|
29
53
|
* @param filePath
|
|
30
54
|
*/
|
|
31
|
-
|
|
55
|
+
findProjectFromImport(importExpr, filePath) {
|
|
32
56
|
if ((0, fileutils_1.isRelativePath)(importExpr)) {
|
|
33
|
-
const resolvedModule =
|
|
57
|
+
const resolvedModule = node_path_1.posix.join((0, node_path_1.dirname)(filePath), importExpr);
|
|
34
58
|
return this.findProjectOfResolvedModule(resolvedModule);
|
|
35
59
|
}
|
|
36
60
|
// find project using tsconfig paths
|
|
@@ -39,7 +63,7 @@ class TargetProjectLocator {
|
|
|
39
63
|
const [path, paths] = results;
|
|
40
64
|
for (let p of paths) {
|
|
41
65
|
const r = p.endsWith('/*')
|
|
42
|
-
? (0,
|
|
66
|
+
? (0, node_path_1.join)((0, node_path_1.dirname)(p), (0, node_path_1.relative)(path.replace(/\*$/, ''), importExpr))
|
|
43
67
|
: p;
|
|
44
68
|
const maybeResolvedProject = this.findProjectOfResolvedModule(r);
|
|
45
69
|
if (maybeResolvedProject) {
|
|
@@ -47,14 +71,14 @@ class TargetProjectLocator {
|
|
|
47
71
|
}
|
|
48
72
|
}
|
|
49
73
|
}
|
|
50
|
-
if (
|
|
74
|
+
if (isBuiltinModuleImport(importExpr)) {
|
|
51
75
|
this.npmResolutionCache.set(importExpr, null);
|
|
52
76
|
return null;
|
|
53
77
|
}
|
|
54
78
|
// try to find npm package before using expensive typescript resolution
|
|
55
|
-
const
|
|
56
|
-
if (
|
|
57
|
-
return
|
|
79
|
+
const externalProject = this.findNpmProjectFromImport(importExpr, filePath);
|
|
80
|
+
if (externalProject) {
|
|
81
|
+
return externalProject;
|
|
58
82
|
}
|
|
59
83
|
if (this.tsConfig.config) {
|
|
60
84
|
// TODO(meeroslav): this block is probably obsolete
|
|
@@ -74,6 +98,52 @@ class TargetProjectLocator {
|
|
|
74
98
|
this.npmResolutionCache.set(importExpr, null);
|
|
75
99
|
return null;
|
|
76
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Resolve any external project that matches the given import expression,
|
|
103
|
+
* relative to the given file path.
|
|
104
|
+
*
|
|
105
|
+
* @param importExpr
|
|
106
|
+
* @param projectRoot
|
|
107
|
+
*/
|
|
108
|
+
findNpmProjectFromImport(importExpr, fromFilePath) {
|
|
109
|
+
const packageName = parsePackageNameFromImportExpression(importExpr);
|
|
110
|
+
let fullFilePath = fromFilePath;
|
|
111
|
+
let workspaceRelativeFilePath = fromFilePath;
|
|
112
|
+
if (fromFilePath.startsWith(workspace_root_1.workspaceRoot)) {
|
|
113
|
+
workspaceRelativeFilePath = fromFilePath.replace(workspace_root_1.workspaceRoot, '');
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
fullFilePath = (0, node_path_1.join)(workspace_root_1.workspaceRoot, fromFilePath);
|
|
117
|
+
}
|
|
118
|
+
const fullDirPath = (0, node_path_1.dirname)(fullFilePath);
|
|
119
|
+
const workspaceRelativeDirPath = (0, node_path_1.dirname)(workspaceRelativeFilePath);
|
|
120
|
+
const npmImportForProject = `${packageName}__${workspaceRelativeDirPath}`;
|
|
121
|
+
if (this.npmResolutionCache.has(npmImportForProject)) {
|
|
122
|
+
return this.npmResolutionCache.get(npmImportForProject);
|
|
123
|
+
}
|
|
124
|
+
try {
|
|
125
|
+
// 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 externalPackageJsonPath = (0, find_external_package_json_path_1.findExternalPackageJsonPath)(packageName, fullDirPath);
|
|
127
|
+
// 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 (!externalPackageJsonPath) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
const externalPackageJson = (0, fileutils_1.readJsonFile)(externalPackageJsonPath);
|
|
132
|
+
const npmProjectKey = `npm:${externalPackageJson.name}@${externalPackageJson.version}`;
|
|
133
|
+
if (!this.npmProjects[npmProjectKey]) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
const matchingExternalNode = this.npmProjects[npmProjectKey];
|
|
137
|
+
this.npmResolutionCache.set(npmImportForProject, matchingExternalNode.name);
|
|
138
|
+
return matchingExternalNode.name;
|
|
139
|
+
}
|
|
140
|
+
catch (e) {
|
|
141
|
+
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
|
142
|
+
console.error(e);
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
77
147
|
/**
|
|
78
148
|
* Return file paths matching the import relative to the repo root
|
|
79
149
|
* @param normalizedImportExpr
|
|
@@ -113,23 +183,10 @@ class TargetProjectLocator {
|
|
|
113
183
|
return;
|
|
114
184
|
}
|
|
115
185
|
resolveImportWithRequire(normalizedImportExpr, filePath) {
|
|
116
|
-
return
|
|
117
|
-
paths: [(0,
|
|
186
|
+
return node_path_1.posix.relative(workspace_root_1.workspaceRoot, require.resolve(normalizedImportExpr, {
|
|
187
|
+
paths: [(0, node_path_1.dirname)(filePath)],
|
|
118
188
|
}));
|
|
119
189
|
}
|
|
120
|
-
findNpmPackage(npmImport) {
|
|
121
|
-
if (this.npmResolutionCache.has(npmImport)) {
|
|
122
|
-
return this.npmResolutionCache.get(npmImport);
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
const pkg = this.npmProjects.find((pkg) => npmImport === pkg.data.packageName ||
|
|
126
|
-
npmImport.startsWith(`${pkg.data.packageName}/`));
|
|
127
|
-
if (pkg) {
|
|
128
|
-
this.npmResolutionCache.set(npmImport, pkg.name);
|
|
129
|
-
return pkg.name;
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
190
|
findProjectOfResolvedModule(resolvedModule) {
|
|
134
191
|
if (resolvedModule.startsWith('node_modules/') ||
|
|
135
192
|
resolvedModule.includes('/node_modules/')) {
|
|
@@ -142,7 +199,7 @@ class TargetProjectLocator {
|
|
|
142
199
|
return importedProject ? importedProject.name : void 0;
|
|
143
200
|
}
|
|
144
201
|
getAbsolutePath(path) {
|
|
145
|
-
return (0,
|
|
202
|
+
return (0, node_path_1.join)(workspace_root_1.workspaceRoot, path);
|
|
146
203
|
}
|
|
147
204
|
getRootTsConfig() {
|
|
148
205
|
const path = (0, typescript_1.getRootTsConfigFileName)();
|
|
@@ -166,18 +223,12 @@ class TargetProjectLocator {
|
|
|
166
223
|
}
|
|
167
224
|
}
|
|
168
225
|
exports.TargetProjectLocator = TargetProjectLocator;
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
return
|
|
174
|
-
}
|
|
175
|
-
const keys = Object.keys(externalNodes);
|
|
176
|
-
const nodes = [];
|
|
177
|
-
for (let i = 0; i < keys.length; i++) {
|
|
178
|
-
if (keys[i].match(ROOT_VERSION_PACKAGE_NAME_REGEX)) {
|
|
179
|
-
nodes.push(externalNodes[keys[i]]);
|
|
180
|
-
}
|
|
226
|
+
function parsePackageNameFromImportExpression(importExpression) {
|
|
227
|
+
// Check if the package is scoped
|
|
228
|
+
if (importExpression.startsWith('@')) {
|
|
229
|
+
// For scoped packages, the package name is up to the second '/'
|
|
230
|
+
return importExpression.split('/').slice(0, 2).join('/');
|
|
181
231
|
}
|
|
182
|
-
|
|
232
|
+
// For unscoped packages, the package name is up to the first '/'
|
|
233
|
+
return importExpression.split('/')[0];
|
|
183
234
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
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;
|
|
@@ -0,0 +1,42 @@
|
|
|
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;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.unparse = exports.isCacheableTask = exports.shouldStreamOutput = exports.getSerializedArgsForTask = exports.getPrintableCommandArgsForTask = exports.getCliPath = exports.calculateReverseDeps = exports.removeIdsFromGraph = exports.removeTasksFromTaskGraph = exports.getCustomHasher = exports.getExecutorForTask = exports.getExecutorNameForTask = exports.getTargetConfigurationForTask = exports.interpolate = exports.getOutputsForTargetAndConfiguration = exports.transformLegacyOutputs = exports.validateOutputs = exports.getOutputs = exports.expandDependencyConfigSyntaxSugar = exports.getDependencyConfigs = void 0;
|
|
4
4
|
const output_1 = require("../utils/output");
|
|
5
5
|
const path_1 = require("path");
|
|
6
|
+
const posix_1 = require("path/posix");
|
|
6
7
|
const workspace_root_1 = require("../utils/workspace-root");
|
|
7
8
|
const path_2 = require("../utils/path");
|
|
8
9
|
const fileutils_1 = require("../utils/fileutils");
|
|
@@ -166,18 +167,32 @@ function getOutputsForTargetAndConfiguration(taskTargetOrTask, overridesOrNode,
|
|
|
166
167
|
}
|
|
167
168
|
}
|
|
168
169
|
exports.getOutputsForTargetAndConfiguration = getOutputsForTargetAndConfiguration;
|
|
170
|
+
/**
|
|
171
|
+
* Matches portions of a string which need to be interpolated.
|
|
172
|
+
* Matches anything within curly braces, excluding the braces.
|
|
173
|
+
*/
|
|
174
|
+
const replacementRegex = /{([\s\S]+?)}/g;
|
|
169
175
|
function interpolate(template, data) {
|
|
176
|
+
// Path is absolute or doesn't need interpolation
|
|
177
|
+
if (template.startsWith('/') || !replacementRegex.test(template)) {
|
|
178
|
+
return template;
|
|
179
|
+
}
|
|
170
180
|
if (template.includes('{workspaceRoot}', 1)) {
|
|
171
181
|
throw new Error(`Output '${template}' is invalid. {workspaceRoot} can only be used at the beginning of the expression.`);
|
|
172
182
|
}
|
|
173
183
|
if (data.projectRoot == '.' && template.includes('{projectRoot}', 1)) {
|
|
174
184
|
throw new Error(`Output '${template}' is invalid. When {projectRoot} is '.', it can only be used at the beginning of the expression.`);
|
|
175
185
|
}
|
|
176
|
-
|
|
186
|
+
const parts = template.split('/').map((s) => _interpolate(s, data));
|
|
187
|
+
return (0, posix_1.join)(...parts).replace('{workspaceRoot}/', '');
|
|
188
|
+
}
|
|
189
|
+
exports.interpolate = interpolate;
|
|
190
|
+
function _interpolate(template, data) {
|
|
191
|
+
let res = template;
|
|
177
192
|
if (data.projectRoot == '.') {
|
|
178
|
-
res = res.replace('{projectRoot}
|
|
193
|
+
res = res.replace('{projectRoot}', '');
|
|
179
194
|
}
|
|
180
|
-
return res.replace(
|
|
195
|
+
return res.replace(replacementRegex, (match) => {
|
|
181
196
|
let value = data;
|
|
182
197
|
let path = match.slice(1, -1).trim().split('.');
|
|
183
198
|
for (let idx = 0; idx < path.length; idx++) {
|
|
@@ -189,7 +204,6 @@ function interpolate(template, data) {
|
|
|
189
204
|
return value;
|
|
190
205
|
});
|
|
191
206
|
}
|
|
192
|
-
exports.interpolate = interpolate;
|
|
193
207
|
function getTargetConfigurationForTask(task, projectGraph) {
|
|
194
208
|
const project = projectGraph.nodes[task.target.project].data;
|
|
195
209
|
return project.targets[task.target.target];
|
package/src/utils/print-help.js
CHANGED
|
@@ -226,7 +226,7 @@ function generateLinkOutput({ pluginName, name, type, }) {
|
|
|
226
226
|
!pluginName.startsWith(nrwlPackagePrefix)) {
|
|
227
227
|
return '';
|
|
228
228
|
}
|
|
229
|
-
const link = `https://nx.dev/
|
|
229
|
+
const link = `https://nx.dev/nx-api/${pluginName.substring(pluginName.startsWith(nxPackagePrefix)
|
|
230
230
|
? nxPackagePrefix.length
|
|
231
231
|
: nrwlPackagePrefix.length)}/${type}/${name}`;
|
|
232
232
|
return `\n\n${chalk.dim('Find more information and examples at:')} ${chalk.bold(link)}`;
|