@nx/devkit 0.0.0-pr-22179-271588f
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 +22 -0
- package/README.md +68 -0
- package/index.d.ts +14 -0
- package/index.js +18 -0
- package/migrations.json +18 -0
- package/ngcli-adapter.d.ts +4 -0
- package/ngcli-adapter.js +11 -0
- package/nx.d.ts +1 -0
- package/nx.js +19 -0
- package/package.json +50 -0
- package/public-api.d.ts +78 -0
- package/public-api.js +100 -0
- package/src/executors/parse-target-string.d.ts +44 -0
- package/src/executors/parse-target-string.js +55 -0
- package/src/executors/read-target-options.d.ts +8 -0
- package/src/executors/read-target-options.js +38 -0
- 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.d.ts +48 -0
- package/src/generators/artifact-name-and-directory-utils.js +239 -0
- package/src/generators/executor-options-utils.d.ts +21 -0
- package/src/generators/executor-options-utils.js +49 -0
- package/src/generators/format-files.d.ts +6 -0
- package/src/generators/format-files.js +91 -0
- package/src/generators/generate-files.d.ts +26 -0
- package/src/generators/generate-files.js +91 -0
- package/src/generators/project-name-and-root-utils.d.ts +47 -0
- package/src/generators/project-name-and-root-utils.js +298 -0
- package/src/generators/run-tasks-in-serial.d.ts +7 -0
- package/src/generators/run-tasks-in-serial.js +16 -0
- package/src/generators/to-js.d.ts +11 -0
- package/src/generators/to-js.js +24 -0
- package/src/generators/typescript/insert-import.d.ts +1 -0
- package/src/generators/typescript/insert-import.js +5 -0
- package/src/generators/typescript/insert-statement.d.ts +1 -0
- package/src/generators/typescript/insert-statement.js +5 -0
- package/src/generators/update-ts-configs-to-js.d.ts +4 -0
- package/src/generators/update-ts-configs-to-js.js +49 -0
- package/src/generators/visit-not-ignored-files.d.ts +5 -0
- package/src/generators/visit-not-ignored-files.js +41 -0
- package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +2 -0
- package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +9 -0
- package/src/migrations/update-16-9-0/migrate-mf-util-usage.d.ts +4 -0
- package/src/migrations/update-16-9-0/migrate-mf-util-usage.js +201 -0
- package/src/tasks/install-packages-task.d.ts +10 -0
- package/src/tasks/install-packages-task.js +41 -0
- package/src/utils/async-iterable/combine-async-iterables.d.ts +3 -0
- package/src/utils/async-iterable/combine-async-iterables.js +58 -0
- package/src/utils/async-iterable/create-async-iterable.d.ts +6 -0
- package/src/utils/async-iterable/create-async-iterable.js +58 -0
- package/src/utils/async-iterable/index.d.ts +4 -0
- package/src/utils/async-iterable/index.js +7 -0
- package/src/utils/async-iterable/map-async-iteratable.d.ts +1 -0
- package/src/utils/async-iterable/map-async-iteratable.js +18 -0
- package/src/utils/async-iterable/tap-async-iteratable.d.ts +1 -0
- package/src/utils/async-iterable/tap-async-iteratable.js +11 -0
- package/src/utils/binary-extensions.d.ts +1 -0
- package/src/utils/binary-extensions.js +275 -0
- 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.d.ts +7 -0
- package/src/utils/convert-nx-executor.js +89 -0
- 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 +24 -0
- package/src/utils/get-workspace-layout.js +52 -0
- package/src/utils/invoke-nx-generator.d.ts +6 -0
- package/src/utils/invoke-nx-generator.js +172 -0
- package/src/utils/log-show-project-command.d.ts +1 -0
- package/src/utils/log-show-project-command.js +14 -0
- package/src/utils/move-dir.d.ts +5 -0
- package/src/utils/move-dir.js +28 -0
- package/src/utils/names.d.ts +18 -0
- package/src/utils/names.js +63 -0
- package/src/utils/offset-from-root.d.ts +13 -0
- package/src/utils/offset-from-root.js +29 -0
- package/src/utils/package-json.d.ts +78 -0
- package/src/utils/package-json.js +375 -0
- package/src/utils/replace-package.d.ts +2 -0
- package/src/utils/replace-package.js +125 -0
- package/src/utils/replace-project-configuration-with-plugin.d.ts +3 -0
- package/src/utils/replace-project-configuration-with-plugin.js +136 -0
- package/src/utils/rxjs-for-await.d.ts +109 -0
- package/src/utils/rxjs-for-await.js +363 -0
- package/src/utils/semver.d.ts +1 -0
- package/src/utils/semver.js +18 -0
- package/src/utils/string-change.d.ts +62 -0
- package/src/utils/string-change.js +109 -0
- package/src/utils/string-utils.d.ts +95 -0
- package/src/utils/string-utils.js +147 -0
- package/src/utils/update-package-scripts.d.ts +3 -0
- package/src/utils/update-package-scripts.js +175 -0
- package/src/utils/versions.d.ts +1 -0
- package/src/utils/versions.js +4 -0
- package/testing.d.ts +1 -0
- package/testing.js +5 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setCwd = exports.getRelativeCwd = exports.determineArtifactNameAndDirectoryOptions = void 0;
|
|
4
|
+
const enquirer_1 = require("enquirer");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const nx_1 = require("../../nx");
|
|
7
|
+
const names_1 = require("../utils/names");
|
|
8
|
+
const { createProjectRootMappingsFromProjectConfigurations, findProjectForPath, getProjects, joinPathFragments, logger, normalizePath, output, workspaceRoot, } = (0, nx_1.requireNx)();
|
|
9
|
+
async function determineArtifactNameAndDirectoryOptions(tree, options) {
|
|
10
|
+
if (!options.nameAndDirectoryFormat &&
|
|
11
|
+
(process.env.NX_INTERACTIVE !== 'true' || !isTTY())) {
|
|
12
|
+
options.nameAndDirectoryFormat = 'derived';
|
|
13
|
+
}
|
|
14
|
+
const formats = getNameAndDirectoryOptionFormats(tree, options);
|
|
15
|
+
const format = options.nameAndDirectoryFormat ?? (await determineFormat(formats, options));
|
|
16
|
+
validateResolvedProject(tree, formats[format]?.project, options, formats[format]?.directory);
|
|
17
|
+
if (format === 'derived' && options.callingGenerator) {
|
|
18
|
+
logDeprecationMessage(options, formats);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
...formats[format],
|
|
22
|
+
nameAndDirectoryFormat: format,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
exports.determineArtifactNameAndDirectoryOptions = determineArtifactNameAndDirectoryOptions;
|
|
26
|
+
async function determineFormat(formats, options) {
|
|
27
|
+
if (!formats.derived) {
|
|
28
|
+
return 'as-provided';
|
|
29
|
+
}
|
|
30
|
+
const asProvidedDescription = `As provided: ${formats['as-provided'].filePath}`;
|
|
31
|
+
const asProvidedSelectedValue = formats['as-provided'].filePath;
|
|
32
|
+
const derivedDescription = `Derived: ${formats['derived'].filePath}`;
|
|
33
|
+
const derivedSelectedValue = formats['derived'].filePath;
|
|
34
|
+
if (asProvidedSelectedValue === derivedSelectedValue) {
|
|
35
|
+
return 'as-provided';
|
|
36
|
+
}
|
|
37
|
+
const result = await (0, enquirer_1.prompt)({
|
|
38
|
+
type: 'select',
|
|
39
|
+
name: 'format',
|
|
40
|
+
message: `Where should the ${options.artifactType} be generated?`,
|
|
41
|
+
choices: [
|
|
42
|
+
{
|
|
43
|
+
message: asProvidedDescription,
|
|
44
|
+
name: asProvidedSelectedValue,
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
message: derivedDescription,
|
|
48
|
+
name: derivedSelectedValue,
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
initial: 0,
|
|
52
|
+
}).then(({ format }) => format === asProvidedSelectedValue ? 'as-provided' : 'derived');
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
function logDeprecationMessage(options, formats) {
|
|
56
|
+
logger.warn(`
|
|
57
|
+
In Nx 19, generating a ${options.artifactType} will no longer support providing a project and deriving the directory.
|
|
58
|
+
Please provide the exact directory in the future.
|
|
59
|
+
Example: nx g ${options.callingGenerator} ${formats['derived'].artifactName} --directory ${formats['derived'].directory}
|
|
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.
|
|
61
|
+
`);
|
|
62
|
+
}
|
|
63
|
+
function getNameAndDirectoryOptionFormats(tree, options) {
|
|
64
|
+
const directory = options.directory
|
|
65
|
+
? normalizePath(options.directory.replace(/^\.?\//, ''))
|
|
66
|
+
: undefined;
|
|
67
|
+
const fileExtension = options.fileExtension ?? 'ts';
|
|
68
|
+
const { name: extractedName, directory: extractedDirectory } = extractNameAndDirectoryFromName(options.name);
|
|
69
|
+
if (extractedDirectory && directory) {
|
|
70
|
+
throw new Error(`You can't specify both a directory (${options.directory}) and a name with a directory path (${options.name}). ` +
|
|
71
|
+
`Please specify either a directory or a name with a directory path.`);
|
|
72
|
+
}
|
|
73
|
+
const asProvidedOptions = getAsProvidedOptions(tree, {
|
|
74
|
+
...options,
|
|
75
|
+
directory: directory ?? extractedDirectory,
|
|
76
|
+
fileExtension,
|
|
77
|
+
name: extractedName,
|
|
78
|
+
});
|
|
79
|
+
if (!options.project) {
|
|
80
|
+
validateResolvedProject(tree, asProvidedOptions.project, options, asProvidedOptions.directory);
|
|
81
|
+
}
|
|
82
|
+
if (options.nameAndDirectoryFormat === 'as-provided') {
|
|
83
|
+
return {
|
|
84
|
+
'as-provided': asProvidedOptions,
|
|
85
|
+
derived: undefined,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
if (options.disallowPathInNameForDerived && options.name.includes('/')) {
|
|
89
|
+
if (!options.nameAndDirectoryFormat) {
|
|
90
|
+
output.warn({
|
|
91
|
+
title: `The provided name "${options.name}" contains a path and this is not supported by the "${options.callingGenerator}" when using the "derived" format.`,
|
|
92
|
+
bodyLines: [
|
|
93
|
+
`The generator will try to generate the ${options.artifactType} using the "as-provided" format at "${asProvidedOptions.filePath}".`,
|
|
94
|
+
],
|
|
95
|
+
});
|
|
96
|
+
return {
|
|
97
|
+
'as-provided': asProvidedOptions,
|
|
98
|
+
derived: undefined,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
throw new Error(`The provided name "${options.name}" contains a path and this is not supported by the "${options.callingGenerator}" when using the "derived" format. ` +
|
|
102
|
+
`Please provide a name without a path or use the "as-provided" format.`);
|
|
103
|
+
}
|
|
104
|
+
const derivedOptions = getDerivedOptions(tree, {
|
|
105
|
+
...options,
|
|
106
|
+
directory,
|
|
107
|
+
fileExtension,
|
|
108
|
+
name: extractedName,
|
|
109
|
+
}, asProvidedOptions, !options.disallowPathInNameForDerived && extractedDirectory
|
|
110
|
+
? extractedDirectory
|
|
111
|
+
: undefined);
|
|
112
|
+
return {
|
|
113
|
+
'as-provided': asProvidedOptions,
|
|
114
|
+
derived: derivedOptions,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function getAsProvidedOptions(tree, options) {
|
|
118
|
+
const relativeCwd = getRelativeCwd();
|
|
119
|
+
const asProvidedDirectory = options.directory
|
|
120
|
+
? joinPathFragments(relativeCwd, options.directory)
|
|
121
|
+
: relativeCwd;
|
|
122
|
+
const asProvidedProject = findProjectFromPath(tree, asProvidedDirectory);
|
|
123
|
+
const asProvidedFileName = options.fileName ??
|
|
124
|
+
(options.suffix ? `${options.name}.${options.suffix}` : options.name);
|
|
125
|
+
const asProvidedFilePath = joinPathFragments(asProvidedDirectory, `${asProvidedFileName}.${options.fileExtension}`);
|
|
126
|
+
return {
|
|
127
|
+
artifactName: options.name,
|
|
128
|
+
directory: asProvidedDirectory,
|
|
129
|
+
fileName: asProvidedFileName,
|
|
130
|
+
filePath: asProvidedFilePath,
|
|
131
|
+
project: asProvidedProject,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function getDerivedOptions(tree, options, asProvidedOptions, extractedDirectory) {
|
|
135
|
+
const projects = getProjects(tree);
|
|
136
|
+
if (options.project && !projects.has(options.project)) {
|
|
137
|
+
throw new Error(`The provided project "${options.project}" does not exist! Please provide an existing project name.`);
|
|
138
|
+
}
|
|
139
|
+
const projectName = options.project ?? asProvidedOptions.project;
|
|
140
|
+
const project = projects.get(projectName);
|
|
141
|
+
const derivedName = options.name;
|
|
142
|
+
const baseDirectory = options.directory
|
|
143
|
+
? (0, names_1.names)(options.directory).fileName
|
|
144
|
+
: joinPathFragments(project.sourceRoot ?? joinPathFragments(project.root, 'src'), project.projectType === 'application' ? 'app' : 'lib', extractedDirectory ?? '');
|
|
145
|
+
const derivedDirectory = typeof options.derivedDirectory === 'string'
|
|
146
|
+
? joinPathFragments(project.sourceRoot ?? project.root, options.derivedDirectory, options.flat
|
|
147
|
+
? ''
|
|
148
|
+
: options.pascalCaseDirectory
|
|
149
|
+
? (0, names_1.names)(derivedName).className
|
|
150
|
+
: (0, names_1.names)(derivedName).fileName)
|
|
151
|
+
: options.flat
|
|
152
|
+
? normalizePath(baseDirectory)
|
|
153
|
+
: joinPathFragments(baseDirectory, options.pascalCaseDirectory
|
|
154
|
+
? (0, names_1.names)(derivedName).className
|
|
155
|
+
: (0, names_1.names)(derivedName).fileName);
|
|
156
|
+
if (options.directory &&
|
|
157
|
+
!isDirectoryUnderProjectRoot(derivedDirectory, project.root)) {
|
|
158
|
+
if (!options.nameAndDirectoryFormat) {
|
|
159
|
+
output.warn({
|
|
160
|
+
title: `The provided directory "${options.directory}" is not under the provided project root "${project.root}".`,
|
|
161
|
+
bodyLines: [
|
|
162
|
+
`The generator will try to generate the ${options.artifactType} using the "as-provided" format.`,
|
|
163
|
+
`With the "as-provided" format, the "project" option is ignored and the ${options.artifactType} will be generated at "${asProvidedOptions.filePath}" (<cwd>/<provided directory>).`,
|
|
164
|
+
],
|
|
165
|
+
});
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
throw new Error(`The provided directory "${options.directory}" is not under the provided project root "${project.root}". ` +
|
|
169
|
+
`Please provide a directory that is under the provided project root or use the "as-provided" format and only provide the directory.`);
|
|
170
|
+
}
|
|
171
|
+
let derivedFileName = options.fileName;
|
|
172
|
+
if (!derivedFileName) {
|
|
173
|
+
derivedFileName = options.suffix
|
|
174
|
+
? `${derivedName}.${options.suffix}`
|
|
175
|
+
: derivedName;
|
|
176
|
+
derivedFileName = options.pascalCaseFile
|
|
177
|
+
? (0, names_1.names)(derivedFileName).className
|
|
178
|
+
: (0, names_1.names)(derivedFileName).fileName;
|
|
179
|
+
}
|
|
180
|
+
const derivedFilePath = joinPathFragments(derivedDirectory, `${derivedFileName}.${options.fileExtension}`);
|
|
181
|
+
return {
|
|
182
|
+
artifactName: derivedName,
|
|
183
|
+
directory: derivedDirectory,
|
|
184
|
+
fileName: derivedFileName,
|
|
185
|
+
filePath: derivedFilePath,
|
|
186
|
+
project: projectName,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function validateResolvedProject(tree, project, options, normalizedDirectory) {
|
|
190
|
+
if (project) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (options.directory) {
|
|
194
|
+
throw new Error(`The provided directory resolved relative to the current working directory "${normalizedDirectory}" does not exist under any project root. ` +
|
|
195
|
+
`Please make sure to navigate to a location or provide a directory that exists under a project root.`);
|
|
196
|
+
}
|
|
197
|
+
throw new Error(`The current working directory "${getRelativeCwd() || '.'}" does not exist under any project root. ` +
|
|
198
|
+
`Please make sure to navigate to a location or provide a directory that exists under a project root.`);
|
|
199
|
+
}
|
|
200
|
+
function findProjectFromPath(tree, path) {
|
|
201
|
+
const projectConfigurations = {};
|
|
202
|
+
const projects = getProjects(tree);
|
|
203
|
+
for (const [projectName, project] of projects) {
|
|
204
|
+
projectConfigurations[projectName] = project;
|
|
205
|
+
}
|
|
206
|
+
const projectRootMappings = createProjectRootMappingsFromProjectConfigurations(projectConfigurations);
|
|
207
|
+
return findProjectForPath(path, projectRootMappings);
|
|
208
|
+
}
|
|
209
|
+
function isDirectoryUnderProjectRoot(directory, projectRoot) {
|
|
210
|
+
const normalizedDirectory = joinPathFragments(workspaceRoot, directory);
|
|
211
|
+
const normalizedProjectRoot = joinPathFragments(workspaceRoot, projectRoot).replace(/\/$/, '');
|
|
212
|
+
return (normalizedDirectory === normalizedProjectRoot ||
|
|
213
|
+
normalizedDirectory.startsWith(`${normalizedProjectRoot}/`));
|
|
214
|
+
}
|
|
215
|
+
function isTTY() {
|
|
216
|
+
return !!process.stdout.isTTY && process.env['CI'] !== 'true';
|
|
217
|
+
}
|
|
218
|
+
function getRelativeCwd() {
|
|
219
|
+
return normalizePath((0, path_1.relative)(workspaceRoot, getCwd()));
|
|
220
|
+
}
|
|
221
|
+
exports.getRelativeCwd = getRelativeCwd;
|
|
222
|
+
/**
|
|
223
|
+
* Function for setting cwd during testing
|
|
224
|
+
*/
|
|
225
|
+
function setCwd(path) {
|
|
226
|
+
process.env.INIT_CWD = (0, path_1.join)(workspaceRoot, path);
|
|
227
|
+
}
|
|
228
|
+
exports.setCwd = setCwd;
|
|
229
|
+
function getCwd() {
|
|
230
|
+
return process.env.INIT_CWD?.startsWith(workspaceRoot)
|
|
231
|
+
? process.env.INIT_CWD
|
|
232
|
+
: process.cwd();
|
|
233
|
+
}
|
|
234
|
+
function extractNameAndDirectoryFromName(rawName) {
|
|
235
|
+
const parsedName = normalizePath(rawName).split('/');
|
|
236
|
+
const name = parsedName.pop();
|
|
237
|
+
const directory = parsedName.length ? parsedName.join('/') : undefined;
|
|
238
|
+
return { name, directory };
|
|
239
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Tree } from 'nx/src/generators/tree';
|
|
2
|
+
import type { ProjectGraph } from 'nx/src/config/project-graph';
|
|
3
|
+
type CallBack<T> = (currentValue: T, project: string, target: string, configuration?: string) => void;
|
|
4
|
+
/**
|
|
5
|
+
* Calls a function for each different options that an executor is configured with
|
|
6
|
+
*/
|
|
7
|
+
export declare function forEachExecutorOptions<Options>(tree: Tree,
|
|
8
|
+
/**
|
|
9
|
+
* Name of the executor to update options for
|
|
10
|
+
*/
|
|
11
|
+
executorName: string,
|
|
12
|
+
/**
|
|
13
|
+
* Callback that is called for each options configured for a builder
|
|
14
|
+
*/
|
|
15
|
+
callback: CallBack<Options>): void;
|
|
16
|
+
/**
|
|
17
|
+
* Calls a function for each different options that an executor is configured with via the project graph
|
|
18
|
+
* this is helpful when you need to get the expaned configuration options from the nx.json
|
|
19
|
+
**/
|
|
20
|
+
export declare function forEachExecutorOptionsInGraph<Options>(graph: ProjectGraph, executorName: string, callback: CallBack<Options>): void;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.forEachExecutorOptionsInGraph = exports.forEachExecutorOptions = void 0;
|
|
4
|
+
const nx_1 = require("../../nx");
|
|
5
|
+
const { getProjects } = (0, nx_1.requireNx)();
|
|
6
|
+
/**
|
|
7
|
+
* Calls a function for each different options that an executor is configured with
|
|
8
|
+
*/
|
|
9
|
+
function forEachExecutorOptions(tree,
|
|
10
|
+
/**
|
|
11
|
+
* Name of the executor to update options for
|
|
12
|
+
*/
|
|
13
|
+
executorName,
|
|
14
|
+
/**
|
|
15
|
+
* Callback that is called for each options configured for a builder
|
|
16
|
+
*/
|
|
17
|
+
callback) {
|
|
18
|
+
forEachProjectConfig(getProjects(tree), executorName, callback);
|
|
19
|
+
}
|
|
20
|
+
exports.forEachExecutorOptions = forEachExecutorOptions;
|
|
21
|
+
/**
|
|
22
|
+
* Calls a function for each different options that an executor is configured with via the project graph
|
|
23
|
+
* this is helpful when you need to get the expaned configuration options from the nx.json
|
|
24
|
+
**/
|
|
25
|
+
function forEachExecutorOptionsInGraph(graph, executorName, callback) {
|
|
26
|
+
const projects = new Map();
|
|
27
|
+
Object.values(graph.nodes).forEach((p) => projects.set(p.name, p.data));
|
|
28
|
+
forEachProjectConfig(projects, executorName, callback);
|
|
29
|
+
}
|
|
30
|
+
exports.forEachExecutorOptionsInGraph = forEachExecutorOptionsInGraph;
|
|
31
|
+
function forEachProjectConfig(projects, executorName, callback) {
|
|
32
|
+
for (const [projectName, project] of projects) {
|
|
33
|
+
for (const [targetName, target] of Object.entries(project.targets || {})) {
|
|
34
|
+
if (executorName !== target.executor) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
if (target.options) {
|
|
38
|
+
callback(target.options, projectName, targetName);
|
|
39
|
+
}
|
|
40
|
+
if (!target.configurations) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
Object.entries(target.configurations).forEach(([configName, options]) => {
|
|
44
|
+
callback(options, projectName, targetName, configName);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// TODO: add a method for updating options
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formatFiles = void 0;
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const nx_1 = require("../../nx");
|
|
6
|
+
let { updateJson, readJson, sortObjectByKeys } = (0, nx_1.requireNx)();
|
|
7
|
+
// TODO: Remove this in Nx 19 when Nx 16.7.0 is no longer supported
|
|
8
|
+
sortObjectByKeys =
|
|
9
|
+
sortObjectByKeys ?? require('nx/src/utils/object-sort').sortObjectByKeys;
|
|
10
|
+
/**
|
|
11
|
+
* Formats all the created or updated files using Prettier
|
|
12
|
+
* @param tree - the file system tree
|
|
13
|
+
*/
|
|
14
|
+
async function formatFiles(tree) {
|
|
15
|
+
let prettier;
|
|
16
|
+
try {
|
|
17
|
+
prettier = await Promise.resolve().then(() => require('prettier'));
|
|
18
|
+
}
|
|
19
|
+
catch { }
|
|
20
|
+
sortTsConfig(tree);
|
|
21
|
+
if (!prettier)
|
|
22
|
+
return;
|
|
23
|
+
const files = new Set(tree.listChanges().filter((file) => file.type !== 'DELETE'));
|
|
24
|
+
const changedPrettierInTree = getChangedPrettierConfigInTree(tree);
|
|
25
|
+
await Promise.all(Array.from(files).map(async (file) => {
|
|
26
|
+
try {
|
|
27
|
+
const systemPath = path.join(tree.root, file.path);
|
|
28
|
+
const resolvedOptions = await prettier.resolveConfig(systemPath, {
|
|
29
|
+
editorconfig: true,
|
|
30
|
+
});
|
|
31
|
+
const options = {
|
|
32
|
+
...resolvedOptions,
|
|
33
|
+
...changedPrettierInTree,
|
|
34
|
+
filepath: systemPath,
|
|
35
|
+
};
|
|
36
|
+
if (file.path.endsWith('.swcrc')) {
|
|
37
|
+
options.parser = 'json';
|
|
38
|
+
}
|
|
39
|
+
const support = await prettier.getFileInfo(systemPath, options);
|
|
40
|
+
if (support.ignored || !support.inferredParser) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
tree.write(file.path,
|
|
44
|
+
// In prettier v3 the format result is a promise
|
|
45
|
+
await prettier.format(file.content.toString('utf-8'), options));
|
|
46
|
+
}
|
|
47
|
+
catch (e) {
|
|
48
|
+
console.warn(`Could not format ${file.path}. Error: "${e.message}"`);
|
|
49
|
+
}
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
exports.formatFiles = formatFiles;
|
|
53
|
+
function sortTsConfig(tree) {
|
|
54
|
+
try {
|
|
55
|
+
const tsConfigPath = getRootTsConfigPath(tree);
|
|
56
|
+
if (!tsConfigPath) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
updateJson(tree, tsConfigPath, (tsconfig) => ({
|
|
60
|
+
...tsconfig,
|
|
61
|
+
compilerOptions: {
|
|
62
|
+
...tsconfig.compilerOptions,
|
|
63
|
+
paths: sortObjectByKeys(tsconfig.compilerOptions.paths),
|
|
64
|
+
},
|
|
65
|
+
}));
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
// catch noop
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function getRootTsConfigPath(tree) {
|
|
72
|
+
for (const path of ['tsconfig.base.json', 'tsconfig.json']) {
|
|
73
|
+
if (tree.exists(path)) {
|
|
74
|
+
return path;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
function getChangedPrettierConfigInTree(tree) {
|
|
80
|
+
if (tree.listChanges().find((file) => file.path === '.prettierrc')) {
|
|
81
|
+
try {
|
|
82
|
+
return readJson(tree, '.prettierrc');
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Tree } from 'nx/src/generators/tree';
|
|
2
|
+
/**
|
|
3
|
+
* Generates a folder of files based on provided templates.
|
|
4
|
+
*
|
|
5
|
+
* While doing so it performs two substitutions:
|
|
6
|
+
* - Substitutes segments of file names surrounded by __
|
|
7
|
+
* - Uses ejs to substitute values in templates
|
|
8
|
+
*
|
|
9
|
+
* Examples:
|
|
10
|
+
* ```typescript
|
|
11
|
+
* generateFiles(tree, path.join(__dirname , 'files'), './tools/scripts', {tmpl: '', name: 'myscript'})
|
|
12
|
+
* ```
|
|
13
|
+
* This command will take all the files from the `files` directory next to the place where the command is invoked from.
|
|
14
|
+
* It will replace all `__tmpl__` with '' and all `__name__` with 'myscript' in the file names, and will replace all
|
|
15
|
+
* `<%= name %>` with `myscript` in the files themselves.
|
|
16
|
+
* `tmpl: ''` is a common pattern. With it you can name files like this: `index.ts__tmpl__`, so your editor
|
|
17
|
+
* doesn't get confused about incorrect TypeScript files.
|
|
18
|
+
*
|
|
19
|
+
* @param tree - the file system tree
|
|
20
|
+
* @param srcFolder - the source folder of files (absolute path)
|
|
21
|
+
* @param target - the target folder (relative to the tree root)
|
|
22
|
+
* @param substitutions - an object of key-value pairs
|
|
23
|
+
*/
|
|
24
|
+
export declare function generateFiles(tree: Tree, srcFolder: string, target: string, substitutions: {
|
|
25
|
+
[k: string]: any;
|
|
26
|
+
}): void;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateFiles = void 0;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const path = require("path");
|
|
6
|
+
const nx_1 = require("../../nx");
|
|
7
|
+
const binary_extensions_1 = require("../utils/binary-extensions");
|
|
8
|
+
const { logger } = (0, nx_1.requireNx)();
|
|
9
|
+
/**
|
|
10
|
+
* Generates a folder of files based on provided templates.
|
|
11
|
+
*
|
|
12
|
+
* While doing so it performs two substitutions:
|
|
13
|
+
* - Substitutes segments of file names surrounded by __
|
|
14
|
+
* - Uses ejs to substitute values in templates
|
|
15
|
+
*
|
|
16
|
+
* Examples:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* generateFiles(tree, path.join(__dirname , 'files'), './tools/scripts', {tmpl: '', name: 'myscript'})
|
|
19
|
+
* ```
|
|
20
|
+
* This command will take all the files from the `files` directory next to the place where the command is invoked from.
|
|
21
|
+
* It will replace all `__tmpl__` with '' and all `__name__` with 'myscript' in the file names, and will replace all
|
|
22
|
+
* `<%= name %>` with `myscript` in the files themselves.
|
|
23
|
+
* `tmpl: ''` is a common pattern. With it you can name files like this: `index.ts__tmpl__`, so your editor
|
|
24
|
+
* doesn't get confused about incorrect TypeScript files.
|
|
25
|
+
*
|
|
26
|
+
* @param tree - the file system tree
|
|
27
|
+
* @param srcFolder - the source folder of files (absolute path)
|
|
28
|
+
* @param target - the target folder (relative to the tree root)
|
|
29
|
+
* @param substitutions - an object of key-value pairs
|
|
30
|
+
*/
|
|
31
|
+
function generateFiles(tree, srcFolder, target, substitutions) {
|
|
32
|
+
const ejs = require('ejs');
|
|
33
|
+
const files = allFilesInDir(srcFolder);
|
|
34
|
+
if (files.length === 0) {
|
|
35
|
+
throw new Error(`generateFiles: No files found in "${srcFolder}". Are you sure you specified the correct path?`);
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
files.forEach((filePath) => {
|
|
39
|
+
let newContent;
|
|
40
|
+
const computedPath = computePath(srcFolder, target, filePath, substitutions);
|
|
41
|
+
if ((0, binary_extensions_1.isBinaryPath)(filePath)) {
|
|
42
|
+
newContent = (0, fs_1.readFileSync)(filePath);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const template = (0, fs_1.readFileSync)(filePath, 'utf-8');
|
|
46
|
+
try {
|
|
47
|
+
newContent = ejs.render(template, substitutions, {
|
|
48
|
+
filename: filePath,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
catch (e) {
|
|
52
|
+
logger.error(`Error in ${filePath.replace(`${tree.root}/`, '')}:`);
|
|
53
|
+
throw e;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
tree.write(computedPath, newContent);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.generateFiles = generateFiles;
|
|
61
|
+
function computePath(srcFolder, target, filePath, substitutions) {
|
|
62
|
+
const relativeFromSrcFolder = path.relative(srcFolder, filePath);
|
|
63
|
+
let computedPath = path.join(target, relativeFromSrcFolder);
|
|
64
|
+
if (computedPath.endsWith('.template')) {
|
|
65
|
+
computedPath = computedPath.substring(0, computedPath.length - 9);
|
|
66
|
+
}
|
|
67
|
+
Object.entries(substitutions).forEach(([propertyName, value]) => {
|
|
68
|
+
computedPath = computedPath.split(`__${propertyName}__`).join(value);
|
|
69
|
+
});
|
|
70
|
+
return computedPath;
|
|
71
|
+
}
|
|
72
|
+
function allFilesInDir(parent) {
|
|
73
|
+
let res = [];
|
|
74
|
+
try {
|
|
75
|
+
(0, fs_1.readdirSync)(parent).forEach((c) => {
|
|
76
|
+
const child = path.join(parent, c);
|
|
77
|
+
try {
|
|
78
|
+
const s = (0, fs_1.statSync)(child);
|
|
79
|
+
if (!s.isDirectory()) {
|
|
80
|
+
res.push(child);
|
|
81
|
+
}
|
|
82
|
+
else if (s.isDirectory()) {
|
|
83
|
+
res = [...res, ...allFilesInDir(child)];
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch { }
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
catch { }
|
|
90
|
+
return res;
|
|
91
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
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
|
+
callingGenerator: string | null;
|
|
8
|
+
directory?: string;
|
|
9
|
+
importPath?: string;
|
|
10
|
+
projectNameAndRootFormat?: ProjectNameAndRootFormat;
|
|
11
|
+
rootProject?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export type ProjectNameAndRootOptions = {
|
|
14
|
+
/**
|
|
15
|
+
* Normalized full project name, including scope if name was provided with
|
|
16
|
+
* scope (e.g., `@scope/name`, only available when `projectNameAndRootFormat`
|
|
17
|
+
* is `as-provided`).
|
|
18
|
+
*/
|
|
19
|
+
projectName: string;
|
|
20
|
+
/**
|
|
21
|
+
* Normalized project root, including the layout directory if configured.
|
|
22
|
+
*/
|
|
23
|
+
projectRoot: string;
|
|
24
|
+
names: {
|
|
25
|
+
/**
|
|
26
|
+
* Normalized project name without scope. It's meant to be used when
|
|
27
|
+
* generating file names that contain the project name.
|
|
28
|
+
*/
|
|
29
|
+
projectFileName: string;
|
|
30
|
+
/**
|
|
31
|
+
* Normalized project name without scope or directory. It's meant to be used
|
|
32
|
+
* when generating shorter file names that contain the project name.
|
|
33
|
+
*/
|
|
34
|
+
projectSimpleName: string;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Normalized import path for the project.
|
|
38
|
+
*/
|
|
39
|
+
importPath?: string;
|
|
40
|
+
};
|
|
41
|
+
export declare function determineProjectNameAndRootOptions(tree: Tree, options: ProjectGenerationOptions): Promise<ProjectNameAndRootOptions & {
|
|
42
|
+
projectNameAndRootFormat: ProjectNameAndRootFormat;
|
|
43
|
+
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Function for setting cwd during testing
|
|
46
|
+
*/
|
|
47
|
+
export declare function setCwd(path: string): void;
|