nx 17.3.1 → 17.3.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.
@@ -4,23 +4,26 @@ const path = require("path");
4
4
  const native_1 = require("../../native");
5
5
  const child_process_1 = require("../../utils/child-process");
6
6
  const package_manager_1 = require("../../utils/package-manager");
7
+ const child_process_2 = require("child_process");
7
8
  async function default_1(options, context) {
8
9
  const pm = (0, package_manager_1.getPackageManagerCommand)();
9
10
  try {
10
- await new Promise((res, rej) => {
11
- const cp = new child_process_1.PseudoTtyProcess((0, native_1.runCommand)(pm.run(options.script, options.__unparsed__.join(' ')), path.join(context.root, context.projectsConfigurations.projects[context.projectName].root), process.env));
12
- cp.onExit((code) => {
13
- if (code === 0) {
14
- res();
15
- }
16
- else if (code >= 128) {
17
- process.exit(code);
18
- }
19
- else {
20
- rej();
21
- }
22
- });
23
- });
11
+ let command = pm.run(options.script, options.__unparsed__.join(' '));
12
+ let cwd = path.join(context.root, context.projectsConfigurations.projects[context.projectName].root);
13
+ let env = process.env;
14
+ // when running nx through npx with node_modules installed with npm, the path gets modified to include the full workspace path with the node_modules folder
15
+ // This causes issues when running in a pty process, so we filter out the node_modules paths from the PATH
16
+ // Since the command here will be run with the package manager script command, the path will be modified again within the PTY process itself.
17
+ let filteredPath = env.PATH?.split(path.delimiter)
18
+ .filter((p) => !p.startsWith(path.join(context.root, 'node_modules')))
19
+ .join(path.delimiter) ?? '';
20
+ env.PATH = filteredPath;
21
+ if (process.stdout.isTTY) {
22
+ await ptyProcess(command, cwd, env);
23
+ }
24
+ else {
25
+ nodeProcess(command, cwd, env);
26
+ }
24
27
  return { success: true };
25
28
  }
26
29
  catch (e) {
@@ -28,3 +31,26 @@ async function default_1(options, context) {
28
31
  }
29
32
  }
30
33
  exports.default = default_1;
34
+ function nodeProcess(command, cwd, env) {
35
+ (0, child_process_2.execSync)(command, {
36
+ stdio: ['inherit', 'inherit', 'inherit'],
37
+ cwd,
38
+ env,
39
+ });
40
+ }
41
+ async function ptyProcess(command, cwd, env) {
42
+ return new Promise((res, rej) => {
43
+ const cp = new child_process_1.PseudoTtyProcess((0, native_1.runCommand)(command, cwd, env));
44
+ cp.onExit((code) => {
45
+ if (code === 0) {
46
+ res();
47
+ }
48
+ else if (code >= 128) {
49
+ process.exit(code);
50
+ }
51
+ else {
52
+ rej();
53
+ }
54
+ });
55
+ });
56
+ }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getGlobPatternsFromPackageManagerWorkspaces = exports.buildProjectConfigurationFromPackageJson = exports.createNodeFromPackageJson = exports.getNxPackageJsonWorkspacesPlugin = void 0;
4
+ const minimatch_1 = require("minimatch");
4
5
  const node_fs_1 = require("node:fs");
5
6
  const node_path_1 = require("node:path");
6
7
  const nx_json_1 = require("../../config/nx-json");
@@ -13,11 +14,31 @@ const package_json_1 = require("../../utils/package-json");
13
14
  const path_1 = require("../../utils/path");
14
15
  function getNxPackageJsonWorkspacesPlugin(root) {
15
16
  const readJson = (f) => (0, fileutils_1.readJsonFile)((0, node_path_1.join)(root, f));
17
+ const patterns = getGlobPatternsFromPackageManagerWorkspaces(root, readJson);
18
+ // If the user only specified a negative pattern, we should find all package.json
19
+ // files and only return those that don't match a negative pattern.
20
+ const negativePatterns = patterns.filter((p) => p.startsWith('!'));
21
+ let positivePatterns = patterns.filter((p) => !p.startsWith('!'));
22
+ if (
23
+ // There are some negative patterns
24
+ negativePatterns.length > 0 &&
25
+ // No positive patterns
26
+ (positivePatterns.length === 0 ||
27
+ // Or only a single positive pattern that is the default coming from root package
28
+ (positivePatterns.length === 1 && positivePatterns[0] === 'package.json'))) {
29
+ positivePatterns.push('**/package.json');
30
+ }
16
31
  return {
17
32
  name: 'nx/core/package-json-workspaces',
18
33
  createNodes: [
19
- (0, globs_1.combineGlobPatterns)(getGlobPatternsFromPackageManagerWorkspaces(root, readJson)),
20
- (p) => createNodeFromPackageJson(p, root),
34
+ (0, globs_1.combineGlobPatterns)(positivePatterns),
35
+ (p) => {
36
+ if (!negativePatterns.some((negative) => (0, minimatch_1.minimatch)(p, negative))) {
37
+ return createNodeFromPackageJson(p, root);
38
+ }
39
+ // A negative pattern matched, so we should not create a node for this package.json
40
+ return {};
41
+ },
21
42
  ],
22
43
  };
23
44
  }
@@ -46,22 +46,30 @@ exports.TargetDefaultsPlugin = {
46
46
  return true;
47
47
  }),
48
48
  ...Object.keys(projectJson?.targets ?? {}),
49
+ ...Object.keys(packageJson?.nx?.targets ?? {}),
49
50
  ]);
50
51
  const executorToTargetMap = getExecutorToTargetMap(packageJson, projectJson);
51
- const newTargets = {};
52
+ const modifiedTargets = {};
52
53
  for (const defaultSpecifier in targetDefaults) {
53
- const targetName = executorToTargetMap.get(defaultSpecifier) ?? defaultSpecifier;
54
- newTargets[targetName] = structuredClone(targetDefaults[defaultSpecifier]);
55
- // TODO: Remove this after we figure out a way to define new targets
56
- // in target defaults
57
- if (!projectDefinedTargets.has(targetName)) {
58
- newTargets[targetName][exports.ONLY_MODIFIES_EXISTING_TARGET] = true;
54
+ const targetNames = executorToTargetMap.get(defaultSpecifier) ?? new Set();
55
+ targetNames.add(defaultSpecifier);
56
+ for (const targetName of targetNames) {
57
+ // Prevents `build` from overwriting `@nx/js:tsc` if both are present
58
+ // and build is specified later in the ordering.
59
+ if (!modifiedTargets[targetName] || targetName !== defaultSpecifier) {
60
+ modifiedTargets[targetName] = JSON.parse(JSON.stringify(targetDefaults[defaultSpecifier]));
61
+ }
62
+ // TODO: Remove this after we figure out a way to define new targets
63
+ // in target defaults
64
+ if (!projectDefinedTargets.has(targetName)) {
65
+ modifiedTargets[targetName][exports.ONLY_MODIFIES_EXISTING_TARGET] = true;
66
+ }
59
67
  }
60
68
  }
61
69
  return {
62
70
  projects: {
63
71
  [root]: {
64
- targets: newTargets,
72
+ targets: modifiedTargets,
65
73
  },
66
74
  },
67
75
  };
@@ -70,20 +78,18 @@ exports.TargetDefaultsPlugin = {
70
78
  };
71
79
  function getExecutorToTargetMap(packageJson, projectJson) {
72
80
  const executorToTargetMap = new Map();
73
- if (packageJson?.scripts) {
74
- for (const script in packageJson.scripts) {
75
- executorToTargetMap.set('nx:run-script', script);
76
- }
77
- }
78
- if (projectJson?.targets) {
79
- for (const target in projectJson.targets) {
80
- if (projectJson.targets[target].executor) {
81
- executorToTargetMap.set(projectJson.targets[target].executor, target);
82
- }
83
- else if (projectJson.targets[target].command) {
84
- executorToTargetMap.set('nx:run-commands', target);
85
- }
86
- }
81
+ const targets = Object.keys({
82
+ ...projectJson?.targets,
83
+ ...packageJson?.scripts,
84
+ ...packageJson?.nx?.targets,
85
+ });
86
+ for (const target of targets) {
87
+ const executor = projectJson?.targets?.[target]?.executor ??
88
+ packageJson?.nx?.targets?.[target]?.executor ??
89
+ 'nx:run-script';
90
+ const targetsForExecutor = executorToTargetMap.get(executor) ?? new Set();
91
+ targetsForExecutor.add(target);
92
+ executorToTargetMap.set(executor, targetsForExecutor);
87
93
  }
88
94
  return executorToTargetMap;
89
95
  }
@@ -132,8 +132,7 @@ async function createRunOneDynamicOutputRenderer({ initiatingProject, tasks, arg
132
132
  };
133
133
  lifeCycle.printTaskTerminalOutput = (task, cacheStatus, terminalOutput) => {
134
134
  if (task.target.project === initiatingProject) {
135
- output_1.output.logCommand(task.id, cacheStatus);
136
- process.stdout.write(terminalOutput);
135
+ output_1.output.logCommandOutput(task.id, cacheStatus, terminalOutput);
137
136
  }
138
137
  else {
139
138
  tasksToTerminalOutputs[task.id] = terminalOutput;
@@ -162,8 +161,7 @@ async function createRunOneDynamicOutputRenderer({ initiatingProject, tasks, arg
162
161
  clearRenderInterval();
163
162
  renderDependentTargets(false);
164
163
  output_1.output.addVerticalSeparator('red');
165
- output_1.output.logCommand(t.task.id, t.status);
166
- process.stdout.write(tasksToTerminalOutputs[t.task.id]);
164
+ output_1.output.logCommandOutput(t.task.id, t.status, tasksToTerminalOutputs[t.task.id]);
167
165
  }
168
166
  break;
169
167
  }
@@ -9,8 +9,7 @@ class EmptyTerminalOutputLifeCycle {
9
9
  cacheStatus === 'failure' ||
10
10
  cacheStatus === 'skipped') {
11
11
  const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
12
- output_1.output.logCommand(args.join(' '), cacheStatus);
13
- process.stdout.write(terminalOutput);
12
+ output_1.output.logCommandOutput(args.join(' '), cacheStatus, terminalOutput);
14
13
  }
15
14
  }
16
15
  }
@@ -61,8 +61,7 @@ class InvokeRunnerTerminalOutputLifeCycle {
61
61
  }
62
62
  printTaskTerminalOutput(task, cacheStatus, terminalOutput) {
63
63
  const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
64
- output_1.output.logCommand(args.join(' '), cacheStatus);
65
- process.stdout.write(terminalOutput);
64
+ output_1.output.logCommandOutput(args.join(' '), cacheStatus, terminalOutput);
66
65
  }
67
66
  }
68
67
  exports.InvokeRunnerTerminalOutputLifeCycle = InvokeRunnerTerminalOutputLifeCycle;
@@ -93,8 +93,7 @@ class StaticRunManyTerminalOutputLifeCycle {
93
93
  }
94
94
  printTaskTerminalOutput(task, cacheStatus, terminalOutput) {
95
95
  const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
96
- output_1.output.logCommand(args.join(' '), cacheStatus);
97
- process.stdout.write(terminalOutput);
96
+ output_1.output.logCommandOutput(args.join(' '), cacheStatus, terminalOutput);
98
97
  }
99
98
  }
100
99
  exports.StaticRunManyTerminalOutputLifeCycle = StaticRunManyTerminalOutputLifeCycle;
@@ -82,8 +82,7 @@ class StaticRunOneTerminalOutputLifeCycle {
82
82
  status === 'failure' ||
83
83
  task.target.project === this.initiatingProject) {
84
84
  const args = (0, utils_1.getPrintableCommandArgsForTask)(task);
85
- output_1.output.logCommand(args.join(' '), status);
86
- process.stdout.write(terminalOutput);
85
+ output_1.output.logCommandOutput(args.join(' '), status, terminalOutput);
87
86
  }
88
87
  }
89
88
  }
@@ -58,6 +58,9 @@ declare class CLIOutput {
58
58
  success({ title, bodyLines }: CLISuccessMessageConfig): void;
59
59
  logSingleLine(message: string): void;
60
60
  logCommand(message: string, taskStatus?: TaskStatus): void;
61
+ logCommandOutput(message: string, taskStatus: TaskStatus, output: string): void;
62
+ private getCommandWithStatus;
63
+ private getStatusIcon;
61
64
  private normalizeMessage;
62
65
  private addTaskStatus;
63
66
  log({ title, bodyLines, color }: CLIWarnMessageConfig & {
@@ -5,6 +5,8 @@ const chalk = require("chalk");
5
5
  const os_1 = require("os");
6
6
  const readline = require("readline");
7
7
  const is_ci_1 = require("./is-ci");
8
+ const GH_GROUP_PREFIX = '::group::';
9
+ const GH_GROUP_SUFFIX = '::endgroup::';
8
10
  /**
9
11
  * Automatically disable styling applied by chalk if CI=true
10
12
  */
@@ -152,11 +154,42 @@ class CLIOutput {
152
154
  }
153
155
  logCommand(message, taskStatus) {
154
156
  this.addNewline();
155
- const commandOutput = chalk.dim('> ') + this.formatCommand(this.normalizeMessage(message));
156
- const commandOutputWithStatus = this.addTaskStatus(taskStatus, commandOutput);
157
+ this.writeToStdOut(this.getCommandWithStatus(message, taskStatus));
158
+ this.addNewline();
159
+ this.addNewline();
160
+ }
161
+ logCommandOutput(message, taskStatus, output) {
162
+ let commandOutputWithStatus = this.getCommandWithStatus(message, taskStatus);
163
+ if (process.env.GITHUB_ACTIONS) {
164
+ const icon = this.getStatusIcon(taskStatus);
165
+ commandOutputWithStatus = `${GH_GROUP_PREFIX}${icon} ${commandOutputWithStatus}`;
166
+ }
167
+ this.addNewline();
157
168
  this.writeToStdOut(commandOutputWithStatus);
158
169
  this.addNewline();
159
170
  this.addNewline();
171
+ this.writeToStdOut(output);
172
+ if (process.env.GITHUB_ACTIONS) {
173
+ this.writeToStdOut(GH_GROUP_SUFFIX);
174
+ }
175
+ }
176
+ getCommandWithStatus(message, taskStatus) {
177
+ const commandOutput = chalk.dim('> ') + this.formatCommand(this.normalizeMessage(message));
178
+ return this.addTaskStatus(taskStatus, commandOutput);
179
+ }
180
+ getStatusIcon(taskStatus) {
181
+ switch (taskStatus) {
182
+ case 'success':
183
+ return '✔️';
184
+ case 'failure':
185
+ return '❌';
186
+ case 'skipped':
187
+ case 'local-cache-kept-existing':
188
+ return '⏩';
189
+ case 'local-cache':
190
+ case 'remote-cache':
191
+ return '🔁';
192
+ }
160
193
  }
161
194
  normalizeMessage(message) {
162
195
  if (message.startsWith('nx run ')) {
@@ -1,12 +1,11 @@
1
1
  import { InputDefinition, TargetConfiguration } from '../config/workspace-json-project-json';
2
- export type PackageJsonTargetConfiguration = Omit<TargetConfiguration, 'executor'>;
3
2
  export interface NxProjectPackageJsonConfiguration {
4
3
  implicitDependencies?: string[];
5
4
  tags?: string[];
6
5
  namedInputs?: {
7
6
  [inputName: string]: (string | InputDefinition)[];
8
7
  };
9
- targets?: Record<string, PackageJsonTargetConfiguration>;
8
+ targets?: Record<string, TargetConfiguration>;
10
9
  includedScripts?: string[];
11
10
  }
12
11
  export type ArrayPackageGroup = {