@nx/devkit 17.0.2 → 17.0.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/LICENSE +1 -1
- package/README.md +9 -4
- package/nx.js +2 -2
- package/package.json +5 -4
- package/public-api.d.ts +1 -1
- package/src/executors/parse-target-string.js +3 -2
- package/src/executors/read-target-options.js +8 -5
- package/src/generators/add-build-target-defaults.d.ts +2 -0
- package/src/generators/add-build-target-defaults.js +18 -0
- package/src/generators/artifact-name-and-directory-utils.js +16 -5
- package/src/generators/format-files.js +1 -1
- package/src/generators/project-name-and-root-utils.js +156 -85
- package/src/generators/to-js.d.ts +7 -1
- package/src/generators/to-js.js +5 -4
- package/src/utils/calculate-hash-for-create-nodes.d.ts +2 -0
- package/src/utils/calculate-hash-for-create-nodes.js +16 -0
- package/src/utils/config-utils.d.ts +4 -0
- package/src/utils/config-utils.js +75 -0
- package/src/utils/convert-nx-executor.js +3 -3
- package/src/utils/get-named-inputs.d.ts +8 -0
- package/src/utils/get-named-inputs.js +26 -0
- package/src/utils/get-workspace-layout.d.ts +3 -3
- package/src/utils/invoke-nx-generator.js +1 -1
- package/src/utils/log-show-project-command.d.ts +1 -0
- package/src/utils/log-show-project-command.js +14 -0
- package/src/utils/package-json.d.ts +2 -1
- package/src/utils/package-json.js +24 -8
- package/src/utils/replace-project-configuration-with-plugin.d.ts +2 -0
- package/src/utils/replace-project-configuration-with-plugin.js +137 -0
- package/src/utils/update-package-scripts.d.ts +2 -0
- package/src/utils/update-package-scripts.js +183 -0
- package/src/utils/versions.d.ts +1 -1
- package/src/utils/versions.js +1 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
<p style="text-align: center;"
|
|
1
|
+
<p style="text-align: center;">
|
|
2
|
+
<picture>
|
|
3
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-dark.svg">
|
|
4
|
+
<img alt="Nx - Smart Monorepos · Fast CI" src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-light.svg" width="100%">
|
|
5
|
+
</picture>
|
|
6
|
+
</p>
|
|
2
7
|
|
|
3
8
|
<div style="text-align: center;">
|
|
4
9
|
|
|
@@ -15,9 +20,9 @@
|
|
|
15
20
|
|
|
16
21
|
<hr>
|
|
17
22
|
|
|
18
|
-
# Nx: Smart
|
|
23
|
+
# Nx: Smart Monorepos · Fast CI
|
|
19
24
|
|
|
20
|
-
Nx is a
|
|
25
|
+
Nx is a build system with built-in tooling and advanced CI capabilities. It helps you maintain and scale monorepos, both locally and on CI.
|
|
21
26
|
|
|
22
27
|
This package contains a set of utilities for creating Nx plugins.
|
|
23
28
|
|
|
@@ -59,5 +64,5 @@ npx nx@latest init
|
|
|
59
64
|
- [Blog Posts About Nx](https://blog.nrwl.io/nx/home)
|
|
60
65
|
|
|
61
66
|
<p style="text-align: center;"><a href="https://nx.dev/#learning-materials" target="_blank" rel="noreferrer"><img src="https://raw.githubusercontent.com/nrwl/nx/master/images/nx-courses-and-videos.svg"
|
|
62
|
-
width="100%" alt="Nx - Smart
|
|
67
|
+
width="100%" alt="Nx - Smart Monorepos · Fast CI"></a></p>
|
|
63
68
|
|
package/nx.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.requireNx = void 0;
|
|
4
|
-
// After Nx
|
|
4
|
+
// After Nx v19, this can be removed and replaced with either:
|
|
5
5
|
// - import {} from 'nx/src/devkit-exports'
|
|
6
6
|
// - import {} from 'nx/src/devkit-internals'
|
|
7
7
|
function requireNx() {
|
|
@@ -9,7 +9,7 @@ function requireNx() {
|
|
|
9
9
|
try {
|
|
10
10
|
result = {
|
|
11
11
|
...result,
|
|
12
|
-
// Remove in Nx
|
|
12
|
+
// Remove in Nx v19, devkit should not support Nx v16.0.2 at that point.
|
|
13
13
|
...require('nx/src/devkit-internals'),
|
|
14
14
|
};
|
|
15
15
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/devkit",
|
|
3
|
-
"version": "17.0.
|
|
3
|
+
"version": "17.0.4",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "The Nx Devkit is used to customize Nx for different technologies and use cases. It contains many utility functions for reading and writing files, updating configuration, working with Abstract Syntax Trees(ASTs), and more.",
|
|
5
|
+
"description": "The Nx Devkit is used to customize Nx for different technologies and use cases. It contains many utility functions for reading and writing files, updating configuration, working with Abstract Syntax Trees(ASTs), and more. Learn more about [extending Nx by leveraging the Nx Devkit](https://nx.dev/extending-nx/intro/getting-started) on our docs.",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
8
8
|
"url": "https://github.com/nrwl/nx.git",
|
|
@@ -33,8 +33,9 @@
|
|
|
33
33
|
"ignore": "^5.0.4",
|
|
34
34
|
"tmp": "~0.2.1",
|
|
35
35
|
"tslib": "^2.3.0",
|
|
36
|
-
"semver": "7.5.3",
|
|
37
|
-
"
|
|
36
|
+
"semver": "^7.5.3",
|
|
37
|
+
"yargs-parser": "21.1.1",
|
|
38
|
+
"@nrwl/devkit": "17.0.4"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
41
|
"nx": ">= 16 <= 18"
|
package/public-api.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.targetToTargetString = exports.parseTargetString = void 0;
|
|
4
4
|
const nx_1 = require("../../nx");
|
|
5
5
|
let { readCachedProjectGraph, splitTarget, splitByColons } = (0, nx_1.requireNx)();
|
|
6
|
-
// TODO: Remove this in Nx
|
|
6
|
+
// TODO: Remove this in Nx 19 when Nx 16.7.0 is no longer supported
|
|
7
7
|
splitTarget = splitTarget ?? require('nx/src/utils/split-target').splitTarget;
|
|
8
8
|
splitByColons =
|
|
9
9
|
splitByColons ?? ((s) => s.split(':'));
|
|
@@ -22,7 +22,8 @@ function parseTargetString(targetString, projectGraphOrCtx) {
|
|
|
22
22
|
const [maybeProject] = splitByColons(targetString);
|
|
23
23
|
if (!projectGraph.nodes[maybeProject] &&
|
|
24
24
|
projectGraphOrCtx &&
|
|
25
|
-
'projectName' in projectGraphOrCtx
|
|
25
|
+
'projectName' in projectGraphOrCtx &&
|
|
26
|
+
maybeProject !== projectGraphOrCtx.projectName) {
|
|
26
27
|
targetString = `${projectGraphOrCtx.projectName}:${targetString}`;
|
|
27
28
|
}
|
|
28
29
|
const [project, target, configuration] = splitTarget(targetString, projectGraph);
|
|
@@ -4,7 +4,7 @@ exports.readTargetOptions = void 0;
|
|
|
4
4
|
const nx_1 = require("../../nx");
|
|
5
5
|
const path_1 = require("path");
|
|
6
6
|
let { Workspaces, getExecutorInformation, calculateDefaultProjectName, combineOptionsForExecutor, } = (0, nx_1.requireNx)();
|
|
7
|
-
// TODO: Remove this in Nx
|
|
7
|
+
// TODO: Remove this in Nx 19 when Nx 16.7.0 is no longer supported
|
|
8
8
|
combineOptionsForExecutor =
|
|
9
9
|
combineOptionsForExecutor ??
|
|
10
10
|
require('nx/src/utils/params').combineOptionsForExecutor;
|
|
@@ -19,16 +19,19 @@ function readTargetOptions({ project, target, configuration }, context) {
|
|
|
19
19
|
throw new Error(`Unable to find project ${project}`);
|
|
20
20
|
}
|
|
21
21
|
const targetConfiguration = projectConfiguration.targets[target];
|
|
22
|
-
|
|
22
|
+
if (!targetConfiguration) {
|
|
23
|
+
throw new Error(`Unable to find target ${target} for project ${project}`);
|
|
24
|
+
}
|
|
25
|
+
// TODO(v19): remove Workspaces.
|
|
23
26
|
const ws = new Workspaces(context.root);
|
|
24
27
|
const [nodeModule, executorName] = targetConfiguration.executor.split(':');
|
|
25
28
|
const { schema } = getExecutorInformation
|
|
26
|
-
? getExecutorInformation(nodeModule, executorName, context.root)
|
|
27
|
-
: // TODO(
|
|
29
|
+
? getExecutorInformation(nodeModule, executorName, context.root, context.projectsConfigurations?.projects ?? context.workspace.projects)
|
|
30
|
+
: // TODO(v19): remove readExecutor. This is to be backwards compatible with Nx 16.5 and below.
|
|
28
31
|
ws.readExecutor(nodeModule, executorName);
|
|
29
32
|
const defaultProject = calculateDefaultProjectName
|
|
30
33
|
? calculateDefaultProjectName(context.cwd, context.root, { version: 2, projects: context.projectsConfigurations.projects }, context.nxJsonConfiguration)
|
|
31
|
-
: // TODO(
|
|
34
|
+
: // TODO(v19): remove calculateDefaultProjectName. This is to be backwards compatible with Nx 16.5 and below.
|
|
32
35
|
ws.calculateDefaultProjectName(context.cwd, { version: 2, projects: context.projectsConfigurations.projects }, context.nxJsonConfiguration);
|
|
33
36
|
return combineOptionsForExecutor({}, configuration ?? targetConfiguration.defaultConfiguration ?? '', targetConfiguration, schema, defaultProject, (0, path_1.relative)(context.root, context.cwd));
|
|
34
37
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.addBuildTargetDefaults = void 0;
|
|
4
|
+
const nx_1 = require("../../nx");
|
|
5
|
+
const { readNxJson, updateNxJson } = (0, nx_1.requireNx)();
|
|
6
|
+
function addBuildTargetDefaults(tree, executorName, buildTargetName = 'build') {
|
|
7
|
+
const nxJson = readNxJson(tree);
|
|
8
|
+
nxJson.targetDefaults ??= {};
|
|
9
|
+
nxJson.targetDefaults[executorName] ??= {
|
|
10
|
+
cache: true,
|
|
11
|
+
dependsOn: [`^${buildTargetName}`],
|
|
12
|
+
inputs: nxJson.namedInputs && 'production' in nxJson.namedInputs
|
|
13
|
+
? ['production', '^production']
|
|
14
|
+
: ['default', '^default'],
|
|
15
|
+
};
|
|
16
|
+
updateNxJson(tree, nxJson);
|
|
17
|
+
}
|
|
18
|
+
exports.addBuildTargetDefaults = addBuildTargetDefaults;
|
|
@@ -48,13 +48,13 @@ async function determineFormat(formats, options) {
|
|
|
48
48
|
name: derivedSelectedValue,
|
|
49
49
|
},
|
|
50
50
|
],
|
|
51
|
-
initial:
|
|
51
|
+
initial: 0,
|
|
52
52
|
}).then(({ format }) => format === asProvidedSelectedValue ? 'as-provided' : 'derived');
|
|
53
53
|
return result;
|
|
54
54
|
}
|
|
55
55
|
function logDeprecationMessage(options, formats) {
|
|
56
56
|
logger.warn(`
|
|
57
|
-
In Nx
|
|
57
|
+
In Nx 19, generating a ${options.artifactType} will no longer support providing a project and deriving the directory.
|
|
58
58
|
Please provide the exact directory in the future.
|
|
59
59
|
Example: nx g ${options.callingGenerator} ${formats['derived'].artifactName} --directory ${formats['derived'].directory}
|
|
60
60
|
NOTE: The example above assumes the command is being run from the workspace root. If the command is being run from a subdirectory, the directory option should be adjusted accordingly.
|
|
@@ -116,9 +116,20 @@ function getNameAndDirectoryOptionFormats(tree, options) {
|
|
|
116
116
|
}
|
|
117
117
|
function getAsProvidedOptions(tree, options) {
|
|
118
118
|
const relativeCwd = getRelativeCwd();
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
let asProvidedDirectory;
|
|
120
|
+
if (options.directory) {
|
|
121
|
+
// append the directory to the current working directory if it doesn't start with it
|
|
122
|
+
if (options.directory === relativeCwd ||
|
|
123
|
+
options.directory.startsWith(`${relativeCwd}/`)) {
|
|
124
|
+
asProvidedDirectory = options.directory;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
asProvidedDirectory = joinPathFragments(relativeCwd, options.directory);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
asProvidedDirectory = relativeCwd;
|
|
132
|
+
}
|
|
122
133
|
const asProvidedProject = findProjectFromPath(tree, asProvidedDirectory);
|
|
123
134
|
const asProvidedFileName = options.fileName ??
|
|
124
135
|
(options.suffix ? `${options.name}.${options.suffix}` : options.name);
|
|
@@ -4,7 +4,7 @@ exports.formatFiles = void 0;
|
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const nx_1 = require("../../nx");
|
|
6
6
|
let { updateJson, readJson, sortObjectByKeys } = (0, nx_1.requireNx)();
|
|
7
|
-
// TODO: Remove this in Nx
|
|
7
|
+
// TODO: Remove this in Nx 19 when Nx 16.7.0 is no longer supported
|
|
8
8
|
sortObjectByKeys =
|
|
9
9
|
sortObjectByKeys ?? require('nx/src/utils/object-sort').sortObjectByKeys;
|
|
10
10
|
/**
|
|
@@ -6,15 +6,18 @@ const path_1 = require("path");
|
|
|
6
6
|
const nx_1 = require("../../nx");
|
|
7
7
|
const get_workspace_layout_1 = require("../utils/get-workspace-layout");
|
|
8
8
|
const names_1 = require("../utils/names");
|
|
9
|
-
const { joinPathFragments, normalizePath,
|
|
10
|
-
const deprecationWarning = stripIndents `
|
|
11
|
-
In Nx 18, generating projects will no longer derive the name and root.
|
|
12
|
-
Please provide the exact project name and root in the future.`;
|
|
9
|
+
const { joinPathFragments, logger, normalizePath, output, readJson, stripIndents, workspaceRoot, } = (0, nx_1.requireNx)();
|
|
13
10
|
async function determineProjectNameAndRootOptions(tree, options) {
|
|
11
|
+
if (!options.projectNameAndRootFormat &&
|
|
12
|
+
(process.env.NX_INTERACTIVE !== 'true' || !isTTY())) {
|
|
13
|
+
options.projectNameAndRootFormat = 'derived';
|
|
14
|
+
}
|
|
14
15
|
validateName(options.name, options.projectNameAndRootFormat);
|
|
15
16
|
const formats = getProjectNameAndRootFormats(tree, options);
|
|
16
|
-
const format = options.projectNameAndRootFormat ??
|
|
17
|
-
|
|
17
|
+
const format = options.projectNameAndRootFormat ?? (await determineFormat(formats));
|
|
18
|
+
if (format === 'derived' && options.callingGenerator) {
|
|
19
|
+
logDeprecationMessage(options.callingGenerator, formats);
|
|
20
|
+
}
|
|
18
21
|
return {
|
|
19
22
|
...formats[format],
|
|
20
23
|
projectNameAndRootFormat: format,
|
|
@@ -41,16 +44,17 @@ function validateName(name, projectNameAndRootFormat) {
|
|
|
41
44
|
throw new Error(`The project name should match the pattern "${pattern}". The provided value "${name}" does not match.`);
|
|
42
45
|
}
|
|
43
46
|
}
|
|
44
|
-
function
|
|
45
|
-
|
|
47
|
+
function logDeprecationMessage(callingGenerator, formats) {
|
|
48
|
+
logger.warn(stripIndents `
|
|
49
|
+
In Nx 19, generating projects will no longer derive the name and root.
|
|
50
|
+
Please provide the exact project name and root in the future.
|
|
51
|
+
Example: nx g ${callingGenerator} ${formats['derived'].projectName} --directory ${formats['derived'].projectRoot}
|
|
52
|
+
`);
|
|
46
53
|
}
|
|
47
|
-
async function determineFormat(
|
|
54
|
+
async function determineFormat(formats) {
|
|
48
55
|
if (!formats.derived) {
|
|
49
56
|
return 'as-provided';
|
|
50
57
|
}
|
|
51
|
-
if (process.env.NX_INTERACTIVE !== 'true' || !isTTY()) {
|
|
52
|
-
return 'derived';
|
|
53
|
-
}
|
|
54
58
|
const asProvidedDescription = `As provided:
|
|
55
59
|
Name: ${formats['as-provided'].projectName}
|
|
56
60
|
Root: ${formats['as-provided'].projectRoot}`;
|
|
@@ -76,115 +80,156 @@ async function determineFormat(tree, formats, callingGenerator) {
|
|
|
76
80
|
name: derivedSelectedValue,
|
|
77
81
|
},
|
|
78
82
|
],
|
|
79
|
-
initial:
|
|
83
|
+
initial: 0,
|
|
80
84
|
}).then(({ format }) => format === asProvidedSelectedValue ? 'as-provided' : 'derived');
|
|
81
|
-
if (result === 'derived' && callingGenerator) {
|
|
82
|
-
const example = getExample(callingGenerator, formats);
|
|
83
|
-
logger.warn(deprecationWarning + '\n' + example);
|
|
84
|
-
}
|
|
85
85
|
return result;
|
|
86
86
|
}
|
|
87
87
|
function getProjectNameAndRootFormats(tree, options) {
|
|
88
88
|
const directory = options.directory
|
|
89
89
|
? normalizePath(options.directory.replace(/^\.?\//, ''))
|
|
90
90
|
: undefined;
|
|
91
|
-
const
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
const { name: asProvidedParsedName, directory: asProvidedParsedDirectory } = parseNameForAsProvided(options.name);
|
|
92
|
+
if (asProvidedParsedDirectory && directory) {
|
|
93
|
+
throw new Error(`You can't specify both a directory (${options.directory}) and a name with a directory path (${options.name}). ` +
|
|
94
|
+
`Please specify either a directory or a name with a directory path.`);
|
|
95
|
+
}
|
|
96
|
+
const asProvidedOptions = getAsProvidedOptions(tree, {
|
|
97
|
+
...options,
|
|
98
|
+
directory: directory ?? asProvidedParsedDirectory,
|
|
99
|
+
name: asProvidedParsedName,
|
|
100
|
+
});
|
|
101
|
+
if (options.projectNameAndRootFormat === 'as-provided') {
|
|
102
|
+
return {
|
|
103
|
+
'as-provided': asProvidedOptions,
|
|
104
|
+
derived: undefined,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
if (asProvidedOptions.projectName.startsWith('@')) {
|
|
108
|
+
if (!options.projectNameAndRootFormat) {
|
|
109
|
+
output.warn({
|
|
110
|
+
title: `The provided name "${options.name}" contains a scoped project name and this is not supported by the "${options.callingGenerator}" when using the "derived" format.`,
|
|
111
|
+
bodyLines: [
|
|
112
|
+
`The generator will try to generate the project "${asProvidedOptions.projectName}" using the "as-provided" format at "${asProvidedOptions.projectRoot}".`,
|
|
113
|
+
],
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
'as-provided': asProvidedOptions,
|
|
117
|
+
derived: undefined,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
throw new Error(`The provided name "${options.name}" contains a scoped project name and this is not supported by the "${options.callingGenerator}" when using the "derived" format. ` +
|
|
121
|
+
`Please provide a name without "@" or use the "as-provided" format.`);
|
|
122
|
+
}
|
|
123
|
+
const { name: derivedParsedName, directory: derivedParsedDirectory } = parseNameForDerived(options.name);
|
|
124
|
+
const derivedOptions = getDerivedOptions(tree, {
|
|
125
|
+
...options,
|
|
126
|
+
directory: directory ?? derivedParsedDirectory,
|
|
127
|
+
name: derivedParsedName,
|
|
128
|
+
});
|
|
129
|
+
return {
|
|
130
|
+
'as-provided': asProvidedOptions,
|
|
131
|
+
derived: derivedOptions,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function getAsProvidedOptions(tree, options) {
|
|
135
|
+
let projectSimpleName;
|
|
136
|
+
let projectFileName;
|
|
137
|
+
if (options.name.startsWith('@')) {
|
|
138
|
+
const [_scope, ...rest] = options.name.split('/');
|
|
139
|
+
projectFileName = rest.join('-');
|
|
140
|
+
projectSimpleName = rest.pop();
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
projectSimpleName = options.name;
|
|
144
|
+
projectFileName = options.name;
|
|
145
|
+
}
|
|
146
|
+
let projectRoot;
|
|
147
|
+
const relativeCwd = getRelativeCwd();
|
|
148
|
+
if (options.directory) {
|
|
95
149
|
// append the directory to the current working directory if it doesn't start with it
|
|
96
|
-
if (directory === relativeCwd ||
|
|
97
|
-
|
|
150
|
+
if (options.directory === relativeCwd ||
|
|
151
|
+
options.directory.startsWith(`${relativeCwd}/`)) {
|
|
152
|
+
projectRoot = options.directory;
|
|
98
153
|
}
|
|
99
154
|
else {
|
|
100
|
-
|
|
155
|
+
projectRoot = joinPathFragments(relativeCwd, options.directory);
|
|
101
156
|
}
|
|
102
157
|
}
|
|
103
158
|
else if (options.rootProject) {
|
|
104
|
-
|
|
159
|
+
projectRoot = '.';
|
|
105
160
|
}
|
|
106
161
|
else {
|
|
107
|
-
|
|
162
|
+
projectRoot = relativeCwd;
|
|
108
163
|
// append the project name to the current working directory if it doesn't end with it
|
|
109
|
-
if (!relativeCwd.endsWith(
|
|
110
|
-
|
|
111
|
-
asProvidedProjectDirectory = joinPathFragments(relativeCwd, asProvidedProjectName);
|
|
164
|
+
if (!relativeCwd.endsWith(options.name)) {
|
|
165
|
+
projectRoot = joinPathFragments(relativeCwd, options.name);
|
|
112
166
|
}
|
|
113
167
|
}
|
|
114
|
-
|
|
115
|
-
const nameWithoutScope = asProvidedProjectName.split('/')[1];
|
|
116
|
-
return {
|
|
117
|
-
'as-provided': {
|
|
118
|
-
projectName: asProvidedProjectName,
|
|
119
|
-
names: {
|
|
120
|
-
projectSimpleName: nameWithoutScope,
|
|
121
|
-
projectFileName: nameWithoutScope,
|
|
122
|
-
},
|
|
123
|
-
importPath: options.importPath ?? asProvidedProjectName,
|
|
124
|
-
projectRoot: asProvidedProjectDirectory,
|
|
125
|
-
},
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
let asProvidedImportPath;
|
|
129
|
-
let npmScope;
|
|
168
|
+
let importPath = undefined;
|
|
130
169
|
if (options.projectType === 'library') {
|
|
131
|
-
|
|
132
|
-
if (!
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
170
|
+
importPath = options.importPath;
|
|
171
|
+
if (!importPath) {
|
|
172
|
+
if (options.name.startsWith('@')) {
|
|
173
|
+
importPath = options.name;
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
const npmScope = getNpmScope(tree);
|
|
177
|
+
importPath =
|
|
178
|
+
projectRoot === '.'
|
|
179
|
+
? readJson(tree, 'package.json').name ??
|
|
180
|
+
getImportPath(npmScope, options.name)
|
|
181
|
+
: getImportPath(npmScope, options.name);
|
|
182
|
+
}
|
|
139
183
|
}
|
|
140
184
|
}
|
|
185
|
+
return {
|
|
186
|
+
projectName: options.name,
|
|
187
|
+
names: {
|
|
188
|
+
projectSimpleName,
|
|
189
|
+
projectFileName,
|
|
190
|
+
},
|
|
191
|
+
importPath,
|
|
192
|
+
projectRoot,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
function getDerivedOptions(tree, options) {
|
|
141
196
|
const name = (0, names_1.names)(options.name).fileName;
|
|
142
|
-
let { projectDirectory, layoutDirectory } = getDirectories(tree, directory, options.projectType);
|
|
143
|
-
const
|
|
197
|
+
let { projectDirectory, layoutDirectory } = getDirectories(tree, options.directory, options.projectType);
|
|
198
|
+
const projectDirectoryWithoutLayout = projectDirectory
|
|
144
199
|
? `${(0, names_1.names)(projectDirectory).fileName}/${name}`
|
|
145
200
|
: options.rootProject
|
|
146
201
|
? '.'
|
|
147
202
|
: name;
|
|
148
203
|
// the project name uses the directory without the layout directory
|
|
149
|
-
const
|
|
204
|
+
const projectName = projectDirectoryWithoutLayout === '.'
|
|
150
205
|
? name
|
|
151
|
-
:
|
|
152
|
-
const
|
|
153
|
-
let
|
|
154
|
-
if (
|
|
206
|
+
: projectDirectoryWithoutLayout.replace(/\//g, '-');
|
|
207
|
+
const projectSimpleName = name;
|
|
208
|
+
let projectRoot = projectDirectoryWithoutLayout;
|
|
209
|
+
if (projectDirectoryWithoutLayout !== '.') {
|
|
155
210
|
// prepend the layout directory
|
|
156
|
-
|
|
211
|
+
projectRoot = joinPathFragments(layoutDirectory, projectRoot);
|
|
157
212
|
}
|
|
158
|
-
let
|
|
213
|
+
let importPath;
|
|
159
214
|
if (options.projectType === 'library') {
|
|
160
|
-
|
|
161
|
-
if (!
|
|
162
|
-
|
|
163
|
-
|
|
215
|
+
importPath = options.importPath;
|
|
216
|
+
if (!importPath) {
|
|
217
|
+
const npmScope = getNpmScope(tree);
|
|
218
|
+
importPath =
|
|
219
|
+
projectRoot === '.'
|
|
164
220
|
? readJson(tree, 'package.json').name ??
|
|
165
|
-
getImportPath(npmScope,
|
|
166
|
-
: getImportPath(npmScope,
|
|
221
|
+
getImportPath(npmScope, projectName)
|
|
222
|
+
: getImportPath(npmScope, projectDirectoryWithoutLayout);
|
|
167
223
|
}
|
|
168
224
|
}
|
|
169
225
|
return {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
projectFileName: asProvidedProjectName,
|
|
175
|
-
},
|
|
176
|
-
importPath: asProvidedImportPath,
|
|
177
|
-
projectRoot: asProvidedProjectDirectory,
|
|
178
|
-
},
|
|
179
|
-
derived: {
|
|
180
|
-
projectName: derivedProjectName,
|
|
181
|
-
names: {
|
|
182
|
-
projectSimpleName: derivedSimpleProjectName,
|
|
183
|
-
projectFileName: derivedProjectName,
|
|
184
|
-
},
|
|
185
|
-
importPath: derivedImportPath,
|
|
186
|
-
projectRoot: derivedProjectDirectory,
|
|
226
|
+
projectName,
|
|
227
|
+
names: {
|
|
228
|
+
projectSimpleName,
|
|
229
|
+
projectFileName: projectName,
|
|
187
230
|
},
|
|
231
|
+
importPath,
|
|
232
|
+
projectRoot,
|
|
188
233
|
};
|
|
189
234
|
}
|
|
190
235
|
function getDirectories(tree, directory, projectType) {
|
|
@@ -218,6 +263,9 @@ function getCwd() {
|
|
|
218
263
|
? process.env.INIT_CWD
|
|
219
264
|
: process.cwd();
|
|
220
265
|
}
|
|
266
|
+
function getRelativeCwd() {
|
|
267
|
+
return normalizePath((0, path_1.relative)(workspaceRoot, getCwd())).replace(/\/$/, '');
|
|
268
|
+
}
|
|
221
269
|
/**
|
|
222
270
|
* Function for setting cwd during testing
|
|
223
271
|
*/
|
|
@@ -225,3 +273,26 @@ function setCwd(path) {
|
|
|
225
273
|
process.env.INIT_CWD = (0, path_1.join)(workspaceRoot, path);
|
|
226
274
|
}
|
|
227
275
|
exports.setCwd = setCwd;
|
|
276
|
+
function parseNameForAsProvided(rawName) {
|
|
277
|
+
const directory = normalizePath(rawName);
|
|
278
|
+
if (rawName.includes('@')) {
|
|
279
|
+
const index = directory.lastIndexOf('@');
|
|
280
|
+
if (index === 0) {
|
|
281
|
+
return { name: rawName, directory: undefined };
|
|
282
|
+
}
|
|
283
|
+
const name = directory.substring(index);
|
|
284
|
+
return { name, directory };
|
|
285
|
+
}
|
|
286
|
+
if (rawName.includes('/')) {
|
|
287
|
+
const index = directory.lastIndexOf('/');
|
|
288
|
+
const name = directory.substring(index + 1);
|
|
289
|
+
return { name, directory };
|
|
290
|
+
}
|
|
291
|
+
return { name: rawName, directory: undefined };
|
|
292
|
+
}
|
|
293
|
+
function parseNameForDerived(rawName) {
|
|
294
|
+
const parsedName = normalizePath(rawName).split('/');
|
|
295
|
+
const name = parsedName.pop();
|
|
296
|
+
const directory = parsedName.length ? parsedName.join('/') : undefined;
|
|
297
|
+
return { name, directory };
|
|
298
|
+
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { Tree } from 'nx/src/generators/tree';
|
|
2
|
+
import type { ScriptTarget, ModuleKind } from 'typescript';
|
|
3
|
+
export type ToJSOptions = {
|
|
4
|
+
target?: ScriptTarget;
|
|
5
|
+
module?: ModuleKind;
|
|
6
|
+
extension: '.js' | '.mjs' | '.cjs';
|
|
7
|
+
};
|
|
2
8
|
/**
|
|
3
9
|
* Rename and transpile any new typescript files created to javascript files
|
|
4
10
|
*/
|
|
5
|
-
export declare function toJS(tree: Tree): void;
|
|
11
|
+
export declare function toJS(tree: Tree, options?: ToJSOptions): void;
|
package/src/generators/to-js.js
CHANGED
|
@@ -6,17 +6,18 @@ const package_json_1 = require("../utils/package-json");
|
|
|
6
6
|
/**
|
|
7
7
|
* Rename and transpile any new typescript files created to javascript files
|
|
8
8
|
*/
|
|
9
|
-
function toJS(tree) {
|
|
10
|
-
const { JsxEmit, ScriptTarget, transpile } = (0, package_json_1.ensurePackage)('typescript', versions_1.typescriptVersion);
|
|
9
|
+
function toJS(tree, options) {
|
|
10
|
+
const { JsxEmit, ScriptTarget, transpile, ModuleKind } = (0, package_json_1.ensurePackage)('typescript', versions_1.typescriptVersion);
|
|
11
11
|
for (const c of tree.listChanges()) {
|
|
12
12
|
if ((c.path.endsWith('.ts') || c.path.endsWith('tsx')) &&
|
|
13
13
|
c.type === 'CREATE') {
|
|
14
14
|
tree.write(c.path, transpile(c.content.toString('utf-8'), {
|
|
15
15
|
allowJs: true,
|
|
16
16
|
jsx: JsxEmit.Preserve,
|
|
17
|
-
target: ScriptTarget.ESNext,
|
|
17
|
+
target: options?.target ?? ScriptTarget.ESNext,
|
|
18
|
+
module: options?.module ?? ModuleKind.ESNext,
|
|
18
19
|
}));
|
|
19
|
-
tree.rename(c.path, c.path.replace(/\.tsx?$/, '.js'));
|
|
20
|
+
tree.rename(c.path, c.path.replace(/\.tsx?$/, options?.extension ?? '.js'));
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateHashForCreateNodes = void 0;
|
|
4
|
+
const nx_1 = require("../../nx");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const { hashWithWorkspaceContext, hashArray, hashObject } = (0, nx_1.requireNx)();
|
|
7
|
+
function calculateHashForCreateNodes(projectRoot, options, context, additionalGlobs = []) {
|
|
8
|
+
return hashArray([
|
|
9
|
+
hashWithWorkspaceContext(context.workspaceRoot, [
|
|
10
|
+
(0, path_1.join)(projectRoot, '**/*'),
|
|
11
|
+
...additionalGlobs,
|
|
12
|
+
]),
|
|
13
|
+
hashObject(options),
|
|
14
|
+
]);
|
|
15
|
+
}
|
|
16
|
+
exports.calculateHashForCreateNodes = calculateHashForCreateNodes;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare let dynamicImport: Function;
|
|
2
|
+
export declare function loadConfigFile<T extends object = any>(configFilePath: string): Promise<T>;
|
|
3
|
+
export declare function getRootTsConfigPath(): string | null;
|
|
4
|
+
export declare function getRootTsConfigFileName(): string | null;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getRootTsConfigFileName = exports.getRootTsConfigPath = exports.loadConfigFile = exports.dynamicImport = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const nx_1 = require("../../nx");
|
|
7
|
+
const { workspaceRoot, registerTsProject } = (0, nx_1.requireNx)();
|
|
8
|
+
exports.dynamicImport = new Function('modulePath', 'return import(modulePath);');
|
|
9
|
+
async function loadConfigFile(configFilePath) {
|
|
10
|
+
{
|
|
11
|
+
let module;
|
|
12
|
+
if ((0, path_1.extname)(configFilePath) === '.ts') {
|
|
13
|
+
const siblingFiles = (0, fs_1.readdirSync)((0, path_1.dirname)(configFilePath));
|
|
14
|
+
const tsConfigPath = siblingFiles.includes('tsconfig.json')
|
|
15
|
+
? (0, path_1.join)((0, path_1.dirname)(configFilePath), 'tsconfig.json')
|
|
16
|
+
: getRootTsConfigPath();
|
|
17
|
+
if (tsConfigPath) {
|
|
18
|
+
const unregisterTsProject = registerTsProject(tsConfigPath);
|
|
19
|
+
try {
|
|
20
|
+
module = await load(configFilePath);
|
|
21
|
+
}
|
|
22
|
+
finally {
|
|
23
|
+
unregisterTsProject();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
module = await load(configFilePath);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
module = await load(configFilePath);
|
|
32
|
+
}
|
|
33
|
+
return module.default ?? module;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.loadConfigFile = loadConfigFile;
|
|
37
|
+
function getRootTsConfigPath() {
|
|
38
|
+
const tsConfigFileName = getRootTsConfigFileName();
|
|
39
|
+
return tsConfigFileName ? (0, path_1.join)(workspaceRoot, tsConfigFileName) : null;
|
|
40
|
+
}
|
|
41
|
+
exports.getRootTsConfigPath = getRootTsConfigPath;
|
|
42
|
+
function getRootTsConfigFileName() {
|
|
43
|
+
for (const tsConfigName of ['tsconfig.base.json', 'tsconfig.json']) {
|
|
44
|
+
const pathExists = (0, fs_1.existsSync)((0, path_1.join)(workspaceRoot, tsConfigName));
|
|
45
|
+
if (pathExists) {
|
|
46
|
+
return tsConfigName;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
exports.getRootTsConfigFileName = getRootTsConfigFileName;
|
|
52
|
+
/**
|
|
53
|
+
* Load the module after ensuring that the require cache is cleared.
|
|
54
|
+
*/
|
|
55
|
+
async function load(path) {
|
|
56
|
+
// Clear cache if the path is in the cache
|
|
57
|
+
if (require.cache[path]) {
|
|
58
|
+
for (const k of Object.keys(require.cache)) {
|
|
59
|
+
delete require.cache[k];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
// Try using `require` first, which works for CJS modules.
|
|
64
|
+
// Modules are CJS unless it is named `.mjs` or `package.json` sets type to "module".
|
|
65
|
+
return require(path);
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
if (e.code === 'ERR_REQUIRE_ESM') {
|
|
69
|
+
// If `require` fails to load ESM, try dynamic `import()`.
|
|
70
|
+
return await (0, exports.dynamicImport)(`${path}?t=${Date.now()}`);
|
|
71
|
+
}
|
|
72
|
+
// Re-throw all other errors
|
|
73
|
+
throw e;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -14,15 +14,15 @@ function convertNxExecutor(executor) {
|
|
|
14
14
|
const workspaces = new Workspaces(builderContext.workspaceRoot);
|
|
15
15
|
const nxJsonConfiguration = readNxJsonFromDisk
|
|
16
16
|
? readNxJsonFromDisk(builderContext.workspaceRoot)
|
|
17
|
-
: // TODO(
|
|
17
|
+
: // TODO(v19): remove readNxJson. This is to be backwards compatible with Nx 16.5 and below.
|
|
18
18
|
workspaces.readNxJson();
|
|
19
19
|
const promise = async () => {
|
|
20
20
|
const projectsConfigurations = retrieveProjectConfigurationsWithAngularProjects
|
|
21
21
|
? {
|
|
22
22
|
version: 2,
|
|
23
|
-
projects: await retrieveProjectConfigurationsWithAngularProjects(builderContext.workspaceRoot, nxJsonConfiguration).then((p) => p.projectNodes),
|
|
23
|
+
projects: await retrieveProjectConfigurationsWithAngularProjects(builderContext.workspaceRoot, nxJsonConfiguration).then((p) => p.projectNodes ?? p.projects),
|
|
24
24
|
}
|
|
25
|
-
: // TODO(
|
|
25
|
+
: // TODO(v19): remove retrieveProjectConfigurations. This is to be backwards compatible with Nx 16.5 and below.
|
|
26
26
|
workspaces.readProjectsConfigurations({
|
|
27
27
|
_includeProjectsFromAngularJson: true,
|
|
28
28
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CreateNodesContext } from 'nx/src/devkit-exports';
|
|
2
|
+
import type { InputDefinition } from 'nx/src/config/workspace-json-project-json';
|
|
3
|
+
/**
|
|
4
|
+
* Get the named inputs available for a directory
|
|
5
|
+
*/
|
|
6
|
+
export declare function getNamedInputs(directory: string, context: CreateNodesContext): {
|
|
7
|
+
[inputName: string]: (string | InputDefinition)[];
|
|
8
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getNamedInputs = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const nx_1 = require("../../nx");
|
|
7
|
+
const { readJsonFile } = (0, nx_1.requireNx)();
|
|
8
|
+
/**
|
|
9
|
+
* Get the named inputs available for a directory
|
|
10
|
+
*/
|
|
11
|
+
function getNamedInputs(directory, context) {
|
|
12
|
+
const projectJsonPath = (0, path_1.join)(directory, 'project.json');
|
|
13
|
+
const projectJson = (0, fs_1.existsSync)(projectJsonPath)
|
|
14
|
+
? readJsonFile(projectJsonPath)
|
|
15
|
+
: null;
|
|
16
|
+
const packageJsonPath = (0, path_1.join)(directory, 'package.json');
|
|
17
|
+
const packageJson = (0, fs_1.existsSync)(packageJsonPath)
|
|
18
|
+
? readJsonFile(packageJsonPath)
|
|
19
|
+
: null;
|
|
20
|
+
return {
|
|
21
|
+
...context.nxJsonConfiguration.namedInputs,
|
|
22
|
+
...packageJson?.nx?.namedInputs,
|
|
23
|
+
...projectJson?.namedInputs,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
exports.getNamedInputs = getNamedInputs;
|
|
@@ -18,7 +18,7 @@ export declare function getWorkspaceLayout(tree: Tree): {
|
|
|
18
18
|
/**
|
|
19
19
|
* Experimental
|
|
20
20
|
*/
|
|
21
|
-
export declare function extractLayoutDirectory(directory
|
|
22
|
-
layoutDirectory: string;
|
|
23
|
-
projectDirectory
|
|
21
|
+
export declare function extractLayoutDirectory(directory?: string): {
|
|
22
|
+
layoutDirectory: string | null;
|
|
23
|
+
projectDirectory?: string;
|
|
24
24
|
};
|
|
@@ -4,7 +4,7 @@ exports.convertNxGenerator = void 0;
|
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const nx_1 = require("../../nx");
|
|
6
6
|
let { logger, stripIndent } = (0, nx_1.requireNx)();
|
|
7
|
-
// TODO: Remove this in Nx
|
|
7
|
+
// TODO: Remove this in Nx 19 when Nx 16.7.0 is no longer supported
|
|
8
8
|
stripIndent = stripIndent ?? require('nx/src/utils/logger').stripIndent;
|
|
9
9
|
class RunCallbackTask {
|
|
10
10
|
constructor(callback) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function logShowProjectCommand(projectName: string): void;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logShowProjectCommand = void 0;
|
|
4
|
+
const nx_1 = require("../../nx");
|
|
5
|
+
function logShowProjectCommand(projectName) {
|
|
6
|
+
const { output } = (0, nx_1.requireNx)();
|
|
7
|
+
output.log({
|
|
8
|
+
title: `👀 View Details of ${projectName}`,
|
|
9
|
+
bodyLines: [
|
|
10
|
+
`Run "nx show project ${projectName} --web" to view details about this project.`,
|
|
11
|
+
],
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
exports.logShowProjectCommand = logShowProjectCommand;
|
|
@@ -13,9 +13,10 @@ import type { GeneratorCallback } from 'nx/src/config/misc-interfaces';
|
|
|
13
13
|
* @param dependencies Dependencies to be added to the dependencies section of package.json
|
|
14
14
|
* @param devDependencies Dependencies to be added to the devDependencies section of package.json
|
|
15
15
|
* @param packageJsonPath Path to package.json
|
|
16
|
+
* @param keepExistingVersions If true, prevents existing dependencies from being bumped to newer versions
|
|
16
17
|
* @returns Callback to install dependencies only if necessary, no-op otherwise
|
|
17
18
|
*/
|
|
18
|
-
export declare function addDependenciesToPackageJson(tree: Tree, dependencies: Record<string, string>, devDependencies: Record<string, string>, packageJsonPath?: string): GeneratorCallback;
|
|
19
|
+
export declare function addDependenciesToPackageJson(tree: Tree, dependencies: Record<string, string>, devDependencies: Record<string, string>, packageJsonPath?: string, keepExistingVersions?: boolean): GeneratorCallback;
|
|
19
20
|
/**
|
|
20
21
|
* Remove Dependencies and Dev Dependencies from package.json
|
|
21
22
|
*
|
|
@@ -86,9 +86,10 @@ function updateExistingDependenciesVersion(dependencies, existingDependencies =
|
|
|
86
86
|
* @param dependencies Dependencies to be added to the dependencies section of package.json
|
|
87
87
|
* @param devDependencies Dependencies to be added to the devDependencies section of package.json
|
|
88
88
|
* @param packageJsonPath Path to package.json
|
|
89
|
+
* @param keepExistingVersions If true, prevents existing dependencies from being bumped to newer versions
|
|
89
90
|
* @returns Callback to install dependencies only if necessary, no-op otherwise
|
|
90
91
|
*/
|
|
91
|
-
function addDependenciesToPackageJson(tree, dependencies, devDependencies, packageJsonPath = 'package.json') {
|
|
92
|
+
function addDependenciesToPackageJson(tree, dependencies, devDependencies, packageJsonPath = 'package.json', keepExistingVersions) {
|
|
92
93
|
const currentPackageJson = readJson(tree, packageJsonPath);
|
|
93
94
|
/** Dependencies to install that are not met in dev dependencies */
|
|
94
95
|
let filteredDependencies = filterExistingDependencies(dependencies, currentPackageJson.devDependencies);
|
|
@@ -96,6 +97,7 @@ function addDependenciesToPackageJson(tree, dependencies, devDependencies, packa
|
|
|
96
97
|
let filteredDevDependencies = filterExistingDependencies(devDependencies, currentPackageJson.dependencies);
|
|
97
98
|
// filtered dependencies should consist of:
|
|
98
99
|
// - dependencies of the same type that are not present
|
|
100
|
+
// by default, filtered dependencies also include these (unless keepExistingVersions is true):
|
|
99
101
|
// - dependencies of the same type that have greater version
|
|
100
102
|
// - specified dependencies of the other type that have greater version and are already installed as current type
|
|
101
103
|
filteredDependencies = {
|
|
@@ -106,8 +108,14 @@ function addDependenciesToPackageJson(tree, dependencies, devDependencies, packa
|
|
|
106
108
|
...updateExistingDependenciesVersion(filteredDevDependencies, currentPackageJson.devDependencies),
|
|
107
109
|
...updateExistingAltDependenciesVersion(dependencies, currentPackageJson.devDependencies),
|
|
108
110
|
};
|
|
109
|
-
|
|
110
|
-
|
|
111
|
+
if (keepExistingVersions) {
|
|
112
|
+
filteredDependencies = removeExistingDependencies(filteredDependencies, currentPackageJson.dependencies);
|
|
113
|
+
filteredDevDependencies = removeExistingDependencies(filteredDevDependencies, currentPackageJson.devDependencies);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
filteredDependencies = removeLowerVersions(filteredDependencies, currentPackageJson.dependencies);
|
|
117
|
+
filteredDevDependencies = removeLowerVersions(filteredDevDependencies, currentPackageJson.devDependencies);
|
|
118
|
+
}
|
|
111
119
|
if (requiresAddingOfPackages(currentPackageJson, filteredDependencies, filteredDevDependencies)) {
|
|
112
120
|
updateJson(tree, packageJsonPath, (json) => {
|
|
113
121
|
json.dependencies = {
|
|
@@ -134,11 +142,19 @@ exports.addDependenciesToPackageJson = addDependenciesToPackageJson;
|
|
|
134
142
|
**/
|
|
135
143
|
function removeLowerVersions(incomingDeps, existingDeps) {
|
|
136
144
|
return Object.keys(incomingDeps).reduce((acc, d) => {
|
|
137
|
-
if (existingDeps?.[d]
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
if (!existingDeps?.[d] ||
|
|
146
|
+
isIncomingVersionGreater(incomingDeps[d], existingDeps[d])) {
|
|
147
|
+
acc[d] = incomingDeps[d];
|
|
148
|
+
}
|
|
149
|
+
return acc;
|
|
150
|
+
}, {});
|
|
151
|
+
}
|
|
152
|
+
function removeExistingDependencies(incomingDeps, existingDeps) {
|
|
153
|
+
return Object.keys(incomingDeps).reduce((acc, d) => {
|
|
154
|
+
if (!existingDeps?.[d]) {
|
|
155
|
+
acc[d] = incomingDeps[d];
|
|
140
156
|
}
|
|
141
|
-
return
|
|
157
|
+
return acc;
|
|
142
158
|
}, {});
|
|
143
159
|
}
|
|
144
160
|
/**
|
|
@@ -273,7 +289,7 @@ function ensurePackage(pkgOrTree, requiredVersionOrPackage, maybeRequiredVersion
|
|
|
273
289
|
}
|
|
274
290
|
}
|
|
275
291
|
if (process.env.NX_DRY_RUN && process.env.NX_DRY_RUN !== 'false') {
|
|
276
|
-
throw new Error('NOTE: This generator does not support --dry-run. If you are running this in Nx Console, it should execute fine once you hit the "
|
|
292
|
+
throw new Error('NOTE: This generator does not support --dry-run. If you are running this in Nx Console, it should execute fine once you hit the "Generate" button.\n');
|
|
277
293
|
}
|
|
278
294
|
const { dir: tempDir } = createTempNpmDirectory?.() ?? {
|
|
279
295
|
dir: (0, tmp_1.dirSync)().name,
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.replaceProjectConfigurationsWithPlugin = void 0;
|
|
4
|
+
const nx_1 = require("../../nx");
|
|
5
|
+
const { readNxJson, updateNxJson, glob, hashObject, findProjectForPath, readProjectConfiguration, updateProjectConfiguration, } = (0, nx_1.requireNx)();
|
|
6
|
+
async function replaceProjectConfigurationsWithPlugin(tree, rootMappings, pluginPath, createNodes, pluginOptions) {
|
|
7
|
+
const nxJson = readNxJson(tree);
|
|
8
|
+
const hasPlugin = nxJson.plugins?.some((p) => typeof p === 'string' ? p === pluginPath : p.plugin === pluginPath);
|
|
9
|
+
if (hasPlugin) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
nxJson.plugins ??= [];
|
|
13
|
+
nxJson.plugins.push({
|
|
14
|
+
plugin: pluginPath,
|
|
15
|
+
options: pluginOptions,
|
|
16
|
+
});
|
|
17
|
+
updateNxJson(tree, nxJson);
|
|
18
|
+
const [pluginGlob, createNodesFunction] = createNodes;
|
|
19
|
+
const configFiles = glob(tree, [pluginGlob]);
|
|
20
|
+
for (const configFile of configFiles) {
|
|
21
|
+
try {
|
|
22
|
+
const projectName = findProjectForPath(configFile, rootMappings);
|
|
23
|
+
const projectConfig = readProjectConfiguration(tree, projectName);
|
|
24
|
+
const nodes = await createNodesFunction(configFile, pluginOptions, {
|
|
25
|
+
workspaceRoot: tree.root,
|
|
26
|
+
nxJsonConfiguration: readNxJson(tree),
|
|
27
|
+
configFiles,
|
|
28
|
+
});
|
|
29
|
+
const node = nodes.projects[Object.keys(nodes.projects)[0]];
|
|
30
|
+
for (const [targetName, targetConfig] of Object.entries(node.targets)) {
|
|
31
|
+
const targetFromProjectConfig = projectConfig.targets[targetName];
|
|
32
|
+
if (targetFromProjectConfig?.executor !== targetConfig.executor) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
const targetFromCreateNodes = node.targets[targetName];
|
|
36
|
+
removeConfigurationDefinedByPlugin(targetName, targetFromProjectConfig, targetFromCreateNodes, projectConfig);
|
|
37
|
+
}
|
|
38
|
+
updateProjectConfiguration(tree, projectName, projectConfig);
|
|
39
|
+
}
|
|
40
|
+
catch (e) {
|
|
41
|
+
console.error(e);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
exports.replaceProjectConfigurationsWithPlugin = replaceProjectConfigurationsWithPlugin;
|
|
46
|
+
function removeConfigurationDefinedByPlugin(targetName, targetFromProjectConfig, targetFromCreateNodes, projectConfig) {
|
|
47
|
+
// Executor
|
|
48
|
+
delete targetFromProjectConfig.executor;
|
|
49
|
+
// Default Configuration
|
|
50
|
+
if (targetFromProjectConfig.defaultConfiguration ===
|
|
51
|
+
targetFromCreateNodes.defaultConfiguration) {
|
|
52
|
+
delete targetFromProjectConfig.defaultConfiguration;
|
|
53
|
+
}
|
|
54
|
+
// Cache
|
|
55
|
+
if (targetFromProjectConfig.cache === targetFromCreateNodes.cache) {
|
|
56
|
+
delete targetFromProjectConfig.cache;
|
|
57
|
+
}
|
|
58
|
+
// Depends On
|
|
59
|
+
if (targetFromProjectConfig.dependsOn &&
|
|
60
|
+
shouldRemoveArrayProperty(targetFromProjectConfig.dependsOn, targetFromCreateNodes.dependsOn)) {
|
|
61
|
+
delete targetFromProjectConfig.dependsOn;
|
|
62
|
+
}
|
|
63
|
+
// Outputs
|
|
64
|
+
if (targetFromProjectConfig.outputs &&
|
|
65
|
+
shouldRemoveArrayProperty(targetFromProjectConfig.outputs, targetFromCreateNodes.outputs)) {
|
|
66
|
+
delete targetFromProjectConfig.outputs;
|
|
67
|
+
}
|
|
68
|
+
// Inputs
|
|
69
|
+
if (targetFromProjectConfig.inputs &&
|
|
70
|
+
shouldRemoveArrayProperty(targetFromProjectConfig.inputs, targetFromCreateNodes.inputs)) {
|
|
71
|
+
delete targetFromProjectConfig.inputs;
|
|
72
|
+
}
|
|
73
|
+
// Options
|
|
74
|
+
for (const [optionName, optionValue] of Object.entries(targetFromProjectConfig.options ?? {})) {
|
|
75
|
+
if (equals(targetFromCreateNodes.options[optionName], optionValue)) {
|
|
76
|
+
delete targetFromProjectConfig.options[optionName];
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (Object.keys(targetFromProjectConfig.options).length === 0) {
|
|
80
|
+
delete targetFromProjectConfig.options;
|
|
81
|
+
}
|
|
82
|
+
// Configurations
|
|
83
|
+
for (const [configName, configOptions] of Object.entries(targetFromProjectConfig.configurations ?? {})) {
|
|
84
|
+
for (const [optionName, optionValue] of Object.entries(configOptions)) {
|
|
85
|
+
if (targetFromCreateNodes.configurations?.[configName]?.[optionName] ===
|
|
86
|
+
optionValue) {
|
|
87
|
+
delete targetFromProjectConfig.configurations[configName][optionName];
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (Object.keys(configOptions).length === 0) {
|
|
91
|
+
delete targetFromProjectConfig.configurations[configName];
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (Object.keys(targetFromProjectConfig.configurations ?? {}).length === 0) {
|
|
95
|
+
delete targetFromProjectConfig.configurations;
|
|
96
|
+
}
|
|
97
|
+
if (Object.keys(targetFromProjectConfig).length === 0) {
|
|
98
|
+
delete projectConfig.targets[targetName];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function equals(a, b) {
|
|
102
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
103
|
+
return a.length === b.length && a.every((v, i) => v === b[i]);
|
|
104
|
+
}
|
|
105
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
106
|
+
return hashObject(a) === hashObject(b);
|
|
107
|
+
}
|
|
108
|
+
return a === b;
|
|
109
|
+
}
|
|
110
|
+
function shouldRemoveArrayProperty(arrayValuesFromProjectConfiguration, arrayValuesFromCreateNodes) {
|
|
111
|
+
const setOfArrayValuesFromProjectConfiguration = new Set(arrayValuesFromProjectConfiguration);
|
|
112
|
+
loopThroughArrayValuesFromCreateNodes: for (const arrayValueFromCreateNodes of arrayValuesFromCreateNodes) {
|
|
113
|
+
if (typeof arrayValueFromCreateNodes === 'string') {
|
|
114
|
+
if (!setOfArrayValuesFromProjectConfiguration.has(arrayValueFromCreateNodes)) {
|
|
115
|
+
// If the inputs from the project configuration is missing an input from createNodes it was removed
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
setOfArrayValuesFromProjectConfiguration.delete(arrayValueFromCreateNodes);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
for (const arrayValue of setOfArrayValuesFromProjectConfiguration.values()) {
|
|
124
|
+
if (typeof arrayValue !== 'string' &&
|
|
125
|
+
hashObject(arrayValue) === hashObject(arrayValueFromCreateNodes)) {
|
|
126
|
+
setOfArrayValuesFromProjectConfiguration.delete(arrayValue);
|
|
127
|
+
// Continue the outer loop, breaking out of this loop
|
|
128
|
+
continue loopThroughArrayValuesFromCreateNodes;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// If an input was not matched, that means the input was removed
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// If there are still inputs in the project configuration, they have added additional inputs
|
|
136
|
+
return setOfArrayValuesFromProjectConfiguration.size === 0;
|
|
137
|
+
}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updatePackageScripts = void 0;
|
|
4
|
+
const path_1 = require("path");
|
|
5
|
+
const yargs = require("yargs-parser");
|
|
6
|
+
const nx_1 = require("../../nx");
|
|
7
|
+
const { glob, readJson, readNxJson, workspaceRoot, writeJson } = (0, nx_1.requireNx)();
|
|
8
|
+
async function updatePackageScripts(tree, createNodesTuple) {
|
|
9
|
+
const nxJson = readNxJson(tree);
|
|
10
|
+
const [pattern, createNodes] = createNodesTuple;
|
|
11
|
+
const matchingFiles = glob(tree, [pattern]);
|
|
12
|
+
for (const file of matchingFiles) {
|
|
13
|
+
const projectRoot = getProjectRootFromConfigFile(file);
|
|
14
|
+
await processProject(tree, projectRoot, file, createNodes, nxJson, matchingFiles);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.updatePackageScripts = updatePackageScripts;
|
|
18
|
+
async function processProject(tree, projectRoot, projectConfigurationFile, createNodesFunction, nxJsonConfiguration, configFiles) {
|
|
19
|
+
const packageJsonPath = `${projectRoot}/package.json`;
|
|
20
|
+
if (!tree.exists(packageJsonPath)) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const packageJson = readJson(tree, packageJsonPath);
|
|
24
|
+
if (!packageJson.scripts || !Object.keys(packageJson.scripts).length) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
const result = await createNodesFunction(projectConfigurationFile, {}, {
|
|
28
|
+
nxJsonConfiguration,
|
|
29
|
+
workspaceRoot,
|
|
30
|
+
configFiles,
|
|
31
|
+
});
|
|
32
|
+
const targetCommands = getInferredTargetCommands(result);
|
|
33
|
+
if (!targetCommands.length) {
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const replacedTargets = new Set();
|
|
37
|
+
for (const targetCommand of targetCommands) {
|
|
38
|
+
const { command, target, configuration } = targetCommand;
|
|
39
|
+
const targetCommandRegex = new RegExp(`(?<=^|&)((?: )*(?:[^&\\r\\n\\s]+ )*)(${command})((?: [^&\\r\\n\\s]+)*(?: )*)(?=$|&)`, 'g');
|
|
40
|
+
for (const scriptName of Object.keys(packageJson.scripts)) {
|
|
41
|
+
const script = packageJson.scripts[scriptName];
|
|
42
|
+
// quick check for exact match within the script
|
|
43
|
+
if (targetCommandRegex.test(script)) {
|
|
44
|
+
packageJson.scripts[scriptName] = script.replace(targetCommandRegex, configuration
|
|
45
|
+
? `$1nx ${target} --configuration=${configuration}$3`
|
|
46
|
+
: `$1nx ${target}$3`);
|
|
47
|
+
replacedTargets.add(target);
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
/**
|
|
51
|
+
* Parse script and command to handle the following:
|
|
52
|
+
* - if command doesn't match script => don't replace
|
|
53
|
+
* - if command has more args => don't replace
|
|
54
|
+
* - if command has same args, regardless of order => replace removing args
|
|
55
|
+
* - if command has less args or with different value => replace leaving args
|
|
56
|
+
*/
|
|
57
|
+
const parsedCommand = yargs(command, {
|
|
58
|
+
configuration: { 'strip-dashed': true },
|
|
59
|
+
});
|
|
60
|
+
// this assumes there are no positional args in the command, everything is a command or subcommand
|
|
61
|
+
const commandCommand = parsedCommand._.join(' ');
|
|
62
|
+
const commandRegex = new RegExp(`(?<=^|&)((?: )*(?:[^&\\r\\n\\s]+ )*)(${commandCommand})((?: [^&\\r\\n\\s]+)*( )*)(?=$|&)`, 'g');
|
|
63
|
+
const matches = script.match(commandRegex);
|
|
64
|
+
if (!matches) {
|
|
65
|
+
// the command doesn't match the script, don't replace
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
for (const match of matches) {
|
|
69
|
+
// parse the matched command within the script
|
|
70
|
+
const parsedScript = yargs(match, {
|
|
71
|
+
configuration: { 'strip-dashed': true },
|
|
72
|
+
});
|
|
73
|
+
let hasArgsWithDifferentValues = false;
|
|
74
|
+
let scriptHasExtraArgs = false;
|
|
75
|
+
let commandHasExtraArgs = false;
|
|
76
|
+
for (const [key, value] of Object.entries(parsedCommand)) {
|
|
77
|
+
if (key === '_') {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (parsedScript[key] === undefined) {
|
|
81
|
+
commandHasExtraArgs = true;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
if (parsedScript[key] !== value) {
|
|
85
|
+
hasArgsWithDifferentValues = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (commandHasExtraArgs) {
|
|
89
|
+
// the command has extra args, don't replace
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
for (const key of Object.keys(parsedScript)) {
|
|
93
|
+
if (key === '_') {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
if (!parsedCommand[key]) {
|
|
97
|
+
scriptHasExtraArgs = true;
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (!hasArgsWithDifferentValues && !scriptHasExtraArgs) {
|
|
102
|
+
// they are the same, replace with the command removing the args
|
|
103
|
+
packageJson.scripts[scriptName] = packageJson.scripts[scriptName].replace(match, match.replace(commandRegex, configuration
|
|
104
|
+
? `$1nx ${target} --configuration=${configuration}$4`
|
|
105
|
+
: `$1nx ${target}$4`));
|
|
106
|
+
replacedTargets.add(target);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
// there are different args or the script has extra args, replace with the command leaving the args
|
|
110
|
+
packageJson.scripts[scriptName] = packageJson.scripts[scriptName].replace(match, match.replace(commandRegex, configuration
|
|
111
|
+
? `$1nx ${target} --configuration=${configuration}$3`
|
|
112
|
+
: `$1nx ${target}$3`));
|
|
113
|
+
replacedTargets.add(target);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (process.env.NX_RUNNING_NX_INIT === 'true') {
|
|
120
|
+
// running `nx init` so we want to exclude everything by default
|
|
121
|
+
packageJson.nx ??= {};
|
|
122
|
+
packageJson.nx.includedScripts = [];
|
|
123
|
+
}
|
|
124
|
+
else if (replacedTargets.size) {
|
|
125
|
+
/**
|
|
126
|
+
* Running `nx add`. In this case we want to:
|
|
127
|
+
* - if `includedScripts` is already set: exclude scripts that match inferred targets that were used to replace a script
|
|
128
|
+
* - if `includedScripts` is not set: set `includedScripts` with all scripts except the ones that match an inferred target that was used to replace a script
|
|
129
|
+
*/
|
|
130
|
+
const includedScripts = packageJson.nx?.includedScripts ?? Object.keys(packageJson.scripts);
|
|
131
|
+
const filteredScripts = includedScripts.filter((s) => !replacedTargets.has(s));
|
|
132
|
+
if (filteredScripts.length !== includedScripts.length) {
|
|
133
|
+
packageJson.nx ??= {};
|
|
134
|
+
packageJson.nx.includedScripts = filteredScripts;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
writeJson(tree, packageJsonPath, packageJson);
|
|
138
|
+
}
|
|
139
|
+
function getInferredTargetCommands(result) {
|
|
140
|
+
const targetCommands = [];
|
|
141
|
+
for (const project of Object.values(result.projects ?? {})) {
|
|
142
|
+
for (const [targetName, target] of Object.entries(project.targets ?? {})) {
|
|
143
|
+
if (target.command) {
|
|
144
|
+
targetCommands.push({ command: target.command, target: targetName });
|
|
145
|
+
}
|
|
146
|
+
else if (target.executor === 'nx:run-commands' &&
|
|
147
|
+
target.options?.command) {
|
|
148
|
+
targetCommands.push({
|
|
149
|
+
command: target.options.command,
|
|
150
|
+
target: targetName,
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
if (!target.configurations) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
for (const [configurationName, configuration] of Object.entries(target.configurations)) {
|
|
157
|
+
if (configuration.command) {
|
|
158
|
+
targetCommands.push({
|
|
159
|
+
command: configuration.command,
|
|
160
|
+
target: targetName,
|
|
161
|
+
configuration: configurationName,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
else if (target.executor === 'nx:run-commands' &&
|
|
165
|
+
configuration.options?.command) {
|
|
166
|
+
targetCommands.push({
|
|
167
|
+
command: configuration.options.command,
|
|
168
|
+
target: targetName,
|
|
169
|
+
configuration: configurationName,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
return targetCommands;
|
|
176
|
+
}
|
|
177
|
+
function getProjectRootFromConfigFile(file) {
|
|
178
|
+
let projectRoot = (0, path_1.dirname)(file);
|
|
179
|
+
if ((0, path_1.basename)(projectRoot) === '.storybook') {
|
|
180
|
+
projectRoot = (0, path_1.dirname)(projectRoot);
|
|
181
|
+
}
|
|
182
|
+
return projectRoot;
|
|
183
|
+
}
|
package/src/utils/versions.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const typescriptVersion = "~5.
|
|
1
|
+
export declare const typescriptVersion = "~5.4.2";
|
package/src/utils/versions.js
CHANGED