nx 20.5.0-canary.20250201-05e0679 → 21.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -11
- package/plugins/package-json.js +2 -1
- package/schemas/nx-schema.json +7 -0
- package/src/command-line/graph/graph.js +2 -0
- package/src/commands-runner/get-command-projects.js +17 -2
- package/src/config/schema-utils.js +4 -4
- package/src/config/task-graph.d.ts +5 -0
- package/src/config/workspace-json-project-json.d.ts +6 -0
- package/src/executors/run-commands/run-commands.impl.d.ts +16 -13
- package/src/executors/run-commands/run-commands.impl.js +24 -263
- package/src/executors/run-commands/running-tasks.d.ts +38 -0
- package/src/executors/run-commands/running-tasks.js +349 -0
- package/src/native/index.d.ts +1 -0
- package/src/native/nx.wasm32-wasi.wasm +0 -0
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.d.ts +2 -1
- package/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +11 -3
- package/src/plugins/js/utils/packages.d.ts +6 -1
- package/src/plugins/js/utils/packages.js +59 -12
- package/src/plugins/package-json/create-nodes.d.ts +3 -3
- package/src/plugins/package-json/create-nodes.js +8 -12
- package/src/project-graph/file-utils.js +2 -1
- package/src/project-graph/plugins/resolve-plugin.js +11 -2
- package/src/tasks-runner/create-task-graph.d.ts +3 -0
- package/src/tasks-runner/create-task-graph.js +36 -5
- package/src/tasks-runner/forked-process-task-runner.d.ts +6 -12
- package/src/tasks-runner/forked-process-task-runner.js +110 -263
- package/src/tasks-runner/init-tasks-runner.js +4 -0
- package/src/tasks-runner/pseudo-terminal.d.ts +7 -1
- package/src/tasks-runner/pseudo-terminal.js +26 -12
- package/src/tasks-runner/running-tasks/batch-process.d.ts +14 -0
- package/src/tasks-runner/running-tasks/batch-process.js +70 -0
- package/src/tasks-runner/running-tasks/node-child-process.d.ts +36 -0
- package/src/tasks-runner/running-tasks/node-child-process.js +184 -0
- package/src/tasks-runner/running-tasks/noop-child-process.d.ts +15 -0
- package/src/tasks-runner/running-tasks/noop-child-process.js +19 -0
- package/src/tasks-runner/running-tasks/running-task.d.ts +8 -0
- package/src/tasks-runner/running-tasks/running-task.js +6 -0
- package/src/tasks-runner/task-orchestrator.d.ts +7 -1
- package/src/tasks-runner/task-orchestrator.js +137 -82
- package/src/tasks-runner/tasks-schedule.js +5 -1
- package/src/tasks-runner/utils.d.ts +0 -8
- package/src/tasks-runner/utils.js +12 -4
- package/src/utils/package-json.d.ts +1 -1
- package/src/utils/package-json.js +4 -2
@@ -0,0 +1,349 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.SeriallyRunningTasks = exports.ParallelRunningTasks = void 0;
|
4
|
+
const child_process_1 = require("child_process");
|
5
|
+
const run_commands_impl_1 = require("./run-commands.impl");
|
6
|
+
const path_1 = require("path");
|
7
|
+
const chalk = require("chalk");
|
8
|
+
const npm_run_path_1 = require("npm-run-path");
|
9
|
+
const task_env_1 = require("../../tasks-runner/task-env");
|
10
|
+
const treeKill = require("tree-kill");
|
11
|
+
class ParallelRunningTasks {
|
12
|
+
constructor(options, context) {
|
13
|
+
this.exitCallbacks = [];
|
14
|
+
this.childProcesses = options.commands.map((commandConfig) => new RunningNodeProcess(commandConfig, options.color, calculateCwd(options.cwd, context), options.env ?? {}, options.readyWhenStatus, options.streamOutput, options.envFile));
|
15
|
+
this.readyWhenStatus = options.readyWhenStatus;
|
16
|
+
this.streamOutput = options.streamOutput;
|
17
|
+
this.run();
|
18
|
+
}
|
19
|
+
async getResults() {
|
20
|
+
return new Promise((res) => {
|
21
|
+
this.onExit((code, terminalOutput) => {
|
22
|
+
res({ code, terminalOutput });
|
23
|
+
});
|
24
|
+
});
|
25
|
+
}
|
26
|
+
onExit(cb) {
|
27
|
+
this.exitCallbacks.push(cb);
|
28
|
+
}
|
29
|
+
send(message) {
|
30
|
+
for (const childProcess of this.childProcesses) {
|
31
|
+
childProcess.send(message);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
async kill(signal) {
|
35
|
+
await Promise.all(this.childProcesses.map(async (p) => {
|
36
|
+
try {
|
37
|
+
return p.kill();
|
38
|
+
}
|
39
|
+
catch (e) {
|
40
|
+
console.error(`Unable to terminate "${p.command}"\nError:`, e);
|
41
|
+
}
|
42
|
+
}));
|
43
|
+
}
|
44
|
+
async run() {
|
45
|
+
if (this.readyWhenStatus.length) {
|
46
|
+
let { childProcess, result: { code, terminalOutput }, } = await Promise.race(this.childProcesses.map((childProcess) => new Promise((res) => {
|
47
|
+
childProcess.onExit((code, terminalOutput) => {
|
48
|
+
res({
|
49
|
+
childProcess,
|
50
|
+
result: { code, terminalOutput },
|
51
|
+
});
|
52
|
+
});
|
53
|
+
})));
|
54
|
+
if (code !== 0) {
|
55
|
+
const output = `Warning: command "${childProcess.command}" exited with non-zero status code`;
|
56
|
+
terminalOutput += output;
|
57
|
+
if (this.streamOutput) {
|
58
|
+
process.stderr.write(output);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
for (const cb of this.exitCallbacks) {
|
62
|
+
cb(code, terminalOutput);
|
63
|
+
}
|
64
|
+
}
|
65
|
+
else {
|
66
|
+
const results = await Promise.all(this.childProcesses.map((childProcess) => childProcess.getResults().then((result) => ({
|
67
|
+
childProcess,
|
68
|
+
result,
|
69
|
+
}))));
|
70
|
+
let terminalOutput = results
|
71
|
+
.map((r) => r.result.terminalOutput)
|
72
|
+
.join('\r\n');
|
73
|
+
const failed = results.filter((result) => result.result.code !== 0);
|
74
|
+
if (failed.length > 0) {
|
75
|
+
const output = failed
|
76
|
+
.map((failedResult) => `Warning: command "${failedResult.childProcess.command}" exited with non-zero status code`)
|
77
|
+
.join('\r\n');
|
78
|
+
terminalOutput += output;
|
79
|
+
if (this.streamOutput) {
|
80
|
+
process.stderr.write(output);
|
81
|
+
}
|
82
|
+
for (const cb of this.exitCallbacks) {
|
83
|
+
cb(1, terminalOutput);
|
84
|
+
}
|
85
|
+
}
|
86
|
+
else {
|
87
|
+
for (const cb of this.exitCallbacks) {
|
88
|
+
cb(0, terminalOutput);
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
94
|
+
exports.ParallelRunningTasks = ParallelRunningTasks;
|
95
|
+
class SeriallyRunningTasks {
|
96
|
+
constructor(options, context, pseudoTerminal) {
|
97
|
+
this.pseudoTerminal = pseudoTerminal;
|
98
|
+
this.terminalOutput = '';
|
99
|
+
this.currentProcess = null;
|
100
|
+
this.exitCallbacks = [];
|
101
|
+
this.code = 0;
|
102
|
+
this.run(options, context)
|
103
|
+
.catch((e) => {
|
104
|
+
this.error = e;
|
105
|
+
})
|
106
|
+
.finally(() => {
|
107
|
+
for (const cb of this.exitCallbacks) {
|
108
|
+
cb(this.code, this.terminalOutput);
|
109
|
+
}
|
110
|
+
});
|
111
|
+
}
|
112
|
+
getResults() {
|
113
|
+
return new Promise((res, rej) => {
|
114
|
+
this.onExit((code) => {
|
115
|
+
if (this.error) {
|
116
|
+
rej(this.error);
|
117
|
+
}
|
118
|
+
else {
|
119
|
+
res({ code, terminalOutput: this.terminalOutput });
|
120
|
+
}
|
121
|
+
});
|
122
|
+
});
|
123
|
+
}
|
124
|
+
onExit(cb) {
|
125
|
+
this.exitCallbacks.push(cb);
|
126
|
+
}
|
127
|
+
send(message) {
|
128
|
+
throw new Error('Not implemented');
|
129
|
+
}
|
130
|
+
kill(signal) {
|
131
|
+
return this.currentProcess.kill(signal);
|
132
|
+
}
|
133
|
+
async run(options, context) {
|
134
|
+
for (const c of options.commands) {
|
135
|
+
const childProcess = await this.createProcess(c, [], options.color, calculateCwd(options.cwd, context), options.processEnv ?? options.env ?? {}, false, options.usePty, options.streamOutput, options.tty, options.envFile);
|
136
|
+
this.currentProcess = childProcess;
|
137
|
+
let { code, terminalOutput } = await childProcess.getResults();
|
138
|
+
this.terminalOutput += terminalOutput;
|
139
|
+
this.code = code;
|
140
|
+
if (code !== 0) {
|
141
|
+
const output = `Warning: command "${c.command}" exited with non-zero status code`;
|
142
|
+
terminalOutput += output;
|
143
|
+
if (options.streamOutput) {
|
144
|
+
process.stderr.write(output);
|
145
|
+
}
|
146
|
+
this.terminalOutput += terminalOutput;
|
147
|
+
// Stop running commands
|
148
|
+
break;
|
149
|
+
}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
async createProcess(commandConfig, readyWhenStatus = [], color, cwd, env, isParallel, usePty = true, streamOutput = true, tty, envFile) {
|
153
|
+
// The rust runCommand is always a tty, so it will not look nice in parallel and if we need prefixes
|
154
|
+
// currently does not work properly in windows
|
155
|
+
if (this.pseudoTerminal &&
|
156
|
+
process.env.NX_NATIVE_COMMAND_RUNNER !== 'false' &&
|
157
|
+
!commandConfig.prefix &&
|
158
|
+
readyWhenStatus.length === 0 &&
|
159
|
+
!isParallel &&
|
160
|
+
usePty) {
|
161
|
+
return createProcessWithPseudoTty(this.pseudoTerminal, commandConfig, color, cwd, env, streamOutput, tty, envFile);
|
162
|
+
}
|
163
|
+
return new RunningNodeProcess(commandConfig, color, cwd, env, readyWhenStatus, streamOutput, envFile);
|
164
|
+
}
|
165
|
+
}
|
166
|
+
exports.SeriallyRunningTasks = SeriallyRunningTasks;
|
167
|
+
class RunningNodeProcess {
|
168
|
+
constructor(commandConfig, color, cwd, env, readyWhenStatus, streamOutput = true, envFile) {
|
169
|
+
this.readyWhenStatus = readyWhenStatus;
|
170
|
+
this.terminalOutput = '';
|
171
|
+
this.exitCallbacks = [];
|
172
|
+
env = processEnv(color, cwd, env, envFile);
|
173
|
+
this.command = commandConfig.command;
|
174
|
+
this.terminalOutput = chalk.dim('> ') + commandConfig.command + '\r\n\r\n';
|
175
|
+
if (streamOutput) {
|
176
|
+
process.stdout.write(this.terminalOutput);
|
177
|
+
}
|
178
|
+
this.childProcess = (0, child_process_1.exec)(commandConfig.command, {
|
179
|
+
maxBuffer: run_commands_impl_1.LARGE_BUFFER,
|
180
|
+
env,
|
181
|
+
cwd,
|
182
|
+
windowsHide: false,
|
183
|
+
});
|
184
|
+
this.addListeners(commandConfig, streamOutput);
|
185
|
+
}
|
186
|
+
getResults() {
|
187
|
+
return new Promise((res) => {
|
188
|
+
this.onExit((code, terminalOutput) => {
|
189
|
+
res({ code, terminalOutput });
|
190
|
+
});
|
191
|
+
});
|
192
|
+
}
|
193
|
+
onExit(cb) {
|
194
|
+
this.exitCallbacks.push(cb);
|
195
|
+
}
|
196
|
+
send(message) {
|
197
|
+
this.childProcess.send(message);
|
198
|
+
}
|
199
|
+
kill(signal) {
|
200
|
+
return new Promise((res, rej) => {
|
201
|
+
treeKill(this.childProcess.pid, signal, (err) => {
|
202
|
+
if (err) {
|
203
|
+
rej(err);
|
204
|
+
}
|
205
|
+
else {
|
206
|
+
res();
|
207
|
+
}
|
208
|
+
});
|
209
|
+
});
|
210
|
+
}
|
211
|
+
addListeners(commandConfig, streamOutput) {
|
212
|
+
this.childProcess.stdout.on('data', (data) => {
|
213
|
+
const output = addColorAndPrefix(data, commandConfig);
|
214
|
+
this.terminalOutput += output;
|
215
|
+
if (streamOutput) {
|
216
|
+
process.stdout.write(output);
|
217
|
+
}
|
218
|
+
if (this.readyWhenStatus.length &&
|
219
|
+
isReady(this.readyWhenStatus, data.toString())) {
|
220
|
+
for (const cb of this.exitCallbacks) {
|
221
|
+
cb(0, this.terminalOutput);
|
222
|
+
}
|
223
|
+
}
|
224
|
+
});
|
225
|
+
this.childProcess.stderr.on('data', (err) => {
|
226
|
+
const output = addColorAndPrefix(err, commandConfig);
|
227
|
+
this.terminalOutput += output;
|
228
|
+
if (streamOutput) {
|
229
|
+
process.stderr.write(output);
|
230
|
+
}
|
231
|
+
if (this.readyWhenStatus.length &&
|
232
|
+
isReady(this.readyWhenStatus, err.toString())) {
|
233
|
+
for (const cb of this.exitCallbacks) {
|
234
|
+
cb(1, this.terminalOutput);
|
235
|
+
}
|
236
|
+
}
|
237
|
+
});
|
238
|
+
this.childProcess.on('error', (err) => {
|
239
|
+
const output = addColorAndPrefix(err.toString(), commandConfig);
|
240
|
+
this.terminalOutput += output;
|
241
|
+
if (streamOutput) {
|
242
|
+
process.stderr.write(output);
|
243
|
+
}
|
244
|
+
for (const cb of this.exitCallbacks) {
|
245
|
+
cb(1, this.terminalOutput);
|
246
|
+
}
|
247
|
+
});
|
248
|
+
this.childProcess.on('exit', (code) => {
|
249
|
+
if (!this.readyWhenStatus.length || isReady(this.readyWhenStatus)) {
|
250
|
+
for (const cb of this.exitCallbacks) {
|
251
|
+
cb(code, this.terminalOutput);
|
252
|
+
}
|
253
|
+
}
|
254
|
+
});
|
255
|
+
}
|
256
|
+
}
|
257
|
+
async function createProcessWithPseudoTty(pseudoTerminal, commandConfig, color, cwd, env, streamOutput = true, tty, envFile) {
|
258
|
+
let terminalOutput = chalk.dim('> ') + commandConfig.command + '\r\n\r\n';
|
259
|
+
if (streamOutput) {
|
260
|
+
process.stdout.write(terminalOutput);
|
261
|
+
}
|
262
|
+
env = processEnv(color, cwd, env, envFile);
|
263
|
+
const childProcess = pseudoTerminal.runCommand(commandConfig.command, {
|
264
|
+
cwd,
|
265
|
+
jsEnv: env,
|
266
|
+
quiet: !streamOutput,
|
267
|
+
tty,
|
268
|
+
});
|
269
|
+
childProcess.onOutput((output) => {
|
270
|
+
terminalOutput += output;
|
271
|
+
});
|
272
|
+
return childProcess;
|
273
|
+
}
|
274
|
+
function addColorAndPrefix(out, config) {
|
275
|
+
if (config.prefix) {
|
276
|
+
out = out
|
277
|
+
.split('\n')
|
278
|
+
.map((l) => {
|
279
|
+
let prefixText = config.prefix;
|
280
|
+
if (config.prefixColor && chalk[config.prefixColor]) {
|
281
|
+
prefixText = chalk[config.prefixColor](prefixText);
|
282
|
+
}
|
283
|
+
prefixText = chalk.bold(prefixText);
|
284
|
+
return l.trim().length > 0 ? `${prefixText} ${l}` : l;
|
285
|
+
})
|
286
|
+
.join('\n');
|
287
|
+
}
|
288
|
+
if (config.color && chalk[config.color]) {
|
289
|
+
out = chalk[config.color](out);
|
290
|
+
}
|
291
|
+
if (config.bgColor && chalk[config.bgColor]) {
|
292
|
+
out = chalk[config.bgColor](out);
|
293
|
+
}
|
294
|
+
return out;
|
295
|
+
}
|
296
|
+
function calculateCwd(cwd, context) {
|
297
|
+
if (!cwd)
|
298
|
+
return context.root;
|
299
|
+
if ((0, path_1.isAbsolute)(cwd))
|
300
|
+
return cwd;
|
301
|
+
return (0, path_1.join)(context.root, cwd);
|
302
|
+
}
|
303
|
+
/**
|
304
|
+
* Env variables are processed in the following order:
|
305
|
+
* - env option from executor options
|
306
|
+
* - env file from envFile option if provided
|
307
|
+
* - local env variables
|
308
|
+
*/
|
309
|
+
function processEnv(color, cwd, envOptionFromExecutor, envFile) {
|
310
|
+
let localEnv = (0, npm_run_path_1.env)({ cwd: cwd ?? process.cwd() });
|
311
|
+
localEnv = {
|
312
|
+
...process.env,
|
313
|
+
...localEnv,
|
314
|
+
};
|
315
|
+
if (process.env.NX_LOAD_DOT_ENV_FILES !== 'false' && envFile) {
|
316
|
+
loadEnvVarsFile(envFile, localEnv);
|
317
|
+
}
|
318
|
+
let res = {
|
319
|
+
...localEnv,
|
320
|
+
...envOptionFromExecutor,
|
321
|
+
};
|
322
|
+
// need to override PATH to make sure we are using the local node_modules
|
323
|
+
if (localEnv.PATH)
|
324
|
+
res.PATH = localEnv.PATH; // UNIX-like
|
325
|
+
if (localEnv.Path)
|
326
|
+
res.Path = localEnv.Path; // Windows
|
327
|
+
if (color) {
|
328
|
+
res.FORCE_COLOR = `${color}`;
|
329
|
+
}
|
330
|
+
return res;
|
331
|
+
}
|
332
|
+
function isReady(readyWhenStatus = [], data) {
|
333
|
+
if (data) {
|
334
|
+
for (const readyWhenElement of readyWhenStatus) {
|
335
|
+
if (data.toString().indexOf(readyWhenElement.stringToMatch) > -1) {
|
336
|
+
readyWhenElement.found = true;
|
337
|
+
break;
|
338
|
+
}
|
339
|
+
}
|
340
|
+
}
|
341
|
+
return readyWhenStatus.every((readyWhenElement) => readyWhenElement.found);
|
342
|
+
}
|
343
|
+
function loadEnvVarsFile(path, env = {}) {
|
344
|
+
(0, task_env_1.unloadDotEnvFile)(path, env);
|
345
|
+
const result = (0, task_env_1.loadAndExpandDotEnvFile)(path, env);
|
346
|
+
if (result.error) {
|
347
|
+
throw result.error;
|
348
|
+
}
|
349
|
+
}
|
package/src/native/index.d.ts
CHANGED
Binary file
|
@@ -15,7 +15,7 @@ export declare class TargetProjectLocator {
|
|
15
15
|
private tsConfig;
|
16
16
|
private paths;
|
17
17
|
private typescriptResolutionCache;
|
18
|
-
private
|
18
|
+
private packagesMetadata;
|
19
19
|
constructor(nodes: Record<string, ProjectGraphProjectNode>, externalNodes?: Record<string, ProjectGraphExternalNode>, npmResolutionCache?: NpmResolutionCache);
|
20
20
|
/**
|
21
21
|
* Resolve any workspace or external project that matches the given import expression,
|
@@ -39,6 +39,7 @@ export declare class TargetProjectLocator {
|
|
39
39
|
* @returns
|
40
40
|
*/
|
41
41
|
findPaths(normalizedImportExpr: string): string[] | undefined;
|
42
|
+
findImportInWorkspaceProjects(importPath: string): string | null;
|
42
43
|
findDependencyInWorkspaceProjects(dep: string): string | null;
|
43
44
|
private resolveImportWithTypescript;
|
44
45
|
private resolveImportWithRequire;
|
@@ -101,7 +101,7 @@ class TargetProjectLocator {
|
|
101
101
|
catch { }
|
102
102
|
// fall back to see if it's a locally linked workspace project where the
|
103
103
|
// output might not exist yet
|
104
|
-
const localProject = this.
|
104
|
+
const localProject = this.findImportInWorkspaceProjects(importExpr);
|
105
105
|
if (localProject) {
|
106
106
|
return localProject;
|
107
107
|
}
|
@@ -189,9 +189,17 @@ class TargetProjectLocator {
|
|
189
189
|
}
|
190
190
|
return undefined;
|
191
191
|
}
|
192
|
+
findImportInWorkspaceProjects(importPath) {
|
193
|
+
this.packagesMetadata ??= (0, packages_1.getWorkspacePackagesMetadata)(this.nodes);
|
194
|
+
if (this.packagesMetadata.entryPointsToProjectMap[importPath]) {
|
195
|
+
return this.packagesMetadata.entryPointsToProjectMap[importPath].name;
|
196
|
+
}
|
197
|
+
const project = (0, packages_1.matchImportToWildcardEntryPointsToProjectMap)(this.packagesMetadata.wildcardEntryPointsToProjectMap, importPath);
|
198
|
+
return project?.name;
|
199
|
+
}
|
192
200
|
findDependencyInWorkspaceProjects(dep) {
|
193
|
-
this.
|
194
|
-
return this.
|
201
|
+
this.packagesMetadata ??= (0, packages_1.getWorkspacePackagesMetadata)(this.nodes);
|
202
|
+
return this.packagesMetadata.packageToProjectMap[dep]?.name;
|
195
203
|
}
|
196
204
|
resolveImportWithTypescript(normalizedImportExpr, filePath) {
|
197
205
|
let resolvedModule;
|
@@ -1,3 +1,8 @@
|
|
1
1
|
import type { ProjectGraphProjectNode } from '../../../config/project-graph';
|
2
2
|
import type { ProjectConfiguration } from '../../../config/workspace-json-project-json';
|
3
|
-
export declare function
|
3
|
+
export declare function getWorkspacePackagesMetadata<T extends ProjectGraphProjectNode | ProjectConfiguration>(projects: Record<string, T>): {
|
4
|
+
entryPointsToProjectMap: Record<string, T>;
|
5
|
+
wildcardEntryPointsToProjectMap: Record<string, T>;
|
6
|
+
packageToProjectMap: Record<string, T>;
|
7
|
+
};
|
8
|
+
export declare function matchImportToWildcardEntryPointsToProjectMap<T extends ProjectGraphProjectNode | ProjectConfiguration>(wildcardEntryPointsToProjectMap: Record<string, T>, importPath: string): T | null;
|
@@ -1,25 +1,72 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.getWorkspacePackagesMetadata = getWorkspacePackagesMetadata;
|
4
|
+
exports.matchImportToWildcardEntryPointsToProjectMap = matchImportToWildcardEntryPointsToProjectMap;
|
5
|
+
const minimatch_1 = require("minimatch");
|
4
6
|
const posix_1 = require("node:path/posix");
|
5
|
-
function
|
6
|
-
const
|
7
|
+
function getWorkspacePackagesMetadata(projects) {
|
8
|
+
const entryPointsToProjectMap = {};
|
9
|
+
const wildcardEntryPointsToProjectMap = {};
|
10
|
+
const packageToProjectMap = {};
|
7
11
|
for (const project of Object.values(projects)) {
|
8
12
|
const metadata = 'data' in project ? project.data.metadata : project.metadata;
|
9
13
|
if (!metadata?.js) {
|
10
14
|
continue;
|
11
15
|
}
|
12
|
-
const { packageName, packageExports } = metadata.js;
|
13
|
-
|
14
|
-
|
15
|
-
//
|
16
|
-
|
16
|
+
const { packageName, packageExports, packageMain, isInPackageManagerWorkspaces, } = metadata.js;
|
17
|
+
packageToProjectMap[packageName] = project;
|
18
|
+
if (!isInPackageManagerWorkspaces) {
|
19
|
+
// it is not included in the package manager workspaces config, so we
|
20
|
+
// skip it since the exports information wouldn't be used by the Node.js
|
21
|
+
// resolution
|
22
|
+
continue;
|
17
23
|
}
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
if (packageExports) {
|
25
|
+
if (typeof packageExports === 'string') {
|
26
|
+
// it points to a file, which would be the equivalent of an '.' export,
|
27
|
+
// in which case the package name is the entry point
|
28
|
+
entryPointsToProjectMap[packageName] = project;
|
29
|
+
}
|
30
|
+
else {
|
31
|
+
for (const entryPoint of Object.keys(packageExports)) {
|
32
|
+
if (packageExports[entryPoint] === null) {
|
33
|
+
// if the entry point is restricted, we skip it
|
34
|
+
continue;
|
35
|
+
}
|
36
|
+
if (entryPoint.startsWith('.')) {
|
37
|
+
// it is a relative subpath export
|
38
|
+
if (entryPoint.includes('*')) {
|
39
|
+
wildcardEntryPointsToProjectMap[(0, posix_1.join)(packageName, entryPoint)] =
|
40
|
+
project;
|
41
|
+
}
|
42
|
+
else {
|
43
|
+
entryPointsToProjectMap[(0, posix_1.join)(packageName, entryPoint)] = project;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
else {
|
47
|
+
// it's a conditional export, so we use the package name as the entry point
|
48
|
+
// https://nodejs.org/api/packages.html#conditional-exports
|
49
|
+
entryPointsToProjectMap[packageName] = project;
|
50
|
+
}
|
51
|
+
}
|
21
52
|
}
|
22
53
|
}
|
54
|
+
else if (packageMain) {
|
55
|
+
// if there is no exports, but there is a main, the package name is the
|
56
|
+
// entry point
|
57
|
+
entryPointsToProjectMap[packageName] = project;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
return {
|
61
|
+
entryPointsToProjectMap,
|
62
|
+
wildcardEntryPointsToProjectMap,
|
63
|
+
packageToProjectMap,
|
64
|
+
};
|
65
|
+
}
|
66
|
+
function matchImportToWildcardEntryPointsToProjectMap(wildcardEntryPointsToProjectMap, importPath) {
|
67
|
+
if (!Object.keys(wildcardEntryPointsToProjectMap).length) {
|
68
|
+
return null;
|
23
69
|
}
|
24
|
-
|
70
|
+
const matchingPair = Object.entries(wildcardEntryPointsToProjectMap).find(([key]) => (0, minimatch_1.minimatch)(importPath, key));
|
71
|
+
return matchingPair?.[1];
|
25
72
|
}
|
@@ -4,13 +4,13 @@ import { PackageJson } from '../../utils/package-json';
|
|
4
4
|
import { CreateNodesV2 } from '../../project-graph/plugins';
|
5
5
|
import { PackageJsonConfigurationCache } from '../../../plugins/package-json';
|
6
6
|
export declare const createNodesV2: CreateNodesV2;
|
7
|
-
export declare function buildPackageJsonWorkspacesMatcher(workspaceRoot: string, readJson: (
|
8
|
-
export declare function createNodeFromPackageJson(pkgJsonPath: string, workspaceRoot: string, cache: PackageJsonConfigurationCache): {
|
7
|
+
export declare function buildPackageJsonWorkspacesMatcher(workspaceRoot: string, readJson: (path: string) => any): (p: string) => boolean;
|
8
|
+
export declare function createNodeFromPackageJson(pkgJsonPath: string, workspaceRoot: string, cache: PackageJsonConfigurationCache, isInPackageManagerWorkspaces: boolean): {
|
9
9
|
projects: {
|
10
10
|
[x: string]: ProjectConfiguration;
|
11
11
|
};
|
12
12
|
};
|
13
|
-
export declare function buildProjectConfigurationFromPackageJson(packageJson: PackageJson, workspaceRoot: string, packageJsonPath: string, nxJson: NxJsonConfiguration): ProjectConfiguration & {
|
13
|
+
export declare function buildProjectConfigurationFromPackageJson(packageJson: PackageJson, workspaceRoot: string, packageJsonPath: string, nxJson: NxJsonConfiguration, isInPackageManagerWorkspaces: boolean): ProjectConfiguration & {
|
14
14
|
name: string;
|
15
15
|
};
|
16
16
|
/**
|
@@ -31,12 +31,13 @@ exports.createNodesV2 = [
|
|
31
31
|
};
|
32
32
|
const cache = (0, package_json_2.readPackageJsonConfigurationCache)();
|
33
33
|
return (0, plugins_1.createNodesFromFiles)((packageJsonPath, options, context) => {
|
34
|
-
|
34
|
+
const isInPackageManagerWorkspaces = isInPackageJsonWorkspaces(packageJsonPath);
|
35
|
+
if (!isInPackageManagerWorkspaces &&
|
35
36
|
!isNextToProjectJson(packageJsonPath)) {
|
36
37
|
// Skip if package.json is not part of the package.json workspaces and not next to a project.json.
|
37
38
|
return null;
|
38
39
|
}
|
39
|
-
return createNodeFromPackageJson(packageJsonPath, context.workspaceRoot, cache);
|
40
|
+
return createNodeFromPackageJson(packageJsonPath, context.workspaceRoot, cache, isInPackageManagerWorkspaces);
|
40
41
|
}, packageJsons, _, context);
|
41
42
|
},
|
42
43
|
];
|
@@ -78,18 +79,13 @@ function buildPackageJsonWorkspacesMatcher(workspaceRoot, readJson) {
|
|
78
79
|
*/
|
79
80
|
negativePatterns.every((negative) => (0, minimatch_1.minimatch)(p, negative));
|
80
81
|
}
|
81
|
-
function createNodeFromPackageJson(pkgJsonPath, workspaceRoot, cache) {
|
82
|
+
function createNodeFromPackageJson(pkgJsonPath, workspaceRoot, cache, isInPackageManagerWorkspaces) {
|
82
83
|
const json = (0, fileutils_1.readJsonFile)((0, node_path_1.join)(workspaceRoot, pkgJsonPath));
|
83
84
|
const projectRoot = (0, node_path_1.dirname)(pkgJsonPath);
|
84
85
|
const hash = (0, file_hasher_1.hashObject)({
|
85
86
|
...json,
|
86
87
|
root: projectRoot,
|
87
|
-
|
88
|
-
* Increment this number to force processing the package.json again. Do it
|
89
|
-
* when the implementation of this plugin is changed and results in different
|
90
|
-
* results for the same package.json contents.
|
91
|
-
*/
|
92
|
-
bust: 1,
|
88
|
+
isInPackageManagerWorkspaces,
|
93
89
|
});
|
94
90
|
const cached = cache[hash];
|
95
91
|
if (cached) {
|
@@ -99,7 +95,7 @@ function createNodeFromPackageJson(pkgJsonPath, workspaceRoot, cache) {
|
|
99
95
|
},
|
100
96
|
};
|
101
97
|
}
|
102
|
-
const project = buildProjectConfigurationFromPackageJson(json, workspaceRoot, pkgJsonPath, (0, nx_json_1.readNxJson)(workspaceRoot));
|
98
|
+
const project = buildProjectConfigurationFromPackageJson(json, workspaceRoot, pkgJsonPath, (0, nx_json_1.readNxJson)(workspaceRoot), isInPackageManagerWorkspaces);
|
103
99
|
cache[hash] = project;
|
104
100
|
return {
|
105
101
|
projects: {
|
@@ -107,7 +103,7 @@ function createNodeFromPackageJson(pkgJsonPath, workspaceRoot, cache) {
|
|
107
103
|
},
|
108
104
|
};
|
109
105
|
}
|
110
|
-
function buildProjectConfigurationFromPackageJson(packageJson, workspaceRoot, packageJsonPath, nxJson) {
|
106
|
+
function buildProjectConfigurationFromPackageJson(packageJson, workspaceRoot, packageJsonPath, nxJson, isInPackageManagerWorkspaces) {
|
111
107
|
const normalizedPath = packageJsonPath.split('\\').join('/');
|
112
108
|
const projectRoot = (0, node_path_1.dirname)(normalizedPath);
|
113
109
|
const siblingProjectJson = tryReadJson((0, node_path_1.join)(workspaceRoot, projectRoot, 'project.json'));
|
@@ -135,7 +131,7 @@ function buildProjectConfigurationFromPackageJson(packageJson, workspaceRoot, pa
|
|
135
131
|
...packageJson.nx,
|
136
132
|
targets: (0, package_json_1.readTargetsFromPackageJson)(packageJson, nxJson),
|
137
133
|
tags: (0, package_json_1.getTagsFromPackageJson)(packageJson),
|
138
|
-
metadata: (0, package_json_1.getMetadataFromPackageJson)(packageJson),
|
134
|
+
metadata: (0, package_json_1.getMetadataFromPackageJson)(packageJson, isInPackageManagerWorkspaces),
|
139
135
|
};
|
140
136
|
if (nxJson?.workspaceLayout?.appsDir != nxJson?.workspaceLayout?.libsDir &&
|
141
137
|
nxJson?.workspaceLayout?.appsDir &&
|
@@ -154,6 +154,7 @@ function getProjectsSync(root, nxJson) {
|
|
154
154
|
...(0, package_json_1.getGlobPatternsFromPackageManagerWorkspaces)(root, fileutils_1.readJsonFile),
|
155
155
|
];
|
156
156
|
const projectFiles = (0, workspace_context_1.globWithWorkspaceContextSync)(root, patterns);
|
157
|
+
const isInPackageJsonWorkspaces = (0, package_json_1.buildPackageJsonWorkspacesMatcher)(root, (f) => (0, fileutils_1.readJsonFile)((0, path_1.join)(root, f)));
|
157
158
|
const rootMap = {};
|
158
159
|
for (const projectFile of projectFiles) {
|
159
160
|
if ((0, path_1.basename)(projectFile) === 'project.json') {
|
@@ -163,7 +164,7 @@ function getProjectsSync(root, nxJson) {
|
|
163
164
|
}
|
164
165
|
else if ((0, path_1.basename)(projectFile) === 'package.json') {
|
165
166
|
const packageJson = (0, fileutils_1.readJsonFile)(projectFile);
|
166
|
-
const config = (0, package_json_1.buildProjectConfigurationFromPackageJson)(packageJson, root, projectFile, nxJson);
|
167
|
+
const config = (0, package_json_1.buildProjectConfigurationFromPackageJson)(packageJson, root, projectFile, nxJson, isInPackageJsonWorkspaces(projectFile));
|
167
168
|
if (!rootMap[config.root]) {
|
168
169
|
(0, project_configuration_utils_1.mergeProjectConfigurationIntoRootMap)(rootMap,
|
169
170
|
// Inferred targets, tags, etc don't show up when running generators
|
@@ -83,6 +83,7 @@ function lookupLocalPlugin(importPath, projects, root = workspace_root_1.workspa
|
|
83
83
|
return { path: path.join(root, projectConfig.root), projectConfig };
|
84
84
|
}
|
85
85
|
let packageEntryPointsToProjectMap;
|
86
|
+
let wildcardEntryPointsToProjectMap;
|
86
87
|
function findNxProjectForImportPath(importPath, projects, root = workspace_root_1.workspaceRoot) {
|
87
88
|
const tsConfigPaths = readTsConfigPaths(root);
|
88
89
|
const possibleTsPaths = tsConfigPaths[importPath]?.map((p) => (0, path_1.normalizePath)(path.relative(root, path.join(root, p)))) ?? [];
|
@@ -101,11 +102,19 @@ function findNxProjectForImportPath(importPath, projects, root = workspace_root_
|
|
101
102
|
}
|
102
103
|
}
|
103
104
|
}
|
104
|
-
packageEntryPointsToProjectMap
|
105
|
-
(
|
105
|
+
if (!packageEntryPointsToProjectMap && !wildcardEntryPointsToProjectMap) {
|
106
|
+
({
|
107
|
+
entryPointsToProjectMap: packageEntryPointsToProjectMap,
|
108
|
+
wildcardEntryPointsToProjectMap,
|
109
|
+
} = (0, packages_1.getWorkspacePackagesMetadata)(projects));
|
110
|
+
}
|
106
111
|
if (packageEntryPointsToProjectMap[importPath]) {
|
107
112
|
return packageEntryPointsToProjectMap[importPath];
|
108
113
|
}
|
114
|
+
const project = (0, packages_1.matchImportToWildcardEntryPointsToProjectMap)(wildcardEntryPointsToProjectMap, importPath);
|
115
|
+
if (project) {
|
116
|
+
return project;
|
117
|
+
}
|
109
118
|
logger_1.logger.verbose('Unable to find local plugin', possibleTsPaths, projectRootMappings);
|
110
119
|
throw new Error('Unable to resolve local plugin with import path ' + importPath);
|
111
120
|
}
|
@@ -11,6 +11,9 @@ export declare class ProcessTasks {
|
|
11
11
|
readonly dependencies: {
|
12
12
|
[k: string]: string[];
|
13
13
|
};
|
14
|
+
readonly continuousDependencies: {
|
15
|
+
[k: string]: string[];
|
16
|
+
};
|
14
17
|
private readonly allTargetNames;
|
15
18
|
constructor(extraTargetDependencies: TargetDependencies, projectGraph: ProjectGraph);
|
16
19
|
processTasks(projectNames: string[], targets: string[], configuration: string, overrides: Object, excludeTaskDependencies: boolean): string[];
|