@nx/devkit 16.7.0-beta.3 → 16.7.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": "16.7.0-beta.
|
|
3
|
+
"version": "16.7.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.",
|
|
6
6
|
"repository": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"Cypress",
|
|
20
20
|
"CLI"
|
|
21
21
|
],
|
|
22
|
-
"main": "./index",
|
|
22
|
+
"main": "./index.js",
|
|
23
23
|
"typings": "./index.d.ts",
|
|
24
24
|
"author": "Victor Savkin",
|
|
25
25
|
"license": "MIT",
|
|
@@ -28,8 +28,9 @@
|
|
|
28
28
|
},
|
|
29
29
|
"homepage": "https://nx.dev",
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@nrwl/devkit": "16.7.0-beta.
|
|
31
|
+
"@nrwl/devkit": "16.7.0-beta.4",
|
|
32
32
|
"ejs": "^3.1.7",
|
|
33
|
+
"enquirer": "~2.3.6",
|
|
33
34
|
"ignore": "^5.0.4",
|
|
34
35
|
"semver": "7.5.3",
|
|
35
36
|
"tmp": "~0.2.1",
|
|
@@ -44,6 +45,6 @@
|
|
|
44
45
|
"nx-migrations": {
|
|
45
46
|
"migrations": "./migrations.json"
|
|
46
47
|
},
|
|
47
|
-
"
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"type": "commonjs",
|
|
49
|
+
"gitHead": "dcbba686b182737b66ebbfb9db372769e77ba005"
|
|
49
50
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { ProjectType } from 'nx/src/config/workspace-json-project-json';
|
|
2
|
+
import type { Tree } from 'nx/src/generators/tree';
|
|
3
|
+
export type ProjectNameAndRootFormat = 'as-provided' | 'derived';
|
|
4
|
+
export type ProjectGenerationOptions = {
|
|
5
|
+
name: string;
|
|
6
|
+
projectType: ProjectType;
|
|
7
|
+
directory?: string;
|
|
8
|
+
importPath?: string;
|
|
9
|
+
projectNameAndRootFormat?: ProjectNameAndRootFormat;
|
|
10
|
+
rootProject?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export type ProjectNameAndRootOptions = {
|
|
13
|
+
/**
|
|
14
|
+
* Normalized full project name, including scope if name was provided with
|
|
15
|
+
* scope (e.g., `@scope/name`, only available when `projectNameAndRootFormat`
|
|
16
|
+
* is `as-provided`).
|
|
17
|
+
*/
|
|
18
|
+
projectName: string;
|
|
19
|
+
/**
|
|
20
|
+
* Normalized project directory, including the layout directory if configured.
|
|
21
|
+
*/
|
|
22
|
+
projectDirectory: string;
|
|
23
|
+
names: {
|
|
24
|
+
/**
|
|
25
|
+
* Normalized project name without scope. It's meant to be used when
|
|
26
|
+
* generating file names that contain the project name.
|
|
27
|
+
*/
|
|
28
|
+
projectFileName: string;
|
|
29
|
+
/**
|
|
30
|
+
* Normalized project name without scope or directory. It's meant to be used
|
|
31
|
+
* when generating shorter file names that contain the project name.
|
|
32
|
+
*/
|
|
33
|
+
projectSimpleName: string;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Normalized import path for the project.
|
|
37
|
+
*/
|
|
38
|
+
importPath?: string;
|
|
39
|
+
};
|
|
40
|
+
export declare function determineProjectNameAndRootOptions(tree: Tree, options: ProjectGenerationOptions): Promise<ProjectNameAndRootOptions>;
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.determineProjectNameAndRootOptions = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const enquirer_1 = require("enquirer");
|
|
6
|
+
const nx_1 = require("../../nx");
|
|
7
|
+
const get_workspace_layout_1 = require("../utils/get-workspace-layout");
|
|
8
|
+
const names_1 = require("../utils/names");
|
|
9
|
+
const { joinPathFragments, readJson, readNxJson } = (0, nx_1.requireNx)();
|
|
10
|
+
function determineProjectNameAndRootOptions(tree, options) {
|
|
11
|
+
var _a;
|
|
12
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
13
|
+
validateName(options.name, options.projectNameAndRootFormat);
|
|
14
|
+
const formats = getProjectNameAndRootFormats(tree, options);
|
|
15
|
+
const format = (_a = options.projectNameAndRootFormat) !== null && _a !== void 0 ? _a : (yield determineFormat(formats));
|
|
16
|
+
return formats[format].options;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
exports.determineProjectNameAndRootOptions = determineProjectNameAndRootOptions;
|
|
20
|
+
function validateName(name, projectNameAndRootFormat) {
|
|
21
|
+
if (projectNameAndRootFormat === 'derived' && name.startsWith('@')) {
|
|
22
|
+
throw new Error(`The project name "${name}" cannot start with "@" when the "projectNameAndRootFormat" is "derived".`);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Matches two types of project names:
|
|
26
|
+
*
|
|
27
|
+
* 1. Valid npm package names (e.g., '@scope/name' or 'name').
|
|
28
|
+
* 2. Names starting with a letter and can contain any character except whitespace and ':'.
|
|
29
|
+
*
|
|
30
|
+
* The second case is to support the legacy behavior (^[a-zA-Z].*$) with the difference
|
|
31
|
+
* that it doesn't allow the ":" character. It was wrong to allow it because it would
|
|
32
|
+
* conflict with the notation for tasks.
|
|
33
|
+
*/
|
|
34
|
+
const pattern = '(?:^@[a-zA-Z0-9-*~][a-zA-Z0-9-*._~]*\\/[a-zA-Z0-9-~][a-zA-Z0-9-._~]*|^[a-zA-Z][^:]*)$';
|
|
35
|
+
const validationRegex = new RegExp(pattern);
|
|
36
|
+
if (!validationRegex.test(name)) {
|
|
37
|
+
throw new Error(`The project name should match the pattern "${pattern}". The provided value "${name}" does not match.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function determineFormat(formats) {
|
|
41
|
+
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
if (!formats.derived) {
|
|
43
|
+
return 'as-provided';
|
|
44
|
+
}
|
|
45
|
+
if (process.env.NX_INTERACTIVE !== 'true' || !isTTY()) {
|
|
46
|
+
return 'derived';
|
|
47
|
+
}
|
|
48
|
+
return yield (0, enquirer_1.prompt)({
|
|
49
|
+
type: 'select',
|
|
50
|
+
name: 'format',
|
|
51
|
+
message: 'What should be the project name and where should it be generated?',
|
|
52
|
+
choices: [
|
|
53
|
+
{
|
|
54
|
+
message: formats['as-provided'].description,
|
|
55
|
+
name: 'as-provided',
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
message: formats['derived'].description,
|
|
59
|
+
name: 'derived',
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
initial: 'as-provided',
|
|
63
|
+
}).then(({ format }) => format);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
function getProjectNameAndRootFormats(tree, options) {
|
|
67
|
+
var _a, _b, _c, _d;
|
|
68
|
+
const name = (0, names_1.names)(options.name).fileName;
|
|
69
|
+
const directory = (_a = options.directory) === null || _a === void 0 ? void 0 : _a.replace(/^\.?\//, '');
|
|
70
|
+
const asProvidedProjectName = name;
|
|
71
|
+
const asProvidedProjectDirectory = directory
|
|
72
|
+
? (0, names_1.names)(directory).fileName
|
|
73
|
+
: options.rootProject
|
|
74
|
+
? '.'
|
|
75
|
+
: asProvidedProjectName;
|
|
76
|
+
if (name.startsWith('@')) {
|
|
77
|
+
const nameWithoutScope = asProvidedProjectName.split('/')[1];
|
|
78
|
+
return {
|
|
79
|
+
'as-provided': {
|
|
80
|
+
description: `Recommended:
|
|
81
|
+
Name: ${asProvidedProjectName}
|
|
82
|
+
Root: ${asProvidedProjectDirectory}`,
|
|
83
|
+
options: {
|
|
84
|
+
projectName: asProvidedProjectName,
|
|
85
|
+
names: {
|
|
86
|
+
projectSimpleName: nameWithoutScope,
|
|
87
|
+
projectFileName: nameWithoutScope,
|
|
88
|
+
},
|
|
89
|
+
importPath: (_b = options.importPath) !== null && _b !== void 0 ? _b : asProvidedProjectName,
|
|
90
|
+
projectDirectory: asProvidedProjectDirectory,
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
let asProvidedImportPath;
|
|
96
|
+
let npmScope;
|
|
97
|
+
if (options.projectType === 'library') {
|
|
98
|
+
asProvidedImportPath = options.importPath;
|
|
99
|
+
if (!asProvidedImportPath) {
|
|
100
|
+
npmScope = getNpmScope(tree);
|
|
101
|
+
asProvidedImportPath =
|
|
102
|
+
asProvidedProjectDirectory === '.'
|
|
103
|
+
? (_c = readJson(tree, 'package.json').name) !== null && _c !== void 0 ? _c : getImportPath(npmScope, asProvidedProjectName)
|
|
104
|
+
: getImportPath(npmScope, asProvidedProjectName);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
let { projectDirectory, layoutDirectory } = getDirectories(tree, directory, options.projectType);
|
|
108
|
+
const derivedProjectDirectoryWithoutLayout = projectDirectory
|
|
109
|
+
? `${(0, names_1.names)(projectDirectory).fileName}/${name}`
|
|
110
|
+
: options.rootProject
|
|
111
|
+
? '.'
|
|
112
|
+
: name;
|
|
113
|
+
// the project name uses the directory without the layout directory
|
|
114
|
+
const derivedProjectName = derivedProjectDirectoryWithoutLayout === '.'
|
|
115
|
+
? name
|
|
116
|
+
: derivedProjectDirectoryWithoutLayout.replace(/\//g, '-');
|
|
117
|
+
const derivedSimpleProjectName = name;
|
|
118
|
+
let derivedProjectDirectory = derivedProjectDirectoryWithoutLayout;
|
|
119
|
+
if (derivedProjectDirectoryWithoutLayout !== '.') {
|
|
120
|
+
// prepend the layout directory
|
|
121
|
+
derivedProjectDirectory = joinPathFragments(layoutDirectory, derivedProjectDirectory);
|
|
122
|
+
}
|
|
123
|
+
let derivedImportPath;
|
|
124
|
+
if (options.projectType === 'library') {
|
|
125
|
+
derivedImportPath = options.importPath;
|
|
126
|
+
if (!derivedImportPath) {
|
|
127
|
+
derivedImportPath =
|
|
128
|
+
derivedProjectDirectory === '.'
|
|
129
|
+
? (_d = readJson(tree, 'package.json').name) !== null && _d !== void 0 ? _d : getImportPath(npmScope, derivedProjectName)
|
|
130
|
+
: getImportPath(npmScope, derivedProjectDirectoryWithoutLayout);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
'as-provided': {
|
|
135
|
+
description: `Recommended:
|
|
136
|
+
Name: ${asProvidedProjectName}
|
|
137
|
+
Root: ${asProvidedProjectDirectory}`,
|
|
138
|
+
options: {
|
|
139
|
+
projectName: asProvidedProjectName,
|
|
140
|
+
names: {
|
|
141
|
+
projectSimpleName: asProvidedProjectName,
|
|
142
|
+
projectFileName: asProvidedProjectName,
|
|
143
|
+
},
|
|
144
|
+
importPath: asProvidedImportPath,
|
|
145
|
+
projectDirectory: asProvidedProjectDirectory,
|
|
146
|
+
},
|
|
147
|
+
},
|
|
148
|
+
derived: {
|
|
149
|
+
description: `Legacy:
|
|
150
|
+
Name: ${derivedProjectName}
|
|
151
|
+
Root: ${derivedProjectDirectory}`,
|
|
152
|
+
options: {
|
|
153
|
+
projectName: derivedProjectName,
|
|
154
|
+
names: {
|
|
155
|
+
projectSimpleName: derivedSimpleProjectName,
|
|
156
|
+
projectFileName: derivedProjectName,
|
|
157
|
+
},
|
|
158
|
+
importPath: derivedImportPath,
|
|
159
|
+
projectDirectory: derivedProjectDirectory,
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
function getDirectories(tree, directory, projectType) {
|
|
165
|
+
let { projectDirectory, layoutDirectory } = (0, get_workspace_layout_1.extractLayoutDirectory)(directory);
|
|
166
|
+
if (!layoutDirectory) {
|
|
167
|
+
const { appsDir, libsDir } = (0, get_workspace_layout_1.getWorkspaceLayout)(tree);
|
|
168
|
+
layoutDirectory = projectType === 'application' ? appsDir : libsDir;
|
|
169
|
+
}
|
|
170
|
+
return { projectDirectory, layoutDirectory };
|
|
171
|
+
}
|
|
172
|
+
function getImportPath(npmScope, name) {
|
|
173
|
+
return npmScope ? `${npmScope === '@' ? '' : '@'}${npmScope}/${name}` : name;
|
|
174
|
+
}
|
|
175
|
+
function getNpmScope(tree) {
|
|
176
|
+
const nxJson = readNxJson(tree);
|
|
177
|
+
// TODO(v17): Remove reading this from nx.json
|
|
178
|
+
if (nxJson === null || nxJson === void 0 ? void 0 : nxJson.npmScope) {
|
|
179
|
+
return nxJson.npmScope;
|
|
180
|
+
}
|
|
181
|
+
const { name } = tree.exists('package.json')
|
|
182
|
+
? readJson(tree, 'package.json')
|
|
183
|
+
: { name: null };
|
|
184
|
+
return (name === null || name === void 0 ? void 0 : name.startsWith('@')) ? name.split('/')[0].substring(1) : undefined;
|
|
185
|
+
}
|
|
186
|
+
function isTTY() {
|
|
187
|
+
return !!process.stdout.isTTY && process.env['CI'] !== 'true';
|
|
188
|
+
}
|