@nx/devkit 17.2.0-beta.2 → 17.2.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/devkit",
|
|
3
|
-
"version": "17.2.0-beta.
|
|
3
|
+
"version": "17.2.0-beta.4",
|
|
4
4
|
"private": false,
|
|
5
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": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"tmp": "~0.2.1",
|
|
35
35
|
"tslib": "^2.3.0",
|
|
36
36
|
"semver": "7.5.3",
|
|
37
|
-
"@nrwl/devkit": "17.2.0-beta.
|
|
37
|
+
"@nrwl/devkit": "17.2.0-beta.4"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"nx": ">= 16 <= 18"
|
|
@@ -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 18, 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}`;
|
|
@@ -78,113 +82,154 @@ async function determineFormat(tree, formats, callingGenerator) {
|
|
|
78
82
|
],
|
|
79
83
|
initial: 'as-provided',
|
|
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
|
+
}
|