nx 23.3.0-beta.8 → 23.3.0-beta.9

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 (34) hide show
  1. package/dist/src/command-line/affected/affected.js +20 -1
  2. package/dist/src/command-line/affected/command-object.js +1 -1
  3. package/dist/src/command-line/reset/reset.js +7 -4
  4. package/dist/src/command-line/show/command-object.js +1 -1
  5. package/dist/src/command-line/show/projects.js +22 -0
  6. package/dist/src/command-line/yargs-utils/shared-options.d.ts +4 -0
  7. package/dist/src/command-line/yargs-utils/shared-options.js +16 -0
  8. package/dist/src/daemon/message-types/select-affected-tasks.d.ts +3 -0
  9. package/dist/src/daemon/server/handle-select-affected-tasks.js +1 -0
  10. package/dist/src/devkit-internals.d.ts +3 -1
  11. package/dist/src/devkit-internals.js +8 -3
  12. package/dist/src/hasher/hash-task.d.ts +1 -1
  13. package/dist/src/hasher/hash-task.js +1 -0
  14. package/dist/src/native/index.d.ts +56 -0
  15. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  16. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  17. package/dist/src/nx-cloud/utilities/client.d.ts +1 -1
  18. package/dist/src/nx-cloud/utilities/client.js +1 -1
  19. package/dist/src/plugins/js/utils/register.js +11 -3
  20. package/dist/src/project-graph/affected/affected-reasons.d.ts +116 -0
  21. package/dist/src/project-graph/affected/affected-reasons.js +459 -0
  22. package/dist/src/project-graph/affected/affected-tasks.d.ts +12 -0
  23. package/dist/src/project-graph/affected/affected-tasks.js +187 -11
  24. package/dist/src/project-graph/affected/print-explanation.d.ts +11 -0
  25. package/dist/src/project-graph/affected/print-explanation.js +44 -0
  26. package/dist/src/tasks-runner/default-tasks-runner.js +1 -1
  27. package/dist/src/tasks-runner/run-command.js +2 -1
  28. package/dist/src/tasks-runner/task-orchestrator.d.ts +7 -3
  29. package/dist/src/tasks-runner/task-orchestrator.js +9 -8
  30. package/dist/src/tasks-runner/tasks-runner.d.ts +2 -0
  31. package/dist/src/utils/command-line-utils.d.ts +1 -0
  32. package/dist/src/utils/create-cli-options.d.ts +6 -0
  33. package/dist/src/utils/create-cli-options.js +29 -0
  34. package/package.json +11 -11
@@ -15,6 +15,8 @@ const configuration_1 = require("../../config/configuration");
15
15
  const find_matching_projects_1 = require("../../utils/find-matching-projects");
16
16
  const graph_1 = require("../graph/graph");
17
17
  const affected_tasks_1 = require("../../project-graph/affected/affected-tasks");
18
+ const affected_reasons_1 = require("../../project-graph/affected/affected-reasons");
19
+ const print_explanation_1 = require("../../project-graph/affected/print-explanation");
18
20
  async function affected(command, args, extraTargetDependencies = {}, extraOptions = {
19
21
  excludeTaskDependencies: args.excludeTaskDependencies,
20
22
  loadDotEnvFiles: process.env.NX_LOAD_DOT_ENV_FILES !== 'false',
@@ -31,12 +33,19 @@ async function affected(command, args, extraTargetDependencies = {}, extraOption
31
33
  const useTasks = (0, affected_tasks_1.selectsAffectedTasks)() &&
32
34
  command === 'affected' &&
33
35
  !!nxArgs.targets?.length;
36
+ if ((0, affected_reasons_1.isExplaining)(nxArgs.explain) && !useTasks) {
37
+ throw new Error((0, affected_reasons_1.explainUnavailable)([
38
+ !(0, affected_tasks_1.selectsAffectedTasks)() && 'NX_LEGACY_AFFECTED=false',
39
+ !nxArgs.targets?.length && 'targets passed with --targets (-t)',
40
+ ].filter(Boolean)));
41
+ }
34
42
  // Outside the try so errors reach handleErrors, as they did from inside runCommand.
35
43
  let projectGraph;
36
44
  let taskSelection;
37
45
  let projects = [];
38
46
  if (useTasks) {
39
- ({ projectGraph, taskSelection } = await (0, affected_tasks_1.computeAffectedTasks)({
47
+ let explanation;
48
+ ({ projectGraph, taskSelection, explanation } = await (0, affected_tasks_1.computeAffectedTasks)({
40
49
  nxJson,
41
50
  targets: nxArgs.targets,
42
51
  touchedFiles: (0, file_utils_1.calculateFileChanges)((0, command_line_utils_1.parseFiles)(nxArgs).files, nxArgs),
@@ -50,8 +59,18 @@ async function affected(command, args, extraTargetDependencies = {}, extraOption
50
59
  extraTargetDependencies,
51
60
  excludeTaskDependencies: extraOptions.excludeTaskDependencies,
52
61
  exclude: nxArgs.exclude,
62
+ explain: (0, affected_reasons_1.isExplaining)(nxArgs.explain),
53
63
  ...(await (0, run_command_1.runnerInputsForSelection)(nxArgs, nxJson)),
54
64
  }));
65
+ // --explain reports the selection rather than acting on it: someone asking
66
+ // why a task is affected does not also want it to run.
67
+ if ((0, affected_reasons_1.isExplaining)(nxArgs.explain)) {
68
+ (0, print_explanation_1.printAffectedExplanation)(explanation, 'Affected tasks', nxArgs.explain, {
69
+ verbose: args.verbose,
70
+ });
71
+ await output_1.output.drain();
72
+ process.exit(0);
73
+ }
55
74
  }
56
75
  else {
57
76
  projectGraph = await (0, project_graph_1.createProjectGraphAsync)({ exitOnError: true });
@@ -8,7 +8,7 @@ const shared_options_1 = require("../yargs-utils/shared-options");
8
8
  exports.yargsAffectedCommand = {
9
9
  command: 'affected',
10
10
  describe: 'Run target for affected projects. Affected projects are projects that have been changed and projects that depend on the changed projects. See https://nx.dev/ci/features/affected for more details.',
11
- builder: (yargs) => (0, documentation_1.linkToNxDevAndExamples)((0, shared_options_1.withAffectedOptions)((0, shared_options_1.withTuiOptions)((0, shared_options_1.withRunOptions)((0, shared_options_1.withOutputStyleOption)((0, shared_options_1.withTargetAndConfigurationOption)((0, shared_options_1.withBatch)(yargs))))))
11
+ builder: (yargs) => (0, documentation_1.linkToNxDevAndExamples)((0, shared_options_1.withAffectedOptions)((0, shared_options_1.withTuiOptions)((0, shared_options_1.withRunOptions)((0, shared_options_1.withOutputStyleOption)((0, shared_options_1.withTargetAndConfigurationOption)((0, shared_options_1.withBatch)((0, shared_options_1.withExplainOption)(yargs)))))))
12
12
  .option('all', {
13
13
  type: 'boolean',
14
14
  deprecated: 'Use `nx run-many` instead',
@@ -83,6 +83,11 @@ async function resetHandler(args) {
83
83
  if ((cloudEnabled && all) || args.onlyCloud) {
84
84
  try {
85
85
  await resetCloudClient();
86
+ }
87
+ catch (e) {
88
+ errors.push('Failed to clean up the Nx Cloud client.', e.toString());
89
+ }
90
+ try {
86
91
  await removeInstalledNxCloudClient();
87
92
  }
88
93
  catch (e) {
@@ -118,10 +123,8 @@ function cleanupDaemonWorkspaceData() {
118
123
  async function resetCloudClient() {
119
124
  // Remove nx cloud marker files. This helps if the use happens to run `nx-cloud start-ci-run` or
120
125
  // similar commands on their local machine.
121
- try {
122
- (await (0, client_2.getCloudClient)((0, get_cloud_options_1.getCloudOptions)())).invoke('cleanup');
123
- }
124
- catch { }
126
+ // `exit` would end the process here, before reset reports its result.
127
+ await (await (0, client_2.getCloudClient)((0, get_cloud_options_1.getCloudOptions)())).invoke('cleanup', false);
125
128
  }
126
129
  function removeInstalledNxCloudClient() {
127
130
  return incrementalBackoff(INCREMENTAL_BACKOFF_FIRST_DELAY, INCREMENTAL_BACKOFF_MAX_DURATION, () => {
@@ -37,7 +37,7 @@ exports.yargsShowCommand = {
37
37
  const showProjectsCommand = {
38
38
  command: 'projects',
39
39
  describe: 'Show a list of projects in the workspace.',
40
- builder: (yargs) => (0, shared_options_1.withVerbose)((0, shared_options_1.withAffectedOptions)(yargs))
40
+ builder: (yargs) => (0, shared_options_1.withVerbose)((0, shared_options_1.withExplainOption)((0, shared_options_1.withAffectedOptions)(yargs)))
41
41
  .option('affected', {
42
42
  type: 'boolean',
43
43
  description: 'Show only affected projects.',
@@ -5,6 +5,8 @@ const output_1 = require("../../utils/output");
5
5
  const nx_json_1 = require("../../config/nx-json");
6
6
  const affected_project_graph_1 = require("../../project-graph/affected/affected-project-graph");
7
7
  const affected_tasks_1 = require("../../project-graph/affected/affected-tasks");
8
+ const print_explanation_1 = require("../../project-graph/affected/print-explanation");
9
+ const affected_reasons_1 = require("../../project-graph/affected/affected-reasons");
8
10
  const file_utils_1 = require("../../project-graph/file-utils");
9
11
  const operators_1 = require("../../project-graph/operators");
10
12
  const project_graph_1 = require("../../project-graph/project-graph");
@@ -18,6 +20,17 @@ async function showProjectsHandler(args) {
18
20
  const { nxArgs } = (0, command_line_utils_1.splitArgsIntoNxArgsAndOverrides)(args, 'affected', {
19
21
  printWarnings: false,
20
22
  }, nxJson);
23
+ const explainsTasks = args.affected &&
24
+ (0, affected_tasks_1.selectsAffectedTasks)() &&
25
+ !!args.withTarget?.length &&
26
+ !args.projects;
27
+ if ((0, affected_reasons_1.isExplaining)(nxArgs.explain) && !explainsTasks) {
28
+ throw new Error((0, affected_reasons_1.explainUnavailable)([
29
+ !(0, affected_tasks_1.selectsAffectedTasks)() && 'NX_LEGACY_AFFECTED=false',
30
+ !args.affected && '--affected',
31
+ !args.withTarget?.length && 'targets passed with --withTarget (-t)',
32
+ ].filter(Boolean), args.projects ? ['--projects'] : []));
33
+ }
21
34
  // Affected touches dependencies so it needs to be processed first.
22
35
  if (args.affected) {
23
36
  const touchedFiles = await getTouchedFiles(nxArgs);
@@ -33,8 +46,17 @@ async function showProjectsHandler(args) {
33
46
  head: nxArgs.head,
34
47
  files: nxArgs.files,
35
48
  },
49
+ explain: (0, affected_reasons_1.isExplaining)(nxArgs.explain),
36
50
  ...(await runCommandModule().runnerInputsForSelection(nxArgs, nxJson)),
37
51
  });
52
+ if ((0, affected_reasons_1.isExplaining)(nxArgs.explain)) {
53
+ (0, print_explanation_1.printAffectedExplanation)(affectedTasks.explanation, 'Affected tasks',
54
+ // show projects declares its own --json, which has no executor to
55
+ // pass through to.
56
+ args.json ? 'stdout' : nxArgs.explain, { verbose: args.verbose });
57
+ await output_1.output.drain();
58
+ return;
59
+ }
38
60
  const { taskGraph, initiatingTaskIds } = affectedTasks.taskSelection;
39
61
  const owning = new Set(initiatingTaskIds.map((id) => taskGraph.tasks[id].target.project));
40
62
  // The graph selection ran against: with the daemon on, the daemon's, not `graph`.
@@ -54,6 +54,10 @@ export declare function withAffectedOptions(yargs: Argv): Argv<ExcludeOptions &
54
54
  } & {
55
55
  head: string;
56
56
  }>;
57
+ /** Only on the commands that report instead of running when it is passed. */
58
+ export declare function withExplainOption<T>(yargs: Argv<T>): Argv<T & {
59
+ explain?: string | boolean;
60
+ }>;
57
61
  export interface RunManyOptions extends RunOptions {
58
62
  projects: string[];
59
63
  /**
@@ -9,6 +9,7 @@ exports.withConfiguration = withConfiguration;
9
9
  exports.withVerbose = withVerbose;
10
10
  exports.withBatch = withBatch;
11
11
  exports.withAffectedOptions = withAffectedOptions;
12
+ exports.withExplainOption = withExplainOption;
12
13
  exports.withRunManyOptions = withRunManyOptions;
13
14
  exports.withOverrides = withOverrides;
14
15
  exports.withOutputStyleOption = withOutputStyleOption;
@@ -244,6 +245,21 @@ function withAffectedOptions(yargs) {
244
245
  }
245
246
  }, true);
246
247
  }
248
+ /** Only on the commands that report instead of running when it is passed. */
249
+ function withExplainOption(yargs) {
250
+ return yargs.option('explain', {
251
+ type: 'string',
252
+ describe: 'Print why each task was considered affected, instead of running anything. Needs task selection (NX_LEGACY_AFFECTED=false). Pass a file path to save the reasons as JSON instead. Pass "stdout" to print the JSON to the terminal.',
253
+ // Same shape as `--graph`: the value is a destination, and a bare
254
+ // `--explain` has to arrive as a boolean. `nx affected` leaves `--json`
255
+ // undeclared so it still reaches the executor.
256
+ coerce: (value) => value === '' || value === 'true' || value === true
257
+ ? true
258
+ : value === 'false' || value === false
259
+ ? false
260
+ : value,
261
+ });
262
+ }
247
263
  function withRunManyOptions(yargs) {
248
264
  return withRunOptions(yargs)
249
265
  .parserConfiguration(exports.defaultYargsParserConfiguration)
@@ -2,6 +2,7 @@ import type { ProjectGraph } from '../../config/project-graph';
2
2
  import type { TaskGraph } from '../../config/task-graph';
3
3
  import type { TaskSelection } from '../../tasks-runner/run-command';
4
4
  import type { AffectedTasksRequest } from '../../project-graph/affected/affected-tasks';
5
+ import type { InternedExplanation } from '../../project-graph/affected/affected-reasons';
5
6
  export declare const SELECT_AFFECTED_TASKS: 'SELECT_AFFECTED_TASKS';
6
7
  export type HandleSelectAffectedTasksMessage = {
7
8
  type: typeof SELECT_AFFECTED_TASKS;
@@ -14,5 +15,7 @@ export type SelectAffectedTasksResponse = {
14
15
  taskGraph: TaskGraph;
15
16
  /** Without a planning context: the plans stay in the daemon. */
16
17
  taskSelection: TaskSelection;
18
+ /** Interned, so it stays small on the wire; the client hydrates it. */
19
+ explanation?: InternedExplanation;
17
20
  };
18
21
  export declare function isHandleSelectAffectedTasksMessage(message: unknown): message is HandleSelectAffectedTasksMessage;
@@ -20,6 +20,7 @@ async function handleSelectAffectedTasks(request) {
20
20
  affectedTaskIds: [...selection.affectedTaskIds],
21
21
  taskGraph: selection.taskGraph,
22
22
  taskSelection: selection.taskSelection,
23
+ explanation: selection.explanation,
23
24
  };
24
25
  return { response, description: 'handleSelectAffectedTasks' };
25
26
  }
@@ -47,6 +47,8 @@ export { getEnvFilesForTask, getGraphTimeDotEnvForTask, } from './tasks-runner/t
47
47
  export { getEnvPathsForTask } from './tasks-runner/task-env-paths';
48
48
  export { hashDaemonClientEnv, getDaemonClientEnvGeneration, getAppliedDaemonClientEnv, applyDaemonEnvFromClient, } from './daemon/client/daemon-environment';
49
49
  export { isCI } from './utils/is-ci';
50
+ export { createCliOptions } from './utils/create-cli-options';
51
+ export { createOverrides } from './utils/command-line-utils';
50
52
  export { isUsingPrettierInTree, prettierConfigFiles, } from './utils/formatters/prettier';
51
53
  export { detectFormatter, detectFormatterInTree } from './utils/formatters';
52
54
  export type { FormatterType } from './utils/formatters';
@@ -85,7 +87,7 @@ export { getRelativeProjectJsonSchemaPath } from './generators/utils/project-con
85
87
  export { hashFile } from './hasher/file-hasher';
86
88
  export { filterUsingGlobPatterns, getTargetInputs } from './hasher/task-hasher';
87
89
  export type { JsonInput } from './native';
88
- export { killProcessTreeGraceful } from './native';
90
+ export { isAiAgent, killProcessTreeGraceful } from './native';
89
91
  export { killChildOnHostExit } from './utils/kill-child-on-host-exit';
90
92
  export { connectToNxCloud } from './nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud';
91
93
  export type { NxCloudOnBoardingStatus } from './nx-cloud/models/onboarding-status';
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getDaemonClientEnvGeneration = exports.hashDaemonClientEnv = exports.getEnvPathsForTask = exports.getGraphTimeDotEnvForTask = exports.getEnvFilesForTask = exports.interpolate = exports.requireWithTsconfigFallback = exports.isTsEsmNamedExportLinkageError = exports.isRequireInEsmScopeError = exports.forceRegisterEsmLoader = exports.loadTsFile = exports.registerTsProject = exports.LoadedNxPlugin = exports.retrieveProjectConfigurations = exports.findProjectForPath = exports.createProjectRootMappings = exports.createProjectRootMappingsFromProjectConfigurations = exports.hashMultiGlobWithWorkspaceContext = exports.hashWithWorkspaceContext = exports.hashObject = exports.splitByColons = exports.installPackageToTmpAsync = exports.installPackageToTmp = exports.readModulePackageJson = exports.stripIndent = exports.sortObjectByKeys = exports.combineOptionsForExecutor = exports.confirmationPrompt = exports.textPrompt = exports.multiselectPrompt = exports.selectPrompt = exports.splitTarget = exports.createPrettierIgnoreChecker = exports.createOxfmtIgnoreChecker = exports.createGitIgnoreChecker = exports.readTargetDefaultsForTarget = exports.createTargetDefaultsResults = exports.findMatchingProjects = exports.findMatchingConfigFiles = exports.readProjectConfigurationsFromRootMap = exports.findMatchingTargetNames = exports.resolveCommandSyntacticSugar = exports.mergeTargetConfigurations = exports.retrieveProjectConfigurationsWithAngularProjects = exports.calculateDefaultProjectName = exports.readNxJsonFromDisk = exports.parseExecutor = exports.getExecutorInformation = exports.parseVersionFromPackageManagerField = exports.createTempNpmDirectory = void 0;
4
- exports.createNxCloudOnboardingURL = exports.getNxCloudAppOnBoardingUrl = exports.createNxCloudOnboardingURLForWelcomeApp = exports.connectToNxCloud = exports.killChildOnHostExit = exports.killProcessTreeGraceful = exports.getTargetInputs = exports.filterUsingGlobPatterns = exports.hashFile = exports.getRelativeProjectJsonSchemaPath = exports.FsTree = exports.LARGE_BUFFER = exports.daemonClient = exports.isProjectGraphProjectNode = exports.isProjectGraphExternalNode = exports.fileDataDepType = exports.fileDataDepTarget = exports.BatchFunctionRunner = exports.getGeneratorInformation = exports.setupAiAgentsGenerator = exports.toOldFormat = exports.toNewFormat = exports.runCommandsExecutor = exports.acknowledgeBuildScripts = exports.getCatalogDependenciesFromPackageJson = exports.getCatalogManager = exports.checkFilesAreOutputs = exports.checkFilesAreInputs = exports.PromptResolutionError = exports.resolvePrompt = exports.SchemaResolutionError = exports.ImplementationResolutionError = exports.resolveSchema = exports.resolveImplementation = exports.emitPluginWorkerLog = exports.safeWriteFileCache = exports.PluginCache = exports.handleImport = exports.signalToCode = exports.globalSpinner = exports.readYamlFile = exports.oxfmtConfigFiles = exports.formatFilesWithOxfmt = exports.detectFormatterInTree = exports.detectFormatter = exports.prettierConfigFiles = exports.isUsingPrettierInTree = exports.isCI = exports.applyDaemonEnvFromClient = exports.getAppliedDaemonClientEnv = void 0;
5
- exports.normalizeDependencyConfigDefinition = exports.isCacheableTask = exports.getUnparsedOverrideArgs = exports.getTargetConfigurationForTask = exports.getSerializedArgsForTask = exports.getPrintableCommandArgsForTask = exports.getOutputs = exports.getExecutorNameForTask = exports.getExecutorForTask = exports.getDependencyConfigs = exports.getCustomHasher = exports.getCliPath = exports.expandWildcardTargetConfiguration = exports.expandInitiatingTasksThroughNoop = exports.expandDependencyConfigSyntaxSugar = exports.createTaskId = exports.calculateReverseDeps = exports.createRunManyDynamicOutputRenderer = exports.CompositeLifeCycle = exports.RemoteCacheV2 = exports.Cache = exports.readCachedProjectConfiguration = exports.preventRecursionInGraphConstruction = exports.handleProjectGraphError = exports.createProjectGraphAndSourceMapsAsync = exports.buildProjectGraphAndSourceMapsWithoutDaemon = exports.isNpmProject = exports.readFileMapCache = exports.readPackageJson = exports.isWholeFileChange = exports.isLockFileChange = exports.isDeletedFileChange = exports.defaultFileRead = exports.calculateFileChanges = exports.WholeFileChange = exports.TEN_MEGABYTES = exports.LockFileChange = exports.DeletedFileChange = exports.buildPackageJsonWorkspacesMatcher = exports.buildPackageJsonPatterns = exports.getGlobPatternsFromPackageManagerWorkspaces = exports.registerTsConfigPaths = exports.getWorkspacePackagesFromGraph = exports.isBuiltinModuleImport = exports.TargetProjectLocator = exports.findProjectsNpmDependencies = exports.createPackageJson = exports.getLockFileName = exports.generatePrunedDeployOutput = exports.createLockFile = void 0;
6
- exports.safeSpawn = exports.safeExecFileSync = exports.workspaceRootInner = exports.setWorkspaceRoot = exports.setupWorkspaceContext = exports.resetWorkspaceContext = exports.globWithWorkspaceContext = exports.getFilesInDirectoryUsingContext = exports.nxVersion = exports.SyncError = exports.quoteShellArg = exports.getSourceDirOfDependentProjects = exports.findAllProjectNodeDependencies = exports.findInstalledPlugins = exports.deriveGroupNameFromTarget = exports.warnUnshippableLocalPathSpec = exports.relocatePrunedLocalPathSpec = exports.movePeerDependencyToDependencies = exports.dropEmptyPeerDependencySections = exports.readNxMigrateConfig = exports.isNxCloudUsed = exports.getNxCloudUrl = exports.orange = exports.NX_PREFIX = exports.getNxRequirePaths = exports.isGlobPattern = exports.combineGlobPatterns = exports.getLatestCommitSha = exports.readFileIfExisting = exports.isRelativePath = exports.fileExists = exports.directoryExists = exports.createDirectory = exports.deduceDefaultBase = exports.codeFrameColumns = exports.runNxSync = exports.workspaceDataDirectory = exports.getLastValueFromAsyncIterableIterator = exports.validateOutputs = exports.unparse = exports.transformLegacyOutputs = exports.shouldStreamOutput = exports.removeTasksFromTaskGraph = exports.readProjectAndTargetFromTargetString = exports.normalizeTargetDependencyWithStringProjects = exports.normalizeDependencyConfigProjects = void 0;
4
+ exports.connectToNxCloud = exports.killChildOnHostExit = exports.killProcessTreeGraceful = exports.isAiAgent = exports.getTargetInputs = exports.filterUsingGlobPatterns = exports.hashFile = exports.getRelativeProjectJsonSchemaPath = exports.FsTree = exports.LARGE_BUFFER = exports.daemonClient = exports.isProjectGraphProjectNode = exports.isProjectGraphExternalNode = exports.fileDataDepType = exports.fileDataDepTarget = exports.BatchFunctionRunner = exports.getGeneratorInformation = exports.setupAiAgentsGenerator = exports.toOldFormat = exports.toNewFormat = exports.runCommandsExecutor = exports.acknowledgeBuildScripts = exports.getCatalogDependenciesFromPackageJson = exports.getCatalogManager = exports.checkFilesAreOutputs = exports.checkFilesAreInputs = exports.PromptResolutionError = exports.resolvePrompt = exports.SchemaResolutionError = exports.ImplementationResolutionError = exports.resolveSchema = exports.resolveImplementation = exports.emitPluginWorkerLog = exports.safeWriteFileCache = exports.PluginCache = exports.handleImport = exports.signalToCode = exports.globalSpinner = exports.readYamlFile = exports.oxfmtConfigFiles = exports.formatFilesWithOxfmt = exports.detectFormatterInTree = exports.detectFormatter = exports.prettierConfigFiles = exports.isUsingPrettierInTree = exports.createOverrides = exports.createCliOptions = exports.isCI = exports.applyDaemonEnvFromClient = exports.getAppliedDaemonClientEnv = void 0;
5
+ exports.getTargetConfigurationForTask = exports.getSerializedArgsForTask = exports.getPrintableCommandArgsForTask = exports.getOutputs = exports.getExecutorNameForTask = exports.getExecutorForTask = exports.getDependencyConfigs = exports.getCustomHasher = exports.getCliPath = exports.expandWildcardTargetConfiguration = exports.expandInitiatingTasksThroughNoop = exports.expandDependencyConfigSyntaxSugar = exports.createTaskId = exports.calculateReverseDeps = exports.createRunManyDynamicOutputRenderer = exports.CompositeLifeCycle = exports.RemoteCacheV2 = exports.Cache = exports.readCachedProjectConfiguration = exports.preventRecursionInGraphConstruction = exports.handleProjectGraphError = exports.createProjectGraphAndSourceMapsAsync = exports.buildProjectGraphAndSourceMapsWithoutDaemon = exports.isNpmProject = exports.readFileMapCache = exports.readPackageJson = exports.isWholeFileChange = exports.isLockFileChange = exports.isDeletedFileChange = exports.defaultFileRead = exports.calculateFileChanges = exports.WholeFileChange = exports.TEN_MEGABYTES = exports.LockFileChange = exports.DeletedFileChange = exports.buildPackageJsonWorkspacesMatcher = exports.buildPackageJsonPatterns = exports.getGlobPatternsFromPackageManagerWorkspaces = exports.registerTsConfigPaths = exports.getWorkspacePackagesFromGraph = exports.isBuiltinModuleImport = exports.TargetProjectLocator = exports.findProjectsNpmDependencies = exports.createPackageJson = exports.getLockFileName = exports.generatePrunedDeployOutput = exports.createLockFile = exports.createNxCloudOnboardingURL = exports.getNxCloudAppOnBoardingUrl = exports.createNxCloudOnboardingURLForWelcomeApp = void 0;
6
+ exports.safeSpawn = exports.safeExecFileSync = exports.workspaceRootInner = exports.setWorkspaceRoot = exports.setupWorkspaceContext = exports.resetWorkspaceContext = exports.globWithWorkspaceContext = exports.getFilesInDirectoryUsingContext = exports.nxVersion = exports.SyncError = exports.quoteShellArg = exports.getSourceDirOfDependentProjects = exports.findAllProjectNodeDependencies = exports.findInstalledPlugins = exports.deriveGroupNameFromTarget = exports.warnUnshippableLocalPathSpec = exports.relocatePrunedLocalPathSpec = exports.movePeerDependencyToDependencies = exports.dropEmptyPeerDependencySections = exports.readNxMigrateConfig = exports.isNxCloudUsed = exports.getNxCloudUrl = exports.orange = exports.NX_PREFIX = exports.getNxRequirePaths = exports.isGlobPattern = exports.combineGlobPatterns = exports.getLatestCommitSha = exports.readFileIfExisting = exports.isRelativePath = exports.fileExists = exports.directoryExists = exports.createDirectory = exports.deduceDefaultBase = exports.codeFrameColumns = exports.runNxSync = exports.workspaceDataDirectory = exports.getLastValueFromAsyncIterableIterator = exports.validateOutputs = exports.unparse = exports.transformLegacyOutputs = exports.shouldStreamOutput = exports.removeTasksFromTaskGraph = exports.readProjectAndTargetFromTargetString = exports.normalizeTargetDependencyWithStringProjects = exports.normalizeDependencyConfigProjects = exports.normalizeDependencyConfigDefinition = exports.isCacheableTask = exports.getUnparsedOverrideArgs = void 0;
7
7
  const tslib_1 = require("tslib");
8
8
  /**
9
9
  * Note to developers: STOP! These are nx internals, not part of the public
@@ -112,6 +112,10 @@ Object.defineProperty(exports, "getAppliedDaemonClientEnv", { enumerable: true,
112
112
  Object.defineProperty(exports, "applyDaemonEnvFromClient", { enumerable: true, get: function () { return daemon_environment_1.applyDaemonEnvFromClient; } });
113
113
  var is_ci_1 = require("./utils/is-ci");
114
114
  Object.defineProperty(exports, "isCI", { enumerable: true, get: function () { return is_ci_1.isCI; } });
115
+ var create_cli_options_1 = require("./utils/create-cli-options");
116
+ Object.defineProperty(exports, "createCliOptions", { enumerable: true, get: function () { return create_cli_options_1.createCliOptions; } });
117
+ var command_line_utils_1 = require("./utils/command-line-utils");
118
+ Object.defineProperty(exports, "createOverrides", { enumerable: true, get: function () { return command_line_utils_1.createOverrides; } });
115
119
  var prettier_1 = require("./utils/formatters/prettier");
116
120
  Object.defineProperty(exports, "isUsingPrettierInTree", { enumerable: true, get: function () { return prettier_1.isUsingPrettierInTree; } });
117
121
  Object.defineProperty(exports, "prettierConfigFiles", { enumerable: true, get: function () { return prettier_1.prettierConfigFiles; } });
@@ -181,6 +185,7 @@ var task_hasher_1 = require("./hasher/task-hasher");
181
185
  Object.defineProperty(exports, "filterUsingGlobPatterns", { enumerable: true, get: function () { return task_hasher_1.filterUsingGlobPatterns; } });
182
186
  Object.defineProperty(exports, "getTargetInputs", { enumerable: true, get: function () { return task_hasher_1.getTargetInputs; } });
183
187
  var native_1 = require("./native");
188
+ Object.defineProperty(exports, "isAiAgent", { enumerable: true, get: function () { return native_1.isAiAgent; } });
184
189
  Object.defineProperty(exports, "killProcessTreeGraceful", { enumerable: true, get: function () { return native_1.killProcessTreeGraceful; } });
185
190
  var kill_child_on_host_exit_1 = require("./utils/kill-child-on-host-exit");
186
191
  Object.defineProperty(exports, "killChildOnHostExit", { enumerable: true, get: function () { return kill_child_on_host_exit_1.killChildOnHostExit; } });
@@ -4,7 +4,7 @@ import { Task, TaskGraph } from '../config/task-graph';
4
4
  import { type UltracacheConfigurations, TaskDetails } from '../native';
5
5
  import { TaskHasher } from './task-hasher';
6
6
  export declare function getTaskDetails(): TaskDetails | null;
7
- export declare function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration, tasksDetails: TaskDetails | null, ultracacheConfigurations?: UltracacheConfigurations): Promise<void>;
7
+ export declare function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, nxJson: NxJsonConfiguration, tasksDetails: TaskDetails | null, ultracacheConfigurations?: UltracacheConfigurations): Promise<Set<string>>;
8
8
  export declare function hashTask(hasher: TaskHasher, projectGraph: ProjectGraph, taskGraph: TaskGraph, task: Task, env: NodeJS.ProcessEnv, taskDetails: TaskDetails | null): Promise<void>;
9
9
  /**
10
10
  * Batch-hash `tasks`. `perTaskEnvs` must contain an entry keyed by
@@ -72,6 +72,7 @@ async function hashTasksThatDoNotDependOnOutputsOfOtherTasks(hasher, projectGrap
72
72
  }
73
73
  performance.mark('hashMultipleTasks:end');
74
74
  performance.measure('hashMultipleTasks', 'hashMultipleTasks:start', 'hashMultipleTasks:end');
75
+ return new Set(tasks.filter((t) => !(t.id in hashes)).map((t) => t.id));
75
76
  }
76
77
  function readsDependencyOutputs(task, taskGraph, projectGraph, nxJson) {
77
78
  return (taskGraph.dependencies[task.id]?.length > 0 &&
@@ -435,6 +435,29 @@ export interface AffectedOptions {
435
435
  workspaceRoot: string
436
436
  }
437
437
 
438
+ /**
439
+ * Why the change reached each task. Covers every task it reached, not just
440
+ * the selection, so a reason naming a producer can be looked up too.
441
+ */
442
+ export interface AffectedTaskExplanation {
443
+ /**
444
+ * The reached tasks the change touched directly, sorted: a matched input,
445
+ * or always touched. Every other reached task was carried through outputs.
446
+ */
447
+ touched: Array<string>
448
+ /** Consumer -> the reached producers whose outputs it reads. */
449
+ producersOf: Record<string, Array<string>>
450
+ /** Changed project configs no longer on disk. Every task was seeded for them. */
451
+ deletedProjectConfigs: Array<string>
452
+ /**
453
+ * What each matching plan instruction matched. Shared rather than copied
454
+ * per task: one lib's fileset can be in the plan of every dependent.
455
+ */
456
+ inputMatches: Array<TaskInputMatches>
457
+ /** Per reached task, the indexes of the matches above that its plan holds. */
458
+ taskInputMatches: Record<string, Array<number>>
459
+ }
460
+
438
461
  export declare function affectedTasks(projectGraph: ExternalObject<ProjectGraph>, hashPlans: ExternalObject<Record<string, Array<HashInstruction>>>, taskGraph: TaskGraph, changedFiles: Array<string>, options: AffectedTasksOptions): AffectedTaskSelection
439
462
 
440
463
  export interface AffectedTaskSelection {
@@ -442,6 +465,8 @@ export interface AffectedTaskSelection {
442
465
  affected: Array<string>
443
466
  /** `affected` plus everything it depends on, sorted: what a run keeps. */
444
467
  required: Array<string>
468
+ /** Why the change reached each task. Only when `explain` was asked for. */
469
+ explanation?: AffectedTaskExplanation
445
470
  }
446
471
 
447
472
  export interface AffectedTasksOptions {
@@ -490,6 +515,8 @@ export interface AffectedTasksOptions {
490
515
  * project's tsconfig `paths` entries, rather than none.
491
516
  */
492
517
  selectivelyHashTsConfig: boolean
518
+ /** Whether to return why each task was reached, for `--explain`. */
519
+ explain: boolean
493
520
  }
494
521
 
495
522
  export interface BatchInfo {
@@ -810,6 +837,16 @@ export declare function initializeTelemetry(connection: ExternalObject<NxDbConne
810
837
  */
811
838
  export declare function initializeTelemetryWithSessionId(sessionId: string, workspaceId: string, userId: string | undefined | null, nxVersion: string, packageManagerName: string, packageManagerVersion: string | undefined | null, nodeVersion: string, osArch: string, osPlatform: string, osRelease: string, isCi: boolean, isNxCloud: boolean): void
812
839
 
840
+ /** A changed file that reached a task, and the input pattern it reached it by. */
841
+ export interface InputMatch {
842
+ file: string
843
+ /**
844
+ * The fileset that matched. Absent for an instruction with no pattern to
845
+ * name, such as the root tsconfig.
846
+ */
847
+ pattern?: string
848
+ }
849
+
813
850
  export interface InputsInput {
814
851
  input: string
815
852
  dependencies?: boolean
@@ -1116,6 +1153,25 @@ export interface TaskHashDetails {
1116
1153
  runtime?: Record<string, string>
1117
1154
  }
1118
1155
 
1156
+ /**
1157
+ * What reached one task: the files its filesets matched and the packages it
1158
+ * hashes that moved.
1159
+ */
1160
+ export interface TaskInputMatches {
1161
+ files: Array<InputMatch>
1162
+ /** External node names the plan hashes one by one that moved. */
1163
+ packages: Array<string>
1164
+ /** The plan hashes every external dependency, and one moved. */
1165
+ allExternals: boolean
1166
+ /** Changed config files of the projects whose configuration the plan hashes. */
1167
+ projectConfigs: Array<string>
1168
+ /**
1169
+ * Ecosystems a change moved whole, without naming packages, that the plan
1170
+ * hashes packages of. Reported once rather than per package.
1171
+ */
1172
+ movedEcosystems: Array<string>
1173
+ }
1174
+
1119
1175
  /**
1120
1176
  * The result of a completed Task.
1121
1177
  *
Binary file
@@ -5,6 +5,6 @@ export declare class UnknownCommandError extends Error {
5
5
  constructor(command: string, availableCommands: string[]);
6
6
  }
7
7
  export declare function getCloudClient(options: CloudTaskRunnerOptions): Promise<{
8
- invoke: (command: string, exit?: boolean) => void;
8
+ invoke: (command: string, exit?: boolean) => Promise<void>;
9
9
  availableCommands: string[];
10
10
  }>;
@@ -19,7 +19,7 @@ async function getCloudClient(options) {
19
19
  return {
20
20
  invoke: (command, exit = true) => {
21
21
  if (command in nxCloudClient.commands) {
22
- nxCloudClient.commands[command]()
22
+ return nxCloudClient.commands[command]()
23
23
  .then(() => {
24
24
  if (exit) {
25
25
  process.exit(0);
@@ -847,6 +847,13 @@ function loadTsFile(filePath, tsConfigPath) {
847
847
  if (isInvokedByTsx) {
848
848
  return require(filePath);
849
849
  }
850
+ // Executors and generators load in processes that never loaded a plugin
851
+ // (batch workers, forked tasks), so the NodeNext `.js` -> `.ts` resolvers the
852
+ // plugin loader installs are not there yet. Both are idempotent.
853
+ ensureCjsResolverPatched();
854
+ if (preferNodeStripTypes) {
855
+ ensureNodeNextEsmResolverRegistered();
856
+ }
850
857
  if (!preferNodeStripTypes) {
851
858
  if (!resolvedTsConfigPath) {
852
859
  throw new Error(`${logger_1.NX_PREFIX} loadTsFile could not find a workspace tsconfig while loading ${filePath} on the swc/ts-node path. Pass an explicit tsConfigPath or add a tsconfig.base.json/tsconfig.json at the workspace root.`);
@@ -859,9 +866,10 @@ function loadTsFile(filePath, tsConfigPath) {
859
866
  cleanup();
860
867
  }
861
868
  }
862
- // Native strip path: no registration up front. pnpm/npm/yarn workspaces
863
- // resolve aliases without tsconfig-paths. On failure, lazy-register what
864
- // the specific error code indicates is needed and retry:
869
+ // Native strip path: no tsconfig-paths or transpiler registration up
870
+ // front. pnpm/npm/yarn workspaces resolve aliases without tsconfig-paths.
871
+ // On failure, lazy-register what the specific error code indicates is
872
+ // needed and retry:
865
873
  // - MODULE_NOT_FOUND -> first try tsconfig-paths (alias resolution).
866
874
  // If that still fails (e.g. extensionless `import './foo'` when
867
875
  // `foo.ts` is adjacent - Node's resolver doesn't add `.ts`), escalate
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Why a task was considered affected.
3
+ *
4
+ * One open shape rather than a discriminated union, because the matches behind
5
+ * these cross the napi boundary as `#[napi(object)]` structs, which carry no
6
+ * tag. `kind` is the discriminant; the rest are populated per kind and absent
7
+ * otherwise.
8
+ *
9
+ * Reasons are collected flat: a task lists every reason that applies to it,
10
+ * and propagation is expressed by naming the producer rather than nesting its
11
+ * reasons, so the producer's own reasons are one lookup away in the same output.
12
+ */
13
+ export type AffectedReasonKind =
14
+ /** A changed file matched one of the task's inputs. */
15
+ 'input-file'
16
+ /** It reads the outputs of a task the change reached. */
17
+ | 'dependent-output'
18
+ /** A project config the task hashes changed. */
19
+ | 'project-configuration'
20
+ /** A project config no longer on disk, so every task was selected. */
21
+ | 'deleted-project-configuration'
22
+ /** A package the task hashes moved, or the root package.json names its project. */
23
+ | 'npm-package'
24
+ /** It hashes every external dependency, and one moved. */
25
+ | 'external-dependencies'
26
+ /** A lockfile changed and `projectsAffectedByDependencyUpdates` names its project. */
27
+ | 'lockfile'
28
+ /** A dependency change could not be pinned to packages, so a whole ecosystem moved. */
29
+ | 'moved-ecosystem'
30
+ /** Its executor hashes outside the plan, so it is always selected. */
31
+ | 'custom-hasher';
32
+ export interface AffectedReason {
33
+ kind: AffectedReasonKind;
34
+ /** The changed file responsible, when one file is. */
35
+ file?: string;
36
+ /** The input pattern that matched, when the signal came from one. */
37
+ pattern?: string;
38
+ /** The package whose version moved. */
39
+ package?: string;
40
+ /** The package ecosystem, such as `npm`, that moved whole. */
41
+ ecosystem?: string;
42
+ /** The task whose outputs this task reads. */
43
+ producer?: string;
44
+ }
45
+ /**
46
+ * Why `--explain` cannot run here, naming only what is missing or in the way.
47
+ * It explains task selection, so it needs what task selection needs.
48
+ */
49
+ export declare function explainUnavailable(missing: string[], conflicting?: string[]): string;
50
+ /** What `--explain` reports, keyed by task id. */
51
+ export interface AffectedExplanation {
52
+ /** The selection, and every reason each entry is in it. */
53
+ affected: Record<string, AffectedReason[]>;
54
+ /**
55
+ * Tasks the change reached that are not in the selection: those a run keeps,
56
+ * and every producer a reason names, followed transitively, so every chain
57
+ * can be traced within the same output.
58
+ */
59
+ upstream: Record<string, AffectedReason[]>;
60
+ /**
61
+ * The entries of `affected` and `upstream` the change reached directly, as
62
+ * selection decided it; every other entry was reached only through another.
63
+ */
64
+ touched: string[];
65
+ /** The requested targets, and how many of their tasks selection chose among. */
66
+ requested?: {
67
+ targets: string[];
68
+ total: number;
69
+ };
70
+ /** The packages each changed dependency file moved, when Nx could name them. */
71
+ moved?: Record<string, string[]>;
72
+ }
73
+ /** Stands in for a task's input reasons: entries of `inputs` to merge. */
74
+ export interface InputsReason {
75
+ kind: 'inputs';
76
+ inputs: number[];
77
+ }
78
+ /**
79
+ * An explanation as selection builds it, before `hydrateExplanation`. A lib's
80
+ * matched files are one `inputs` entry however many tasks reach them, so this
81
+ * stays small across the daemon boundary where the expanded form would not.
82
+ */
83
+ export interface InternedExplanation extends Omit<AffectedExplanation, 'affected' | 'upstream'> {
84
+ /** The input reasons each matching plan instruction produced, sorted per kind. */
85
+ inputs: AffectedReason[][];
86
+ affected: Record<string, (AffectedReason | InputsReason)[]>;
87
+ upstream: Record<string, (AffectedReason | InputsReason)[]>;
88
+ }
89
+ /** Expands each task's `inputs` stand-in into its reasons. */
90
+ export declare function hydrateExplanation({ inputs, affected, upstream, ...rest }: InternedExplanation): AffectedExplanation;
91
+ /**
92
+ * One line of `--explain` output, without the leading bullet. `many` is set
93
+ * when `file` names several files.
94
+ */
95
+ export declare function formatAffectedReason(reason: AffectedReason, many?: boolean): string;
96
+ /**
97
+ * Renders `--explain` output: one block per entity, its reasons beneath it.
98
+ *
99
+ * It follows the chain: what the change touched, what it reached through
100
+ * those, and last the selection itself, so the reader's own entries stay at
101
+ * the bottom however long the chain grows.
102
+ *
103
+ * An entity with no reason is still listed, with a line saying so, because a
104
+ * blank line is indistinguishable from a bug when you are troubleshooting.
105
+ */
106
+ export declare function formatAffectedExplanation({ affected, upstream, touched: touchedNames, requested, moved, }: AffectedExplanation, heading: string, { verbose, styleTask, dim, bold, }?: {
107
+ verbose?: boolean;
108
+ /** Styles a listed task id; plain unless the printer passes a style. */
109
+ styleTask?: (id: string, requested: boolean) => string;
110
+ /** Styles the secondary part of a line, such as a matched pattern. */
111
+ dim?: (text: string) => string;
112
+ /** Styles the targets you asked for where a count names them. */
113
+ bold?: (text: string) => string;
114
+ }): string;
115
+ /** Whether `--explain` was asked for at all, in any of its forms. */
116
+ export declare function isExplaining(value: string | boolean | undefined): boolean;