@ohos-ports/nx 23.3.0-beta.3 → 24.0.2-beta.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.
Files changed (301) hide show
  1. package/README.md +3 -6
  2. package/dist/bin/nx.js +2 -2
  3. package/dist/bin/post-install.js +5 -3
  4. package/dist/nx-cloud-internals.d.ts +1 -0
  5. package/dist/nx-cloud-internals.js +7 -1
  6. package/dist/src/adapter/ngcli-adapter.js +2 -2
  7. package/dist/src/ai/clone-ai-config-repo.js +49 -12
  8. package/dist/src/command-line/add/add.d.ts +2 -0
  9. package/dist/src/command-line/add/add.js +24 -6
  10. package/dist/src/command-line/affected/affected.js +2 -2
  11. package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +1 -13
  12. package/dist/src/command-line/graph/graph.js +38 -10
  13. package/dist/src/command-line/init/command-object.js +0 -12
  14. package/dist/src/command-line/init/implementation/add-nx-to-nest.js +21 -62
  15. package/dist/src/command-line/init/init-v2.js +1 -3
  16. package/dist/src/command-line/migrate/agentic/close-agent-session.d.ts +1 -1
  17. package/dist/src/command-line/migrate/agentic/close-agent-session.js +4 -3
  18. package/dist/src/command-line/migrate/agentic/definitions.d.ts +1 -3
  19. package/dist/src/command-line/migrate/agentic/definitions.js +5 -97
  20. package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +7 -45
  21. package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +9 -51
  22. package/dist/src/command-line/migrate/agentic/handoff.d.ts +1 -43
  23. package/dist/src/command-line/migrate/agentic/handoff.js +3 -119
  24. package/dist/src/command-line/migrate/agentic/instruction-files.d.ts +0 -21
  25. package/dist/src/command-line/migrate/agentic/instruction-files.js +6 -27
  26. package/dist/src/command-line/migrate/agentic/master/run-master-session.d.ts +19 -1
  27. package/dist/src/command-line/migrate/agentic/master/run-master-session.js +88 -49
  28. package/dist/src/command-line/migrate/agentic/master/spawn-master.d.ts +1 -0
  29. package/dist/src/command-line/migrate/agentic/master/spawn-master.js +86 -24
  30. package/dist/src/command-line/migrate/agentic/print-dropped-agent-context.d.ts +2 -2
  31. package/dist/src/command-line/migrate/agentic/print-dropped-agent-context.js +2 -2
  32. package/dist/src/command-line/migrate/agentic/prompts/fragments.d.ts +1 -12
  33. package/dist/src/command-line/migrate/agentic/prompts/fragments.js +8 -17
  34. package/dist/src/command-line/migrate/agentic/prompts/shared-rendering.d.ts +0 -15
  35. package/dist/src/command-line/migrate/agentic/prompts/shared-rendering.js +3 -100
  36. package/dist/src/command-line/migrate/agentic/select.d.ts +12 -6
  37. package/dist/src/command-line/migrate/agentic/select.js +38 -8
  38. package/dist/src/command-line/migrate/agentic/types.d.ts +9 -68
  39. package/dist/src/command-line/migrate/agentic/types.js +6 -8
  40. package/dist/src/command-line/migrate/command-object.js +6 -10
  41. package/dist/src/command-line/migrate/execute-migration.d.ts +6 -6
  42. package/dist/src/command-line/migrate/execute-migration.js +25 -15
  43. package/dist/src/command-line/migrate/migrate-analytics.d.ts +18 -1
  44. package/dist/src/command-line/migrate/migrate-analytics.js +38 -0
  45. package/dist/src/command-line/migrate/migrate-commits.d.ts +29 -17
  46. package/dist/src/command-line/migrate/migrate-commits.js +86 -32
  47. package/dist/src/command-line/migrate/migrate-config.d.ts +6 -6
  48. package/dist/src/command-line/migrate/migrate-config.js +12 -6
  49. package/dist/src/command-line/migrate/migrate-output.d.ts +1 -6
  50. package/dist/src/command-line/migrate/migrate-output.js +1 -10
  51. package/dist/src/command-line/migrate/migrate.d.ts +6 -30
  52. package/dist/src/command-line/migrate/migrate.js +257 -255
  53. package/dist/src/command-line/migrate/resolve-package-version.d.ts +2 -4
  54. package/dist/src/command-line/migrate/resolve-package-version.js +2 -35
  55. package/dist/src/command-line/migrate/run/agent-output.d.ts +2 -0
  56. package/dist/src/command-line/migrate/run/agent-output.js +9 -0
  57. package/dist/src/command-line/migrate/run/broker.d.ts +14 -5
  58. package/dist/src/command-line/migrate/run/broker.js +69 -21
  59. package/dist/src/command-line/migrate/run/clean-retry.js +4 -2
  60. package/dist/src/command-line/migrate/run/existing-run-report.d.ts +1 -1
  61. package/dist/src/command-line/migrate/run/existing-run-report.js +7 -5
  62. package/dist/src/command-line/migrate/run/give-up.d.ts +4 -3
  63. package/dist/src/command-line/migrate/run/give-up.js +8 -5
  64. package/dist/src/command-line/migrate/run/index.d.ts +7 -5
  65. package/dist/src/command-line/migrate/run/index.js +16 -1
  66. package/dist/src/command-line/migrate/run/issues.js +7 -2
  67. package/dist/src/command-line/migrate/run/orchestrator.d.ts +61 -4
  68. package/dist/src/command-line/migrate/run/orchestrator.js +397 -133
  69. package/dist/src/command-line/migrate/run/run-state.d.ts +17 -1
  70. package/dist/src/command-line/migrate/run/run-state.js +41 -2
  71. package/dist/src/command-line/migrate/run/runbook.d.ts +1 -0
  72. package/dist/src/command-line/migrate/run/runbook.js +115 -18
  73. package/dist/src/command-line/migrate/run/state-lock.d.ts +29 -4
  74. package/dist/src/command-line/migrate/run/state-lock.js +102 -10
  75. package/dist/src/command-line/migrate/run/state-machine.js +4 -1
  76. package/dist/src/command-line/migrate/run/util.d.ts +7 -2
  77. package/dist/src/command-line/migrate/run/util.js +30 -3
  78. package/dist/src/command-line/migrate/run/worker.d.ts +1 -1
  79. package/dist/src/command-line/migrate/run/worker.js +252 -250
  80. package/dist/src/command-line/migrate/sort-migrations.d.ts +1 -7
  81. package/dist/src/command-line/migrate/sort-migrations.js +1 -12
  82. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +17 -12
  83. package/dist/src/command-line/release/changelog.js +9 -6
  84. package/dist/src/command-line/release/config/config.d.ts +1 -0
  85. package/dist/src/command-line/release/config/config.js +48 -9
  86. package/dist/src/command-line/release/release.js +2 -2
  87. package/dist/src/command-line/release/utils/git.js +8 -7
  88. package/dist/src/command-line/release/utils/interpolate-release-config.d.ts +6 -0
  89. package/dist/src/command-line/release/utils/interpolate-release-config.js +39 -0
  90. package/dist/src/command-line/release/utils/release-graph.d.ts +5 -0
  91. package/dist/src/command-line/release/utils/release-graph.js +1 -0
  92. package/dist/src/command-line/release/utils/remote-release-clients/github.js +5 -6
  93. package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +5 -6
  94. package/dist/src/command-line/release/utils/resolve-changelog-renderer.js +2 -2
  95. package/dist/src/command-line/release/utils/shared.js +10 -10
  96. package/dist/src/command-line/release/utils/version-plan-utils.d.ts +3 -12
  97. package/dist/src/command-line/release/utils/version-plan-utils.js +33 -55
  98. package/dist/src/command-line/release/version/version-actions.js +2 -1
  99. package/dist/src/command-line/release/version.js +5 -2
  100. package/dist/src/command-line/repair/repair.js +1 -1
  101. package/dist/src/command-line/report/report.js +1 -1
  102. package/dist/src/command-line/reset/reset.js +58 -62
  103. package/dist/src/command-line/run/executor-utils.js +1 -0
  104. package/dist/src/command-line/run/run-one.d.ts +20 -1
  105. package/dist/src/command-line/run/run-one.js +153 -5
  106. package/dist/src/command-line/run/run.js +2 -1
  107. package/dist/src/command-line/show/projects.js +5 -3
  108. package/dist/src/command-line/show/show-target/info.d.ts +10 -1
  109. package/dist/src/command-line/show/show-target/info.js +100 -15
  110. package/dist/src/command-line/show/show-target/inputs.js +10 -2
  111. package/dist/src/command-line/show/show-target/utils.js +1 -0
  112. package/dist/src/command-line/watch/command-object.js +3 -22
  113. package/dist/src/command-line/watch/watch.d.ts +0 -7
  114. package/dist/src/command-line/watch/watch.js +1 -1
  115. package/dist/src/command-line/yargs-utils/shared-options.js +1 -1
  116. package/dist/src/config/misc-interfaces.d.ts +18 -0
  117. package/dist/src/config/nx-json.d.ts +22 -11
  118. package/dist/src/config/task-graph.d.ts +1 -1
  119. package/dist/src/config/workspace-json-project-json.d.ts +88 -0
  120. package/dist/src/core/graph/main.js +1 -1
  121. package/dist/src/core/graph/runtime.js +1 -1
  122. package/dist/src/core/graph/styles.css +1 -1
  123. package/dist/src/core/graph/styles.js +1 -1
  124. package/dist/src/daemon/client/client.d.ts +15 -0
  125. package/dist/src/daemon/client/client.js +181 -71
  126. package/dist/src/daemon/client/daemon-socket-messenger.d.ts +1 -1
  127. package/dist/src/daemon/client/daemon-socket-messenger.js +2 -2
  128. package/dist/src/daemon/server/client-socket-context.js +1 -1
  129. package/dist/src/daemon/server/handle-configure-ai-agents.js +2 -2
  130. package/dist/src/daemon/server/handle-process-in-background.js +21 -9
  131. package/dist/src/daemon/server/handle-select-affected-tasks.d.ts +2 -1
  132. package/dist/src/daemon/server/handle-select-affected-tasks.js +21 -13
  133. package/dist/src/daemon/server/native-js-loader.d.ts +1 -0
  134. package/dist/src/daemon/server/native-js-loader.js +21 -0
  135. package/dist/src/daemon/server/nx-console-operations.js +2 -2
  136. package/dist/src/daemon/server/project-graph-incremental-recomputation.js +4 -8
  137. package/dist/src/daemon/server/server.d.ts +2 -1
  138. package/dist/src/daemon/server/server.js +17 -4
  139. package/dist/src/daemon/server/shutdown-utils.js +1 -4
  140. package/dist/src/daemon/server/start.d.ts +1 -0
  141. package/dist/src/daemon/server/start.js +2 -0
  142. package/dist/src/daemon/socket-utils.d.ts +11 -9
  143. package/dist/src/daemon/socket-utils.js +31 -61
  144. package/dist/src/daemon/tmp-dir.d.ts +19 -14
  145. package/dist/src/daemon/tmp-dir.js +142 -354
  146. package/dist/src/devkit-exports.d.ts +9 -1
  147. package/dist/src/devkit-exports.js +12 -1
  148. package/dist/src/devkit-internals.d.ts +6 -5
  149. package/dist/src/devkit-internals.js +13 -4
  150. package/dist/src/executors/run-commands/run-commands.impl.d.ts +4 -2
  151. package/dist/src/executors/run-commands/run-commands.impl.js +53 -27
  152. package/dist/src/executors/run-commands/running-tasks.d.ts +13 -4
  153. package/dist/src/executors/run-commands/running-tasks.js +148 -95
  154. package/dist/src/executors/run-commands/schema.json +1 -1
  155. package/dist/src/hasher/check-task-files.js +5 -8
  156. package/dist/src/hasher/file-hasher.js +9 -7
  157. package/dist/src/hasher/hash-task.js +4 -0
  158. package/dist/src/hasher/native-task-hasher-impl.js +3 -1
  159. package/dist/src/hasher/task-hasher.d.ts +2 -0
  160. package/dist/src/hasher/task-hasher.js +4 -1
  161. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.d.ts +1 -2
  162. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.js +6 -11
  163. package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.md +2 -2
  164. package/dist/src/migrations/update-24-0-0/enable-legacy-affected.d.ts +4 -0
  165. package/dist/src/migrations/update-24-0-0/enable-legacy-affected.js +15 -0
  166. package/dist/src/migrations/update-24-0-0/enable-legacy-affected.md +30 -0
  167. package/dist/src/migrations/update-24-0-0/find-custom-hashers.d.ts +3 -0
  168. package/dist/src/migrations/update-24-0-0/find-custom-hashers.js +100 -0
  169. package/dist/src/migrations/update-24-0-0/find-custom-hashers.md +63 -0
  170. package/dist/src/migrations/update-24-0-0/move-custom-hashers-to-inputs.md +146 -0
  171. package/dist/src/migrations/update-24-0-0/rename-ultracache-ignore-options.d.ts +3 -0
  172. package/dist/src/migrations/update-24-0-0/rename-ultracache-ignore-options.js +130 -0
  173. package/dist/src/migrations/update-24-0-0/rename-ultracache-ignore-options.md +62 -0
  174. package/dist/src/native/assert-supported-platform.js +1 -1
  175. package/dist/src/native/index.d.ts +238 -18
  176. package/dist/src/native/index.js +6 -1
  177. package/dist/src/native/native-bindings.js +15 -6
  178. package/dist/src/native/nx.openharmony-arm64.node +0 -0
  179. package/dist/src/native/nx.wasi-browser.js +1 -0
  180. package/dist/src/native/nx.wasi.cjs +1 -0
  181. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  182. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  183. package/dist/src/nx-cloud/update-manager.d.ts +14 -0
  184. package/dist/src/nx-cloud/update-manager.js +237 -50
  185. package/dist/src/plugins/js/lock-file/pnpm-parser.js +3 -4
  186. package/dist/src/plugins/js/lock-file/pruned-output.d.ts +2 -2
  187. package/dist/src/plugins/js/lock-file/pruned-output.js +4 -4
  188. package/dist/src/plugins/js/utils/register.js +9 -4
  189. package/dist/src/project-graph/affected/affected-tasks.d.ts +9 -6
  190. package/dist/src/project-graph/affected/affected-tasks.js +31 -7
  191. package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +7 -0
  192. package/dist/src/project-graph/plugins/loaded-nx-plugin.js +49 -6
  193. package/dist/src/project-graph/utils/project-configuration/target-merging.js +1 -1
  194. package/dist/src/project-graph/utils/project-configuration/target-normalization.js +12 -133
  195. package/dist/src/project-graph/utils/project-configuration-utils.js +2 -2
  196. package/dist/src/project-graph/utils/retrieve-workspace-files.js +27 -6
  197. package/dist/src/tasks-runner/create-task-graph.d.ts +8 -7
  198. package/dist/src/tasks-runner/create-task-graph.js +50 -27
  199. package/dist/src/tasks-runner/default-tasks-runner.js +1 -1
  200. package/dist/src/tasks-runner/init-tasks-runner.js +116 -59
  201. package/dist/src/tasks-runner/life-cycle.d.ts +4 -1
  202. package/dist/src/tasks-runner/life-cycle.js +7 -0
  203. package/dist/src/tasks-runner/life-cycles/performance-analysis.d.ts +5 -2
  204. package/dist/src/tasks-runner/life-cycles/performance-analysis.js +13 -7
  205. package/dist/src/tasks-runner/life-cycles/performance-life-cycle.d.ts +4 -3
  206. package/dist/src/tasks-runner/life-cycles/performance-life-cycle.js +9 -2
  207. package/dist/src/tasks-runner/life-cycles/static-run-many-terminal-output-life-cycle.js +5 -2
  208. package/dist/src/tasks-runner/life-cycles/static-run-one-terminal-output-life-cycle.js +4 -1
  209. package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.js +5 -1
  210. package/dist/src/tasks-runner/pseudo-ipc.d.ts +1 -0
  211. package/dist/src/tasks-runner/pseudo-ipc.js +4 -0
  212. package/dist/src/tasks-runner/pseudo-terminal.d.ts +1 -1
  213. package/dist/src/tasks-runner/pseudo-terminal.js +2 -2
  214. package/dist/src/tasks-runner/readiness/executor-ready-signal.d.ts +7 -0
  215. package/dist/src/tasks-runner/readiness/executor-ready-signal.js +43 -0
  216. package/dist/src/tasks-runner/readiness/probes.d.ts +14 -0
  217. package/dist/src/tasks-runner/readiness/probes.js +101 -0
  218. package/dist/src/tasks-runner/readiness/ready-signal-server.d.ts +18 -0
  219. package/dist/src/tasks-runner/readiness/ready-signal-server.js +72 -0
  220. package/dist/src/tasks-runner/readiness/ready-signal.d.ts +33 -0
  221. package/dist/src/tasks-runner/readiness/ready-signal.js +92 -0
  222. package/dist/src/tasks-runner/readiness/ready-when.d.ts +84 -0
  223. package/dist/src/tasks-runner/readiness/ready-when.js +371 -0
  224. package/dist/src/tasks-runner/readiness/startup-host.d.ts +1 -0
  225. package/dist/src/tasks-runner/readiness/startup-host.js +32 -0
  226. package/dist/src/tasks-runner/run-command.d.ts +6 -2
  227. package/dist/src/tasks-runner/run-command.js +21 -31
  228. package/dist/src/tasks-runner/run-outcome.d.ts +16 -0
  229. package/dist/src/tasks-runner/run-outcome.js +39 -0
  230. package/dist/src/tasks-runner/running-tasks/batch-process.js +6 -0
  231. package/dist/src/tasks-runner/running-tasks/node-child-process.js +5 -4
  232. package/dist/src/tasks-runner/running-tasks/running-task.d.ts +1 -1
  233. package/dist/src/tasks-runner/task-env.d.ts +10 -0
  234. package/dist/src/tasks-runner/task-env.js +37 -5
  235. package/dist/src/tasks-runner/task-graph-utils.d.ts +9 -6
  236. package/dist/src/tasks-runner/task-graph-utils.js +17 -12
  237. package/dist/src/tasks-runner/task-orchestrator.d.ts +62 -18
  238. package/dist/src/tasks-runner/task-orchestrator.js +750 -150
  239. package/dist/src/tasks-runner/tasks-runner.d.ts +1 -1
  240. package/dist/src/tasks-runner/tasks-schedule.d.ts +18 -1
  241. package/dist/src/tasks-runner/tasks-schedule.js +63 -6
  242. package/dist/src/tasks-runner/tokens.d.ts +54 -0
  243. package/dist/src/tasks-runner/tokens.js +161 -0
  244. package/dist/src/tasks-runner/utils.d.ts +35 -6
  245. package/dist/src/tasks-runner/utils.js +149 -68
  246. package/dist/src/ultracache/ci-status.d.ts +24 -0
  247. package/dist/src/ultracache/ci-status.js +87 -0
  248. package/dist/src/ultracache/config.d.ts +3 -3
  249. package/dist/src/ultracache/config.js +4 -4
  250. package/dist/src/ultracache/fetch.d.ts +2 -0
  251. package/dist/src/ultracache/fetch.js +1 -0
  252. package/dist/src/ultracache/overrides.js +4 -0
  253. package/dist/src/utils/acknowledge-build-scripts.d.ts +34 -1
  254. package/dist/src/utils/acknowledge-build-scripts.js +171 -32
  255. package/dist/src/utils/child-process.js +2 -1
  256. package/dist/src/utils/find-matching-projects.js +9 -6
  257. package/dist/src/utils/git-utils.d.ts +12 -5
  258. package/dist/src/utils/git-utils.js +69 -11
  259. package/dist/src/utils/long-running-target.d.ts +1 -3
  260. package/dist/src/utils/long-running-target.js +1 -3
  261. package/dist/src/utils/nx-package-group.js +1 -1
  262. package/dist/src/utils/output.d.ts +4 -3
  263. package/dist/src/utils/output.js +4 -3
  264. package/dist/src/utils/owned-private-dir.d.ts +1 -17
  265. package/dist/src/utils/owned-private-dir.js +10 -62
  266. package/dist/src/utils/package-json.js +1 -1
  267. package/dist/src/utils/package-manager.d.ts +8 -0
  268. package/dist/src/utils/package-manager.js +65 -8
  269. package/dist/src/utils/perf-hooks.d.ts +1 -0
  270. package/dist/src/utils/plugins/core-plugins.js +5 -1
  271. package/dist/src/utils/progress-topics.d.ts +1 -0
  272. package/dist/src/utils/progress-topics.js +1 -0
  273. package/dist/src/utils/safe-spawn.js +1 -5
  274. package/dist/src/utils/shell-quoting.d.ts +8 -1
  275. package/dist/src/utils/shell-quoting.js +12 -1
  276. package/dist/src/utils/spawn-without-terminal.d.ts +27 -0
  277. package/dist/src/utils/spawn-without-terminal.js +110 -0
  278. package/dist/src/utils/string-similarity.d.ts +38 -0
  279. package/dist/src/utils/string-similarity.js +108 -0
  280. package/dist/src/utils/versions.js +1 -1
  281. package/migrations.json +20 -6
  282. package/package.json +15 -24
  283. package/schemas/migrations-schema.json +11 -0
  284. package/schemas/nx-schema.json +133 -11
  285. package/schemas/project-schema.json +114 -4
  286. package/dist/src/command-line/migrate/agentic/prompts/generic-validation.d.ts +0 -56
  287. package/dist/src/command-line/migrate/agentic/prompts/generic-validation.js +0 -67
  288. package/dist/src/command-line/migrate/agentic/prompts/hybrid-prompt-migration.d.ts +0 -49
  289. package/dist/src/command-line/migrate/agentic/prompts/hybrid-prompt-migration.js +0 -53
  290. package/dist/src/command-line/migrate/agentic/prompts/prompt-migration.d.ts +0 -26
  291. package/dist/src/command-line/migrate/agentic/prompts/prompt-migration.js +0 -27
  292. package/dist/src/command-line/migrate/agentic/prompts/system-prompt.d.ts +0 -70
  293. package/dist/src/command-line/migrate/agentic/prompts/system-prompt.js +0 -113
  294. package/dist/src/command-line/migrate/agentic/run-step.d.ts +0 -68
  295. package/dist/src/command-line/migrate/agentic/run-step.js +0 -148
  296. package/dist/src/command-line/migrate/agentic/runner.d.ts +0 -21
  297. package/dist/src/command-line/migrate/agentic/runner.js +0 -262
  298. package/dist/src/migrations/update-23-0-0/consolidate-release-tag-config.d.ts +0 -9
  299. package/dist/src/migrations/update-23-0-0/consolidate-release-tag-config.js +0 -18
  300. package/dist/src/tasks-runner/legacy-depends-on-warning.d.ts +0 -18
  301. package/dist/src/tasks-runner/legacy-depends-on-warning.js +0 -109
@@ -2,14 +2,22 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DirectoryRefusedError = void 0;
4
4
  exports.describeRefusal = describeRefusal;
5
- exports.remedyFor = remedyFor;
6
5
  exports.canonicalDir = canonicalDir;
7
6
  exports.isSafeSharedRoot = isSafeSharedRoot;
8
- exports.isPeerWritable = isPeerWritable;
9
7
  exports.ensureSafeSharedRoot = ensureSafeSharedRoot;
10
8
  exports.isOwnedRealDirectory = isOwnedRealDirectory;
11
9
  exports.getUserSegment = getUserSegment;
12
10
  exports.ensureOwnedPrivateDir = ensureOwnedPrivateDir;
11
+ /**
12
+ * Directory guards for Nx's runtime state: create a directory only when it is
13
+ * ours and unreachable by other users on this machine.
14
+ *
15
+ * `native/utils/owned_dir.rs` implements the same rules and must change with
16
+ * this file. This copy exists because the native binding loader has to place
17
+ * and lock down the `.node` before Rust can be called, and `cache-directory.ts`,
18
+ * `git-utils.ts` and `nx-tmp-dir.ts` share it. Node builtins only, for the
19
+ * loader's sake.
20
+ */
13
21
  const node_fs_1 = require("node:fs");
14
22
  const node_os_1 = require("node:os");
15
23
  const node_path_1 = require("node:path");
@@ -56,42 +64,6 @@ function describeRefusal(r) {
56
64
  }
57
65
  }
58
66
  }
59
- /** Single-quoted for a shell, so a path with a space or quote survives a paste. */
60
- const shellQuote = (s) => `'${s.replace(/'/g, `'\\''`)}'`;
61
- /** What the user can do about a refusal, or `undefined` when there is nothing. */
62
- function remedyFor(r) {
63
- switch (r.kind) {
64
- case 'not-a-directory':
65
- return r.symlink
66
- ? `${r.dir} is a symlink where Nx expects a directory. If you did not create it, treat it as hostile: remove the link itself (not what it points at) and run the command again.`
67
- : undefined;
68
- case 'foreign-owner':
69
- return `${r.dir} belongs to another user on this machine, so Nx cannot keep its own directory there. Set NX_SOCKET_DIR to a short directory your user owns, or move it aside — which you can do yourself if you own the directory it sits in, and otherwise needs an administrator.`;
70
- case 'not-tightenable':
71
- // Both producers reach here having already established that the directory
72
- // is ours, so `chmod` is the user's to run. Names no cause: one producer
73
- // is a mount that discards the mode, the other is any `chmod` failure.
74
- return `${r.dir} is reachable by other users (mode ${asMode(r.mode)}) and Nx could not restrict it. Run \`chmod 0700 ${shellQuote(r.dir)}\` and try again; if the mode does not stick, set NX_SOCKET_DIR to a short directory on a filesystem that keeps POSIX permissions.`;
75
- case 'foreign-shared-container':
76
- // Unreachable today: `isSafeSharedRoot` denies with this kind only when
77
- // `stats.uid !== 0`, so a root-owned container never reaches here.
78
- if (r.uid === 0) {
79
- return undefined;
80
- }
81
- const q = shellQuote(r.dir);
82
- return `${r.dir} belongs to another user on this machine, so Nx cannot keep a private directory beneath it. Ask an administrator to hand it to root with \`sudo chown root ${q} && sudo chmod 1777 ${q}\`; every user can then keep their own directory under it.`;
83
- case 'not-created':
84
- case 'not-inspectable':
85
- case 'peer-writable-not-sticky':
86
- return undefined;
87
- default: {
88
- // Matches `describeRefusal`'s arm, so a new kind cannot ship with a
89
- // sentence and no advice — which is how `not-tightenable` went unadvised.
90
- const unhandled = r;
91
- return undefined;
92
- }
93
- }
94
- }
95
67
  /** One refusal as an `Error`, so several can travel in an `AggregateError`. */
96
68
  class DirectoryRefusedError extends Error {
97
69
  constructor(refusal) {
@@ -207,30 +179,6 @@ function isSafeSharedRoot(dir) {
207
179
  return deny({ kind: 'not-inspectable', dir, code: e?.code });
208
180
  }
209
181
  }
210
- /**
211
- * Whether other users on this machine can write into `dir`. Gates whether a
212
- * refusal message may cite other users, so it must not over-report: `false` on
213
- * Windows, where libuv synthesizes `st_mode` from the READONLY attribute and
214
- * reports an ordinary per-account directory as `0666`, and `false` on a path
215
- * that cannot be inspected.
216
- *
217
- * `statSync`, not `lstatSync`: the question is about the directory that will be
218
- * used, not the link pointing at it. Link modes mislead in both directions —
219
- * Linux creates symlinks `0777`, macOS applies the umask. Nothing here decides
220
- * whether a path is accepted, so following the link costs nothing the guards
221
- * do not already re-check.
222
- */
223
- function isPeerWritable(dir) {
224
- if (process.platform === 'win32') {
225
- return false;
226
- }
227
- try {
228
- return !!((0, node_fs_1.statSync)(dir).mode & 0o022);
229
- }
230
- catch {
231
- return false;
232
- }
233
- }
234
182
  /**
235
183
  * Create a shared container as sticky + world-writable if it does not exist,
236
184
  * and report whether the resulting path is safe for the current user.
@@ -231,7 +231,7 @@ function readModulePackageJson(moduleSpecifier, requirePaths = (0, installation_
231
231
  * path instead of the workspace path.
232
232
  *
233
233
  * 2. Package self-reference. When a file inside package `nx` calls
234
- * `require.resolve('@ohos-ports/nx/...')`, Node returns that calling package's
234
+ * `require.resolve('nx/...')`, Node returns that calling package's
235
235
  * own file regardless of `paths`. We avoid that by issuing the
236
236
  * resolve from a `createRequire` rooted at a synthetic path that is
237
237
  * outside any package, so the resolver has no "self" to reference
@@ -13,7 +13,15 @@ export interface PackageManagerCommands {
13
13
  why: string;
14
14
  run: (script: string, args?: string) => string;
15
15
  getRegistryUrl?: string;
16
+ /**
17
+ * @deprecated Use `publishArgv` instead, which needs no shell off Windows.
18
+ * This will be removed in Nx 25.
19
+ */
16
20
  publish: (packageRoot: string, registry: string, registryConfigKey: string, tag: string) => string;
21
+ publishArgv: (packageRoot: string, registry: string, registryConfigKey: string, tag: string) => {
22
+ command: string;
23
+ args: string[];
24
+ };
17
25
  ignoreScriptsFlag?: string;
18
26
  }
19
27
  /**
@@ -23,6 +23,7 @@ exports.addPackagePathToWorkspaces = addPackagePathToWorkspaces;
23
23
  const child_process_1 = require("child_process");
24
24
  const fs_1 = require("fs");
25
25
  const promises_1 = require("node:fs/promises");
26
+ const node_os_1 = require("node:os");
26
27
  const path_1 = require("path");
27
28
  const semver_1 = require("semver");
28
29
  const tmp_1 = require("tmp");
@@ -124,6 +125,13 @@ function isWorkspacesEnabled(packageManager = detectPackageManager(), root = wor
124
125
  const packageJson = (0, file_utils_1.readPackageJson)(root);
125
126
  return !!packageJson?.workspaces;
126
127
  }
128
+ /**
129
+ * The registry and tag reach `publish` from `.npmrc`, which an install script
130
+ * can write, so every token is quoted before it becomes shell syntax.
131
+ */
132
+ function publishCommandFromArgv({ command, args, }) {
133
+ return [command, ...args].map(shell_quoting_1.quoteShellArg).join(' ');
134
+ }
127
135
  /**
128
136
  * Returns commands for the package manager used in the workspace.
129
137
  * By default, the package manager is derived based on the lock file,
@@ -150,6 +158,16 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
150
158
  yarnVersion = 'latest';
151
159
  useBerry = true;
152
160
  }
161
+ const publishArgv = (packageRoot, registry, registryConfigKey, tag) => ({
162
+ command: 'npm',
163
+ args: [
164
+ 'publish',
165
+ packageRoot,
166
+ '--json',
167
+ `--${registryConfigKey}=${registry}`,
168
+ `--tag=${tag}`,
169
+ ],
170
+ });
153
171
  // new versions of yarn only support ignoring scripts via .yarnrc.yml
154
172
  return {
155
173
  preInstall: `yarn set version ${yarnVersion}`,
@@ -171,7 +189,8 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
171
189
  getRegistryUrl: useBerry
172
190
  ? 'yarn config get npmRegistryServer'
173
191
  : 'yarn config get registry',
174
- publish: (packageRoot, registry, registryConfigKey, tag) => `npm publish "${packageRoot}" --json --"${registryConfigKey}=${registry}" --tag=${tag}`,
192
+ publish: (...args) => publishCommandFromArgv(publishArgv(...args)),
193
+ publishArgv,
175
194
  ignoreScriptsFlag: useBerry ? undefined : `--ignore-scripts`,
176
195
  };
177
196
  },
@@ -194,6 +213,21 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
194
213
  scopedForm = false;
195
214
  }
196
215
  const isPnpmWorkspace = (0, fs_1.existsSync)((0, path_1.join)(root, 'pnpm-workspace.yaml'));
216
+ const publishArgv = (packageRoot, registry, registryConfigKey, tag) => ({
217
+ command: 'pnpm',
218
+ args: [
219
+ 'publish',
220
+ packageRoot,
221
+ '--json',
222
+ `--${configForm
223
+ ? `config.${registryConfigKey}`
224
+ : scopedForm
225
+ ? registryConfigKey
226
+ : 'registry'}=${registry}`,
227
+ `--tag=${tag}`,
228
+ '--no-git-checks',
229
+ ],
230
+ });
197
231
  return {
198
232
  install: 'pnpm install --no-frozen-lockfile', // explicitly disable in case of CI
199
233
  ciInstall: 'pnpm install --frozen-lockfile',
@@ -215,15 +249,22 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
215
249
  list: 'pnpm ls --depth 100',
216
250
  why: 'pnpm why',
217
251
  getRegistryUrl: 'pnpm config get registry',
218
- publish: (packageRoot, registry, registryConfigKey, tag) => `pnpm publish "${packageRoot}" --json --"${configForm
219
- ? `config.${registryConfigKey}`
220
- : scopedForm
221
- ? registryConfigKey
222
- : 'registry'}=${registry}" --tag=${tag} --no-git-checks`,
252
+ publish: (...args) => publishCommandFromArgv(publishArgv(...args)),
253
+ publishArgv,
223
254
  ignoreScriptsFlag: '--ignore-scripts',
224
255
  };
225
256
  },
226
257
  npm: () => {
258
+ const publishArgv = (packageRoot, registry, registryConfigKey, tag) => ({
259
+ command: 'npm',
260
+ args: [
261
+ 'publish',
262
+ packageRoot,
263
+ '--json',
264
+ `--${registryConfigKey}=${registry}`,
265
+ `--tag=${tag}`,
266
+ ],
267
+ });
227
268
  return {
228
269
  install: 'npm install',
229
270
  ciInstall: 'npm ci',
@@ -237,11 +278,22 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
237
278
  list: 'npm ls',
238
279
  why: 'npm explain',
239
280
  getRegistryUrl: 'npm config get registry',
240
- publish: (packageRoot, registry, registryConfigKey, tag) => `npm publish "${packageRoot}" --json --"${registryConfigKey}=${registry}" --tag=${tag}`,
281
+ publish: (...args) => publishCommandFromArgv(publishArgv(...args)),
282
+ publishArgv,
241
283
  ignoreScriptsFlag: '--ignore-scripts',
242
284
  };
243
285
  },
244
286
  bun: () => {
287
+ const publishArgv = (packageRoot, registry, _registryConfigKey, tag) => ({
288
+ command: 'bun',
289
+ args: [
290
+ 'publish',
291
+ `--cwd=${packageRoot}`,
292
+ '--json',
293
+ `--registry=${registry}`,
294
+ `--tag=${tag}`,
295
+ ],
296
+ });
245
297
  // bun doesn't current support programmatically reading config https://github.com/oven-sh/bun/issues/7140
246
298
  return {
247
299
  install: 'bun install',
@@ -256,7 +308,8 @@ function getPackageManagerCommand(packageManager = detectPackageManager(), root
256
308
  list: 'bun pm ls',
257
309
  why: 'bun why',
258
310
  // Unlike npm, bun publish does not support a custom registryConfigKey option
259
- publish: (packageRoot, registry, registryConfigKey, tag) => `bun publish --cwd="${packageRoot}" --json --registry="${registry}" --tag=${tag}`,
311
+ publish: (...args) => publishCommandFromArgv(publishArgv(...args)),
312
+ publishArgv,
260
313
  ignoreScriptsFlag: '--ignore-scripts',
261
314
  };
262
315
  },
@@ -283,6 +336,10 @@ function getPackageManagerVersion(packageManager = detectPackageManager(), cwd =
283
336
  cwd,
284
337
  encoding: 'utf-8',
285
338
  windowsHide: true,
339
+ // Store discovery creates temporary workspace files even for --version.
340
+ env: packageManager === 'pnpm'
341
+ ? { ...process.env, PNPM_CONFIG_STORE_DIR: (0, node_os_1.tmpdir)() }
342
+ : undefined,
286
343
  }).trim();
287
344
  }
288
345
  catch { }
@@ -1,3 +1,4 @@
1
+ // tsc doesn't emit hand-written .d.ts files; assets.json copies this one into dist.
1
2
  import type { EventParameters } from '../analytics/analytics';
2
3
 
3
4
  export interface TrackedDetail extends EventParameters {
@@ -80,7 +80,11 @@ exports.CORE_PLUGINS = [
80
80
  },
81
81
  {
82
82
  name: '@nx/remix',
83
- capabilities: 'executors,generators',
83
+ capabilities: 'generators',
84
+ },
85
+ {
86
+ name: '@nx/rolldown',
87
+ capabilities: 'generators',
84
88
  },
85
89
  {
86
90
  name: '@nx/rollup',
@@ -15,5 +15,6 @@
15
15
  */
16
16
  export declare const ProgressTopics: {
17
17
  readonly GraphConstruction: 'graph-construction';
18
+ readonly AffectedTasks: 'affected-tasks';
18
19
  };
19
20
  export type ProgressTopic = (typeof ProgressTopics)[keyof typeof ProgressTopics];
@@ -18,4 +18,5 @@ exports.ProgressTopics = void 0;
18
18
  */
19
19
  exports.ProgressTopics = {
20
20
  GraphConstruction: 'graph-construction',
21
+ AffectedTasks: 'affected-tasks',
21
22
  };
@@ -25,9 +25,6 @@ function needsShell(binary) {
25
25
  const ext = path_1.win32.extname(binary).toLowerCase();
26
26
  return ext === '' || ext === '.cmd' || ext === '.bat';
27
27
  }
28
- // A line break ends the command line whatever the quoting, so nothing can carry
29
- // one.
30
- //
31
28
  // `%` is deliberately NOT refused, and this is a known gap rather than a safe
32
29
  // case. cmd.exe expands `%VAR%` whether or not the value is quoted — see
33
30
  // `quoteShellArg`'s own docstring in ./shell-quoting, which says so and pins it
@@ -42,7 +39,6 @@ function needsShell(binary) {
42
39
  // is bounded by the argument that bounds this whole class: a repo that can reach
43
40
  // here already has `mvnw` / `pom.xml` executing on its behalf. Closing it
44
41
  // properly is tracked as NXC-4798.
45
- const LINE_BREAK = /[\r\n]/;
46
42
  /**
47
43
  * Spawn a binary that may be a Windows `.cmd`/`.bat` shim, without letting its
48
44
  * arguments become shell syntax.
@@ -91,7 +87,7 @@ function quoteBinary(binary, shell) {
91
87
  return quoteForCmd(binary, `the path ${JSON.stringify(binary)}`);
92
88
  }
93
89
  function quoteForCmd(value, described, remedy = '') {
94
- if (LINE_BREAK.test(value)) {
90
+ if (shell_quoting_1.LINE_BREAK.test(value)) {
95
91
  throw new Error(`Cannot pass ${described} to cmd.exe: a line break inside it would end the command line before cmd.exe reached the rest of it.${remedy}`);
96
92
  }
97
93
  return (0, shell_quoting_1.quoteShellArg)(value);
@@ -1,3 +1,9 @@
1
+ /**
2
+ * A line break ends a cmd.exe command line whatever the quoting, so no quoted
3
+ * run can carry one. POSIX single quotes hold a newline fine, which is why the
4
+ * refusal in `quoteShellArg` is Windows-only.
5
+ */
6
+ export declare const LINE_BREAK: RegExp;
1
7
  /**
2
8
  * Check if a string contains shell metacharacters that require quoting.
3
9
  * These characters have special meaning in shell and would be interpreted
@@ -20,6 +26,7 @@ export declare function isAlreadyQuoted(str: string): boolean;
20
26
  * @throws on Windows when the argument contains a double quote, which ends that
21
27
  * run, since cmd.exe recognizes no backslash escape. Carrying one means
22
28
  * caret-escaping every metacharacter instead, doubled for a `.cmd` shim, which
23
- * this path does not implement.
29
+ * this path does not implement. Also throws on a line break, which ends the
30
+ * command line itself and so survives no quoting at all.
24
31
  */
25
32
  export declare function quoteShellArg(arg: string): string;
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LINE_BREAK = void 0;
3
4
  exports.needsShellQuoting = needsShellQuoting;
4
5
  exports.isAlreadyQuoted = isAlreadyQuoted;
5
6
  exports.quoteShellArg = quoteShellArg;
@@ -24,6 +25,12 @@ exports.quoteShellArg = quoteShellArg;
24
25
  * - \s - whitespace (spaces, tabs, newlines)
25
26
  */
26
27
  const SHELL_META_CHARS = /[|&;<>()$`\\!"'*?[\]{}~#\s]/;
28
+ /**
29
+ * A line break ends a cmd.exe command line whatever the quoting, so no quoted
30
+ * run can carry one. POSIX single quotes hold a newline fine, which is why the
31
+ * refusal in `quoteShellArg` is Windows-only.
32
+ */
33
+ exports.LINE_BREAK = /[\r\n]/;
27
34
  /**
28
35
  * Check if a string contains shell metacharacters that require quoting.
29
36
  * These characters have special meaning in shell and would be interpreted
@@ -52,10 +59,14 @@ function isAlreadyQuoted(str) {
52
59
  * @throws on Windows when the argument contains a double quote, which ends that
53
60
  * run, since cmd.exe recognizes no backslash escape. Carrying one means
54
61
  * caret-escaping every metacharacter instead, doubled for a `.cmd` shim, which
55
- * this path does not implement.
62
+ * this path does not implement. Also throws on a line break, which ends the
63
+ * command line itself and so survives no quoting at all.
56
64
  */
57
65
  function quoteShellArg(arg) {
58
66
  const isWindows = process.platform === 'win32';
67
+ if (isWindows && exports.LINE_BREAK.test(arg)) {
68
+ throw new Error(`Cannot safely pass ${arg} to cmd.exe as a single argument: a line break inside it would end the command line and leave the rest of the argument to be read as commands. Remove the line break and run the command again.`);
69
+ }
59
70
  if (isWindows && arg.includes('"')) {
60
71
  throw new Error(`Cannot safely pass ${arg} to cmd.exe as a single argument: a double quote inside it would end the quoting and leave the rest of the argument to be read as commands. Remove the double quote and run the command again.`);
61
72
  }
@@ -0,0 +1,27 @@
1
+ import { type ChildProcess, type SpawnOptions } from 'child_process';
2
+ /**
3
+ * Runs `command` in a shell that cannot reach the terminal nx shares with
4
+ * another program, so a prompt fails instead of waiting for keys that program
5
+ * reads. On POSIX the shell leads a new session with no controlling terminal,
6
+ * and loses every environment variable that names nx's terminal. Windows
7
+ * spawns it as usual, and with no stdio inherited it gets no console, so the
8
+ * terminal's Ctrl+C misses it there too. Whoever shares the terminal forwards
9
+ * signals with `signalCommandsWithoutTerminal`, and an nx that exits first
10
+ * kills each command whose output is still open.
11
+ */
12
+ export declare function spawnWithoutTerminal(command: string, options: Omit<SpawnOptions, 'shell' | 'detached'>): ChildProcess;
13
+ /**
14
+ * Sends `signal` to every command started by `spawnWithoutTerminal` whose
15
+ * output is still open: to its process group on POSIX, and on a SIGKILL also to
16
+ * the processes still descending from its shell, since a parent killed outright
17
+ * cannot stop the ones it started in groups of their own. Windows has no
18
+ * process groups, so there those descendants are terminated, whatever the
19
+ * signal.
20
+ */
21
+ export declare function signalCommandsWithoutTerminal(signal: NodeJS.Signals): void;
22
+ /**
23
+ * `env` without the variables whose value is the path of one of `terminals`
24
+ * (device ids). A process outside the new session, such as gpg-agent reading
25
+ * `GPG_TTY`, would otherwise open that terminal itself.
26
+ */
27
+ export declare function withoutTerminalPaths(env: NodeJS.ProcessEnv, terminals: ReadonlySet<number>): NodeJS.ProcessEnv;
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.spawnWithoutTerminal = spawnWithoutTerminal;
4
+ exports.signalCommandsWithoutTerminal = signalCommandsWithoutTerminal;
5
+ exports.withoutTerminalPaths = withoutTerminalPaths;
6
+ const child_process_1 = require("child_process");
7
+ const fs_1 = require("fs");
8
+ const tty_1 = require("tty");
9
+ // The commands spawned below whose output is still open, by pid. On POSIX each
10
+ // one leads its own process group.
11
+ const commands = new Map();
12
+ /**
13
+ * Runs `command` in a shell that cannot reach the terminal nx shares with
14
+ * another program, so a prompt fails instead of waiting for keys that program
15
+ * reads. On POSIX the shell leads a new session with no controlling terminal,
16
+ * and loses every environment variable that names nx's terminal. Windows
17
+ * spawns it as usual, and with no stdio inherited it gets no console, so the
18
+ * terminal's Ctrl+C misses it there too. Whoever shares the terminal forwards
19
+ * signals with `signalCommandsWithoutTerminal`, and an nx that exits first
20
+ * kills each command whose output is still open.
21
+ */
22
+ function spawnWithoutTerminal(command, options) {
23
+ const child = (0, child_process_1.spawn)(command, {
24
+ ...options,
25
+ shell: true,
26
+ windowsHide: true,
27
+ detached: process.platform !== 'win32',
28
+ ...(process.platform !== 'win32' && {
29
+ env: withoutTerminalPaths(options.env ?? process.env, stdioTerminals()),
30
+ }),
31
+ });
32
+ const pid = child.pid;
33
+ if (pid !== undefined) {
34
+ if (commands.size === 0)
35
+ process.on('exit', killCommands);
36
+ commands.set(pid, child);
37
+ child.once('close', () => {
38
+ commands.delete(pid);
39
+ if (commands.size === 0)
40
+ process.removeListener('exit', killCommands);
41
+ });
42
+ }
43
+ return child;
44
+ }
45
+ /**
46
+ * Sends `signal` to every command started by `spawnWithoutTerminal` whose
47
+ * output is still open: to its process group on POSIX, and on a SIGKILL also to
48
+ * the processes still descending from its shell, since a parent killed outright
49
+ * cannot stop the ones it started in groups of their own. Windows has no
50
+ * process groups, so there those descendants are terminated, whatever the
51
+ * signal.
52
+ */
53
+ function signalCommandsWithoutTerminal(signal) {
54
+ for (const [pid, child] of commands) {
55
+ // Tree first: killing the group reparents its members' children.
56
+ if (process.platform === 'win32' || signal === 'SIGKILL') {
57
+ killTree(child, pid, signal);
58
+ }
59
+ if (process.platform !== 'win32') {
60
+ try {
61
+ process.kill(-pid, signal);
62
+ }
63
+ catch {
64
+ // The command already ended; its `close` is on the way.
65
+ }
66
+ }
67
+ }
68
+ }
69
+ // Only while the shell lives: once it has exited, its pid can be reused.
70
+ function killTree(child, pid, signal) {
71
+ if (child.exitCode !== null || child.signalCode !== null)
72
+ return;
73
+ try {
74
+ const { killProcessTree } = require('../native');
75
+ killProcessTree(pid, signal);
76
+ }
77
+ catch {
78
+ // No native killer in this build; on POSIX the group signal still goes out.
79
+ }
80
+ }
81
+ function killCommands() {
82
+ signalCommandsWithoutTerminal('SIGKILL');
83
+ }
84
+ function stdioTerminals() {
85
+ const devices = new Set();
86
+ for (const fd of [0, 1, 2]) {
87
+ if ((0, tty_1.isatty)(fd))
88
+ devices.add((0, fs_1.fstatSync)(fd).rdev);
89
+ }
90
+ return devices;
91
+ }
92
+ /**
93
+ * `env` without the variables whose value is the path of one of `terminals`
94
+ * (device ids). A process outside the new session, such as gpg-agent reading
95
+ * `GPG_TTY`, would otherwise open that terminal itself.
96
+ */
97
+ function withoutTerminalPaths(env, terminals) {
98
+ return Object.fromEntries(Object.entries(env).filter(([, value]) => !namesTerminal(value, terminals)));
99
+ }
100
+ function namesTerminal(value, terminals) {
101
+ if (!value?.startsWith('/dev/'))
102
+ return false;
103
+ try {
104
+ const stat = (0, fs_1.statSync)(value);
105
+ return stat.isCharacterDevice() && terminals.has(stat.rdev);
106
+ }
107
+ catch {
108
+ return false;
109
+ }
110
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Computes the Levenshtein edit distance between two strings, i.e. the minimum
3
+ * number of single-character insertions, deletions, or substitutions required
4
+ * to turn `a` into `b`.
5
+ */
6
+ export declare function levenshteinDistance(a: string, b: string): number;
7
+ /**
8
+ * Ranks every candidate by how closely it resembles `input`, from closest to
9
+ * furthest, tie-broken alphabetically so the order is deterministic. Each entry
10
+ * keeps its computed distance so callers can reuse it (e.g. to both pick the
11
+ * closest match and order a list) without recomputing.
12
+ */
13
+ export declare function rankByDistance(input: string, candidates: readonly string[]): {
14
+ candidate: string;
15
+ distance: number;
16
+ }[];
17
+ /**
18
+ * Whether a candidate at edit `distance` from `input` is close enough to be a
19
+ * useful suggestion. Exposed so callers that already have a distance (e.g. from
20
+ * `rankByDistance`) can gate on it without recomputing.
21
+ */
22
+ export declare function isWithinSuggestionThreshold(input: string, candidate: string, distance: number): boolean;
23
+ /**
24
+ * Ranks the candidates that are similar enough to `input` to be worth
25
+ * suggesting, closest first (ties broken alphabetically). Each entry keeps its
26
+ * distance so callers can compare suggestions found for different forms of the
27
+ * same input without recomputing.
28
+ */
29
+ export declare function rankSuggestions(input: string, candidates: readonly string[]): {
30
+ candidate: string;
31
+ distance: number;
32
+ }[];
33
+ /**
34
+ * Returns up to `limit` candidates that most closely resemble `input`, sorted
35
+ * from closest to furthest. Candidates that are not similar enough to be a
36
+ * useful suggestion are excluded.
37
+ */
38
+ export declare function findClosestMatches(input: string, candidates: readonly string[], limit?: number): string[];
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.levenshteinDistance = levenshteinDistance;
4
+ exports.rankByDistance = rankByDistance;
5
+ exports.isWithinSuggestionThreshold = isWithinSuggestionThreshold;
6
+ exports.rankSuggestions = rankSuggestions;
7
+ exports.findClosestMatches = findClosestMatches;
8
+ /**
9
+ * Computes the Levenshtein edit distance between two strings, i.e. the minimum
10
+ * number of single-character insertions, deletions, or substitutions required
11
+ * to turn `a` into `b`.
12
+ */
13
+ function levenshteinDistance(a, b) {
14
+ if (a === b) {
15
+ return 0;
16
+ }
17
+ if (a.length === 0) {
18
+ return b.length;
19
+ }
20
+ if (b.length === 0) {
21
+ return a.length;
22
+ }
23
+ let previousRow = Array.from({ length: b.length + 1 }, (_, i) => i);
24
+ let currentRow = new Array(b.length + 1);
25
+ for (let i = 0; i < a.length; i++) {
26
+ currentRow[0] = i + 1;
27
+ for (let j = 0; j < b.length; j++) {
28
+ const cost = a[i] === b[j] ? 0 : 1;
29
+ currentRow[j + 1] = Math.min(currentRow[j] + 1, // insertion
30
+ previousRow[j + 1] + 1, // deletion
31
+ previousRow[j] + cost // substitution
32
+ );
33
+ }
34
+ [previousRow, currentRow] = [currentRow, previousRow];
35
+ }
36
+ return previousRow[b.length];
37
+ }
38
+ /**
39
+ * Ranks every candidate by how closely it resembles `input`, from closest to
40
+ * furthest, tie-broken alphabetically so the order is deterministic. Each entry
41
+ * keeps its computed distance so callers can reuse it (e.g. to both pick the
42
+ * closest match and order a list) without recomputing.
43
+ */
44
+ function rankByDistance(input, candidates) {
45
+ return candidates
46
+ .map((candidate) => ({
47
+ candidate,
48
+ distance: levenshteinDistance(input, candidate),
49
+ }))
50
+ .sort((a, b) => a.distance - b.distance || a.candidate.localeCompare(b.candidate));
51
+ }
52
+ /**
53
+ * The number of edits tolerated before `candidate` stops being a useful
54
+ * suggestion for `input`.
55
+ *
56
+ * The tolerance scales with length so longer words allow for more typos, but it
57
+ * scales with the length of the part that actually *differs* — the shared
58
+ * prefix and suffix are stripped first. Scaling on the raw length lets text the
59
+ * user typed correctly buy a bigger budget for the part they got wrong, which
60
+ * matters because these inputs are joined `project:target[:configuration]`
61
+ * specifiers: `zzz:build` and `api:build` are 3 edits apart, but the shared
62
+ * `:build` inflates the raw-length budget to 4 and a project name with no
63
+ * character in common gets suggested.
64
+ *
65
+ * Stripping a common prefix and suffix does not change the Levenshtein
66
+ * distance, so a caller's precomputed `distance` remains directly comparable.
67
+ */
68
+ function suggestionThreshold(input, candidate) {
69
+ const shortest = Math.min(input.length, candidate.length);
70
+ let prefix = 0;
71
+ while (prefix < shortest && input[prefix] === candidate[prefix]) {
72
+ prefix++;
73
+ }
74
+ let suffix = 0;
75
+ while (suffix < shortest - prefix &&
76
+ input[input.length - 1 - suffix] ===
77
+ candidate[candidate.length - 1 - suffix]) {
78
+ suffix++;
79
+ }
80
+ return Math.max(2, Math.ceil((input.length - prefix - suffix) * 0.4));
81
+ }
82
+ /**
83
+ * Whether a candidate at edit `distance` from `input` is close enough to be a
84
+ * useful suggestion. Exposed so callers that already have a distance (e.g. from
85
+ * `rankByDistance`) can gate on it without recomputing.
86
+ */
87
+ function isWithinSuggestionThreshold(input, candidate, distance) {
88
+ return distance <= suggestionThreshold(input, candidate);
89
+ }
90
+ /**
91
+ * Ranks the candidates that are similar enough to `input` to be worth
92
+ * suggesting, closest first (ties broken alphabetically). Each entry keeps its
93
+ * distance so callers can compare suggestions found for different forms of the
94
+ * same input without recomputing.
95
+ */
96
+ function rankSuggestions(input, candidates) {
97
+ return rankByDistance(input, candidates).filter(({ candidate, distance }) => isWithinSuggestionThreshold(input, candidate, distance));
98
+ }
99
+ /**
100
+ * Returns up to `limit` candidates that most closely resemble `input`, sorted
101
+ * from closest to furthest. Candidates that are not similar enough to be a
102
+ * useful suggestion are excluded.
103
+ */
104
+ function findClosestMatches(input, candidates, limit = 3) {
105
+ return rankSuggestions(input, candidates)
106
+ .slice(0, limit)
107
+ .map(({ candidate }) => candidate);
108
+ }