nx 22.7.1 → 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.
Files changed (41) hide show
  1. package/dist/bin/nx.d.ts +1 -0
  2. package/dist/bin/nx.js +3 -0
  3. package/dist/src/ai/clone-ai-config-repo.js +20 -3
  4. package/dist/src/analytics/analytics.js +10 -1
  5. package/dist/src/command-line/graph/graph.js +0 -1
  6. package/dist/src/command-line/release/config/use-legacy-versioning.d.ts +2 -0
  7. package/dist/src/command-line/release/config/use-legacy-versioning.js +8 -0
  8. package/dist/src/config/misc-interfaces.d.ts +6 -0
  9. package/dist/src/core/graph/main.js +1 -1
  10. package/dist/src/core/graph/styles.css +1 -1
  11. package/dist/src/daemon/server/latest-nx.js +2 -0
  12. package/dist/src/daemon/server/start.d.ts +1 -1
  13. package/dist/src/daemon/server/start.js +2 -0
  14. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  15. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  16. package/dist/src/plugins/js/lock-file/npm-parser.js +37 -19
  17. package/dist/src/plugins/js/lock-file/pnpm-parser.js +51 -4
  18. package/dist/src/plugins/js/lock-file/project-graph-pruning.js +12 -4
  19. package/dist/src/project-graph/plugins/isolation/plugin-worker.d.ts +1 -0
  20. package/dist/src/project-graph/plugins/isolation/plugin-worker.js +2 -0
  21. package/dist/src/tasks-runner/life-cycles/task-history-life-cycle-old.js +13 -2
  22. package/dist/src/tasks-runner/life-cycles/task-history-life-cycle.js +16 -5
  23. package/dist/src/tasks-runner/life-cycles/tui-summary-life-cycle.js +11 -2
  24. package/dist/src/tasks-runner/run-command.js +8 -1
  25. package/dist/src/tasks-runner/task-orchestrator.js +20 -4
  26. package/dist/src/utils/ab-testing.js +12 -0
  27. package/dist/src/utils/compile-cache.d.ts +24 -0
  28. package/dist/src/utils/compile-cache.js +49 -0
  29. package/dist/src/utils/enable-compile-cache.d.ts +1 -0
  30. package/dist/src/utils/enable-compile-cache.js +7 -0
  31. package/dist/src/utils/has-nx-js-plugin.d.ts +9 -0
  32. package/dist/src/utils/has-nx-js-plugin.js +24 -0
  33. package/dist/src/utils/logger.d.ts +12 -1
  34. package/dist/src/utils/logger.js +57 -36
  35. package/dist/src/utils/nx-key.d.ts +0 -1
  36. package/dist/src/utils/nx-key.js +20 -23
  37. package/dist/src/utils/output.d.ts +3 -2
  38. package/dist/src/utils/output.js +29 -28
  39. package/dist/src/utils/package-json.js +2 -13
  40. package/dist/src/utils/perf-logging.js +3 -1
  41. package/package.json +22 -15
@@ -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) {
@@ -498,11 +506,18 @@ class TaskOrchestrator {
498
506
  // Heavy operations (caching, scheduling, complete) happen at batch-end in postRunSteps
499
507
  batchProcess.onTaskResults((taskId, result) => {
500
508
  const task = this.taskGraph.tasks[taskId];
501
- const status = result.success ? 'success' : 'failure';
502
- this.options.lifeCycle.printTaskTerminalOutput(task, status, result.terminalOutput ?? '');
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.
503
512
  if (result.terminalOutput) {
504
513
  this.options.lifeCycle.appendTaskOutput(taskId, result.terminalOutput, false);
505
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
+ }
506
521
  task.startTime = result.startTime;
507
522
  task.endTime = result.endTime;
508
523
  if (result.startTime && result.endTime) {
@@ -516,10 +531,11 @@ class TaskOrchestrator {
516
531
  const task = this.taskGraph.tasks[taskId];
517
532
  task.startTime = result.startTime;
518
533
  task.endTime = result.endTime;
534
+ const status = resolveBatchTaskStatus(result);
519
535
  return {
520
- code: result.success ? 0 : 1,
536
+ code: status === 'success' ? 0 : 1,
521
537
  task,
522
- status: (result.success ? 'success' : 'failure'),
538
+ status,
523
539
  terminalOutput: result.terminalOutput,
524
540
  };
525
541
  });
@@ -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
+ }
@@ -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: (s: any) => void;
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 {};
@@ -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
- exports.logger = {
10
- warn: (s) => console.warn(pc.bold(pc.yellow(s))),
11
- error: (s) => {
12
- if (typeof s === 'string' && s.startsWith('NX ')) {
13
- console.error(`\n${exports.NX_ERROR} ${pc.bold(pc.red(s.slice(3)))}\n`);
14
- }
15
- else if (s instanceof Error && s.stack) {
16
- console.error(pc.bold(pc.red(s.stack)));
17
- }
18
- else {
19
- console.error(pc.bold(pc.red(s)));
20
- }
21
- },
22
- info: (s) => {
23
- if (typeof s === 'string' && s.startsWith('NX ')) {
24
- console.info(`\n${exports.NX_PREFIX} ${pc.bold(s.slice(3))}\n`);
25
- }
26
- else {
27
- console.info(s);
28
- }
29
- },
30
- log: (...s) => {
31
- console.log(...s);
32
- },
33
- debug: (...s) => {
34
- console.debug(...s);
35
- },
36
- fatal: (...s) => {
37
- console.error(...s);
38
- },
39
- verbose: (...s) => {
40
- if (process.env.NX_VERBOSE_LOGGING === 'true') {
41
- console.log(...s);
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);
@@ -2,12 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.NxKeyNotInstalledError = void 0;
4
4
  exports.createNxKeyLicenseeInformation = createNxKeyLicenseeInformation;
5
- exports.printNxKey = printNxKey;
6
5
  exports.getNxKeyInformation = getNxKeyInformation;
7
- const logger_1 = require("./logger");
6
+ const installation_directory_1 = require("./installation-directory");
8
7
  const package_manager_1 = require("./package-manager");
9
8
  const workspace_root_1 = require("./workspace-root");
10
- const handle_import_1 = require("./handle-import");
11
9
  function createNxKeyLicenseeInformation(nxKey) {
12
10
  if ('isPowerpack' in nxKey && nxKey.isPowerpack) {
13
11
  return `Licensed to ${nxKey.organizationName} for ${nxKey.seatCount} user${nxKey.seatCount > 1 ? 's' : ''} in ${nxKey.workspaceCount === 9999
@@ -18,32 +16,31 @@ function createNxKeyLicenseeInformation(nxKey) {
18
16
  return `Licensed to ${nxKey.organizationName}.`;
19
17
  }
20
18
  }
21
- async function printNxKey() {
19
+ // `await handleImport` walks node_modules and pays ~25ms per miss; `resolve`
20
+ // is just the filesystem lookup and is microseconds when the package is absent.
21
+ // Only treat MODULE_NOT_FOUND as "not installed" so unrelated errors (permission,
22
+ // corrupt package.json, etc.) still surface instead of being silently hidden.
23
+ function packageInstalled(name) {
22
24
  try {
23
- const key = await getNxKeyInformation();
24
- if (key) {
25
- logger_1.logger.log(createNxKeyLicenseeInformation(key));
26
- }
25
+ require.resolve(name, { paths: (0, installation_directory_1.getNxRequirePaths)() });
26
+ return true;
27
+ }
28
+ catch (e) {
29
+ if (e?.code === 'MODULE_NOT_FOUND')
30
+ return false;
31
+ throw e;
27
32
  }
28
- catch { }
29
33
  }
30
34
  async function getNxKeyInformation() {
31
- try {
32
- const { getPowerpackLicenseInformation, getPowerpackLicenseInformationAsync, } = (await (0, handle_import_1.handleImport)('@nx/powerpack-license'));
33
- return (getPowerpackLicenseInformationAsync ?? getPowerpackLicenseInformation)(workspace_root_1.workspaceRoot);
35
+ if (packageInstalled('@nx/key')) {
36
+ const { getNxKeyInformationAsync } = await import('@nx/key');
37
+ return getNxKeyInformationAsync(workspace_root_1.workspaceRoot);
34
38
  }
35
- catch (e) {
36
- try {
37
- const { getNxKeyInformationAsync } = (await (0, handle_import_1.handleImport)('@nx/key'));
38
- return getNxKeyInformationAsync(workspace_root_1.workspaceRoot);
39
- }
40
- catch (e) {
41
- if ('code' in e && e.code === 'MODULE_NOT_FOUND') {
42
- throw new NxKeyNotInstalledError(e);
43
- }
44
- throw e;
45
- }
39
+ if (packageInstalled('@nx/powerpack-license')) {
40
+ const { getPowerpackLicenseInformation, getPowerpackLicenseInformationAsync, } = await import('@nx/powerpack-license');
41
+ return (getPowerpackLicenseInformationAsync ?? getPowerpackLicenseInformation)(workspace_root_1.workspaceRoot);
46
42
  }
43
+ throw new NxKeyNotInstalledError(new Error('MODULE_NOT_FOUND'));
47
44
  }
48
45
  class NxKeyNotInstalledError extends Error {
49
46
  constructor(e) {
@@ -1,3 +1,4 @@
1
+ import { WriteStream } from 'tty';
1
2
  import type { TaskStatus } from '../tasks-runner/tasks-runner';
2
3
  export interface CLIErrorMessageConfig {
3
4
  title: string;
@@ -47,12 +48,12 @@ declare class CLIOutput {
47
48
  bold: import("picocolors/types").Formatter;
48
49
  underline: import("picocolors/types").Formatter;
49
50
  dim: import("picocolors/types").Formatter;
50
- private writeToStdOut;
51
+ private writeToStream;
51
52
  overwriteLine(lineText?: string): void;
52
53
  private writeOutputTitle;
53
54
  private writeOptionalOutputBody;
54
55
  applyNxPrefix(color: string, text: string): string;
55
- addNewline(): void;
56
+ addNewline(stream?: WriteStream): void;
56
57
  addVerticalSeparator(color?: string): void;
57
58
  addVerticalSeparatorWithoutNewLines(color?: string): void;
58
59
  getVerticalSeparatorLines(color?: string): string[];
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.output = void 0;
4
4
  exports.orange = orange;
5
5
  const tslib_1 = require("tslib");
6
- const pc = tslib_1.__importStar(require("picocolors"));
7
6
  const os_1 = require("os");
7
+ const pc = tslib_1.__importStar(require("picocolors"));
8
8
  const readline = tslib_1.__importStar(require("readline"));
9
9
  const GH_GROUP_PREFIX = '::group::';
10
10
  const GH_GROUP_SUFFIX = '::endgroup::';
@@ -62,8 +62,8 @@ class CLIOutput {
62
62
  }
63
63
  return divider;
64
64
  }
65
- writeToStdOut(str) {
66
- process.stdout.write(str);
65
+ writeToStream(str, stream = process.stdout) {
66
+ stream.write(str);
67
67
  }
68
68
  overwriteLine(lineText = '') {
69
69
  // Ensure we always start writing from column 0.
@@ -78,23 +78,23 @@ class CLIOutput {
78
78
  process.stdout.write('\n');
79
79
  readline.cursorTo(process.stdout, 0);
80
80
  }
81
- writeOutputTitle({ color, title, }) {
82
- this.writeToStdOut(`${this.applyNxPrefix(color, title)}${os_1.EOL}`);
81
+ writeOutputTitle({ color, title, }, stream = process.stdout) {
82
+ this.writeToStream(`${this.applyNxPrefix(color, title)}${os_1.EOL}`, stream);
83
83
  }
84
- writeOptionalOutputBody(bodyLines) {
84
+ writeOptionalOutputBody(bodyLines, stream = process.stdout) {
85
85
  if (!bodyLines) {
86
86
  return;
87
87
  }
88
- this.addNewline();
89
- bodyLines.forEach((bodyLine) => this.writeToStdOut(`${bodyLine}${os_1.EOL}`));
88
+ this.addNewline(stream);
89
+ bodyLines.forEach((bodyLine) => this.writeToStream(`${bodyLine}${os_1.EOL}`, stream));
90
90
  }
91
91
  applyNxPrefix(color = 'cyan', text) {
92
92
  const colorFn = pcColors[color] || ((t) => t);
93
93
  const nxPrefix = pc.inverse(pc.bold(colorFn(` ${this.cliName} `)));
94
94
  return `${nxPrefix} ${text}`;
95
95
  }
96
- addNewline() {
97
- this.writeToStdOut(os_1.EOL);
96
+ addNewline(stream = process.stdout) {
97
+ this.writeToStream(os_1.EOL, stream);
98
98
  }
99
99
  addVerticalSeparator(color = 'gray') {
100
100
  this.addNewline();
@@ -102,7 +102,7 @@ class CLIOutput {
102
102
  this.addNewline();
103
103
  }
104
104
  addVerticalSeparatorWithoutNewLines(color = 'gray') {
105
- this.writeToStdOut(`${this.getVerticalSeparator(color)}${os_1.EOL}`);
105
+ this.writeToStream(`${this.getVerticalSeparator(color)}${os_1.EOL}`);
106
106
  }
107
107
  getVerticalSeparatorLines(color = 'gray') {
108
108
  return ['', this.getVerticalSeparator(color), ''];
@@ -112,36 +112,37 @@ class CLIOutput {
112
112
  return pc.dim(colorFn(this.VERTICAL_SEPARATOR));
113
113
  }
114
114
  error({ title, slug, bodyLines }) {
115
- this.addNewline();
115
+ const stream = process.stderr;
116
+ this.addNewline(stream);
116
117
  this.writeOutputTitle({
117
118
  color: 'red',
118
119
  title: pc.red(title),
119
- });
120
- this.writeOptionalOutputBody(bodyLines);
120
+ }, stream);
121
+ this.writeOptionalOutputBody(bodyLines, stream);
121
122
  /**
122
123
  * Optional slug to be used in an Nx error message redirect URL
123
124
  */
124
125
  if (slug && typeof slug === 'string') {
125
- this.addNewline();
126
- this.writeToStdOut(`${pc.gray(' Learn more about this error: ')}https://errors.nx.dev/${slug}${os_1.EOL}`);
126
+ this.addNewline(stream);
127
+ this.writeToStream(`${pc.gray(' Learn more about this error: ')}https://errors.nx.dev/${slug}${os_1.EOL}`, stream);
127
128
  }
128
- this.addNewline();
129
+ this.addNewline(stream);
129
130
  }
130
131
  warn({ title, slug, bodyLines }) {
131
- this.addNewline();
132
+ this.addNewline(process.stderr);
132
133
  this.writeOutputTitle({
133
134
  color: 'yellow',
134
135
  title: pc.yellow(title),
135
- });
136
- this.writeOptionalOutputBody(bodyLines);
136
+ }, process.stderr);
137
+ this.writeOptionalOutputBody(bodyLines, process.stderr);
137
138
  /**
138
139
  * Optional slug to be used in an Nx warning message redirect URL
139
140
  */
140
141
  if (slug && typeof slug === 'string') {
141
- this.addNewline();
142
- this.writeToStdOut(`${pc.gray(' Learn more about this warning: ')}https://errors.nx.dev/${slug}${os_1.EOL}`);
142
+ this.addNewline(process.stderr);
143
+ this.writeToStream(`${pc.gray(' Learn more about this warning: ')}https://errors.nx.dev/${slug}${os_1.EOL}`, process.stderr);
143
144
  }
144
- this.addNewline();
145
+ this.addNewline(process.stderr);
145
146
  }
146
147
  note({ title, bodyLines }) {
147
148
  this.addNewline();
@@ -170,12 +171,12 @@ class CLIOutput {
170
171
  this.addNewline();
171
172
  }
172
173
  logRawLine(message) {
173
- this.writeToStdOut(`${message}${os_1.EOL}`);
174
+ this.writeToStream(`${message}${os_1.EOL}`);
174
175
  this.addNewline();
175
176
  }
176
177
  logCommand(message, taskStatus) {
177
178
  this.addNewline();
178
- this.writeToStdOut(this.getCommandWithStatus(message, taskStatus));
179
+ this.writeToStream(this.getCommandWithStatus(message, taskStatus));
179
180
  this.addNewline();
180
181
  this.addNewline();
181
182
  }
@@ -187,13 +188,13 @@ class CLIOutput {
187
188
  commandOutputWithStatus = `${GH_GROUP_PREFIX}${icon} ${commandOutputWithStatus}`;
188
189
  }
189
190
  this.addNewline();
190
- this.writeToStdOut(commandOutputWithStatus);
191
+ this.writeToStream(commandOutputWithStatus);
191
192
  this.addNewline();
192
193
  this.addNewline();
193
- this.writeToStdOut(output);
194
+ this.writeToStream(output);
194
195
  if (process.env.NX_SKIP_LOG_GROUPING !== 'true' &&
195
196
  process.env.GITHUB_ACTIONS) {
196
- this.writeToStdOut(GH_GROUP_SUFFIX);
197
+ this.writeToStream(GH_GROUP_SUFFIX);
197
198
  }
198
199
  }
199
200
  getCommandWithStatus(message, taskStatus) {
@@ -21,6 +21,7 @@ const json_1 = require("../generators/utils/json");
21
21
  const target_merging_1 = require("../project-graph/utils/project-configuration/target-merging");
22
22
  const catalog_1 = require("./catalog");
23
23
  const fileutils_1 = require("./fileutils");
24
+ const has_nx_js_plugin_1 = require("./has-nx-js-plugin");
24
25
  const installation_directory_1 = require("./installation-directory");
25
26
  const package_manager_1 = require("./package-manager");
26
27
  const workspace_root_1 = require("./workspace-root");
@@ -124,7 +125,7 @@ function readTargetsFromPackageJson(packageJson, nxJson, projectRoot, workspaceR
124
125
  */
125
126
  if (!isPrivate &&
126
127
  !res['nx-release-publish'] &&
127
- hasNxJsPlugin(projectRoot, workspaceRoot)) {
128
+ (0, has_nx_js_plugin_1.hasNxJsPlugin)(projectRoot, workspaceRoot)) {
128
129
  const nxReleasePublishTargetDefaults = nxJson?.targetDefaults?.['nx-release-publish'] ?? {};
129
130
  res['nx-release-publish'] = {
130
131
  executor: '@nx/js:release-publish',
@@ -141,18 +142,6 @@ function readTargetsFromPackageJson(packageJson, nxJson, projectRoot, workspaceR
141
142
  }
142
143
  return res;
143
144
  }
144
- function hasNxJsPlugin(projectRoot, workspaceRoot) {
145
- try {
146
- // nx-ignore-next-line
147
- require.resolve('@nx/js/package.json', {
148
- paths: [projectRoot, ...(0, installation_directory_1.getNxRequirePaths)(workspaceRoot), __dirname],
149
- });
150
- return true;
151
- }
152
- catch {
153
- return false;
154
- }
155
- }
156
145
  /**
157
146
  * Uses `require.resolve` to read the package.json for a module.
158
147
  *
@@ -7,6 +7,7 @@ function isTrackedDetail(detail) {
7
7
  detail.track === true);
8
8
  }
9
9
  new perf_hooks_1.PerformanceObserver((list) => {
10
+ // observer is configured for 'measure' entries only (see .observe call below)
10
11
  const entries = list.getEntries();
11
12
  const logEnabled = process.env.NX_PERF_LOGGING === 'true';
12
13
  const tracked = entries.filter((e) => isTrackedDetail(e.detail));
@@ -17,9 +18,10 @@ new perf_hooks_1.PerformanceObserver((list) => {
17
18
  if (logEnabled) {
18
19
  const { isOnDaemon } = require('../daemon/is-on-daemon');
19
20
  const { serverLogger } = require('../daemon/logger');
21
+ const { logger } = require('./logger');
20
22
  const log = isOnDaemon()
21
23
  ? (msg) => serverLogger.log(msg)
22
- : console.log;
24
+ : (msg) => logger.warn(msg);
23
25
  for (const entry of entries) {
24
26
  log(`Time taken for '${entry.name}' ${entry.duration}ms`);
25
27
  }