nx 22.7.0 → 22.7.2
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/dist/bin/nx.d.ts +1 -0
- package/dist/bin/nx.js +5 -2
- package/dist/src/ai/clone-ai-config-repo.js +20 -3
- package/dist/src/ai/set-up-ai-agents/set-up-ai-agents.js +15 -23
- package/dist/src/analytics/analytics.js +10 -1
- package/dist/src/command-line/graph/graph.js +0 -1
- package/dist/src/command-line/init/implementation/dot-nx/add-nx-scripts.js +13 -1
- package/dist/src/command-line/init/implementation/dot-nx/nxw.js +2 -1
- package/dist/src/command-line/migrate/command-object.js +5 -0
- package/dist/src/command-line/migrate/migrate.d.ts +10 -2
- package/dist/src/command-line/migrate/migrate.js +157 -30
- package/dist/src/command-line/release/config/use-legacy-versioning.d.ts +2 -0
- package/dist/src/command-line/release/config/use-legacy-versioning.js +8 -0
- package/dist/src/command-line/release/utils/shared.js +22 -12
- package/dist/src/config/misc-interfaces.d.ts +6 -0
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/core/graph/styles.css +1 -1
- package/dist/src/daemon/client/client.js +1 -1
- package/dist/src/daemon/client/daemon-environment.js +2 -0
- package/dist/src/daemon/is-nx-version-mismatch.d.ts +0 -1
- package/dist/src/daemon/is-nx-version-mismatch.js +2 -18
- package/dist/src/daemon/server/latest-nx.js +2 -0
- package/dist/src/daemon/server/server.js +2 -1
- package/dist/src/daemon/server/start.d.ts +1 -1
- package/dist/src/daemon/server/start.js +2 -0
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/plugins/js/lock-file/npm-parser.js +37 -19
- package/dist/src/plugins/js/lock-file/pnpm-parser.js +51 -4
- package/dist/src/plugins/js/lock-file/project-graph-pruning.js +12 -4
- package/dist/src/project-graph/plugins/isolation/plugin-worker.d.ts +1 -0
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +2 -0
- package/dist/src/tasks-runner/life-cycles/task-history-life-cycle-old.js +13 -2
- package/dist/src/tasks-runner/life-cycles/task-history-life-cycle.js +16 -5
- package/dist/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +11 -2
- package/dist/src/tasks-runner/run-command.js +10 -4
- package/dist/src/tasks-runner/task-orchestrator.js +26 -5
- package/dist/src/tasks-runner/utils.d.ts +11 -0
- package/dist/src/tasks-runner/utils.js +37 -0
- package/dist/src/utils/ab-testing.js +12 -0
- package/dist/src/utils/compile-cache.d.ts +24 -0
- package/dist/src/utils/compile-cache.js +49 -0
- package/dist/src/utils/enable-compile-cache.d.ts +1 -0
- package/dist/src/utils/enable-compile-cache.js +7 -0
- package/dist/src/utils/has-nx-js-plugin.d.ts +9 -0
- package/dist/src/utils/has-nx-js-plugin.js +24 -0
- package/dist/src/utils/installed-nx-version.d.ts +8 -0
- package/dist/src/utils/installed-nx-version.js +67 -0
- package/dist/src/utils/logger.d.ts +12 -1
- package/dist/src/utils/logger.js +57 -36
- package/dist/src/utils/nx-key.d.ts +0 -1
- package/dist/src/utils/nx-key.js +20 -23
- package/dist/src/utils/output.d.ts +3 -2
- package/dist/src/utils/output.js +29 -28
- package/dist/src/utils/package-json.js +2 -13
- package/dist/src/utils/perf-logging.js +3 -1
- package/dist/src/utils/workspace-context.js +1 -1
- package/package.json +22 -15
|
@@ -79,14 +79,25 @@ class TaskHistoryLifeCycle {
|
|
|
79
79
|
}
|
|
80
80
|
printFlakyTasksMessage() {
|
|
81
81
|
if (this.flakyTasks?.length > 0) {
|
|
82
|
+
const MAX_VISIBLE_FLAKY = 5;
|
|
83
|
+
const visibleFlaky = this.flakyTasks.length > MAX_VISIBLE_FLAKY + 1
|
|
84
|
+
? this.flakyTasks.slice(0, MAX_VISIBLE_FLAKY)
|
|
85
|
+
: this.flakyTasks;
|
|
86
|
+
const hiddenCount = this.flakyTasks.length - visibleFlaky.length;
|
|
87
|
+
const flakyRows = visibleFlaky.map((hash) => {
|
|
88
|
+
const taskRun = this.taskRuns.get(hash);
|
|
89
|
+
return ` ${(0, serialize_target_1.serializeTarget)(taskRun.target.project, taskRun.target.target, taskRun.target.configuration)}`;
|
|
90
|
+
});
|
|
91
|
+
if (hiddenCount > 0) {
|
|
92
|
+
flakyRows.push(` ${hiddenCount} more...`);
|
|
93
|
+
}
|
|
82
94
|
output_1.output.warn({
|
|
83
|
-
title: `Nx detected ${this.flakyTasks.length === 1
|
|
95
|
+
title: `Nx detected ${this.flakyTasks.length === 1
|
|
96
|
+
? 'a flaky task'
|
|
97
|
+
: `${this.flakyTasks.length} flaky tasks`}`,
|
|
84
98
|
bodyLines: [
|
|
85
99
|
,
|
|
86
|
-
...
|
|
87
|
-
const taskRun = this.taskRuns.get(hash);
|
|
88
|
-
return ` ${(0, serialize_target_1.serializeTarget)(taskRun.target.project, taskRun.target.target, taskRun.target.configuration)}`;
|
|
89
|
-
}),
|
|
100
|
+
...flakyRows,
|
|
90
101
|
...((0, nx_cloud_utils_1.isNxCloudUsed)((0, nx_json_1.readNxJson)())
|
|
91
102
|
? []
|
|
92
103
|
: [
|
|
@@ -67,6 +67,12 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, taskGraph, args,
|
|
|
67
67
|
displayStoppedTasks.add(taskId);
|
|
68
68
|
inProgressTasks.delete(taskId);
|
|
69
69
|
}
|
|
70
|
+
else if (taskStatus === 2 /* NativeTaskStatus.Skipped */) {
|
|
71
|
+
// Skipped tasks don't get an endTasks() call; clear them here so the run
|
|
72
|
+
// summary doesn't treat them as still-in-progress and report Cancelled.
|
|
73
|
+
tasksToTaskStatus[taskId] = 'skipped';
|
|
74
|
+
inProgressTasks.delete(taskId);
|
|
75
|
+
}
|
|
70
76
|
};
|
|
71
77
|
lifeCycle.endTasks = (taskResults) => {
|
|
72
78
|
for (const { task, status, terminalOutput } of taskResults) {
|
|
@@ -132,10 +138,13 @@ function getTuiTerminalSummaryLifeCycle({ projectNames, tasks, taskGraph, args,
|
|
|
132
138
|
(0, task_history_life_cycle_1.getTasksHistoryLifeCycle)().printFlakyTasksMessage();
|
|
133
139
|
};
|
|
134
140
|
const printRunOneSummary = ({ failure, cancelled, }) => {
|
|
135
|
-
//
|
|
136
|
-
// above the summary, since run-one should print all task results.
|
|
141
|
+
// Print task outputs in completion order above the summary.
|
|
137
142
|
for (const taskId of taskIdsInTheOrderTheyStart) {
|
|
138
143
|
const taskStatus = tasksToTaskStatus[taskId];
|
|
144
|
+
// Skipped tasks never ran; don't print a misleading `> nx run` header.
|
|
145
|
+
if (taskStatus === 'skipped') {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
139
148
|
const terminalOutput = getTerminalOutput(taskId);
|
|
140
149
|
output_1.output.logCommandOutput(taskId, taskStatus, terminalOutput);
|
|
141
150
|
}
|
|
@@ -11,9 +11,9 @@ const tslib_1 = require("tslib");
|
|
|
11
11
|
const enquirer_1 = require("enquirer");
|
|
12
12
|
const node_path_1 = require("node:path");
|
|
13
13
|
const node_util_1 = require("node:util");
|
|
14
|
-
const ora = require('ora');
|
|
15
14
|
const nx_json_1 = require("../config/nx-json");
|
|
16
15
|
const client_1 = require("../daemon/client/client");
|
|
16
|
+
const spinner_1 = require("../utils/spinner");
|
|
17
17
|
const create_task_hasher_1 = require("../hasher/create-task-hasher");
|
|
18
18
|
const hash_task_1 = require("../hasher/hash-task");
|
|
19
19
|
const native_1 = require("../native");
|
|
@@ -22,6 +22,7 @@ const project_graph_1 = require("../project-graph/project-graph");
|
|
|
22
22
|
const handle_errors_1 = require("../utils/handle-errors");
|
|
23
23
|
const is_ci_1 = require("../utils/is-ci");
|
|
24
24
|
const nx_cloud_utils_1 = require("../utils/nx-cloud-utils");
|
|
25
|
+
const logger_1 = require("../utils/logger");
|
|
25
26
|
const nx_key_1 = require("../utils/nx-key");
|
|
26
27
|
const output_1 = require("../utils/output");
|
|
27
28
|
const sync_generators_1 = require("../utils/sync-generators");
|
|
@@ -324,6 +325,10 @@ async function runCommand(projectsToRun, currentProjectGraph, { nxJson }, nxArgs
|
|
|
324
325
|
return status;
|
|
325
326
|
}
|
|
326
327
|
async function runCommandForTasks(projectsToRun, currentProjectGraph, { nxJson }, nxArgs, overrides, initiatingProject, extraTargetDependencies, extraOptions) {
|
|
328
|
+
// Kick off the license lookup in the background so it overlaps with task
|
|
329
|
+
// execution. The log itself is deferred to the print site below so it
|
|
330
|
+
// never lands in the middle of task output.
|
|
331
|
+
const nxKeyPromise = (0, nx_key_1.getNxKeyInformation)().catch(() => null);
|
|
327
332
|
const projectNames = projectsToRun.map((t) => t.name);
|
|
328
333
|
const projectNameSet = new Set(projectNames);
|
|
329
334
|
const { projectGraph, taskGraph } = await ensureWorkspaceIsInSyncAndGetGraphs(currentProjectGraph, nxJson, projectNames, nxArgs, overrides, extraTargetDependencies, extraOptions);
|
|
@@ -348,7 +353,9 @@ async function runCommandForTasks(projectsToRun, currentProjectGraph, { nxJson }
|
|
|
348
353
|
printSummary();
|
|
349
354
|
}
|
|
350
355
|
await printConfigureAiAgentsDisclaimer();
|
|
351
|
-
await
|
|
356
|
+
const nxKey = await nxKeyPromise;
|
|
357
|
+
if (nxKey)
|
|
358
|
+
logger_1.logger.log((0, nx_key_1.createNxKeyLicenseeInformation)(nxKey));
|
|
352
359
|
return {
|
|
353
360
|
taskResults,
|
|
354
361
|
completed: didCommandComplete(tasks, taskResults),
|
|
@@ -486,8 +493,7 @@ async function ensureWorkspaceIsInSyncAndGetGraphs(projectGraph, nxJson, project
|
|
|
486
493
|
const applyChanges = nxJson.sync?.applyChanges === true ||
|
|
487
494
|
(await promptForApplyingSyncGeneratorChanges());
|
|
488
495
|
if (applyChanges) {
|
|
489
|
-
const spinner =
|
|
490
|
-
spinner.start();
|
|
496
|
+
const spinner = spinner_1.globalSpinner.start('Syncing the workspace...');
|
|
491
497
|
// Flush sync generator changes to disk
|
|
492
498
|
const flushResult = await (0, sync_generators_1.flushSyncGeneratorChanges)(results);
|
|
493
499
|
if ('generatorFailures' in flushResult) {
|
|
@@ -29,6 +29,14 @@ const task_env_1 = require("./task-env");
|
|
|
29
29
|
const tasks_schedule_1 = require("./tasks-schedule");
|
|
30
30
|
const utils_1 = require("./utils");
|
|
31
31
|
const shared_running_task_1 = require("./running-tasks/shared-running-task");
|
|
32
|
+
/**
|
|
33
|
+
* Resolve a batch executor's per-task result to a TaskStatus. Prefers an
|
|
34
|
+
* explicit `status` from the executor; falls back to the `success` boolean
|
|
35
|
+
* for executors that pre-date the `status` field.
|
|
36
|
+
*/
|
|
37
|
+
function resolveBatchTaskStatus(result) {
|
|
38
|
+
return result.status ?? (result.success ? 'success' : 'failure');
|
|
39
|
+
}
|
|
32
40
|
class TaskOrchestrator {
|
|
33
41
|
// endregion internal state
|
|
34
42
|
constructor(hasher, initiatingProject, initiatingTasks, projectGraph, taskGraph, nxJson, options, bail, daemon, outputStyle, taskGraphForHashing = taskGraph) {
|
|
@@ -57,7 +65,12 @@ class TaskOrchestrator {
|
|
|
57
65
|
// region internal state
|
|
58
66
|
this.batchEnv = (0, task_env_1.getEnvVariablesForBatchProcess)(this.options.skipNxCache, this.options.captureStderr);
|
|
59
67
|
this.reverseTaskDeps = (0, utils_1.calculateReverseDeps)(this.taskGraph);
|
|
60
|
-
|
|
68
|
+
// `nx:noop` initiating tasks exit instantly via the fast-path in
|
|
69
|
+
// `spawnProcess`. If we treat the noop itself as the keep-alive anchor for
|
|
70
|
+
// its continuous dependencies, `cleanUpUnneededContinuousTasks` kills those
|
|
71
|
+
// children the moment the noop finishes. Expand through noops so the
|
|
72
|
+
// underlying real tasks become the anchors.
|
|
73
|
+
this.initializingTaskIds = (0, utils_1.expandInitiatingTasksThroughNoop)(this.initiatingTasks, this.taskGraph, this.projectGraph);
|
|
61
74
|
this.processedTasks = new Map();
|
|
62
75
|
this.completedTasks = new Map();
|
|
63
76
|
this.waitingForTasks = [];
|
|
@@ -493,11 +506,18 @@ class TaskOrchestrator {
|
|
|
493
506
|
// Heavy operations (caching, scheduling, complete) happen at batch-end in postRunSteps
|
|
494
507
|
batchProcess.onTaskResults((taskId, result) => {
|
|
495
508
|
const task = this.taskGraph.tasks[taskId];
|
|
496
|
-
const status = result
|
|
497
|
-
|
|
509
|
+
const status = resolveBatchTaskStatus(result);
|
|
510
|
+
// Append before print so printTaskTerminalOutput finds the PTY already
|
|
511
|
+
// populated and no-ops; reversing the order writes terminalOutput twice.
|
|
498
512
|
if (result.terminalOutput) {
|
|
499
513
|
this.options.lifeCycle.appendTaskOutput(taskId, result.terminalOutput, false);
|
|
500
514
|
}
|
|
515
|
+
// Skipped tasks didn't run, so they have no terminal output and don't
|
|
516
|
+
// need a per-task PTY — calling printTaskTerminalOutput would otherwise
|
|
517
|
+
// allocate one just to write a cursor-hide escape.
|
|
518
|
+
if (status !== 'skipped') {
|
|
519
|
+
this.options.lifeCycle.printTaskTerminalOutput(task, status, result.terminalOutput ?? '');
|
|
520
|
+
}
|
|
501
521
|
task.startTime = result.startTime;
|
|
502
522
|
task.endTime = result.endTime;
|
|
503
523
|
if (result.startTime && result.endTime) {
|
|
@@ -511,10 +531,11 @@ class TaskOrchestrator {
|
|
|
511
531
|
const task = this.taskGraph.tasks[taskId];
|
|
512
532
|
task.startTime = result.startTime;
|
|
513
533
|
task.endTime = result.endTime;
|
|
534
|
+
const status = resolveBatchTaskStatus(result);
|
|
514
535
|
return {
|
|
515
|
-
code:
|
|
536
|
+
code: status === 'success' ? 0 : 1,
|
|
516
537
|
task,
|
|
517
|
-
status
|
|
538
|
+
status,
|
|
518
539
|
terminalOutput: result.terminalOutput,
|
|
519
540
|
};
|
|
520
541
|
});
|
|
@@ -31,6 +31,17 @@ export declare function getOutputsForTargetAndConfiguration(target: Task['target
|
|
|
31
31
|
export declare function interpolate(template: string, data: any): string;
|
|
32
32
|
export declare function getTargetConfigurationForTask(task: Task, projectGraph: ProjectGraph): TargetConfiguration | undefined;
|
|
33
33
|
export declare function getExecutorNameForTask(task: Task, projectGraph: ProjectGraph): string;
|
|
34
|
+
/**
|
|
35
|
+
* Expand a set of initiating task IDs by walking through any `nx:noop` tasks
|
|
36
|
+
* and replacing them with their direct dependencies + continuous dependencies.
|
|
37
|
+
* Non-noop tasks are kept as-is; cycles are safe.
|
|
38
|
+
*
|
|
39
|
+
* An `nx:noop` executor returns immediately, so if it is the only thing
|
|
40
|
+
* anchoring a continuous child, the child gets killed by
|
|
41
|
+
* `cleanUpUnneededContinuousTasks` the moment the noop completes. Treating the
|
|
42
|
+
* noop's dependencies as the real anchors preserves the intended orchestration.
|
|
43
|
+
*/
|
|
44
|
+
export declare function expandInitiatingTasksThroughNoop(initiatingTasks: Task[], taskGraph: TaskGraph, projectGraph: ProjectGraph): Set<string>;
|
|
34
45
|
export declare function getExecutorForTask(task: Task, projects: Record<string, ProjectConfiguration>): ExecutorConfig & {
|
|
35
46
|
isNgCompat: boolean;
|
|
36
47
|
isNxExecutor: boolean;
|
|
@@ -14,6 +14,7 @@ exports.getOutputsForTargetAndConfiguration = getOutputsForTargetAndConfiguratio
|
|
|
14
14
|
exports.interpolate = interpolate;
|
|
15
15
|
exports.getTargetConfigurationForTask = getTargetConfigurationForTask;
|
|
16
16
|
exports.getExecutorNameForTask = getExecutorNameForTask;
|
|
17
|
+
exports.expandInitiatingTasksThroughNoop = expandInitiatingTasksThroughNoop;
|
|
17
18
|
exports.getExecutorForTask = getExecutorForTask;
|
|
18
19
|
exports.getCustomHasher = getCustomHasher;
|
|
19
20
|
exports.removeTasksFromTaskGraph = removeTasksFromTaskGraph;
|
|
@@ -291,6 +292,42 @@ function getTargetConfigurationForTask(task, projectGraph) {
|
|
|
291
292
|
function getExecutorNameForTask(task, projectGraph) {
|
|
292
293
|
return getTargetConfigurationForTask(task, projectGraph)?.executor;
|
|
293
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Expand a set of initiating task IDs by walking through any `nx:noop` tasks
|
|
297
|
+
* and replacing them with their direct dependencies + continuous dependencies.
|
|
298
|
+
* Non-noop tasks are kept as-is; cycles are safe.
|
|
299
|
+
*
|
|
300
|
+
* An `nx:noop` executor returns immediately, so if it is the only thing
|
|
301
|
+
* anchoring a continuous child, the child gets killed by
|
|
302
|
+
* `cleanUpUnneededContinuousTasks` the moment the noop completes. Treating the
|
|
303
|
+
* noop's dependencies as the real anchors preserves the intended orchestration.
|
|
304
|
+
*/
|
|
305
|
+
function expandInitiatingTasksThroughNoop(initiatingTasks, taskGraph, projectGraph) {
|
|
306
|
+
const expanded = new Set();
|
|
307
|
+
const visited = new Set();
|
|
308
|
+
const queue = initiatingTasks.map((t) => t.id);
|
|
309
|
+
while (queue.length > 0) {
|
|
310
|
+
const taskId = queue.shift();
|
|
311
|
+
if (visited.has(taskId))
|
|
312
|
+
continue;
|
|
313
|
+
visited.add(taskId);
|
|
314
|
+
const task = taskGraph.tasks[taskId];
|
|
315
|
+
if (!task)
|
|
316
|
+
continue;
|
|
317
|
+
if (getExecutorNameForTask(task, projectGraph) === 'nx:noop') {
|
|
318
|
+
for (const dep of taskGraph.dependencies[taskId] ?? []) {
|
|
319
|
+
queue.push(dep);
|
|
320
|
+
}
|
|
321
|
+
for (const dep of taskGraph.continuousDependencies[taskId] ?? []) {
|
|
322
|
+
queue.push(dep);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
expanded.add(taskId);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return expanded;
|
|
330
|
+
}
|
|
294
331
|
function getExecutorForTask(task, projects) {
|
|
295
332
|
const executor = projects[task.target.project]?.targets?.[task.target.target]?.executor;
|
|
296
333
|
const [nodeModule, executorName] = (0, executor_utils_1.parseExecutor)(executor);
|
|
@@ -21,6 +21,18 @@ const messageOptions = {
|
|
|
21
21
|
],
|
|
22
22
|
footer: '\nFree for small teams. Remote caching and task distribution. 2-minute setup: https://nx.dev/nx-cloud',
|
|
23
23
|
},
|
|
24
|
+
{
|
|
25
|
+
code: 'cloud-self-healing-remote-cache',
|
|
26
|
+
message: `Would you like to enable AI-powered Self-Healing CI and Remote Caching?`,
|
|
27
|
+
initial: 0,
|
|
28
|
+
choices: [
|
|
29
|
+
{ value: 'yes', name: 'Yes' },
|
|
30
|
+
{ value: 'skip', name: 'Skip for now' },
|
|
31
|
+
{ value: 'never', name: pc.dim("No, don't ask again") },
|
|
32
|
+
],
|
|
33
|
+
footer: '\nLearn about it at https://nx.dev/nx-cloud',
|
|
34
|
+
hint: `\n(it's free and can be disabled any time)`,
|
|
35
|
+
},
|
|
24
36
|
],
|
|
25
37
|
setupViewLogs: [
|
|
26
38
|
{
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enables V8's on-disk bytecode cache for the current process.
|
|
3
|
+
*
|
|
4
|
+
* Calls `module.enableCompileCache()` with no arguments and lets Node pick
|
|
5
|
+
* the location, which means Node's standard env vars work transparently:
|
|
6
|
+
* - `NODE_COMPILE_CACHE=<dir>` — override the cache directory.
|
|
7
|
+
* - `NODE_DISABLE_COMPILE_CACHE=1` — disable entirely.
|
|
8
|
+
*
|
|
9
|
+
* The default location lives under the OS temp dir keyed by V8 version, so
|
|
10
|
+
* the cache is shared across workspaces and self-invalidates on Node
|
|
11
|
+
* upgrades — no nx-specific cleanup needed.
|
|
12
|
+
*
|
|
13
|
+
* Called at the entry point of every long-lived nx process (main CLI,
|
|
14
|
+
* daemon, plugin workers) via `enable-compile-cache.ts`, which side-effects
|
|
15
|
+
* this on import.
|
|
16
|
+
*
|
|
17
|
+
* Set `NX_COMPILE_CACHE=false` to opt out without disabling the cache for
|
|
18
|
+
* non-nx Node processes the way `NODE_DISABLE_COMPILE_CACHE` would.
|
|
19
|
+
*
|
|
20
|
+
* No-op on Node versions without the `module.enableCompileCache` API.
|
|
21
|
+
* Errors are swallowed — the compile cache is a pure performance
|
|
22
|
+
* optimization and must never break the CLI.
|
|
23
|
+
*/
|
|
24
|
+
export declare function enableCompileCache(...override: [unknown?]): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enableCompileCache = enableCompileCache;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const nodeModule = tslib_1.__importStar(require("node:module"));
|
|
6
|
+
/**
|
|
7
|
+
* Enables V8's on-disk bytecode cache for the current process.
|
|
8
|
+
*
|
|
9
|
+
* Calls `module.enableCompileCache()` with no arguments and lets Node pick
|
|
10
|
+
* the location, which means Node's standard env vars work transparently:
|
|
11
|
+
* - `NODE_COMPILE_CACHE=<dir>` — override the cache directory.
|
|
12
|
+
* - `NODE_DISABLE_COMPILE_CACHE=1` — disable entirely.
|
|
13
|
+
*
|
|
14
|
+
* The default location lives under the OS temp dir keyed by V8 version, so
|
|
15
|
+
* the cache is shared across workspaces and self-invalidates on Node
|
|
16
|
+
* upgrades — no nx-specific cleanup needed.
|
|
17
|
+
*
|
|
18
|
+
* Called at the entry point of every long-lived nx process (main CLI,
|
|
19
|
+
* daemon, plugin workers) via `enable-compile-cache.ts`, which side-effects
|
|
20
|
+
* this on import.
|
|
21
|
+
*
|
|
22
|
+
* Set `NX_COMPILE_CACHE=false` to opt out without disabling the cache for
|
|
23
|
+
* non-nx Node processes the way `NODE_DISABLE_COMPILE_CACHE` would.
|
|
24
|
+
*
|
|
25
|
+
* No-op on Node versions without the `module.enableCompileCache` API.
|
|
26
|
+
* Errors are swallowed — the compile cache is a pure performance
|
|
27
|
+
* optimization and must never break the CLI.
|
|
28
|
+
*/
|
|
29
|
+
function enableCompileCache(
|
|
30
|
+
// Test seam: production callers omit this. `unknown` (rather than
|
|
31
|
+
// `EnableCompileCacheFn | undefined`) lets tests pass a non-function to
|
|
32
|
+
// simulate pre-22.8 Node where `module.enableCompileCache` is missing. We
|
|
33
|
+
// read `arguments.length` so callers can *explicitly* pass `undefined`.
|
|
34
|
+
...override) {
|
|
35
|
+
if (process.env.NX_COMPILE_CACHE === 'false')
|
|
36
|
+
return false;
|
|
37
|
+
const impl = override.length === 0
|
|
38
|
+
? nodeModule.enableCompileCache
|
|
39
|
+
: override[0];
|
|
40
|
+
if (typeof impl !== 'function')
|
|
41
|
+
return false;
|
|
42
|
+
try {
|
|
43
|
+
impl();
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
// Side-effect-only module: import this as the *first* import in any nx
|
|
4
|
+
// process entry point so V8's compile cache is enabled before the rest of
|
|
5
|
+
// the import chain (which is what we actually want to cache) starts loading.
|
|
6
|
+
const compile_cache_1 = require("./compile-cache");
|
|
7
|
+
(0, compile_cache_1.enableCompileCache)();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if `@nx/js` is installed by attempting to resolve its `package.json`.
|
|
3
|
+
*
|
|
4
|
+
* Lives in its own module so unit tests can `jest.doMock` it without having to
|
|
5
|
+
* intercept Node's resolver at the global level. The previous in-`package-json`
|
|
6
|
+
* definition was unreachable to mocks because callers in the same module
|
|
7
|
+
* referenced it via the local lexical binding rather than `module.exports`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function hasNxJsPlugin(projectRoot: string, workspaceRoot: string): boolean;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.hasNxJsPlugin = hasNxJsPlugin;
|
|
4
|
+
const installation_directory_1 = require("./installation-directory");
|
|
5
|
+
/**
|
|
6
|
+
* Checks if `@nx/js` is installed by attempting to resolve its `package.json`.
|
|
7
|
+
*
|
|
8
|
+
* Lives in its own module so unit tests can `jest.doMock` it without having to
|
|
9
|
+
* intercept Node's resolver at the global level. The previous in-`package-json`
|
|
10
|
+
* definition was unreachable to mocks because callers in the same module
|
|
11
|
+
* referenced it via the local lexical binding rather than `module.exports`.
|
|
12
|
+
*/
|
|
13
|
+
function hasNxJsPlugin(projectRoot, workspaceRoot) {
|
|
14
|
+
try {
|
|
15
|
+
// nx-ignore-next-line
|
|
16
|
+
require.resolve('@nx/js/package.json', {
|
|
17
|
+
paths: [projectRoot, ...(0, installation_directory_1.getNxRequirePaths)(workspaceRoot), __dirname],
|
|
18
|
+
});
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the workspace's installed `nx` version, or `null` if no installed
|
|
3
|
+
* `nx` can be located. Routed through a cache-shielded, self-reference-free
|
|
4
|
+
* `require.resolve` so the answer always reflects the workspace's
|
|
5
|
+
* `node_modules`/PnP store rather than whichever `nx` package happens to be
|
|
6
|
+
* loaded in the current process. See nrwl/nx#35444.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getInstalledNxVersion(): string | null;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getInstalledNxVersion = getInstalledNxVersion;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const node_module_1 = tslib_1.__importStar(require("node:module"));
|
|
6
|
+
const fileutils_1 = require("./fileutils");
|
|
7
|
+
const workspace_root_1 = require("./workspace-root");
|
|
8
|
+
const installation_directory_1 = require("./installation-directory");
|
|
9
|
+
/**
|
|
10
|
+
* Resolve the workspace's installed `nx` version, or `null` if no installed
|
|
11
|
+
* `nx` can be located. Routed through a cache-shielded, self-reference-free
|
|
12
|
+
* `require.resolve` so the answer always reflects the workspace's
|
|
13
|
+
* `node_modules`/PnP store rather than whichever `nx` package happens to be
|
|
14
|
+
* loaded in the current process. See nrwl/nx#35444.
|
|
15
|
+
*/
|
|
16
|
+
function getInstalledNxVersion() {
|
|
17
|
+
const nxPackageJsonPath = resolvePackageJsonWithoutCachePollution('nx', (0, installation_directory_1.getNxRequirePaths)(workspace_root_1.workspaceRoot));
|
|
18
|
+
if (!nxPackageJsonPath) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
return (0, fileutils_1.readJsonFile)(nxPackageJsonPath).version ?? null;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Resolve `<packageName>/package.json` via Node's CJS resolver while
|
|
30
|
+
* neutralising both ways `require.resolve(req, { paths })` can lie about
|
|
31
|
+
* the `paths` argument:
|
|
32
|
+
*
|
|
33
|
+
* 1. Process-wide `Module._pathCache` — swapped out for the duration of
|
|
34
|
+
* the call, so any cache entries written are discarded and any
|
|
35
|
+
* previously-poisoned entries are not read. Without this, an
|
|
36
|
+
* in-process load of a second `nx` package (e.g. the temp `nx@latest`
|
|
37
|
+
* install used by the daemon's AI-agents and console-status checks)
|
|
38
|
+
* can poison the cache key this call uses and make us read the temp
|
|
39
|
+
* path instead of the workspace path.
|
|
40
|
+
*
|
|
41
|
+
* 2. Package self-reference — when a file inside package `nx` calls
|
|
42
|
+
* `require.resolve('nx/...')`, Node returns that calling package's
|
|
43
|
+
* own file regardless of `paths`. We avoid that by issuing the
|
|
44
|
+
* resolve from a `createRequire` rooted at a synthetic path that is
|
|
45
|
+
* outside any package, so the resolver has no "self" to reference
|
|
46
|
+
* and must honour `paths`.
|
|
47
|
+
*
|
|
48
|
+
* Node's single-threaded synchronous execution means `require.resolve` does
|
|
49
|
+
* not yield, so no other code in the process can observe the swapped cache.
|
|
50
|
+
*/
|
|
51
|
+
function resolvePackageJsonWithoutCachePollution(packageName, requirePaths) {
|
|
52
|
+
// `_pathCache` is an internal Node API not exposed in @types/node.
|
|
53
|
+
const realCache = node_module_1.default._pathCache;
|
|
54
|
+
node_module_1.default._pathCache = Object.create(null);
|
|
55
|
+
try {
|
|
56
|
+
const detachedRequire = (0, node_module_1.createRequire)('/__nx_detached_resolver__/x.js');
|
|
57
|
+
return detachedRequire.resolve(`${packageName}/package.json`, {
|
|
58
|
+
paths: requirePaths,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
finally {
|
|
65
|
+
node_module_1.default._pathCache = realCache;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
export declare const NX_PREFIX: string;
|
|
2
2
|
export declare const NX_ERROR: string;
|
|
3
|
+
type LogDriver = Pick<Console, 'warn' | 'error' | 'info' | 'log' | 'debug'>;
|
|
4
|
+
export declare function createLogger(driver: LogDriver): {
|
|
5
|
+
warn: (...v: any[]) => void;
|
|
6
|
+
error: (s: any) => void;
|
|
7
|
+
info: (s: any) => void;
|
|
8
|
+
log: (...s: any[]) => void;
|
|
9
|
+
debug: (...s: any[]) => void;
|
|
10
|
+
fatal: (...s: any[]) => void;
|
|
11
|
+
verbose: (...s: any[]) => void;
|
|
12
|
+
};
|
|
3
13
|
export declare const logger: {
|
|
4
|
-
warn: (
|
|
14
|
+
warn: (...v: any[]) => void;
|
|
5
15
|
error: (s: any) => void;
|
|
6
16
|
info: (s: any) => void;
|
|
7
17
|
log: (...s: any[]) => void;
|
|
@@ -10,3 +20,4 @@ export declare const logger: {
|
|
|
10
20
|
verbose: (...s: any[]) => void;
|
|
11
21
|
};
|
|
12
22
|
export declare function stripIndent(str: string): string;
|
|
23
|
+
export {};
|
package/dist/src/utils/logger.js
CHANGED
|
@@ -1,47 +1,68 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.logger = exports.NX_ERROR = exports.NX_PREFIX = void 0;
|
|
4
|
+
exports.createLogger = createLogger;
|
|
4
5
|
exports.stripIndent = stripIndent;
|
|
5
6
|
const tslib_1 = require("tslib");
|
|
6
7
|
const pc = tslib_1.__importStar(require("picocolors"));
|
|
8
|
+
const is_on_daemon_1 = require("../daemon/is-on-daemon");
|
|
9
|
+
const logger_1 = require("../daemon/logger");
|
|
7
10
|
exports.NX_PREFIX = pc.inverse(pc.bold(pc.cyan(' NX ')));
|
|
8
11
|
exports.NX_ERROR = pc.inverse(pc.bold(pc.red(' ERROR ')));
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
12
|
+
function createLogger(driver) {
|
|
13
|
+
return {
|
|
14
|
+
warn: (...v) => driver.warn(...v.map((s) => pc.bold(pc.yellow(s)))),
|
|
15
|
+
error: (s) => {
|
|
16
|
+
if (typeof s === 'string' && s.startsWith('NX ')) {
|
|
17
|
+
driver.error(`\n${exports.NX_ERROR} ${pc.bold(pc.red(s.slice(3)))}\n`);
|
|
18
|
+
}
|
|
19
|
+
else if (s instanceof Error && s.stack) {
|
|
20
|
+
driver.error(pc.bold(pc.red(s.stack)));
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
driver.error(pc.bold(pc.red(s)));
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
info: (s) => {
|
|
27
|
+
if (typeof s === 'string' && s.startsWith('NX ')) {
|
|
28
|
+
driver.info(`\n${exports.NX_PREFIX} ${pc.bold(s.slice(3))}\n`);
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
driver.info(s);
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
log: (...s) => {
|
|
35
|
+
driver.log(...s);
|
|
36
|
+
},
|
|
37
|
+
debug: (...s) => {
|
|
38
|
+
driver.debug(...s);
|
|
39
|
+
},
|
|
40
|
+
fatal: (...s) => {
|
|
41
|
+
driver.error(...s);
|
|
42
|
+
},
|
|
43
|
+
verbose: (...s) => {
|
|
44
|
+
if (process.env.NX_VERBOSE_LOGGING === 'true') {
|
|
45
|
+
// verbose logs go to stderr to prevent things like `nx show projects | grep`
|
|
46
|
+
// breaking when you enable verbose logging. The only potential breakage from
|
|
47
|
+
// this would be if a tool counts any output on stderr as being an issue, but
|
|
48
|
+
// there are likely other places that would trigger those same issues.
|
|
49
|
+
driver.warn(...s);
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
exports.logger = createLogger((0, is_on_daemon_1.isOnDaemon)()
|
|
55
|
+
? (() => {
|
|
56
|
+
const log = logger_1.serverLogger.log.bind(logger_1.serverLogger);
|
|
57
|
+
return {
|
|
58
|
+
warn: log,
|
|
59
|
+
error: log,
|
|
60
|
+
debug: log,
|
|
61
|
+
info: log,
|
|
62
|
+
log: log,
|
|
63
|
+
};
|
|
64
|
+
})()
|
|
65
|
+
: console);
|
|
45
66
|
function stripIndent(str) {
|
|
46
67
|
const match = str.match(/^[ \t]*(?=\S)/gm);
|
|
47
68
|
if (!match) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { NxKey } from '@nx/key';
|
|
2
2
|
export declare function createNxKeyLicenseeInformation(nxKey: NxKey): string;
|
|
3
|
-
export declare function printNxKey(): Promise<void>;
|
|
4
3
|
export declare function getNxKeyInformation(): Promise<NxKey | null>;
|
|
5
4
|
export declare class NxKeyNotInstalledError extends Error {
|
|
6
5
|
constructor(e: Error);
|