@depup/nx 23.2.1-depup.7 → 23.3.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -19
- package/changes.json +10 -54
- package/dist/bin/init-local.js +7 -1
- package/dist/nx-cloud-internals.d.ts +1 -0
- package/dist/nx-cloud-internals.js +9 -0
- package/dist/plugins/package-json.js +1 -1
- package/dist/src/command-line/add/add.js +5 -1
- package/dist/src/command-line/affected/affected.js +70 -9
- package/dist/src/command-line/affected/command-object.js +1 -1
- package/dist/src/command-line/format/format.js +2 -18
- package/dist/src/command-line/graph/graph.d.ts +31 -0
- package/dist/src/command-line/graph/graph.js +113 -20
- package/dist/src/command-line/init/implementation/add-nx-to-monorepo.js +0 -3
- package/dist/src/command-line/init/implementation/add-nx-to-nest.js +0 -3
- package/dist/src/command-line/init/implementation/add-nx-to-npm-repo.js +0 -3
- package/dist/src/command-line/init/implementation/angular/index.js +0 -3
- package/dist/src/command-line/init/implementation/angular/legacy-angular-versions.js +0 -3
- package/dist/src/command-line/init/implementation/format.js +2 -3
- package/dist/src/command-line/init/implementation/utils.d.ts +0 -1
- package/dist/src/command-line/init/implementation/utils.js +6 -9
- package/dist/src/command-line/init/init-v2.js +0 -3
- package/dist/src/command-line/migrate/agentic/capture-generator-output.d.ts +25 -0
- package/dist/src/command-line/migrate/agentic/capture-generator-output.js +121 -5
- package/dist/src/command-line/migrate/agentic/close-agent-session.d.ts +21 -0
- package/dist/src/command-line/migrate/agentic/close-agent-session.js +126 -0
- package/dist/src/command-line/migrate/agentic/definitions.d.ts +24 -0
- package/dist/src/command-line/migrate/agentic/definitions.js +79 -20
- package/dist/src/command-line/migrate/agentic/format-command.d.ts +14 -0
- package/dist/src/command-line/migrate/agentic/format-command.js +44 -0
- package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +3 -3
- package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +3 -3
- package/dist/src/command-line/migrate/agentic/handoff.d.ts +50 -17
- package/dist/src/command-line/migrate/agentic/handoff.js +166 -24
- package/dist/src/command-line/migrate/agentic/instruction-files.d.ts +23 -0
- package/dist/src/command-line/migrate/agentic/instruction-files.js +41 -0
- package/dist/src/command-line/migrate/agentic/master/invocations.d.ts +12 -0
- package/dist/src/command-line/migrate/agentic/master/invocations.js +54 -0
- package/dist/src/command-line/migrate/agentic/master/run-master-session.d.ts +16 -0
- package/dist/src/command-line/migrate/agentic/master/run-master-session.js +175 -0
- package/dist/src/command-line/migrate/agentic/master/spawn-master.d.ts +31 -0
- package/dist/src/command-line/migrate/agentic/master/spawn-master.js +222 -0
- package/dist/src/command-line/migrate/agentic/prompts/final-validation.d.ts +13 -0
- package/dist/src/command-line/migrate/agentic/prompts/final-validation.js +41 -0
- package/dist/src/command-line/migrate/agentic/prompts/fragments.d.ts +17 -0
- package/dist/src/command-line/migrate/agentic/prompts/fragments.js +90 -0
- package/dist/src/command-line/migrate/agentic/prompts/generic-validation.js +4 -3
- package/dist/src/command-line/migrate/agentic/prompts/system-prompt.d.ts +25 -1
- package/dist/src/command-line/migrate/agentic/prompts/system-prompt.js +57 -34
- package/dist/src/command-line/migrate/agentic/run-step.js +28 -4
- package/dist/src/command-line/migrate/agentic/runner.d.ts +3 -15
- package/dist/src/command-line/migrate/agentic/runner.js +57 -239
- package/dist/src/command-line/migrate/agentic/terminal-repair.d.ts +1 -0
- package/dist/src/command-line/migrate/agentic/terminal-repair.js +27 -0
- package/dist/src/command-line/migrate/agentic/types.d.ts +23 -8
- package/dist/src/command-line/migrate/agentic/types.js +10 -7
- package/dist/src/command-line/migrate/agentic/windows-cmd.d.ts +33 -0
- package/dist/src/command-line/migrate/agentic/windows-cmd.js +88 -0
- package/dist/src/command-line/migrate/command-object.d.ts +2 -0
- package/dist/src/command-line/migrate/command-object.js +11 -1
- package/dist/src/command-line/migrate/deferred-output.d.ts +44 -0
- package/dist/src/command-line/migrate/deferred-output.js +92 -0
- package/dist/src/command-line/migrate/execute-migration.d.ts +9 -3
- package/dist/src/command-line/migrate/execute-migration.js +53 -16
- package/dist/src/command-line/migrate/migrate-analytics.d.ts +34 -9
- package/dist/src/command-line/migrate/migrate-analytics.js +71 -10
- package/dist/src/command-line/migrate/migrate-commits.d.ts +5 -4
- package/dist/src/command-line/migrate/migrate-commits.js +16 -6
- package/dist/src/command-line/migrate/migrate-config.d.ts +5 -2
- package/dist/src/command-line/migrate/migrate-config.js +19 -11
- package/dist/src/command-line/migrate/migrate-output.d.ts +3 -7
- package/dist/src/command-line/migrate/migrate-output.js +3 -7
- package/dist/src/command-line/migrate/migrate.d.ts +3 -0
- package/dist/src/command-line/migrate/migrate.js +183 -46
- package/dist/src/command-line/migrate/resolve-package-version.js +2 -19
- package/dist/src/command-line/migrate/run/agent-output.d.ts +11 -0
- package/dist/src/command-line/migrate/run/agent-output.js +21 -2
- package/dist/src/command-line/migrate/run/agent-work-payload.d.ts +37 -0
- package/dist/src/command-line/migrate/run/agent-work-payload.js +156 -0
- package/dist/src/command-line/migrate/run/atomic-write.d.ts +8 -0
- package/dist/src/command-line/migrate/run/atomic-write.js +17 -0
- package/dist/src/command-line/migrate/run/broker.d.ts +150 -0
- package/dist/src/command-line/migrate/run/broker.js +568 -0
- package/dist/src/command-line/migrate/run/clean-retry.d.ts +12 -0
- package/dist/src/command-line/migrate/run/clean-retry.js +99 -0
- package/dist/src/command-line/migrate/run/existing-run-report.d.ts +55 -0
- package/dist/src/command-line/migrate/run/existing-run-report.js +227 -0
- package/dist/src/command-line/migrate/run/give-up.d.ts +41 -0
- package/dist/src/command-line/migrate/run/give-up.js +148 -0
- package/dist/src/command-line/migrate/run/index.d.ts +9 -6
- package/dist/src/command-line/migrate/run/index.js +21 -2
- package/dist/src/command-line/migrate/run/issues.d.ts +127 -0
- package/dist/src/command-line/migrate/run/issues.js +1121 -0
- package/dist/src/command-line/migrate/run/orchestrator.d.ts +59 -1
- package/dist/src/command-line/migrate/run/orchestrator.js +1529 -457
- package/dist/src/command-line/migrate/run/run-id.d.ts +0 -8
- package/dist/src/command-line/migrate/run/run-id.js +0 -30
- package/dist/src/command-line/migrate/run/run-state.d.ts +77 -17
- package/dist/src/command-line/migrate/run/run-state.js +263 -32
- package/dist/src/command-line/migrate/run/runbook.d.ts +18 -0
- package/dist/src/command-line/migrate/run/runbook.js +118 -0
- package/dist/src/command-line/migrate/run/state-lock.d.ts +33 -2
- package/dist/src/command-line/migrate/run/state-lock.js +128 -2
- package/dist/src/command-line/migrate/run/state-machine.d.ts +50 -1
- package/dist/src/command-line/migrate/run/state-machine.js +339 -26
- package/dist/src/command-line/migrate/run/util.d.ts +3 -1
- package/dist/src/command-line/migrate/run/util.js +24 -3
- package/dist/src/command-line/migrate/run/worker.js +290 -129
- package/dist/src/command-line/migrate/step-actions.d.ts +1 -1
- package/dist/src/command-line/migrate/step-actions.js +7 -1
- package/dist/src/command-line/migrate/text.d.ts +6 -0
- package/dist/src/command-line/migrate/text.js +25 -0
- package/dist/src/command-line/migrate/version-skew-guard.js +2 -0
- package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +5 -11
- package/dist/src/command-line/release/publish.js +11 -8
- package/dist/src/command-line/release/utils/get-touched-projects-for-group.js +3 -3
- package/dist/src/command-line/release/utils/release-graph.js +1 -1
- package/dist/src/command-line/release/utils/remote-release-clients/github.js +5 -8
- package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +3 -3
- package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.d.ts +4 -2
- package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.js +37 -3
- package/dist/src/command-line/release/version/version-actions.d.ts +3 -0
- package/dist/src/command-line/reset/reset.js +10 -4
- package/dist/src/command-line/run/run-one.js +5 -1
- package/dist/src/command-line/run-many/run-many.js +6 -12
- package/dist/src/command-line/show/command-object.js +1 -1
- package/dist/src/command-line/show/projects.js +52 -1
- package/dist/src/command-line/yargs-utils/shared-options.d.ts +5 -1
- package/dist/src/command-line/yargs-utils/shared-options.js +38 -4
- package/dist/src/config/task-graph.d.ts +1 -1
- package/dist/src/config/workspace-json-project-json.d.ts +23 -1
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/core/graph/runtime.js +1 -1
- package/dist/src/core/graph/styles.js +1 -1
- package/dist/src/daemon/client/client.d.ts +14 -8
- package/dist/src/daemon/client/client.js +41 -12
- package/dist/src/daemon/message-types/get-plugin-capabilities.d.ts +5 -0
- package/dist/src/daemon/message-types/get-plugin-capabilities.js +11 -0
- package/dist/src/daemon/message-types/run-tasks-execution-hooks.d.ts +3 -2
- package/dist/src/daemon/message-types/select-affected-tasks.d.ts +21 -0
- package/dist/src/daemon/message-types/select-affected-tasks.js +11 -0
- package/dist/src/daemon/message-types/ultracache-configuration-version.d.ts +8 -0
- package/dist/src/daemon/message-types/ultracache-configuration-version.js +2 -0
- package/dist/src/daemon/server/dotenv-graph-changes.d.ts +1 -1
- package/dist/src/daemon/server/dotenv-graph-changes.js +2 -2
- package/dist/src/daemon/server/handle-get-plugin-capabilities.d.ts +2 -0
- package/dist/src/daemon/server/handle-get-plugin-capabilities.js +13 -0
- package/dist/src/daemon/server/handle-hash-tasks.d.ts +10 -2
- package/dist/src/daemon/server/handle-hash-tasks.js +18 -3
- package/dist/src/daemon/server/handle-select-affected-tasks.d.ts +3 -0
- package/dist/src/daemon/server/handle-select-affected-tasks.js +26 -0
- package/dist/src/daemon/server/handle-tasks-execution-hooks.d.ts +3 -2
- package/dist/src/daemon/server/{handle-outputs-changes.d.ts → handle-watch-events.d.ts} +4 -4
- package/dist/src/daemon/server/{handle-outputs-changes.js → handle-watch-events.js} +36 -37
- package/dist/src/daemon/server/outputs-tracking.d.ts +7 -19
- package/dist/src/daemon/server/outputs-tracking.js +7 -107
- package/dist/src/daemon/server/planning-context.d.ts +8 -0
- package/dist/src/daemon/server/planning-context.js +18 -0
- package/dist/src/daemon/server/project-graph-incremental-recomputation.d.ts +22 -7
- package/dist/src/daemon/server/project-graph-incremental-recomputation.js +104 -74
- package/dist/src/daemon/server/restart-checks.d.ts +22 -0
- package/dist/src/daemon/server/restart-checks.js +77 -0
- package/dist/src/daemon/server/server.d.ts +1 -0
- package/dist/src/daemon/server/server.js +54 -30
- package/dist/src/daemon/server/shutdown-utils.d.ts +0 -5
- package/dist/src/daemon/server/shutdown-utils.js +3 -26
- package/dist/src/daemon/server/ultracache-configuration-state.d.ts +7 -0
- package/dist/src/daemon/server/ultracache-configuration-state.js +36 -0
- package/dist/src/devkit-internals.d.ts +3 -1
- package/dist/src/devkit-internals.js +8 -3
- package/dist/src/executors/run-commands/run-commands.impl.d.ts +2 -1
- package/dist/src/executors/run-commands/run-commands.impl.js +19 -5
- package/dist/src/executors/run-commands/running-tasks.d.ts +5 -4
- package/dist/src/executors/run-commands/running-tasks.js +13 -13
- package/dist/src/hasher/create-task-hasher.d.ts +8 -1
- package/dist/src/hasher/create-task-hasher.js +13 -3
- package/dist/src/hasher/hash-plan-inspector.js +2 -2
- package/dist/src/hasher/hash-task.d.ts +2 -2
- package/dist/src/hasher/hash-task.js +28 -17
- package/dist/src/hasher/native-task-hasher-impl.d.ts +20 -4
- package/dist/src/hasher/native-task-hasher-impl.js +75 -9
- package/dist/src/hasher/task-hasher.d.ts +24 -7
- package/dist/src/hasher/task-hasher.js +27 -8
- package/dist/src/hasher/task-planning-context.d.ts +13 -0
- package/dist/src/hasher/task-planning-context.js +12 -0
- package/dist/src/native/index.d.ts +582 -21
- package/dist/src/native/index.js +3 -3
- package/dist/src/native/native-bindings.js +13 -1
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/native/transform-objects.d.ts +11 -2
- package/dist/src/native/transform-objects.js +46 -0
- package/dist/src/nx-cloud/generators/connect-to-nx-cloud/connect-to-nx-cloud.js +15 -8
- package/dist/src/nx-cloud/update-manager.d.ts +3 -0
- package/dist/src/nx-cloud/update-manager.js +19 -13
- package/dist/src/nx-cloud/utilities/client.d.ts +1 -1
- package/dist/src/nx-cloud/utilities/client.js +1 -1
- package/dist/src/nx-cloud/utilities/is-workspace-claimed.js +2 -1
- package/dist/src/nx-cloud/utilities/nx-cloud-http-client.d.ts +5 -0
- package/dist/src/nx-cloud/utilities/nx-cloud-http-client.js +16 -0
- package/dist/src/nx-cloud/utilities/url-shorten.js +17 -10
- package/dist/src/plugins/js/index.js +45 -64
- package/dist/src/plugins/js/lock-file/lock-file.d.ts +4 -4
- package/dist/src/plugins/js/lock-file/lock-file.js +6 -7
- package/dist/src/plugins/js/lock-file/pnpm-parser.js +1 -1
- package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.d.ts +2 -0
- package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.js +22 -0
- package/dist/src/plugins/js/project-graph/affected/lock-file-changes.d.ts +10 -2
- package/dist/src/plugins/js/project-graph/affected/lock-file-changes.js +51 -29
- package/dist/src/plugins/js/project-graph/affected/npm-packages.d.ts +10 -2
- package/dist/src/plugins/js/project-graph/affected/npm-packages.js +32 -11
- package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +22 -18
- package/dist/src/plugins/js/utils/register.js +13 -4
- package/dist/src/plugins/package-json/create-nodes.d.ts +2 -2
- package/dist/src/plugins/package-json/create-nodes.js +13 -13
- package/dist/src/project-graph/affected/affected-project-graph-models.d.ts +14 -0
- package/dist/src/project-graph/affected/affected-project-graph.js +5 -18
- package/dist/src/project-graph/affected/affected-projects.d.ts +7 -0
- package/dist/src/project-graph/affected/affected-projects.js +42 -0
- package/dist/src/project-graph/affected/affected-reasons.d.ts +116 -0
- package/dist/src/project-graph/affected/affected-reasons.js +459 -0
- package/dist/src/project-graph/affected/affected-tasks.d.ts +103 -0
- package/dist/src/project-graph/affected/affected-tasks.js +386 -0
- package/dist/src/project-graph/affected/print-explanation.d.ts +11 -0
- package/dist/src/project-graph/affected/print-explanation.js +44 -0
- package/dist/src/project-graph/error-types.d.ts +5 -0
- package/dist/src/project-graph/error-types.js +44 -5
- package/dist/src/project-graph/file-utils.d.ts +2 -0
- package/dist/src/project-graph/file-utils.js +12 -3
- package/dist/src/project-graph/nx-deps-cache.d.ts +5 -2
- package/dist/src/project-graph/nx-deps-cache.js +4 -4
- package/dist/src/project-graph/plugins/get-plugins.d.ts +3 -1
- package/dist/src/project-graph/plugins/get-plugins.js +60 -82
- package/dist/src/project-graph/plugins/in-process-loader.d.ts +1 -1
- package/dist/src/project-graph/plugins/in-process-loader.js +1 -4
- package/dist/src/project-graph/plugins/isolation/index.d.ts +1 -1
- package/dist/src/project-graph/plugins/isolation/index.js +3 -1
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +8 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +42 -6
- package/dist/src/project-graph/plugins/isolation/load-isolated-plugin.d.ts +10 -1
- package/dist/src/project-graph/plugins/isolation/load-isolated-plugin.js +67 -17
- package/dist/src/project-graph/plugins/isolation/messaging.d.ts +3 -2
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +5 -1
- package/dist/src/project-graph/plugins/loaded-nx-plugin.d.ts +5 -2
- package/dist/src/project-graph/plugins/loaded-nx-plugin.js +14 -1
- package/dist/src/project-graph/plugins/nx-plugin-capabilities.d.ts +6 -0
- package/dist/src/project-graph/plugins/nx-plugin-capabilities.js +28 -0
- package/dist/src/project-graph/plugins/task-results-stub.d.ts +50 -0
- package/dist/src/project-graph/plugins/task-results-stub.js +111 -0
- package/dist/src/project-graph/plugins/tasks-execution-hooks.d.ts +3 -2
- package/dist/src/project-graph/plugins/tasks-execution-hooks.js +14 -1
- package/dist/src/project-graph/project-graph.js +43 -42
- package/dist/src/project-graph/utils/project-configuration/target-merging.js +67 -0
- package/dist/src/project-graph/utils/project-configuration/target-normalization.js +83 -0
- package/dist/src/project-graph/utils/project-configuration/utils.d.ts +1 -0
- package/dist/src/project-graph/utils/project-configuration/utils.js +1 -0
- package/dist/src/tasks-runner/batch/run-batch.js +15 -0
- package/dist/src/tasks-runner/cache.d.ts +37 -2
- package/dist/src/tasks-runner/cache.js +42 -1
- package/dist/src/tasks-runner/create-task-graph.d.ts +24 -1
- package/dist/src/tasks-runner/create-task-graph.js +57 -2
- package/dist/src/tasks-runner/default-tasks-runner.js +1 -1
- package/dist/src/tasks-runner/forked-process-task-runner.d.ts +1 -1
- package/dist/src/tasks-runner/forked-process-task-runner.js +11 -10
- package/dist/src/tasks-runner/init-tasks-runner.d.ts +7 -2
- package/dist/src/tasks-runner/init-tasks-runner.js +15 -7
- package/dist/src/tasks-runner/is-tui-enabled.js +4 -3
- package/dist/src/tasks-runner/life-cycle.d.ts +7 -0
- package/dist/src/tasks-runner/life-cycle.js +7 -0
- package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.d.ts +35 -0
- package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.js +146 -0
- package/dist/src/tasks-runner/prune-task-graph.d.ts +17 -0
- package/dist/src/tasks-runner/prune-task-graph.js +45 -0
- package/dist/src/tasks-runner/run-command.d.ts +41 -5
- package/dist/src/tasks-runner/run-command.js +98 -22
- package/dist/src/tasks-runner/running-tasks/batch-process.d.ts +93 -19
- package/dist/src/tasks-runner/running-tasks/batch-process.js +184 -88
- package/dist/src/tasks-runner/task-io-service.d.ts +11 -3
- package/dist/src/tasks-runner/task-io-service.js +14 -5
- package/dist/src/tasks-runner/task-orchestrator.d.ts +71 -4
- package/dist/src/tasks-runner/task-orchestrator.js +266 -66
- package/dist/src/tasks-runner/tasks-runner.d.ts +2 -0
- package/dist/src/tasks-runner/terminal-output-path.d.ts +11 -0
- package/dist/src/tasks-runner/terminal-output-path.js +18 -0
- package/dist/src/tasks-runner/utils.d.ts +5 -0
- package/dist/src/tasks-runner/utils.js +14 -2
- package/dist/src/ultracache/config.d.ts +21 -0
- package/dist/src/ultracache/config.js +29 -0
- package/dist/src/ultracache/fetch.d.ts +21 -0
- package/dist/src/ultracache/fetch.js +43 -0
- package/dist/src/ultracache/overrides.d.ts +17 -0
- package/dist/src/ultracache/overrides.js +61 -0
- package/dist/src/ultracache/report.d.ts +13 -0
- package/dist/src/ultracache/report.js +62 -0
- package/dist/src/ultracache/store.d.ts +41 -0
- package/dist/src/ultracache/store.js +158 -0
- package/dist/src/utils/ab-testing.d.ts +4 -1
- package/dist/src/utils/ab-testing.js +22 -19
- package/dist/src/utils/chunkify.d.ts +1 -7
- package/dist/src/utils/chunkify.js +2 -8
- package/dist/src/utils/command-line-utils.d.ts +20 -0
- package/dist/src/utils/command-line-utils.js +10 -3
- package/dist/src/utils/create-cli-options.d.ts +6 -0
- package/dist/src/utils/create-cli-options.js +29 -0
- package/dist/src/utils/db-connection.d.ts +2 -0
- package/dist/src/utils/db-connection.js +2 -0
- package/dist/src/utils/formatters/index.d.ts +6 -0
- package/dist/src/utils/formatters/index.js +5 -0
- package/dist/src/utils/formatters/prettier.d.ts +0 -8
- package/dist/src/utils/formatters/prettier.js +4 -26
- package/dist/src/utils/git-utils.d.ts +19 -0
- package/dist/src/utils/git-utils.js +97 -39
- package/dist/src/utils/handle-errors.js +5 -43
- package/dist/src/utils/http-client.d.ts +27 -0
- package/dist/src/utils/http-client.js +193 -0
- package/dist/src/utils/installed-nx-version.js +2 -48
- package/dist/src/utils/json-diff.d.ts +4 -2
- package/dist/src/utils/json-diff.js +6 -94
- package/dist/src/utils/min-release-age/packument.js +1 -1
- package/dist/src/utils/nx-cloud-utils.d.ts +2 -0
- package/dist/src/utils/nx-cloud-utils.js +6 -1
- package/dist/src/utils/output.d.ts +22 -3
- package/dist/src/utils/output.js +28 -5
- package/dist/src/utils/package-json.d.ts +25 -0
- package/dist/src/utils/package-json.js +49 -6
- package/dist/src/utils/package-manager.d.ts +6 -0
- package/dist/src/utils/package-manager.js +10 -0
- package/dist/src/utils/plugins/plugin-capabilities.js +7 -2
- package/dist/src/utils/project-graph-utils.d.ts +2 -0
- package/dist/src/utils/project-graph-utils.js +12 -0
- package/dist/src/utils/provenance.js +20 -4
- package/dist/src/utils/serialize-overrides-into-command-line.js +2 -4
- package/dist/src/utils/workspace-context.d.ts +51 -3
- package/dist/src/utils/workspace-context.js +174 -10
- package/package.json +38 -100
- package/schemas/nx-schema.json +38 -0
- package/schemas/project-schema.json +35 -0
- package/dist/src/daemon/server/file-watching/route-workspace-changes.d.ts +0 -9
- package/dist/src/daemon/server/file-watching/route-workspace-changes.js +0 -76
- package/dist/src/daemon/server/watcher.d.ts +0 -18
- package/dist/src/daemon/server/watcher.js +0 -126
- package/dist/src/nx-cloud/utilities/axios.d.ts +0 -4
- package/dist/src/nx-cloud/utilities/axios.js +0 -17
- package/dist/src/project-graph/affected/locators/project-glob-changes.d.ts +0 -2
- package/dist/src/project-graph/affected/locators/project-glob-changes.js +0 -47
- package/dist/src/project-graph/affected/locators/workspace-json-changes.d.ts +0 -4
- package/dist/src/project-graph/affected/locators/workspace-json-changes.js +0 -47
- package/dist/src/project-graph/affected/locators/workspace-projects.d.ts +0 -3
- package/dist/src/project-graph/affected/locators/workspace-projects.js +0 -74
- package/dist/src/utils/collapse-expanded-outputs.d.ts +0 -10
- package/dist/src/utils/collapse-expanded-outputs.js +0 -72
|
@@ -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;
|
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.explainUnavailable = explainUnavailable;
|
|
4
|
+
exports.hydrateExplanation = hydrateExplanation;
|
|
5
|
+
exports.formatAffectedReason = formatAffectedReason;
|
|
6
|
+
exports.formatAffectedExplanation = formatAffectedExplanation;
|
|
7
|
+
exports.isExplaining = isExplaining;
|
|
8
|
+
/**
|
|
9
|
+
* Why `--explain` cannot run here, naming only what is missing or in the way.
|
|
10
|
+
* It explains task selection, so it needs what task selection needs.
|
|
11
|
+
*/
|
|
12
|
+
function explainUnavailable(missing, conflicting = []) {
|
|
13
|
+
const sentences = [
|
|
14
|
+
missing.length && `--explain needs ${listed(missing)}.`,
|
|
15
|
+
conflicting.length &&
|
|
16
|
+
`--explain can't be combined with ${listed(conflicting)}.`,
|
|
17
|
+
].filter(Boolean);
|
|
18
|
+
return sentences.length
|
|
19
|
+
? sentences.join(' ')
|
|
20
|
+
: '--explain only works with nx affected and nx show projects --affected.';
|
|
21
|
+
}
|
|
22
|
+
/** The order input reasons are listed in, matching one task's own matches. */
|
|
23
|
+
const INPUT_KINDS = [
|
|
24
|
+
'input-file',
|
|
25
|
+
'npm-package',
|
|
26
|
+
'moved-ecosystem',
|
|
27
|
+
'external-dependencies',
|
|
28
|
+
'project-configuration',
|
|
29
|
+
];
|
|
30
|
+
/** Expands each task's `inputs` stand-in into its reasons. */
|
|
31
|
+
function hydrateExplanation({ inputs, affected, upstream, ...rest }) {
|
|
32
|
+
const hydrate = (reasons) => reasons.flatMap((reason) => reason.kind === 'inputs' ? mergeInputs(reason.inputs, inputs) : [reason]);
|
|
33
|
+
const all = (byTask) => Object.fromEntries(Object.entries(byTask).map(([id, reasons]) => [id, hydrate(reasons)]));
|
|
34
|
+
return { affected: all(affected), upstream: all(upstream), ...rest };
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Several entries' reasons as one task's: grouped by kind, sorted, and with a
|
|
38
|
+
* reason two instructions both produced listed once.
|
|
39
|
+
*/
|
|
40
|
+
function mergeInputs(indexes, inputs) {
|
|
41
|
+
// Each entry is already sorted and deduplicated.
|
|
42
|
+
if (indexes.length === 1) {
|
|
43
|
+
return inputs[indexes[0]];
|
|
44
|
+
}
|
|
45
|
+
const merged = indexes.flatMap((index) => inputs[index]);
|
|
46
|
+
const sortKey = (reason) => reason.kind === 'npm-package'
|
|
47
|
+
? reason.package
|
|
48
|
+
: reason.kind === 'moved-ecosystem'
|
|
49
|
+
? reason.ecosystem
|
|
50
|
+
: reason.kind === 'external-dependencies'
|
|
51
|
+
? ''
|
|
52
|
+
: reason.file;
|
|
53
|
+
const result = [];
|
|
54
|
+
for (const kind of INPUT_KINDS) {
|
|
55
|
+
const seen = new Set();
|
|
56
|
+
const ofKind = merged
|
|
57
|
+
.filter((reason) => reason.kind === kind)
|
|
58
|
+
.sort((a, b) => compare(sortKey(a), sortKey(b)) || compare(a.pattern, b.pattern));
|
|
59
|
+
for (const reason of ofKind) {
|
|
60
|
+
const key = `${reason.file}\0${reason.pattern}\0${reason.package}\0${reason.ecosystem}`;
|
|
61
|
+
if (!seen.has(key)) {
|
|
62
|
+
seen.add(key);
|
|
63
|
+
result.push(reason);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
/** Code-point order, as the native side sorts. */
|
|
70
|
+
function compare(a = '', b = '') {
|
|
71
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* One line of `--explain` output, without the leading bullet. `many` is set
|
|
75
|
+
* when `file` names several files.
|
|
76
|
+
*/
|
|
77
|
+
function formatAffectedReason(reason, many = false) {
|
|
78
|
+
const changes = many ? 'change' : 'changes';
|
|
79
|
+
switch (reason.kind) {
|
|
80
|
+
case 'deleted-project-configuration':
|
|
81
|
+
return `${reason.file} ${many ? 'are' : 'is'} deleted`;
|
|
82
|
+
case 'project-configuration':
|
|
83
|
+
return `project configuration in ${reason.file} ${changes}`;
|
|
84
|
+
case 'lockfile':
|
|
85
|
+
return `lockfile ${reason.file} ${changes}`;
|
|
86
|
+
case 'npm-package':
|
|
87
|
+
return `depends on ${reason.package}, whose version changes`;
|
|
88
|
+
case 'moved-ecosystem':
|
|
89
|
+
return `${reason.file ?? 'a dependency manifest'} ${changes} and can't be narrowed to packages, so every ${reason.ecosystem} package counts as changed`;
|
|
90
|
+
case 'input-file':
|
|
91
|
+
return reason.pattern
|
|
92
|
+
? `${reason.file} (${reason.pattern})`
|
|
93
|
+
: reason.file;
|
|
94
|
+
case 'dependent-output':
|
|
95
|
+
return `reads the outputs of ${reason.producer}`;
|
|
96
|
+
case 'external-dependencies':
|
|
97
|
+
return `hashes every external dependency, and ${reason.file} ${changes}`;
|
|
98
|
+
case 'custom-hasher':
|
|
99
|
+
return `its executor uses a custom hasher, so it is always selected`;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Renders `--explain` output: one block per entity, its reasons beneath it.
|
|
104
|
+
*
|
|
105
|
+
* It follows the chain: what the change touched, what it reached through
|
|
106
|
+
* those, and last the selection itself, so the reader's own entries stay at
|
|
107
|
+
* the bottom however long the chain grows.
|
|
108
|
+
*
|
|
109
|
+
* An entity with no reason is still listed, with a line saying so, because a
|
|
110
|
+
* blank line is indistinguishable from a bug when you are troubleshooting.
|
|
111
|
+
*/
|
|
112
|
+
function formatAffectedExplanation({ affected, upstream, touched: touchedNames, requested, moved = {}, }, heading, { verbose = false, styleTask = (id) => id, dim = (text) => text, bold = (text) => text, } = {}) {
|
|
113
|
+
const names = Object.keys(affected).sort();
|
|
114
|
+
if (!names.length) {
|
|
115
|
+
return `Nothing affected.`;
|
|
116
|
+
}
|
|
117
|
+
const reasonsOf = (name) => affected[name] ?? upstream[name] ?? [];
|
|
118
|
+
const touchedSet = new Set(touchedNames);
|
|
119
|
+
const touched = (name) => touchedSet.has(name);
|
|
120
|
+
// Out of the requested targets' tasks, so the title says what selection saved.
|
|
121
|
+
const n = names.length;
|
|
122
|
+
const title = requested
|
|
123
|
+
? `${n} out of ${requested.total} ${listed(requested.targets)} ${requested.total === 1 ? 'task' : 'tasks'} ${n === 1 ? 'is' : 'are'} affected`
|
|
124
|
+
: `${heading} (${n})`;
|
|
125
|
+
const lines = [`${title}:`, ''];
|
|
126
|
+
// The tasks asked for are marked by count and listed first in each group,
|
|
127
|
+
// rather than split into a section of their own, so each cause shows once.
|
|
128
|
+
const requestedSet = new Set(names);
|
|
129
|
+
// Your tasks are counted per target, in the order the targets were given.
|
|
130
|
+
const targets = requested?.targets ?? [];
|
|
131
|
+
const targetOf = (name) => targets.find((target) => name.endsWith(`:${target}`) || name.includes(`:${target}:`)) ?? 'requested';
|
|
132
|
+
const breakdown = (group, more) => {
|
|
133
|
+
const byTarget = new Map([...targets, 'requested'].map((target) => [target, 0]));
|
|
134
|
+
let rest = 0;
|
|
135
|
+
for (const name of group) {
|
|
136
|
+
if (requestedSet.has(name)) {
|
|
137
|
+
const target = targetOf(name);
|
|
138
|
+
byTarget.set(target, byTarget.get(target) + 1);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
rest++;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const mine = [...byTarget.values()].reduce((sum, count) => sum + count, 0);
|
|
145
|
+
const parts = [...byTarget]
|
|
146
|
+
.filter(([, count]) => count)
|
|
147
|
+
.map(([target, count]) => `${count} ${more}${bold(target)} ${count === 1 ? 'task' : 'tasks'}`);
|
|
148
|
+
// Named as the run summary names them: the tasks yours depend on.
|
|
149
|
+
if (rest) {
|
|
150
|
+
const whose = mine
|
|
151
|
+
? mine === 1
|
|
152
|
+
? 'it depends on'
|
|
153
|
+
: 'they depend on'
|
|
154
|
+
: `the ${listed((targets.length ? targets : ['requested']).map(bold))} tasks depend on`;
|
|
155
|
+
parts.push(`${rest} ${mine ? '' : more}${rest === 1 ? 'task' : 'tasks'} ${whose}`);
|
|
156
|
+
}
|
|
157
|
+
return listed(parts);
|
|
158
|
+
};
|
|
159
|
+
const counted = (group) => breakdown(group, '');
|
|
160
|
+
// The tasks a list leaves out, as "N more build tasks and M tasks they depend on".
|
|
161
|
+
const otherCounted = (group) => breakdown(group, 'more ');
|
|
162
|
+
const requestedFirst = (group) => [
|
|
163
|
+
...group.filter((name) => requestedSet.has(name)),
|
|
164
|
+
...group.filter((name) => !requestedSet.has(name)),
|
|
165
|
+
];
|
|
166
|
+
const shown = (name) => styleTask(name, requestedSet.has(name));
|
|
167
|
+
const detail = (name, indent) => {
|
|
168
|
+
lines.push(`${indent}${shown(name)}`);
|
|
169
|
+
const forName = reasonsOf(name);
|
|
170
|
+
if (!forName.length) {
|
|
171
|
+
lines.push(`${indent} - selected, but no reason is recorded`);
|
|
172
|
+
}
|
|
173
|
+
for (const line of reasonLines(forName, moved, dim)) {
|
|
174
|
+
lines.push(`${indent} - ${line}`);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
// --verbose shows each task with its reasons; otherwise up to five names.
|
|
178
|
+
const list = (group, indent, detailed) => {
|
|
179
|
+
const ordered = requestedFirst(group);
|
|
180
|
+
if (detailed) {
|
|
181
|
+
ordered.forEach((name) => detail(name, indent));
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
for (const name of ordered.slice(0, 5)) {
|
|
185
|
+
lines.push(`${indent}- ${shown(name)}`);
|
|
186
|
+
}
|
|
187
|
+
if (ordered.length > 5) {
|
|
188
|
+
lines.push(`${indent}- and ${otherCounted(ordered.slice(5))}`);
|
|
189
|
+
}
|
|
190
|
+
};
|
|
191
|
+
const hint = '. Pass --verbose to list each with its reasons.';
|
|
192
|
+
const all = [...new Set([...names, ...Object.keys(upstream)])].sort();
|
|
193
|
+
const touchedAll = all.filter(touched);
|
|
194
|
+
// Every task reading a changed output, so a touched one can be listed twice.
|
|
195
|
+
const reachedAll = all.filter((name) => !touched(name) || reasonsOf(name).some(isUpstreamReason));
|
|
196
|
+
// Touched tasks: a section for files, then one for packages, each grouped
|
|
197
|
+
// by what changed. A task touched by both is listed in each.
|
|
198
|
+
const kinds = [
|
|
199
|
+
{ noun: 'file', groups: new Map() },
|
|
200
|
+
{ noun: 'package', groups: new Map() },
|
|
201
|
+
];
|
|
202
|
+
const unnamed = [];
|
|
203
|
+
for (const name of touchedAll) {
|
|
204
|
+
const changed = changedIn(reasonsOf(name), moved);
|
|
205
|
+
if (!changed.length)
|
|
206
|
+
unnamed.push(name);
|
|
207
|
+
for (const { noun, groups } of kinds) {
|
|
208
|
+
const ofKind = changed.filter((change) => change.isPackage === (noun === 'package'));
|
|
209
|
+
if (!ofKind.length)
|
|
210
|
+
continue;
|
|
211
|
+
// Keyed by the whole set: two sets can share a shortened heading.
|
|
212
|
+
const key = ofKind.map((change) => change.name).join('\0');
|
|
213
|
+
const group = groups.get(key) ?? {
|
|
214
|
+
heading: describeChanged(ofKind, noun),
|
|
215
|
+
names: ofKind.map((change) => change.name),
|
|
216
|
+
members: [],
|
|
217
|
+
};
|
|
218
|
+
group.members.push(name);
|
|
219
|
+
groups.set(key, group);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
for (const { noun, groups } of kinds) {
|
|
223
|
+
if (!groups.size)
|
|
224
|
+
continue;
|
|
225
|
+
if (verbose) {
|
|
226
|
+
for (const group of groups.values())
|
|
227
|
+
group.heading = listed(group.names);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
disambiguate([...groups.values()], noun);
|
|
231
|
+
}
|
|
232
|
+
const members = [
|
|
233
|
+
...new Set([...groups.values()].flatMap((group) => group.members)),
|
|
234
|
+
];
|
|
235
|
+
const sorted = [...groups].sort(([a, x], [b, y]) => y.members.length - x.members.length ||
|
|
236
|
+
x.heading.localeCompare(y.heading) ||
|
|
237
|
+
a.localeCompare(b));
|
|
238
|
+
const changes = new Set(members.flatMap((name) => changedIn(reasonsOf(name), moved)
|
|
239
|
+
.filter((change) => change.isPackage === (noun === 'package'))
|
|
240
|
+
.map((change) => change.name)));
|
|
241
|
+
const header = `Changing ${changes.size} ${noun}${changes.size === 1 ? '' : 's'} touches ${counted(members)}`;
|
|
242
|
+
lines.push(verbose ? `${header}:` : `${header}${hint}`);
|
|
243
|
+
for (const [, { heading, members: inGroup }] of sorted) {
|
|
244
|
+
lines.push('', ` ${heading}:`);
|
|
245
|
+
list(inGroup, ' ', verbose);
|
|
246
|
+
}
|
|
247
|
+
lines.push('');
|
|
248
|
+
}
|
|
249
|
+
if (unnamed.length) {
|
|
250
|
+
const header = `${counted(unnamed)} ${unnamed.length === 1 ? 'is' : 'are'} touched with no changed file to name`;
|
|
251
|
+
lines.push(verbose ? `${header}:` : `${header}${hint}`);
|
|
252
|
+
list(unnamed, ' ', verbose);
|
|
253
|
+
lines.push('');
|
|
254
|
+
}
|
|
255
|
+
if (reachedAll.length) {
|
|
256
|
+
const header = `Touching those tasks changes outputs read by ${counted(reachedAll)}`;
|
|
257
|
+
lines.push(verbose ? `${header}:` : `${header}${hint}`);
|
|
258
|
+
list(reachedAll, ' ', verbose);
|
|
259
|
+
lines.push('');
|
|
260
|
+
}
|
|
261
|
+
lines.pop();
|
|
262
|
+
return lines.join('\n');
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* One line per reason, and per matched file with the patterns it matched.
|
|
266
|
+
* Producers read share a line that names them all. Moved packages name the
|
|
267
|
+
* first and count the rest: a dependency bump can move thousands. The JSON
|
|
268
|
+
* keeps them all.
|
|
269
|
+
*/
|
|
270
|
+
function reasonLines(reasons, moved, dim = (text) => text) {
|
|
271
|
+
const externals = reasons.filter((reason) => reason.kind === 'external-dependencies');
|
|
272
|
+
const movedPackages = [
|
|
273
|
+
...new Set(externals.flatMap((reason) => moved[reason.file] ?? [])),
|
|
274
|
+
].sort();
|
|
275
|
+
// Hashing every external covers every package in an ecosystem that moved,
|
|
276
|
+
// unless the line names packages instead of files.
|
|
277
|
+
if (externals.length && !movedPackages.length) {
|
|
278
|
+
reasons = reasons.filter((reason) => reason.kind !== 'moved-ecosystem');
|
|
279
|
+
}
|
|
280
|
+
const grouped = new Map();
|
|
281
|
+
const keyOf = (reason) => {
|
|
282
|
+
switch (reason.kind) {
|
|
283
|
+
case 'input-file':
|
|
284
|
+
return `input-file\0${reason.file}`;
|
|
285
|
+
case 'npm-package':
|
|
286
|
+
case 'dependent-output':
|
|
287
|
+
case 'external-dependencies':
|
|
288
|
+
case 'project-configuration':
|
|
289
|
+
case 'deleted-project-configuration':
|
|
290
|
+
case 'lockfile':
|
|
291
|
+
return reason.kind;
|
|
292
|
+
case 'moved-ecosystem':
|
|
293
|
+
return `moved-ecosystem\0${reason.ecosystem}`;
|
|
294
|
+
default:
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
for (const reason of reasons) {
|
|
299
|
+
const key = keyOf(reason);
|
|
300
|
+
if (key) {
|
|
301
|
+
grouped.set(key, [...(grouped.get(key) ?? []), reason]);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
const lines = [];
|
|
305
|
+
const done = new Set();
|
|
306
|
+
for (const reason of reasons) {
|
|
307
|
+
const key = keyOf(reason);
|
|
308
|
+
if (reason.kind === 'external-dependencies' && movedPackages.length) {
|
|
309
|
+
if (done.has(key))
|
|
310
|
+
continue;
|
|
311
|
+
done.add(key);
|
|
312
|
+
const [first] = movedPackages;
|
|
313
|
+
const others = movedPackages.length - 1;
|
|
314
|
+
lines.push(`hashes every external dependency, and ${first}${others
|
|
315
|
+
? ` and ${others} other ${others === 1 ? 'package' : 'packages'}`
|
|
316
|
+
: ''} changed version`);
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
const group = key ? grouped.get(key) : undefined;
|
|
320
|
+
if (reason.kind === 'input-file') {
|
|
321
|
+
if (done.has(key))
|
|
322
|
+
continue;
|
|
323
|
+
done.add(key);
|
|
324
|
+
const patterns = group.map((r) => r.pattern).filter(Boolean);
|
|
325
|
+
lines.push(patterns.length
|
|
326
|
+
? `${reason.file} ${dim(`(${patterns.join(', ')})`)}`
|
|
327
|
+
: reason.file);
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
if (!group || group.length === 1) {
|
|
331
|
+
lines.push(formatAffectedReason(reason));
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (done.has(key))
|
|
335
|
+
continue;
|
|
336
|
+
done.add(key);
|
|
337
|
+
const [first] = group;
|
|
338
|
+
const others = group.length - 1;
|
|
339
|
+
switch (first.kind) {
|
|
340
|
+
case 'dependent-output':
|
|
341
|
+
lines.push(`reads the outputs of ${listed(group.map((r) => r.producer).sort())}`);
|
|
342
|
+
break;
|
|
343
|
+
case 'npm-package':
|
|
344
|
+
lines.push(`depends on ${first.package} and ${others} other ${others === 1 ? 'package' : 'packages'}, whose versions change`);
|
|
345
|
+
break;
|
|
346
|
+
default: {
|
|
347
|
+
// The same reason for several files: name them in one.
|
|
348
|
+
const files = group.map((r) => r.file ?? '').sort();
|
|
349
|
+
lines.push(formatAffectedReason({ ...first, file: listed(files) }, true));
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return lines;
|
|
354
|
+
}
|
|
355
|
+
/**
|
|
356
|
+
* Two sets of the same size and first name shorten to the same heading. Such
|
|
357
|
+
* a heading instead leads with the files that tell it apart, picked one at a
|
|
358
|
+
* time to rule out the most lookalikes, so it grows with the collisions rather
|
|
359
|
+
* than with the files.
|
|
360
|
+
*/
|
|
361
|
+
function disambiguate(groups, noun) {
|
|
362
|
+
const others = (count) => count ? [`${count} other ${noun}${count === 1 ? '' : 's'}`] : [];
|
|
363
|
+
const byHeading = new Map();
|
|
364
|
+
for (const group of groups) {
|
|
365
|
+
byHeading.set(group.heading, [
|
|
366
|
+
...(byHeading.get(group.heading) ?? []),
|
|
367
|
+
group,
|
|
368
|
+
]);
|
|
369
|
+
}
|
|
370
|
+
const telling = new Map();
|
|
371
|
+
for (const alike of byHeading.values()) {
|
|
372
|
+
if (alike.length < 2)
|
|
373
|
+
continue;
|
|
374
|
+
for (const group of alike) {
|
|
375
|
+
const [, ...rest] = group.names;
|
|
376
|
+
const picked = [];
|
|
377
|
+
let lookalikes = alike
|
|
378
|
+
.filter((other) => other !== group)
|
|
379
|
+
.map((other) => new Set(other.names));
|
|
380
|
+
while (lookalikes.length) {
|
|
381
|
+
const ruledOut = (name) => lookalikes.filter((names) => !names.has(name)).length;
|
|
382
|
+
const pick = rest
|
|
383
|
+
.filter((name) => !picked.includes(name))
|
|
384
|
+
.reduce((best, name) => ruledOut(name) > ruledOut(best) ? name : best);
|
|
385
|
+
picked.push(pick);
|
|
386
|
+
lookalikes = lookalikes.filter((names) => names.has(pick));
|
|
387
|
+
}
|
|
388
|
+
telling.set(group, picked.sort());
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
const leading = new Map([...telling].map(([group, picked]) => [
|
|
392
|
+
group,
|
|
393
|
+
listed([...picked, ...others(group.names.length - picked.length)]),
|
|
394
|
+
]));
|
|
395
|
+
const taken = new Map();
|
|
396
|
+
for (const group of groups) {
|
|
397
|
+
const heading = leading.get(group) ?? group.heading;
|
|
398
|
+
taken.set(heading, (taken.get(heading) ?? 0) + 1);
|
|
399
|
+
}
|
|
400
|
+
for (const [group, picked] of telling) {
|
|
401
|
+
// Leading with a telling file can, rarely, read like an unrelated group;
|
|
402
|
+
// the first name keeps it apart from everything outside its lookalikes.
|
|
403
|
+
group.heading =
|
|
404
|
+
taken.get(leading.get(group)) === 1
|
|
405
|
+
? leading.get(group)
|
|
406
|
+
: listed([
|
|
407
|
+
group.names[0],
|
|
408
|
+
...picked,
|
|
409
|
+
...others(group.names.length - 1 - picked.length),
|
|
410
|
+
]);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* What a task's own reasons name as changed: a moved package by its name,
|
|
415
|
+
* anything else by its file.
|
|
416
|
+
*/
|
|
417
|
+
function changedIn(reasons, moved) {
|
|
418
|
+
const changed = new Map();
|
|
419
|
+
const add = (name, isPackage) => {
|
|
420
|
+
if (name)
|
|
421
|
+
changed.set(name, { name, isPackage });
|
|
422
|
+
};
|
|
423
|
+
for (const reason of reasons) {
|
|
424
|
+
if (isUpstreamReason(reason))
|
|
425
|
+
continue;
|
|
426
|
+
const packages = reason.kind === 'external-dependencies' ? moved[reason.file] : undefined;
|
|
427
|
+
if (packages?.length) {
|
|
428
|
+
packages.forEach((name) => add(name, true));
|
|
429
|
+
}
|
|
430
|
+
else if (reason.kind === 'npm-package') {
|
|
431
|
+
add(reason.package, true);
|
|
432
|
+
}
|
|
433
|
+
else {
|
|
434
|
+
add(reason.file, false);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return [...changed.values()].sort((a, b) => a.name.localeCompare(b.name));
|
|
438
|
+
}
|
|
439
|
+
/** "a", "a and b", or "a and N other files". */
|
|
440
|
+
function describeChanged(changed, noun) {
|
|
441
|
+
if (changed.length <= 2) {
|
|
442
|
+
return changed.map((change) => change.name).join(' and ');
|
|
443
|
+
}
|
|
444
|
+
return `${changed[0].name} and ${changed.length - 1} other ${noun}s`;
|
|
445
|
+
}
|
|
446
|
+
/** A reason that names another entry rather than a change. */
|
|
447
|
+
function isUpstreamReason(reason) {
|
|
448
|
+
return reason.kind === 'dependent-output';
|
|
449
|
+
}
|
|
450
|
+
/** Whether `--explain` was asked for at all, in any of its forms. */
|
|
451
|
+
function isExplaining(value) {
|
|
452
|
+
return value !== undefined && value !== false;
|
|
453
|
+
}
|
|
454
|
+
/** "a", "a and b", or "a, b and c". */
|
|
455
|
+
function listed(items) {
|
|
456
|
+
return items.length <= 2
|
|
457
|
+
? items.join(' and ')
|
|
458
|
+
: `${items.slice(0, -1).join(', ')} and ${items[items.length - 1]}`;
|
|
459
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { NxJsonConfiguration, TargetDependencies } from '../../config/nx-json';
|
|
2
|
+
import { ProjectGraph } from '../../config/project-graph';
|
|
3
|
+
import { TaskGraph } from '../../config/task-graph';
|
|
4
|
+
import { type UltracacheConfigurations } from '../../native';
|
|
5
|
+
import { type UltracacheConfigurationOutcome } from '../../ultracache/store';
|
|
6
|
+
import type { UltracacheConfigurationVersion } from '../../daemon/message-types/ultracache-configuration-version';
|
|
7
|
+
import { FileChange } from '../file-utils';
|
|
8
|
+
import type { NxArgs } from '../../utils/command-line-utils';
|
|
9
|
+
import { type AffectedExplanation, type InternedExplanation } from './affected-reasons';
|
|
10
|
+
import { TaskPlanningContext } from '../../hasher/task-planning-context';
|
|
11
|
+
import type { TaskSelection } from '../../tasks-runner/run-command';
|
|
12
|
+
/**
|
|
13
|
+
* Whether `nx affected` selects the individual tasks whose inputs a change
|
|
14
|
+
* reaches, rather than whole projects. Off by default while the task path
|
|
15
|
+
* settles.
|
|
16
|
+
*
|
|
17
|
+
* Env-var only, so `nx show projects --affected` and `nx affected` in one CI
|
|
18
|
+
* script agree. The run also executes the selected tasks' dependencies.
|
|
19
|
+
*/
|
|
20
|
+
export declare function selectsAffectedTasks(): boolean;
|
|
21
|
+
export interface AffectedTasksResult {
|
|
22
|
+
/** The graph selection ran against, which the command should run with too. */
|
|
23
|
+
projectGraph: ProjectGraph;
|
|
24
|
+
/** Tasks that are themselves affected — NOT their dependency closure. */
|
|
25
|
+
affectedTaskIds: Set<string>;
|
|
26
|
+
/** The full, unpruned graph the answer was computed over. */
|
|
27
|
+
taskGraph: TaskGraph;
|
|
28
|
+
/** What the run executes: the affected tasks and what they depend on. */
|
|
29
|
+
taskSelection: TaskSelection;
|
|
30
|
+
/**
|
|
31
|
+
* Why each task is affected, plus the tasks outside the selection that
|
|
32
|
+
* carried the change to it, such as a `prebuild` under `-t build`. Only
|
|
33
|
+
* when `explain` was asked for.
|
|
34
|
+
*/
|
|
35
|
+
explanation?: AffectedExplanation;
|
|
36
|
+
}
|
|
37
|
+
export interface ComputeAffectedTasksOptions {
|
|
38
|
+
/** Fetched when absent. Unused when the daemon selects; it returns its own graph. */
|
|
39
|
+
projectGraph?: ProjectGraph;
|
|
40
|
+
nxJson: NxJsonConfiguration;
|
|
41
|
+
targets: string[];
|
|
42
|
+
touchedFiles: FileChange[];
|
|
43
|
+
/** What `touchedFiles` was computed from, so the daemon reads the same diff. */
|
|
44
|
+
fileChangeArgs?: FileChangeArgs;
|
|
45
|
+
configuration?: string;
|
|
46
|
+
overrides?: Record<string, unknown>;
|
|
47
|
+
extraTargetDependencies?: TargetDependencies;
|
|
48
|
+
excludeTaskDependencies?: boolean;
|
|
49
|
+
/** `--exclude` project patterns. Their tasks leave the selection but still carry a change and run as dependencies. */
|
|
50
|
+
exclude?: string[];
|
|
51
|
+
packageJson?: any;
|
|
52
|
+
/** This command's Ultracache configurations. Selection plans with them, as the run hashes with them. */
|
|
53
|
+
ultracacheConfigurationOutcome?: UltracacheConfigurationOutcome | null;
|
|
54
|
+
selectivelyHashTsConfig?: boolean;
|
|
55
|
+
/** Whether to say why each task is affected, for `--explain`. */
|
|
56
|
+
explain?: boolean;
|
|
57
|
+
}
|
|
58
|
+
export type FileChangeArgs = Pick<NxArgs, 'base' | 'head' | 'files'>;
|
|
59
|
+
/**
|
|
60
|
+
* What selection needs from the command, reduced to plain data so the daemon
|
|
61
|
+
* can run it. Anything read against the project graph, like `--exclude` and the
|
|
62
|
+
* lockfile diff, is resolved by whichever process selects.
|
|
63
|
+
*/
|
|
64
|
+
export interface AffectedTasksRequest {
|
|
65
|
+
targets: string[];
|
|
66
|
+
changedFiles: string[];
|
|
67
|
+
fileChangeArgs?: FileChangeArgs;
|
|
68
|
+
configuration?: string;
|
|
69
|
+
overrides: Record<string, unknown>;
|
|
70
|
+
extraTargetDependencies: TargetDependencies;
|
|
71
|
+
excludeTaskDependencies: boolean;
|
|
72
|
+
exclude: string[];
|
|
73
|
+
ultracacheConfigurationsVersion?: UltracacheConfigurationVersion;
|
|
74
|
+
/** The runner's `selectivelyHashTsConfig`, which decides what the tsconfig hash reads. */
|
|
75
|
+
selectivelyHashTsConfig?: boolean;
|
|
76
|
+
/** Whether to return why each task is affected. Off, nothing is collected. */
|
|
77
|
+
explain?: boolean;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Selects the tasks a change reaches, rather than the projects that own a
|
|
81
|
+
* changed file.
|
|
82
|
+
*
|
|
83
|
+
* With the daemon on, the daemon selects: it hashes the run's tasks, so its
|
|
84
|
+
* planner is the one that remembers the plans. It returns the graph it selected
|
|
85
|
+
* against, which the command must run with.
|
|
86
|
+
*/
|
|
87
|
+
export declare function computeAffectedTasks(opts: ComputeAffectedTasksOptions): Promise<AffectedTasksResult>;
|
|
88
|
+
/**
|
|
89
|
+
* Plans the targets' full task graph and matches the changed paths against
|
|
90
|
+
* every plan. No project-level prefilter: under Ultracache configurations a
|
|
91
|
+
* task can read files no affected project owns. Shared by the client and the
|
|
92
|
+
* daemon.
|
|
93
|
+
*/
|
|
94
|
+
export declare function selectAffectedTasks(projectGraph: ProjectGraph, nxJson: NxJsonConfiguration, planningContext: TaskPlanningContext, request: AffectedTasksRequest, { touchedFiles, packageJson, ultracacheConfigurations, }?: {
|
|
95
|
+
touchedFiles?: FileChange[];
|
|
96
|
+
packageJson?: any;
|
|
97
|
+
ultracacheConfigurations?: UltracacheConfigurations;
|
|
98
|
+
}): Promise<{
|
|
99
|
+
affectedTaskIds: Set<string>;
|
|
100
|
+
taskGraph: TaskGraph;
|
|
101
|
+
taskSelection: TaskSelection;
|
|
102
|
+
explanation?: InternedExplanation;
|
|
103
|
+
}>;
|