nx 23.2.1 → 23.3.0-beta.1

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 (149) hide show
  1. package/dist/src/command-line/format/format.js +2 -18
  2. package/dist/src/command-line/graph/graph.js +42 -3
  3. package/dist/src/command-line/init/implementation/format.js +2 -3
  4. package/dist/src/command-line/migrate/agentic/definitions.js +75 -19
  5. package/dist/src/command-line/migrate/agentic/format-command.d.ts +14 -0
  6. package/dist/src/command-line/migrate/agentic/format-command.js +44 -0
  7. package/dist/src/command-line/migrate/agentic/handoff-gitignore.d.ts +3 -3
  8. package/dist/src/command-line/migrate/agentic/handoff-gitignore.js +3 -3
  9. package/dist/src/command-line/migrate/agentic/handoff.d.ts +27 -17
  10. package/dist/src/command-line/migrate/agentic/handoff.js +107 -24
  11. package/dist/src/command-line/migrate/agentic/instruction-files.d.ts +21 -0
  12. package/dist/src/command-line/migrate/agentic/instruction-files.js +36 -0
  13. package/dist/src/command-line/migrate/agentic/prompts/fragments.d.ts +16 -0
  14. package/dist/src/command-line/migrate/agentic/prompts/fragments.js +70 -0
  15. package/dist/src/command-line/migrate/agentic/prompts/generic-validation.js +4 -3
  16. package/dist/src/command-line/migrate/agentic/prompts/system-prompt.d.ts +25 -1
  17. package/dist/src/command-line/migrate/agentic/prompts/system-prompt.js +57 -34
  18. package/dist/src/command-line/migrate/agentic/run-step.js +28 -4
  19. package/dist/src/command-line/migrate/agentic/runner.d.ts +17 -8
  20. package/dist/src/command-line/migrate/agentic/runner.js +110 -55
  21. package/dist/src/command-line/migrate/agentic/types.d.ts +23 -8
  22. package/dist/src/command-line/migrate/agentic/types.js +10 -7
  23. package/dist/src/command-line/migrate/migrate-commits.d.ts +1 -0
  24. package/dist/src/command-line/migrate/migrate-commits.js +9 -0
  25. package/dist/src/command-line/migrate/migrate-output.d.ts +3 -7
  26. package/dist/src/command-line/migrate/migrate-output.js +3 -7
  27. package/dist/src/command-line/migrate/migrate.js +21 -8
  28. package/dist/src/command-line/migrate/run/agent-output.d.ts +10 -0
  29. package/dist/src/command-line/migrate/run/agent-output.js +16 -2
  30. package/dist/src/command-line/migrate/run/agent-work-payload.d.ts +37 -0
  31. package/dist/src/command-line/migrate/run/agent-work-payload.js +142 -0
  32. package/dist/src/command-line/migrate/run/atomic-write.d.ts +8 -0
  33. package/dist/src/command-line/migrate/run/atomic-write.js +17 -0
  34. package/dist/src/command-line/migrate/run/index.d.ts +1 -1
  35. package/dist/src/command-line/migrate/run/issues.d.ts +106 -0
  36. package/dist/src/command-line/migrate/run/issues.js +980 -0
  37. package/dist/src/command-line/migrate/run/orchestrator.d.ts +1 -0
  38. package/dist/src/command-line/migrate/run/orchestrator.js +662 -105
  39. package/dist/src/command-line/migrate/run/run-state.d.ts +43 -8
  40. package/dist/src/command-line/migrate/run/run-state.js +184 -20
  41. package/dist/src/command-line/migrate/run/runbook.d.ts +17 -0
  42. package/dist/src/command-line/migrate/run/runbook.js +97 -0
  43. package/dist/src/command-line/migrate/run/state-lock.d.ts +2 -2
  44. package/dist/src/command-line/migrate/run/state-lock.js +2 -2
  45. package/dist/src/command-line/migrate/run/state-machine.d.ts +5 -1
  46. package/dist/src/command-line/migrate/run/state-machine.js +27 -1
  47. package/dist/src/command-line/migrate/run/worker.js +206 -56
  48. package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +5 -1
  49. package/dist/src/command-line/release/publish.js +11 -4
  50. package/dist/src/command-line/release/utils/remote-release-clients/github.js +3 -3
  51. package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +3 -3
  52. package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.d.ts +2 -0
  53. package/dist/src/command-line/release/utils/remote-release-clients/remote-release-client.js +35 -0
  54. package/dist/src/command-line/yargs-utils/shared-options.d.ts +1 -1
  55. package/dist/src/command-line/yargs-utils/shared-options.js +22 -4
  56. package/dist/src/config/workspace-json-project-json.d.ts +2 -0
  57. package/dist/src/core/graph/main.js +1 -1
  58. package/dist/src/daemon/client/client.d.ts +4 -2
  59. package/dist/src/daemon/client/client.js +20 -11
  60. package/dist/src/daemon/message-types/run-tasks-execution-hooks.d.ts +3 -2
  61. package/dist/src/daemon/server/handle-hash-tasks.d.ts +8 -2
  62. package/dist/src/daemon/server/handle-hash-tasks.js +16 -3
  63. package/dist/src/daemon/server/handle-outputs-changes.d.ts +2 -2
  64. package/dist/src/daemon/server/handle-outputs-changes.js +21 -6
  65. package/dist/src/daemon/server/handle-tasks-execution-hooks.d.ts +3 -2
  66. package/dist/src/daemon/server/outputs-tracking.d.ts +6 -0
  67. package/dist/src/daemon/server/outputs-tracking.js +18 -0
  68. package/dist/src/daemon/server/project-graph-incremental-recomputation.d.ts +22 -7
  69. package/dist/src/daemon/server/project-graph-incremental-recomputation.js +99 -69
  70. package/dist/src/daemon/server/restart-checks.d.ts +22 -0
  71. package/dist/src/daemon/server/restart-checks.js +77 -0
  72. package/dist/src/daemon/server/server.js +28 -18
  73. package/dist/src/daemon/server/shutdown-utils.d.ts +0 -5
  74. package/dist/src/daemon/server/shutdown-utils.js +3 -26
  75. package/dist/src/hasher/hash-task.js +20 -16
  76. package/dist/src/hasher/native-task-hasher-impl.d.ts +8 -0
  77. package/dist/src/hasher/native-task-hasher-impl.js +46 -3
  78. package/dist/src/hasher/task-hasher.d.ts +9 -0
  79. package/dist/src/hasher/task-hasher.js +14 -0
  80. package/dist/src/native/index.d.ts +202 -21
  81. package/dist/src/native/index.js +3 -3
  82. package/dist/src/native/native-bindings.js +3 -1
  83. package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
  84. package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
  85. package/dist/src/plugins/js/lock-file/pnpm-parser.js +1 -1
  86. package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.d.ts +2 -0
  87. package/dist/src/plugins/js/lock-file/utils/pnpm-normalizer.js +22 -0
  88. package/dist/src/plugins/js/utils/register.js +2 -1
  89. package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +2 -1
  90. package/dist/src/project-graph/plugins/isolation/messaging.d.ts +3 -2
  91. package/dist/src/project-graph/plugins/isolation/plugin-worker.js +5 -1
  92. package/dist/src/project-graph/plugins/loaded-nx-plugin.d.ts +3 -2
  93. package/dist/src/project-graph/plugins/loaded-nx-plugin.js +5 -1
  94. package/dist/src/project-graph/plugins/task-results-stub.d.ts +50 -0
  95. package/dist/src/project-graph/plugins/task-results-stub.js +111 -0
  96. package/dist/src/project-graph/plugins/tasks-execution-hooks.d.ts +3 -2
  97. package/dist/src/project-graph/plugins/tasks-execution-hooks.js +2 -1
  98. package/dist/src/project-graph/project-graph.js +2 -0
  99. package/dist/src/tasks-runner/batch/run-batch.js +15 -0
  100. package/dist/src/tasks-runner/cache.d.ts +35 -0
  101. package/dist/src/tasks-runner/cache.js +40 -0
  102. package/dist/src/tasks-runner/create-task-graph.js +1 -0
  103. package/dist/src/tasks-runner/default-tasks-runner.js +1 -1
  104. package/dist/src/tasks-runner/forked-process-task-runner.d.ts +1 -1
  105. package/dist/src/tasks-runner/forked-process-task-runner.js +8 -7
  106. package/dist/src/tasks-runner/init-tasks-runner.js +5 -1
  107. package/dist/src/tasks-runner/is-tui-enabled.js +4 -3
  108. package/dist/src/tasks-runner/life-cycle.d.ts +7 -0
  109. package/dist/src/tasks-runner/life-cycle.js +7 -0
  110. package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.d.ts +35 -0
  111. package/dist/src/tasks-runner/life-cycles/summary-terminal-output-life-cycle.js +146 -0
  112. package/dist/src/tasks-runner/prune-task-graph.d.ts +17 -0
  113. package/dist/src/tasks-runner/prune-task-graph.js +45 -0
  114. package/dist/src/tasks-runner/run-command.js +14 -3
  115. package/dist/src/tasks-runner/running-tasks/batch-process.d.ts +93 -19
  116. package/dist/src/tasks-runner/running-tasks/batch-process.js +184 -88
  117. package/dist/src/tasks-runner/task-orchestrator.d.ts +64 -2
  118. package/dist/src/tasks-runner/task-orchestrator.js +232 -46
  119. package/dist/src/tasks-runner/terminal-output-path.d.ts +11 -0
  120. package/dist/src/tasks-runner/terminal-output-path.js +18 -0
  121. package/dist/src/tasks-runner/utils.js +5 -2
  122. package/dist/src/utils/ab-testing.d.ts +3 -0
  123. package/dist/src/utils/ab-testing.js +11 -3
  124. package/dist/src/utils/chunkify.d.ts +1 -7
  125. package/dist/src/utils/chunkify.js +2 -8
  126. package/dist/src/utils/command-line-utils.d.ts +19 -0
  127. package/dist/src/utils/command-line-utils.js +10 -3
  128. package/dist/src/utils/formatters/index.d.ts +6 -0
  129. package/dist/src/utils/formatters/index.js +5 -0
  130. package/dist/src/utils/formatters/prettier.d.ts +0 -8
  131. package/dist/src/utils/formatters/prettier.js +4 -26
  132. package/dist/src/utils/installed-nx-version.js +2 -48
  133. package/dist/src/utils/min-release-age/packument.js +1 -1
  134. package/dist/src/utils/output.d.ts +22 -3
  135. package/dist/src/utils/output.js +28 -5
  136. package/dist/src/utils/package-json.d.ts +25 -0
  137. package/dist/src/utils/package-json.js +41 -6
  138. package/dist/src/utils/package-manager.d.ts +6 -0
  139. package/dist/src/utils/package-manager.js +10 -0
  140. package/dist/src/utils/provenance.js +20 -4
  141. package/dist/src/utils/workspace-context.d.ts +47 -3
  142. package/dist/src/utils/workspace-context.js +162 -10
  143. package/package.json +12 -12
  144. package/schemas/nx-schema.json +4 -0
  145. package/schemas/project-schema.json +4 -0
  146. package/dist/src/daemon/server/file-watching/route-workspace-changes.d.ts +0 -9
  147. package/dist/src/daemon/server/file-watching/route-workspace-changes.js +0 -76
  148. package/dist/src/daemon/server/watcher.d.ts +0 -18
  149. package/dist/src/daemon/server/watcher.js +0 -126
@@ -8,10 +8,19 @@ exports.multiGlobWithWorkspaceContext = multiGlobWithWorkspaceContext;
8
8
  exports.hashWithWorkspaceContext = hashWithWorkspaceContext;
9
9
  exports.hashMultiGlobWithWorkspaceContext = hashMultiGlobWithWorkspaceContext;
10
10
  exports.updateContextWithChangedFiles = updateContextWithChangedFiles;
11
+ exports.trackedFilesInContext = trackedFilesInContext;
11
12
  exports.updateFilesInContext = updateFilesInContext;
12
13
  exports.getAllFileDataInContext = getAllFileDataInContext;
14
+ exports.subscribeToWorkspaceChanges = subscribeToWorkspaceChanges;
15
+ exports.settleWorkspaceContext = settleWorkspaceContext;
16
+ exports.takeAppliedWorkspaceChanges = takeAppliedWorkspaceChanges;
17
+ exports.isWatchingWorkspaceContext = isWatchingWorkspaceContext;
18
+ exports.subscribeToWatchEvents = subscribeToWatchEvents;
19
+ exports.isEmptyBatch = isEmptyBatch;
20
+ exports.stopWatchingWorkspaceContext = stopWatchingWorkspaceContext;
13
21
  exports.getFilesInDirectoryUsingContext = getFilesInDirectoryUsingContext;
14
22
  exports.updateProjectFiles = updateProjectFiles;
23
+ exports.refreshWorkspaceContext = refreshWorkspaceContext;
15
24
  exports.resetWorkspaceContext = resetWorkspaceContext;
16
25
  const perf_hooks_1 = require("perf_hooks");
17
26
  const cache_directory_1 = require("./cache-directory");
@@ -19,16 +28,36 @@ const is_on_daemon_1 = require("../daemon/is-on-daemon");
19
28
  const client_1 = require("../daemon/client/client");
20
29
  const handle_import_1 = require("./handle-import");
21
30
  let workspaceContext;
22
- function setupWorkspaceContext(workspaceRoot) {
31
+ let filesReady;
32
+ // Survive a reset: the daemon tears its context down and lets the next read
33
+ // recreate it, and that context must watch and report like the one before.
34
+ let contextOptions;
35
+ let contextRoot;
36
+ let contextGeneration = 0;
37
+ const changeListeners = new Set();
38
+ const eventListeners = new Set();
39
+ function setupWorkspaceContext(workspaceRoot, options) {
23
40
  const { WorkspaceContext } = require('../native');
24
41
  perf_hooks_1.performance.mark('workspace-context');
25
- workspaceContext = new WorkspaceContext(workspaceRoot, (0, cache_directory_1.workspaceDataDirectoryForWorkspace)(workspaceRoot));
42
+ const cacheDir = (0, cache_directory_1.workspaceDataDirectoryForWorkspace)(workspaceRoot);
43
+ // A plugin worker is only asked for files after its host finished walking
44
+ // and wrote the archive, so it loads that rather than walking again.
45
+ workspaceContext = global.NX_PLUGIN_WORKER
46
+ ? WorkspaceContext.fromArchive(workspaceRoot, cacheDir, options)
47
+ : new WorkspaceContext(workspaceRoot, cacheDir, options);
48
+ contextOptions = options;
49
+ contextRoot = workspaceRoot;
50
+ contextGeneration++;
51
+ filesReady = undefined;
52
+ if (options?.watch) {
53
+ attachSubscribers();
54
+ }
26
55
  perf_hooks_1.performance.mark('workspace-context:end');
27
56
  perf_hooks_1.performance.measure('workspace context init', 'workspace-context', 'workspace-context:end');
28
57
  }
29
58
  async function getNxWorkspaceFilesFromContext(workspaceRoot, projectRootMap, useDaemonProcess = true) {
30
59
  if (!useDaemonProcess || (0, is_on_daemon_1.isOnDaemon)() || !client_1.daemonClient.enabled()) {
31
- ensureContextAvailable(workspaceRoot);
60
+ await ensureFilesReady(workspaceRoot);
32
61
  return workspaceContext.getWorkspaceFiles(projectRootMap);
33
62
  }
34
63
  return client_1.daemonClient.getWorkspaceFiles(projectRootMap);
@@ -46,7 +75,7 @@ function globWithWorkspaceContextSync(workspaceRoot, globs, exclude) {
46
75
  }
47
76
  async function globWithWorkspaceContext(workspaceRoot, globs, exclude) {
48
77
  if (workspaceRoot === '/virtual' || (0, is_on_daemon_1.isOnDaemon)() || !client_1.daemonClient.enabled()) {
49
- ensureContextAvailable(workspaceRoot);
78
+ await ensureFilesReady(workspaceRoot);
50
79
  return workspaceContext.glob(globs, exclude);
51
80
  }
52
81
  else {
@@ -55,21 +84,21 @@ async function globWithWorkspaceContext(workspaceRoot, globs, exclude) {
55
84
  }
56
85
  async function multiGlobWithWorkspaceContext(workspaceRoot, globs, exclude) {
57
86
  if (workspaceRoot === '/virtual' || (0, is_on_daemon_1.isOnDaemon)() || !client_1.daemonClient.enabled()) {
58
- ensureContextAvailable(workspaceRoot);
87
+ await ensureFilesReady(workspaceRoot);
59
88
  return workspaceContext.multiGlob(globs, exclude);
60
89
  }
61
90
  return client_1.daemonClient.multiGlob(globs, exclude);
62
91
  }
63
92
  async function hashWithWorkspaceContext(workspaceRoot, globs, exclude) {
64
93
  if ((0, is_on_daemon_1.isOnDaemon)() || !client_1.daemonClient.enabled()) {
65
- ensureContextAvailable(workspaceRoot);
94
+ await ensureFilesReady(workspaceRoot);
66
95
  return workspaceContext.hashFilesMatchingGlob(globs, exclude);
67
96
  }
68
97
  return client_1.daemonClient.hashGlob(globs, exclude);
69
98
  }
70
99
  async function hashMultiGlobWithWorkspaceContext(workspaceRoot, globGroups) {
71
100
  if ((0, is_on_daemon_1.isOnDaemon)() || !client_1.daemonClient.enabled()) {
72
- ensureContextAvailable(workspaceRoot);
101
+ await ensureFilesReady(workspaceRoot);
73
102
  return workspaceContext.hashFilesMatchingGlobs(globGroups);
74
103
  }
75
104
  return client_1.daemonClient.hashMultiGlob(globGroups);
@@ -89,20 +118,106 @@ async function updateContextWithChangedFiles(workspaceRoot, createdFiles, update
89
118
  await client_1.daemonClient.updateWorkspaceContext(createdFiles, updatedFiles, deletedFiles);
90
119
  }
91
120
  }
121
+ /**
122
+ * The subset of `paths` the workspace file map holds: what the watch tracks,
123
+ * with the ignore rules applied.
124
+ */
125
+ function trackedFilesInContext(workspaceRoot, paths) {
126
+ ensureContextAvailable(workspaceRoot);
127
+ return workspaceContext?.trackedFiles(paths) ?? [];
128
+ }
92
129
  function updateFilesInContext(workspaceRoot, updatedFiles, deletedFiles) {
93
130
  ensureContextAvailable(workspaceRoot);
94
131
  return workspaceContext?.incrementalUpdate(updatedFiles, deletedFiles);
95
132
  }
96
133
  async function getAllFileDataInContext(workspaceRoot) {
97
134
  if ((0, is_on_daemon_1.isOnDaemon)() || !client_1.daemonClient.enabled()) {
98
- ensureContextAvailable(workspaceRoot);
135
+ await ensureFilesReady(workspaceRoot);
99
136
  return workspaceContext.allFileData();
100
137
  }
101
138
  return client_1.daemonClient.getWorkspaceContextFileData();
102
139
  }
140
+ /**
141
+ * Listens for the changes a watching context applies: each change reaches the
142
+ * listeners once, here or in `settleWorkspaceContext`, whichever takes it
143
+ * first. Any number of listeners may listen. Returns a function that stops
144
+ * this one.
145
+ */
146
+ function subscribeToWorkspaceChanges(workspaceRoot, listener) {
147
+ changeListeners.add(listener);
148
+ ensureContextAvailable(workspaceRoot);
149
+ attachSubscribers();
150
+ return () => changeListeners.delete(listener);
151
+ }
152
+ /**
153
+ * Applies every change the watcher has delivered, waiting out the kernel hop,
154
+ * and takes every change applied and not yet handed out. Empty when the
155
+ * context is not watching.
156
+ */
157
+ function settleWorkspaceContext(workspaceRoot) {
158
+ ensureContextAvailable(workspaceRoot);
159
+ return workspaceContext.settle();
160
+ }
161
+ /**
162
+ * Takes every change applied and not yet handed out, without waiting for the
163
+ * watcher: for a caller that has just applied changes itself.
164
+ */
165
+ function takeAppliedWorkspaceChanges(workspaceRoot) {
166
+ ensureContextAvailable(workspaceRoot);
167
+ return workspaceContext.takeAppliedChanges();
168
+ }
169
+ function isWatchingWorkspaceContext() {
170
+ return !!contextOptions?.watch;
171
+ }
172
+ /**
173
+ * Listens for every event the context's watch delivers, including writes
174
+ * under ignored directories and the `rescan` marker. Any number of listeners
175
+ * may listen. Returns a function that stops this one.
176
+ */
177
+ function subscribeToWatchEvents(workspaceRoot, listener) {
178
+ eventListeners.add(listener);
179
+ ensureContextAvailable(workspaceRoot);
180
+ attachSubscribers();
181
+ return () => eventListeners.delete(listener);
182
+ }
183
+ /** Whether a batch carries no change at all. */
184
+ function isEmptyBatch(batch) {
185
+ return (batch.createdFiles.length === 0 &&
186
+ batch.updatedFiles.length === 0 &&
187
+ batch.deletedFiles.length === 0);
188
+ }
189
+ /**
190
+ * The native context takes one subscriber per stream; it fans out here. A
191
+ * delivery a replaced context had already queued does not reach listeners as
192
+ * if it came from the current one.
193
+ */
194
+ function attachSubscribers() {
195
+ if (!workspaceContext || !contextOptions?.watch)
196
+ return;
197
+ const generation = contextGeneration;
198
+ const current = () => generation === contextGeneration;
199
+ workspaceContext.onChanges((err, batch) => {
200
+ if (!current() || (!err && (!batch || isEmptyBatch(batch))))
201
+ return;
202
+ for (const listener of changeListeners)
203
+ listener(err, batch);
204
+ });
205
+ workspaceContext.onWatchEvents((err, events) => {
206
+ if (!current())
207
+ return;
208
+ for (const listener of eventListeners)
209
+ listener(err, events);
210
+ });
211
+ }
212
+ function stopWatchingWorkspaceContext() {
213
+ changeListeners.clear();
214
+ eventListeners.clear();
215
+ contextOptions = undefined;
216
+ workspaceContext?.stopWatching();
217
+ }
103
218
  async function getFilesInDirectoryUsingContext(workspaceRoot, dir) {
104
219
  if ((0, is_on_daemon_1.isOnDaemon)() || !client_1.daemonClient.enabled()) {
105
- ensureContextAvailable(workspaceRoot);
220
+ await ensureFilesReady(workspaceRoot);
106
221
  return workspaceContext.getFilesInDirectory(dir);
107
222
  }
108
223
  return client_1.daemonClient.getFilesInDirectory(dir);
@@ -110,11 +225,48 @@ async function getFilesInDirectoryUsingContext(workspaceRoot, dir) {
110
225
  function updateProjectFiles(projectRootMappings, rustReferences, updatedFiles, deletedFiles) {
111
226
  return workspaceContext?.updateProjectFiles(projectRootMappings, rustReferences.projectFiles, rustReferences.globalFiles, updatedFiles, deletedFiles);
112
227
  }
228
+ /**
229
+ * Waits for the walk behind the context without holding the event loop. The
230
+ * native readers block the calling thread until the files exist, so the async
231
+ * entry points await this first; a plugin host is then never frozen while a
232
+ * worker is connecting to it.
233
+ */
234
+ async function ensureFilesReady(workspaceRoot) {
235
+ ensureContextAvailable(workspaceRoot);
236
+ // A binding without `ready` (an older native build, a mocked one) reads
237
+ // synchronously as before.
238
+ filesReady ??= workspaceContext.ready?.() ?? Promise.resolve();
239
+ await filesReady;
240
+ }
241
+ /**
242
+ * Re-walks the host's files so the archive its plugin workers load includes
243
+ * writes made since the last walk, such as a migration flushing to disk. The
244
+ * walk is selective and shared through the files lock; one still running is
245
+ * reused rather than repeated.
246
+ */
247
+ function refreshWorkspaceContext(workspaceRoot) {
248
+ if (workspaceRoot === '/virtual' || (0, is_on_daemon_1.isOnDaemon)() || client_1.daemonClient.enabled()) {
249
+ return;
250
+ }
251
+ if (workspaceContext?.workspaceRoot !== workspaceRoot) {
252
+ setupWorkspaceContext(workspaceRoot);
253
+ return;
254
+ }
255
+ workspaceContext.refresh();
256
+ filesReady = undefined;
257
+ }
113
258
  function ensureContextAvailable(workspaceRoot) {
114
259
  if (!workspaceContext || workspaceContext?.workspaceRoot !== workspaceRoot) {
115
- setupWorkspaceContext(workspaceRoot);
260
+ setupWorkspaceContext(workspaceRoot, contextOptions);
116
261
  }
117
262
  }
118
263
  function resetWorkspaceContext() {
264
+ workspaceContext?.stopWatching?.();
119
265
  workspaceContext = undefined;
266
+ filesReady = undefined;
267
+ // A watching context is the daemon's only watch; left for the next read to
268
+ // re-create, output and dotenv events in between would be lost.
269
+ if (contextOptions?.watch && contextRoot) {
270
+ setupWorkspaceContext(contextRoot, contextOptions);
271
+ }
120
272
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nx",
3
- "version": "23.2.1",
3
+ "version": "23.3.0-beta.1",
4
4
  "private": false,
5
5
  "type": "commonjs",
6
6
  "description": "The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.",
@@ -152,7 +152,7 @@
152
152
  "semver": "7.8.4",
153
153
  "signal-exit": "3.0.7",
154
154
  "sisteransi": "1.0.5",
155
- "smol-toml": "1.6.1",
155
+ "smol-toml": "1.7.1",
156
156
  "string-width": "4.2.3",
157
157
  "string_decoder": "1.3.0",
158
158
  "strip-ansi": "6.0.1",
@@ -185,16 +185,16 @@
185
185
  }
186
186
  },
187
187
  "optionalDependencies": {
188
- "@nx/nx-darwin-arm64": "23.2.1",
189
- "@nx/nx-darwin-x64": "23.2.1",
190
- "@nx/nx-freebsd-x64": "23.2.1",
191
- "@nx/nx-linux-arm-gnueabihf": "23.2.1",
192
- "@nx/nx-linux-arm64-gnu": "23.2.1",
193
- "@nx/nx-linux-arm64-musl": "23.2.1",
194
- "@nx/nx-linux-x64-gnu": "23.2.1",
195
- "@nx/nx-linux-x64-musl": "23.2.1",
196
- "@nx/nx-win32-arm64-msvc": "23.2.1",
197
- "@nx/nx-win32-x64-msvc": "23.2.1"
188
+ "@nx/nx-darwin-arm64": "23.3.0-beta.1",
189
+ "@nx/nx-darwin-x64": "23.3.0-beta.1",
190
+ "@nx/nx-freebsd-x64": "23.3.0-beta.1",
191
+ "@nx/nx-linux-arm-gnueabihf": "23.3.0-beta.1",
192
+ "@nx/nx-linux-arm64-gnu": "23.3.0-beta.1",
193
+ "@nx/nx-linux-arm64-musl": "23.3.0-beta.1",
194
+ "@nx/nx-linux-x64-gnu": "23.3.0-beta.1",
195
+ "@nx/nx-linux-x64-musl": "23.3.0-beta.1",
196
+ "@nx/nx-win32-arm64-msvc": "23.3.0-beta.1",
197
+ "@nx/nx-win32-x64-msvc": "23.3.0-beta.1"
198
198
  },
199
199
  "nx-migrations": {
200
200
  "migrations": "./migrations.json",
@@ -664,6 +664,10 @@
664
664
  "dependencies": {
665
665
  "type": "boolean",
666
666
  "description": "Include files matching the fileset for all the project dependencies of this target."
667
+ },
668
+ "includeIgnored": {
669
+ "type": "boolean",
670
+ "description": "Hash the glob straight from disk instead of the workspace file map, so gitignored or generated files can be inputs. A missing exact path still takes part in the hash. A ! negation only filters includeIgnored matches when it also sets includeIgnored: true."
667
671
  }
668
672
  },
669
673
  "required": ["fileset"],
@@ -220,6 +220,10 @@
220
220
  "dependencies": {
221
221
  "type": "boolean",
222
222
  "description": "Include files matching the fileset for all the project dependencies of this target."
223
+ },
224
+ "includeIgnored": {
225
+ "type": "boolean",
226
+ "description": "Hash the glob straight from disk instead of the workspace file map, so gitignored or generated files can be inputs. A missing exact path still takes part in the hash. A ! negation only filters includeIgnored matches when it also sets includeIgnored: true."
223
227
  }
224
228
  },
225
229
  "required": ["fileset"],
@@ -1,9 +0,0 @@
1
- import type { WatchEvent } from '../../../native';
2
- /**
3
- * Categorise a batch of watcher events by type and route them into the
4
- * recomputation queue. Deletions are taken at face value; created and
5
- * updated paths are stat'd to skip directories (the project graph only
6
- * cares about files). A stat error means the file was unlinked between
7
- * the watcher firing and us looking — drop the event.
8
- */
9
- export declare function routeWorkspaceChanges(events: WatchEvent[]): void;
@@ -1,76 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.routeWorkspaceChanges = routeWorkspaceChanges;
4
- const node_fs_1 = require("node:fs");
5
- const node_path_1 = require("node:path");
6
- const workspace_root_1 = require("../../../utils/workspace-root");
7
- const logger_1 = require("../../logger");
8
- const project_graph_incremental_recomputation_1 = require("../project-graph-incremental-recomputation");
9
- const SUMMARY_CAP = 10;
10
- function summarize(files) {
11
- if (files.length === 0)
12
- return '(none)';
13
- if (files.length <= SUMMARY_CAP) {
14
- return files.map((f) => ` - ${f}`).join('\n');
15
- }
16
- return (files
17
- .slice(0, SUMMARY_CAP)
18
- .map((f) => ` - ${f}`)
19
- .join('\n') + `\n ... and ${files.length - SUMMARY_CAP} more`);
20
- }
21
- /**
22
- * Categorise a batch of watcher events by type and route them into the
23
- * recomputation queue. Deletions are taken at face value; created and
24
- * updated paths are stat'd to skip directories (the project graph only
25
- * cares about files). A stat error means the file was unlinked between
26
- * the watcher firing and us looking — drop the event.
27
- */
28
- function routeWorkspaceChanges(events) {
29
- logger_1.serverLogger.watcherLog(`[watcher] routeWorkspaceChanges batch: ${events.length} events: ` +
30
- events.map((e) => `${e.type}:${e.path}`).join(', '));
31
- const updatedFilesToHash = [];
32
- const createdFilesToHash = [];
33
- const deletedFiles = [];
34
- const droppedDirs = [];
35
- const droppedStatErrors = [];
36
- for (const event of events) {
37
- if (event.type === 'delete') {
38
- deletedFiles.push(event.path);
39
- continue;
40
- }
41
- try {
42
- const s = (0, node_fs_1.statSync)((0, node_path_1.join)(workspace_root_1.workspaceRoot, event.path));
43
- if (!s.isFile()) {
44
- droppedDirs.push(event.path);
45
- continue;
46
- }
47
- if (event.type === 'update') {
48
- updatedFilesToHash.push(event.path);
49
- }
50
- else {
51
- createdFilesToHash.push(event.path);
52
- }
53
- }
54
- catch (e) {
55
- droppedStatErrors.push(`${event.path} (${e instanceof Error ? e.message : String(e)})`);
56
- // File deleted between watcher emit and stat — drop it.
57
- }
58
- }
59
- if (createdFilesToHash.length ||
60
- updatedFilesToHash.length ||
61
- deletedFiles.length ||
62
- droppedDirs.length ||
63
- droppedStatErrors.length) {
64
- logger_1.serverLogger.watcherLog(`File changes detected:\n` +
65
- `Created:\n${summarize(createdFilesToHash)}\n` +
66
- `Updated:\n${summarize(updatedFilesToHash)}\n` +
67
- `Deleted:\n${summarize(deletedFiles)}` +
68
- (droppedDirs.length
69
- ? `\nDropped (dirs):\n${summarize(droppedDirs)}`
70
- : '') +
71
- (droppedStatErrors.length
72
- ? `\nDropped (stat errors):\n${summarize(droppedStatErrors)}`
73
- : ''));
74
- }
75
- (0, project_graph_incremental_recomputation_1.scheduleProjectGraphRecomputation)(createdFilesToHash, updatedFilesToHash, deletedFiles);
76
- }
@@ -1,18 +0,0 @@
1
- import { Server } from 'net';
2
- import type { WatchEvent } from '../../native';
3
- export type FileWatcherCallback = (err: Error | string | null, changeEvents: WatchEvent[] | null) => Promise<void>;
4
- export declare function watchWorkspace(server: Server, cb: FileWatcherCallback): Promise<any>;
5
- /**
6
- * Synchronously drain anything the workspace watcher has buffered and feed
7
- * it through the normal change-handling pipeline. Call this before serving
8
- * a cached project graph so we never return data that the watcher has
9
- * already seen invalidated but hasn't flushed yet.
10
- */
11
- export declare function flushPendingWorkspaceChanges(): Promise<void>;
12
- export declare function watchOutputFiles(server: Server, cb: FileWatcherCallback): Promise<any>;
13
- /**
14
- * NOTE: An event type of "create" will also apply to the case where the user has restored
15
- * an original version of a file after modifying/deleting it by using git, so we adjust
16
- * our log language accordingly.
17
- */
18
- export declare function convertChangeEventsToLogMessage(changeEvents: WatchEvent[]): string;
@@ -1,126 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.watchWorkspace = watchWorkspace;
4
- exports.flushPendingWorkspaceChanges = flushPendingWorkspaceChanges;
5
- exports.watchOutputFiles = watchOutputFiles;
6
- exports.convertChangeEventsToLogMessage = convertChangeEventsToLogMessage;
7
- const workspace_root_1 = require("../../utils/workspace-root");
8
- const path_1 = require("path");
9
- const shutdown_utils_1 = require("./shutdown-utils");
10
- const path_2 = require("../../utils/path");
11
- const cache_1 = require("../cache");
12
- const server_1 = require("./server");
13
- const handle_import_1 = require("../../utils/handle-import");
14
- // Captured by watchWorkspace so flushPendingWorkspaceChanges can route
15
- // force-flushed events through the same handling as the async callback.
16
- // Definite-assignment: dispatchWorkspaceChanges only runs after
17
- // watchWorkspace has set both, so reading them as non-nullable is safe.
18
- let activeServer;
19
- let workspaceChangesCallback;
20
- function dispatchWorkspaceChanges(events) {
21
- for (const event of events) {
22
- if (event.path.endsWith('.gitignore') || event.path === '.nxignore') {
23
- // If the ignore files themselves have changed we need to dynamically
24
- // update our cached ignoreGlobs
25
- (0, shutdown_utils_1.handleServerProcessTermination)({
26
- server: activeServer,
27
- reason: 'Stopping the daemon the set of ignored files changed (native)',
28
- sockets: server_1.openSockets,
29
- });
30
- }
31
- }
32
- return workspaceChangesCallback(null, events);
33
- }
34
- async function watchWorkspace(server, cb) {
35
- const { Watcher } = await (0, handle_import_1.handleImport)('../../native/index.js', __dirname);
36
- activeServer = server;
37
- workspaceChangesCallback = cb;
38
- const watcher = new Watcher(workspace_root_1.workspaceRoot);
39
- watcher.watch((err, events) => {
40
- if (err) {
41
- return cb(err, null);
42
- }
43
- dispatchWorkspaceChanges(events);
44
- });
45
- return watcher;
46
- }
47
- /**
48
- * Synchronously drain anything the workspace watcher has buffered and feed
49
- * it through the normal change-handling pipeline. Call this before serving
50
- * a cached project graph so we never return data that the watcher has
51
- * already seen invalidated but hasn't flushed yet.
52
- */
53
- async function flushPendingWorkspaceChanges() {
54
- const watcher = (0, shutdown_utils_1.getWatcherInstance)();
55
- if (!watcher)
56
- return;
57
- const events = watcher.forceFlushPending();
58
- if (events.length === 0)
59
- return;
60
- await dispatchWorkspaceChanges(events);
61
- }
62
- async function watchOutputFiles(server, cb) {
63
- const { Watcher } = await (0, handle_import_1.handleImport)('../../native/index.js', __dirname);
64
- const relativeServerProcess = (0, path_2.normalizePath)((0, path_1.relative)(workspace_root_1.workspaceRoot, cache_1.serverProcessJsonPath));
65
- const watcher = new Watcher(workspace_root_1.workspaceRoot, [`!${relativeServerProcess}`], false);
66
- watcher.watch((err, events) => {
67
- if (err) {
68
- return cb(err, null);
69
- }
70
- for (const event of events) {
71
- if (event.path == relativeServerProcess &&
72
- (0, cache_1.getDaemonProcessIdSync)() !== process.pid) {
73
- return (0, shutdown_utils_1.handleServerProcessTermination)({
74
- server,
75
- reason: 'this process is no longer the current daemon (native)',
76
- sockets: server_1.openSockets,
77
- });
78
- }
79
- }
80
- if (events.length !== 0) {
81
- cb(null, events);
82
- }
83
- });
84
- return watcher;
85
- }
86
- /**
87
- * NOTE: An event type of "create" will also apply to the case where the user has restored
88
- * an original version of a file after modifying/deleting it by using git, so we adjust
89
- * our log language accordingly.
90
- */
91
- function convertChangeEventsToLogMessage(changeEvents) {
92
- // If only a single file was changed, show the information inline
93
- if (changeEvents.length === 1) {
94
- const { path, type } = changeEvents[0];
95
- let typeLog = 'updated';
96
- switch (type) {
97
- case 'create':
98
- typeLog = 'created or restored';
99
- break;
100
- case 'update':
101
- typeLog = 'modified';
102
- break;
103
- case 'delete':
104
- typeLog = 'deleted';
105
- break;
106
- }
107
- return `${path} was ${typeLog}`;
108
- }
109
- let numCreatedOrRestoredFiles = 0;
110
- let numModifiedFiles = 0;
111
- let numDeletedFiles = 0;
112
- for (const event of changeEvents) {
113
- switch (event.type) {
114
- case 'create':
115
- numCreatedOrRestoredFiles++;
116
- break;
117
- case 'update':
118
- numModifiedFiles++;
119
- break;
120
- case 'delete':
121
- numDeletedFiles++;
122
- break;
123
- }
124
- }
125
- return `${numCreatedOrRestoredFiles} file(s) created or restored, ${numModifiedFiles} file(s) modified, ${numDeletedFiles} file(s) deleted`;
126
- }