nx 22.7.0-beta.12 → 22.7.0-beta.13
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/dist/schemas/nx-schema.json +25 -0
- package/dist/schemas/project-schema.json +25 -0
- package/dist/src/adapter/ngcli-adapter.js +11 -12
- package/dist/src/command-line/daemon/daemon.js +8 -4
- package/dist/src/command-line/graph/graph.js +8 -1
- package/dist/src/command-line/show/show-target/utils.js +4 -3
- package/dist/src/command-line/yargs-utils/shared-options.js +5 -1
- package/dist/src/config/nx-json.d.ts +3 -1
- package/dist/src/config/workspace-json-project-json.d.ts +2 -1
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/daemon/client/client.d.ts +10 -3
- package/dist/src/daemon/client/client.js +21 -31
- package/dist/src/daemon/client/daemon-environment.d.ts +4 -0
- package/dist/src/daemon/client/daemon-environment.js +119 -0
- package/dist/src/daemon/client/daemon-socket-messenger.d.ts +2 -5
- package/dist/src/daemon/client/daemon-socket-messenger.js +1 -1
- package/dist/src/daemon/message-types/daemon-message.d.ts +6 -0
- package/dist/src/daemon/message-types/daemon-message.js +6 -0
- package/dist/src/daemon/server/handle-hash-tasks.d.ts +1 -1
- package/dist/src/daemon/server/handle-hash-tasks.js +1 -1
- package/dist/src/daemon/server/handle-outputs-tracking.d.ts +4 -4
- package/dist/src/daemon/server/handle-outputs-tracking.js +11 -11
- package/dist/src/daemon/server/outputs-tracking.d.ts +18 -3
- package/dist/src/daemon/server/outputs-tracking.js +49 -22
- package/dist/src/daemon/server/project-graph-incremental-recomputation.d.ts +2 -1
- package/dist/src/daemon/server/project-graph-incremental-recomputation.js +20 -4
- package/dist/src/daemon/server/server.js +71 -40
- package/dist/src/executors/run-commands/running-tasks.js +2 -3
- package/dist/src/executors/run-script/run-script.impl.js +16 -8
- package/dist/src/hasher/hash-task.d.ts +9 -1
- package/dist/src/hasher/hash-task.js +41 -14
- package/dist/src/hasher/native-task-hasher-impl.d.ts +1 -1
- package/dist/src/hasher/native-task-hasher-impl.js +4 -6
- package/dist/src/hasher/task-hasher.d.ts +20 -9
- package/dist/src/hasher/task-hasher.js +34 -6
- package/dist/src/native/index.d.ts +34 -7
- package/dist/src/native/native-bindings.js +1 -1
- package/dist/src/native/nx.wasi-browser.js +0 -1
- package/dist/src/native/nx.wasi.cjs +0 -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/plugins/js/utils/register.js +83 -4
- package/dist/src/project-graph/error-types.js +31 -11
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +1 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +9 -0
- package/dist/src/project-graph/plugins/isolation/message-types.d.ts +1 -1
- package/dist/src/project-graph/plugins/isolation/messaging.d.ts +9 -0
- package/dist/src/project-graph/plugins/isolation/messaging.js +2 -0
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +36 -68
- package/dist/src/project-graph/plugins/loaded-nx-plugin.d.ts +6 -0
- package/dist/src/tasks-runner/cache.d.ts +6 -0
- package/dist/src/tasks-runner/cache.js +58 -0
- package/dist/src/tasks-runner/init-tasks-runner.js +13 -7
- package/dist/src/tasks-runner/run-command.js +13 -5
- package/dist/src/tasks-runner/task-env.js +17 -1
- package/dist/src/tasks-runner/task-orchestrator.d.ts +79 -7
- package/dist/src/tasks-runner/task-orchestrator.js +327 -120
- package/dist/src/tasks-runner/tasks-schedule.d.ts +5 -2
- package/dist/src/tasks-runner/tasks-schedule.js +31 -17
- package/dist/src/tasks-runner/utils.d.ts +3 -3
- package/dist/src/tasks-runner/utils.js +5 -6
- package/package.json +12 -12
- package/dist/src/daemon/client/exec-is-server-available.d.ts +0 -1
- package/dist/src/daemon/client/exec-is-server-available.js +0 -11
- package/dist/src/daemon/client/generate-help-output.d.ts +0 -1
- package/dist/src/daemon/client/generate-help-output.js +0 -26
|
@@ -44,7 +44,7 @@ export declare class DaemonClient {
|
|
|
44
44
|
sourceMaps: ConfigurationSourceMaps;
|
|
45
45
|
}>;
|
|
46
46
|
getAllFileData(): Promise<FileData[]>;
|
|
47
|
-
hashTasks(runnerOptions: any, tasks: Task[], taskGraph: TaskGraph,
|
|
47
|
+
hashTasks(runnerOptions: any, tasks: Task[], taskGraph: TaskGraph, perTaskEnvs: Record<string, NodeJS.ProcessEnv>, cwd: string, collectInputs?: boolean): Promise<Hash[]>;
|
|
48
48
|
registerFileWatcher(config: {
|
|
49
49
|
watchProjects: string[] | 'all';
|
|
50
50
|
includeGlobalWorkspaceFiles?: boolean;
|
|
@@ -62,8 +62,14 @@ export declare class DaemonClient {
|
|
|
62
62
|
} | null) => void): Promise<UnregisterCallback>;
|
|
63
63
|
private reconnectProjectGraphListener;
|
|
64
64
|
processInBackground(requirePath: string, data: any): Promise<any>;
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
recordOutputsHashBatch(entries: {
|
|
66
|
+
outputs: string[];
|
|
67
|
+
hash: string;
|
|
68
|
+
}[]): Promise<any>;
|
|
69
|
+
outputsHashesMatchBatch(entries: {
|
|
70
|
+
outputs: string[];
|
|
71
|
+
hash: string;
|
|
72
|
+
}[]): Promise<boolean[]>;
|
|
67
73
|
glob(globs: string[], exclude?: string[]): Promise<string[]>;
|
|
68
74
|
multiGlob(globs: string[], exclude?: string[]): Promise<string[][]>;
|
|
69
75
|
getWorkspaceContextFileData(): Promise<FileData[]>;
|
|
@@ -100,6 +106,7 @@ export declare class DaemonClient {
|
|
|
100
106
|
* Used for reconnection - throws VersionMismatchError if daemon version differs.
|
|
101
107
|
*/
|
|
102
108
|
private waitForServerToBeAvailable;
|
|
109
|
+
private envReflectionSent;
|
|
103
110
|
private sendMessageToDaemon;
|
|
104
111
|
private registerDaemonProcessWithMetricsService;
|
|
105
112
|
private handleMessage;
|
|
@@ -15,13 +15,13 @@ const native_1 = require("../../native");
|
|
|
15
15
|
const error_types_1 = require("../../project-graph/error-types");
|
|
16
16
|
const project_graph_1 = require("../../project-graph/project-graph");
|
|
17
17
|
const consume_messages_from_socket_1 = require("../../utils/consume-messages-from-socket");
|
|
18
|
-
const wait_for_socket_connection_1 = require("../../utils/wait-for-socket-connection");
|
|
19
18
|
const delayed_spinner_1 = require("../../utils/delayed-spinner");
|
|
20
19
|
const handle_import_1 = require("../../utils/handle-import");
|
|
21
20
|
const is_ci_1 = require("../../utils/is-ci");
|
|
22
21
|
const is_sandbox_1 = require("../../utils/is-sandbox");
|
|
23
22
|
const output_1 = require("../../utils/output");
|
|
24
23
|
const promised_based_queue_1 = require("../../utils/promised-based-queue");
|
|
24
|
+
const wait_for_socket_connection_1 = require("../../utils/wait-for-socket-connection");
|
|
25
25
|
const workspace_root_1 = require("../../utils/workspace-root");
|
|
26
26
|
const cache_1 = require("../cache");
|
|
27
27
|
const is_nx_version_mismatch_1 = require("../is-nx-version-mismatch");
|
|
@@ -41,15 +41,7 @@ const task_history_1 = require("../message-types/task-history");
|
|
|
41
41
|
const update_workspace_context_1 = require("../message-types/update-workspace-context");
|
|
42
42
|
const tmp_dir_1 = require("../tmp-dir");
|
|
43
43
|
const daemon_socket_messenger_1 = require("./daemon-socket-messenger");
|
|
44
|
-
const
|
|
45
|
-
NX_PROJECT_GLOB_CACHE: 'false',
|
|
46
|
-
NX_CACHE_PROJECTS_CONFIG: 'false',
|
|
47
|
-
};
|
|
48
|
-
const DAEMON_ENV_OVERRIDABLE_SETTINGS = {
|
|
49
|
-
NX_VERBOSE_LOGGING: 'true',
|
|
50
|
-
NX_PERF_LOGGING: 'true',
|
|
51
|
-
NX_NATIVE_LOGGING: 'nx=debug',
|
|
52
|
-
};
|
|
44
|
+
const daemon_environment_1 = require("./daemon-environment");
|
|
53
45
|
var DaemonStatus;
|
|
54
46
|
(function (DaemonStatus) {
|
|
55
47
|
DaemonStatus[DaemonStatus["CONNECTING"] = 0] = "CONNECTING";
|
|
@@ -72,6 +64,7 @@ class DaemonClient {
|
|
|
72
64
|
this.fileWatcherConfigs = new Map();
|
|
73
65
|
this.projectGraphListenerReconnecting = false;
|
|
74
66
|
this.projectGraphListenerCallbacks = new Map();
|
|
67
|
+
this.envReflectionSent = false;
|
|
75
68
|
try {
|
|
76
69
|
this.nxJson = (0, configuration_1.readNxJson)();
|
|
77
70
|
}
|
|
@@ -187,13 +180,11 @@ class DaemonClient {
|
|
|
187
180
|
async getAllFileData() {
|
|
188
181
|
return await this.sendToDaemonViaQueue({ type: 'REQUEST_FILE_DATA' });
|
|
189
182
|
}
|
|
190
|
-
hashTasks(runnerOptions, tasks, taskGraph,
|
|
183
|
+
hashTasks(runnerOptions, tasks, taskGraph, perTaskEnvs, cwd, collectInputs) {
|
|
191
184
|
return this.sendToDaemonViaQueue({
|
|
192
185
|
type: 'HASH_TASKS',
|
|
193
186
|
runnerOptions,
|
|
194
|
-
|
|
195
|
-
? structuredClone(process.env)
|
|
196
|
-
: env,
|
|
187
|
+
perTaskEnvs,
|
|
197
188
|
tasks,
|
|
198
189
|
taskGraph,
|
|
199
190
|
cwd,
|
|
@@ -525,22 +516,16 @@ class DaemonClient {
|
|
|
525
516
|
// so we force JSON serialization here
|
|
526
517
|
}, 'json');
|
|
527
518
|
}
|
|
528
|
-
|
|
519
|
+
recordOutputsHashBatch(entries) {
|
|
529
520
|
return this.sendToDaemonViaQueue({
|
|
530
|
-
type: '
|
|
531
|
-
data:
|
|
532
|
-
outputs,
|
|
533
|
-
hash,
|
|
534
|
-
},
|
|
521
|
+
type: 'RECORD_OUTPUTS_HASH_BATCH',
|
|
522
|
+
data: entries,
|
|
535
523
|
});
|
|
536
524
|
}
|
|
537
|
-
|
|
525
|
+
outputsHashesMatchBatch(entries) {
|
|
538
526
|
return this.sendToDaemonViaQueue({
|
|
539
|
-
type: '
|
|
540
|
-
data:
|
|
541
|
-
outputs,
|
|
542
|
-
hash,
|
|
543
|
-
},
|
|
527
|
+
type: 'OUTPUTS_HASHES_MATCH_BATCH',
|
|
528
|
+
data: entries,
|
|
544
529
|
});
|
|
545
530
|
}
|
|
546
531
|
glob(globs, exclude) {
|
|
@@ -868,6 +853,12 @@ class DaemonClient {
|
|
|
868
853
|
return false;
|
|
869
854
|
}
|
|
870
855
|
async sendMessageToDaemon(message, force) {
|
|
856
|
+
// the first message sent to the daemon includes an env prop
|
|
857
|
+
// that updates the process.env values on the daemon.
|
|
858
|
+
if (!this.envReflectionSent && !global.NX_PLUGIN_WORKER) {
|
|
859
|
+
message.env = (0, daemon_environment_1.getDaemonEnv)();
|
|
860
|
+
this.envReflectionSent = true;
|
|
861
|
+
}
|
|
871
862
|
await this.startDaemonIfNecessary();
|
|
872
863
|
let keepAlive;
|
|
873
864
|
return new Promise((resolve, reject) => {
|
|
@@ -947,12 +938,11 @@ class DaemonClient {
|
|
|
947
938
|
detached: true,
|
|
948
939
|
windowsHide: true,
|
|
949
940
|
shell: false,
|
|
950
|
-
env:
|
|
951
|
-
...DAEMON_ENV_OVERRIDABLE_SETTINGS,
|
|
952
|
-
...process.env,
|
|
953
|
-
...DAEMON_ENV_REQUIRED_SETTINGS,
|
|
954
|
-
},
|
|
941
|
+
env: (0, daemon_environment_1.getDaemonEnv)(),
|
|
955
942
|
});
|
|
943
|
+
// if this process is the process that spawned the daemon,
|
|
944
|
+
// the daemon env is already up to date
|
|
945
|
+
this.envReflectionSent = true;
|
|
956
946
|
backgroundProcess.unref();
|
|
957
947
|
/**
|
|
958
948
|
* Ensure the server is actually available to connect to via IPC before resolving
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDaemonEnv = getDaemonEnv;
|
|
4
|
+
const DAEMON_ENV_REQUIRED_SETTINGS = {
|
|
5
|
+
NX_PROJECT_GLOB_CACHE: 'false',
|
|
6
|
+
NX_CACHE_PROJECTS_CONFIG: 'false',
|
|
7
|
+
};
|
|
8
|
+
const DAEMON_ENV_OVERRIDABLE_SETTINGS = {
|
|
9
|
+
NX_VERBOSE_LOGGING: 'true',
|
|
10
|
+
NX_PERF_LOGGING: 'true',
|
|
11
|
+
NX_NATIVE_LOGGING: 'nx=debug',
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Env vars that should NOT be sent to the daemon because they cannot affect
|
|
15
|
+
* the project graph. Only vars that can actually affect the project graph
|
|
16
|
+
* (e.g. PATH, JAVA_HOME, GRADLE_HOME) should be allowed through.
|
|
17
|
+
*/
|
|
18
|
+
const DAEMON_ENV_VARS_EXCLUSIONS = new Set([
|
|
19
|
+
// Nx task-scoped vars
|
|
20
|
+
'NX_TASK_TARGET_CONFIGURATION',
|
|
21
|
+
'NX_TASK_TARGET_PROJECT',
|
|
22
|
+
'NX_TASK_TARGET_TARGET',
|
|
23
|
+
'NX_TASK_HASH',
|
|
24
|
+
'NX_TERMINAL_OUTPUT_PATH',
|
|
25
|
+
'NX_TERMINAL_CAPTURE_STDERR',
|
|
26
|
+
'NX_STREAM_OUTPUT',
|
|
27
|
+
'NX_PREFIX_OUTPUT',
|
|
28
|
+
'NX_FORKED_TASK_EXECUTOR',
|
|
29
|
+
'NX_SET_CLI',
|
|
30
|
+
'NX_INVOKED_BY_RUNNER',
|
|
31
|
+
'NX_LOAD_DOT_ENV_FILES',
|
|
32
|
+
'NX_SKIP_NX_CACHE',
|
|
33
|
+
'NX_CACHE_FAILURES',
|
|
34
|
+
'NX_REJECT_UNKNOWN_LOCAL_CACHE',
|
|
35
|
+
'NX_IGNORE_CYCLES',
|
|
36
|
+
'NX_BATCH_MODE',
|
|
37
|
+
'NX_CI_EXECUTION_ID',
|
|
38
|
+
'NX_DAEMON_PROCESS',
|
|
39
|
+
// Nx UI/logging vars (don't affect graph structure)
|
|
40
|
+
'NX_TUI',
|
|
41
|
+
'NX_TUI_AUTO_EXIT',
|
|
42
|
+
'NX_TUI_SKIP_CAPABILITY_CHECK',
|
|
43
|
+
'NX_VERBOSE_LOGGING',
|
|
44
|
+
'NX_PERF_LOGGING',
|
|
45
|
+
'NX_NATIVE_LOGGING',
|
|
46
|
+
'NX_PROFILE',
|
|
47
|
+
'NX_DAEMON_VERBOSE_LOGGING',
|
|
48
|
+
// AI agent detection vars (the daemon itself is not an AI agent)
|
|
49
|
+
'CLAUDECODE',
|
|
50
|
+
'CLAUDE_CODE',
|
|
51
|
+
'REPL_ID',
|
|
52
|
+
'CURSOR_TRACE_ID',
|
|
53
|
+
'COMPOSER_NO_INTERACTION',
|
|
54
|
+
'OPENCODE',
|
|
55
|
+
'GEMINI_CLI',
|
|
56
|
+
// Shell mechanics
|
|
57
|
+
'_',
|
|
58
|
+
'SHLVL',
|
|
59
|
+
'OLDPWD',
|
|
60
|
+
'SHELL_SESSION_ID',
|
|
61
|
+
'TERM_SESSION_ID',
|
|
62
|
+
'SECURITYSESSIONID',
|
|
63
|
+
'COMMAND_MODE',
|
|
64
|
+
'WINDOWID',
|
|
65
|
+
'COLUMNS',
|
|
66
|
+
'LINES',
|
|
67
|
+
'TMPDIR',
|
|
68
|
+
// Session / auth
|
|
69
|
+
'SSH_AUTH_SOCK',
|
|
70
|
+
'SSH_AGENT_PID',
|
|
71
|
+
'XDG_SESSION_ID',
|
|
72
|
+
'DBUS_SESSION_BUS_ADDRESS',
|
|
73
|
+
'DISPLAY',
|
|
74
|
+
// macOS internals
|
|
75
|
+
'__CF_USER_TEXT_ENCODING',
|
|
76
|
+
'__CFBundleIdentifier',
|
|
77
|
+
]);
|
|
78
|
+
/**
|
|
79
|
+
* Env var prefixes that should never be sent to the daemon.
|
|
80
|
+
* These cover CI platforms, package managers, editors, and terminals.
|
|
81
|
+
*/
|
|
82
|
+
const DAEMON_ENV_PREFIX_EXCLUSIONS = [
|
|
83
|
+
// CI platforms
|
|
84
|
+
'GITHUB_',
|
|
85
|
+
'RUNNER_',
|
|
86
|
+
'CI_JOB_',
|
|
87
|
+
'CI_PIPELINE_',
|
|
88
|
+
'CIRCLE_',
|
|
89
|
+
'JENKINS_',
|
|
90
|
+
'BUILD_',
|
|
91
|
+
'AGENT_',
|
|
92
|
+
'SYSTEM_TASK',
|
|
93
|
+
// Package managers (process-scoped)
|
|
94
|
+
'npm_',
|
|
95
|
+
'pnpm_',
|
|
96
|
+
// Editors / IDEs
|
|
97
|
+
'VSCODE_',
|
|
98
|
+
'JETBRAINS_',
|
|
99
|
+
// Terminal emulators
|
|
100
|
+
'ITERM_',
|
|
101
|
+
'KITTY_',
|
|
102
|
+
'WEZTERM_',
|
|
103
|
+
'ALACRITTY_',
|
|
104
|
+
'KONSOLE_',
|
|
105
|
+
'TMUX',
|
|
106
|
+
];
|
|
107
|
+
function isExcludedEnvVar(key) {
|
|
108
|
+
return (DAEMON_ENV_VARS_EXCLUSIONS.has(key) ||
|
|
109
|
+
DAEMON_ENV_PREFIX_EXCLUSIONS.some((prefix) => key.startsWith(prefix)));
|
|
110
|
+
}
|
|
111
|
+
function getDaemonEnv() {
|
|
112
|
+
const env = { ...DAEMON_ENV_OVERRIDABLE_SETTINGS };
|
|
113
|
+
for (const key in process.env) {
|
|
114
|
+
if (!isExcludedEnvVar(key)) {
|
|
115
|
+
env[key] = process.env[key];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return Object.assign(env, DAEMON_ENV_REQUIRED_SETTINGS);
|
|
119
|
+
}
|
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
import { Socket } from 'net';
|
|
2
|
-
|
|
3
|
-
type: string;
|
|
4
|
-
data?: any;
|
|
5
|
-
}
|
|
2
|
+
import { DaemonMessage } from '../message-types/daemon-message';
|
|
6
3
|
export declare class VersionMismatchError extends Error {
|
|
7
4
|
constructor();
|
|
8
5
|
}
|
|
9
6
|
export declare class DaemonSocketMessenger {
|
|
10
7
|
private socket;
|
|
11
8
|
constructor(socket: Socket);
|
|
12
|
-
sendMessage(messageToDaemon:
|
|
9
|
+
sendMessage<T extends DaemonMessage>(messageToDaemon: T, force?: 'v8' | 'json'): void;
|
|
13
10
|
listen(onData: (message: string) => void, onClose?: () => void, onError?: (err: Error) => void): DaemonSocketMessenger;
|
|
14
11
|
close(): void;
|
|
15
12
|
}
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DaemonSocketMessenger = exports.VersionMismatchError = void 0;
|
|
4
4
|
const perf_hooks_1 = require("perf_hooks");
|
|
5
5
|
const consume_messages_from_socket_1 = require("../../utils/consume-messages-from-socket");
|
|
6
|
-
const socket_utils_1 = require("../socket-utils");
|
|
7
6
|
const logger_1 = require("../logger");
|
|
7
|
+
const socket_utils_1 = require("../socket-utils");
|
|
8
8
|
class VersionMismatchError extends Error {
|
|
9
9
|
constructor() {
|
|
10
10
|
super('Version mismatch with daemon server');
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Task, TaskGraph } from '../../config/task-graph';
|
|
2
2
|
export declare function handleHashTasks(payload: {
|
|
3
3
|
runnerOptions: any;
|
|
4
|
-
env: any;
|
|
5
4
|
tasks: Task[];
|
|
6
5
|
taskGraph: TaskGraph;
|
|
6
|
+
perTaskEnvs: Record<string, NodeJS.ProcessEnv>;
|
|
7
7
|
cwd: string;
|
|
8
8
|
collectInputs?: boolean;
|
|
9
9
|
}): Promise<{
|
|
@@ -20,7 +20,7 @@ async function handleHashTasks(payload) {
|
|
|
20
20
|
storedProjectGraph = projectGraph;
|
|
21
21
|
storedHasher = new task_hasher_1.InProcessTaskHasher(projectGraph, nxJson, rustReferences, payload.runnerOptions);
|
|
22
22
|
}
|
|
23
|
-
const response = await storedHasher.hashTasks(payload.tasks, payload.taskGraph, payload.
|
|
23
|
+
const response = await storedHasher.hashTasks(payload.tasks, payload.taskGraph, payload.perTaskEnvs, payload.cwd, payload.collectInputs);
|
|
24
24
|
return {
|
|
25
25
|
response,
|
|
26
26
|
description: 'handleHashTasks',
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { HandlerResult } from './server';
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function handleRecordOutputsHashBatch(payload: {
|
|
3
3
|
type: string;
|
|
4
4
|
data: {
|
|
5
5
|
outputs: string[];
|
|
6
6
|
hash: string;
|
|
7
|
-
};
|
|
7
|
+
}[];
|
|
8
8
|
}): Promise<HandlerResult>;
|
|
9
|
-
export declare function
|
|
9
|
+
export declare function handleOutputsHashesMatchBatch(payload: {
|
|
10
10
|
type: string;
|
|
11
11
|
data: {
|
|
12
12
|
outputs: string[];
|
|
13
13
|
hash: string;
|
|
14
|
-
};
|
|
14
|
+
}[];
|
|
15
15
|
}): Promise<HandlerResult>;
|
|
@@ -1,34 +1,34 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.
|
|
3
|
+
exports.handleRecordOutputsHashBatch = handleRecordOutputsHashBatch;
|
|
4
|
+
exports.handleOutputsHashesMatchBatch = handleOutputsHashesMatchBatch;
|
|
5
5
|
const outputs_tracking_1 = require("./outputs-tracking");
|
|
6
|
-
async function
|
|
6
|
+
async function handleRecordOutputsHashBatch(payload) {
|
|
7
7
|
try {
|
|
8
|
-
|
|
8
|
+
(0, outputs_tracking_1.recordOutputsHashBatch)(payload.data);
|
|
9
9
|
return {
|
|
10
|
-
description: '
|
|
10
|
+
description: 'recordOutputsHashBatch',
|
|
11
11
|
response: '{}',
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
14
|
catch (e) {
|
|
15
15
|
return {
|
|
16
|
-
description: '
|
|
16
|
+
description: 'recordOutputsHashBatch failed',
|
|
17
17
|
error: new Error(`Critical error when recording metadata about outputs: '${e.message}'.`),
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
-
async function
|
|
21
|
+
async function handleOutputsHashesMatchBatch(payload) {
|
|
22
22
|
try {
|
|
23
|
-
const
|
|
23
|
+
const results = (0, outputs_tracking_1.outputsHashesMatchBatch)(payload.data);
|
|
24
24
|
return {
|
|
25
|
-
response:
|
|
26
|
-
description: '
|
|
25
|
+
response: results,
|
|
26
|
+
description: 'outputsHashesMatchBatch',
|
|
27
27
|
};
|
|
28
28
|
}
|
|
29
29
|
catch (e) {
|
|
30
30
|
return {
|
|
31
|
-
description: '
|
|
31
|
+
description: 'outputsHashesMatchBatch failed',
|
|
32
32
|
error: new Error(`Critical error when verifying the contents of the outputs haven't changed: '${e.message}'.`),
|
|
33
33
|
};
|
|
34
34
|
}
|
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
import { WatchEvent } from '../../native';
|
|
2
2
|
export declare function _recordOutputsHash(outputs: string[], hash: string): void;
|
|
3
3
|
export declare function _outputsHashesMatch(outputs: string[], hash: string): boolean;
|
|
4
|
-
export declare function recordedHash(output: string): string;
|
|
5
|
-
export declare function recordOutputsHash(_outputs: string[], hash: string): Promise<void>;
|
|
6
|
-
export declare function outputsHashesMatch(_outputs: string[], hash: string): Promise<boolean>;
|
|
7
4
|
export declare function processFileChangesInOutputs(changeEvents: WatchEvent[], now?: number): void;
|
|
5
|
+
/**
|
|
6
|
+
* Check whether the on-disk outputs of each entry still match the hash
|
|
7
|
+
* the daemon recorded for them. Uses Rayon-parallel filesystem scanning
|
|
8
|
+
* for uncached entries.
|
|
9
|
+
*/
|
|
10
|
+
export declare function outputsHashesMatchBatch(entries: {
|
|
11
|
+
outputs: string[];
|
|
12
|
+
hash: string;
|
|
13
|
+
}[]): boolean[];
|
|
14
|
+
/**
|
|
15
|
+
* Record the hash of each entry's on-disk outputs so future
|
|
16
|
+
* outputsHashesMatchBatch calls can skip redundant cache copies.
|
|
17
|
+
* Uses Rayon-parallel filesystem scanning.
|
|
18
|
+
*/
|
|
19
|
+
export declare function recordOutputsHashBatch(entries: {
|
|
20
|
+
outputs: string[];
|
|
21
|
+
hash: string;
|
|
22
|
+
}[]): void;
|
|
8
23
|
export declare function disableOutputsTracking(): void;
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports._recordOutputsHash = _recordOutputsHash;
|
|
4
4
|
exports._outputsHashesMatch = _outputsHashesMatch;
|
|
5
|
-
exports.recordedHash = recordedHash;
|
|
6
|
-
exports.recordOutputsHash = recordOutputsHash;
|
|
7
|
-
exports.outputsHashesMatch = outputsHashesMatch;
|
|
8
5
|
exports.processFileChangesInOutputs = processFileChangesInOutputs;
|
|
6
|
+
exports.outputsHashesMatchBatch = outputsHashesMatchBatch;
|
|
7
|
+
exports.recordOutputsHashBatch = recordOutputsHashBatch;
|
|
9
8
|
exports.disableOutputsTracking = disableOutputsTracking;
|
|
10
9
|
const path_1 = require("path");
|
|
11
10
|
const native_1 = require("../../native");
|
|
@@ -44,25 +43,6 @@ function _outputsHashesMatch(outputs, hash) {
|
|
|
44
43
|
}
|
|
45
44
|
return true;
|
|
46
45
|
}
|
|
47
|
-
function recordedHash(output) {
|
|
48
|
-
return recordedHashes[output];
|
|
49
|
-
}
|
|
50
|
-
async function recordOutputsHash(_outputs, hash) {
|
|
51
|
-
const outputs = await normalizeOutputs(_outputs);
|
|
52
|
-
if (disabled)
|
|
53
|
-
return;
|
|
54
|
-
_recordOutputsHash(outputs, hash);
|
|
55
|
-
}
|
|
56
|
-
async function outputsHashesMatch(_outputs, hash) {
|
|
57
|
-
const outputs = await normalizeOutputs(_outputs);
|
|
58
|
-
if (disabled)
|
|
59
|
-
return false;
|
|
60
|
-
return _outputsHashesMatch(outputs, hash);
|
|
61
|
-
}
|
|
62
|
-
async function normalizeOutputs(outputs) {
|
|
63
|
-
let expandedOutputs = (0, collapse_expanded_outputs_1.collapseExpandedOutputs)((0, native_1.getFilesForOutputs)(workspace_root_1.workspaceRoot, outputs));
|
|
64
|
-
return expandedOutputs;
|
|
65
|
-
}
|
|
66
46
|
function processFileChangesInOutputs(changeEvents, now = undefined) {
|
|
67
47
|
if (!now) {
|
|
68
48
|
now = new Date().getTime();
|
|
@@ -88,6 +68,53 @@ function processFileChangesInOutputs(changeEvents, now = undefined) {
|
|
|
88
68
|
}
|
|
89
69
|
}
|
|
90
70
|
}
|
|
71
|
+
/**
|
|
72
|
+
* Check whether the on-disk outputs of each entry still match the hash
|
|
73
|
+
* the daemon recorded for them. Uses Rayon-parallel filesystem scanning
|
|
74
|
+
* for uncached entries.
|
|
75
|
+
*/
|
|
76
|
+
function outputsHashesMatchBatch(entries) {
|
|
77
|
+
if (disabled)
|
|
78
|
+
return entries.map(() => false);
|
|
79
|
+
// Fast path: skip filesystem scan for entries with no recorded hash.
|
|
80
|
+
// _outputsHashesMatch will return false immediately if the hash isn't
|
|
81
|
+
// in numberOfExpandedOutputs, so scanning the filesystem is wasted work.
|
|
82
|
+
const needsScan = [];
|
|
83
|
+
const results = new Array(entries.length);
|
|
84
|
+
for (let i = 0; i < entries.length; i++) {
|
|
85
|
+
if (numberOfExpandedOutputs[entries[i].hash] === undefined) {
|
|
86
|
+
results[i] = false;
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
needsScan.push(i);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (needsScan.length > 0) {
|
|
93
|
+
// Only scan outputs for entries that have recorded hashes
|
|
94
|
+
const outputsBatch = needsScan.map((i) => entries[i].outputs);
|
|
95
|
+
const expandedBatch = (0, native_1.getFilesForOutputsBatch)(workspace_root_1.workspaceRoot, outputsBatch);
|
|
96
|
+
for (let j = 0; j < needsScan.length; j++) {
|
|
97
|
+
const expanded = (0, collapse_expanded_outputs_1.collapseExpandedOutputs)(expandedBatch[j]);
|
|
98
|
+
results[needsScan[j]] = _outputsHashesMatch(expanded, entries[needsScan[j]].hash);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return results;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Record the hash of each entry's on-disk outputs so future
|
|
105
|
+
* outputsHashesMatchBatch calls can skip redundant cache copies.
|
|
106
|
+
* Uses Rayon-parallel filesystem scanning.
|
|
107
|
+
*/
|
|
108
|
+
function recordOutputsHashBatch(entries) {
|
|
109
|
+
if (disabled)
|
|
110
|
+
return;
|
|
111
|
+
const outputsBatch = entries.map((e) => e.outputs);
|
|
112
|
+
const expandedBatch = (0, native_1.getFilesForOutputsBatch)(workspace_root_1.workspaceRoot, outputsBatch);
|
|
113
|
+
for (let i = 0; i < entries.length; i++) {
|
|
114
|
+
const expanded = (0, collapse_expanded_outputs_1.collapseExpandedOutputs)(expandedBatch[i]);
|
|
115
|
+
_recordOutputsHash(expanded, entries[i].hash);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
91
118
|
function disableOutputsTracking() {
|
|
92
119
|
disabled = true;
|
|
93
120
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FileData, FileMap, ProjectGraph } from '../../config/project-graph';
|
|
2
|
-
import { FileMapCache } from '../../project-graph/nx-deps-cache';
|
|
3
2
|
import { NxWorkspaceFilesExternals } from '../../native';
|
|
3
|
+
import { FileMapCache } from '../../project-graph/nx-deps-cache';
|
|
4
4
|
import { ConfigurationSourceMaps } from '../../project-graph/utils/project-configuration/source-maps';
|
|
5
5
|
interface SerializedProjectGraph {
|
|
6
6
|
error: Error | null;
|
|
@@ -24,4 +24,5 @@ export declare let currentSourceMaps: ConfigurationSourceMaps | undefined;
|
|
|
24
24
|
export declare function getCachedSerializedProjectGraphPromise(): Promise<SerializedProjectGraph>;
|
|
25
25
|
export declare function addUpdatedAndDeletedFiles(createdFiles: string[], updatedFiles: string[], deletedFiles: string[]): void;
|
|
26
26
|
export declare function registerProjectGraphRecomputationListener(listener: (projectGraph: ProjectGraph, sourceMaps: ConfigurationSourceMaps, error: Error | null) => void): void;
|
|
27
|
+
export declare function invalidateGraphCache(): void;
|
|
27
28
|
export {};
|
|
@@ -4,22 +4,23 @@ exports.currentSourceMaps = exports.currentProjectGraph = exports.currentProject
|
|
|
4
4
|
exports.getCachedSerializedProjectGraphPromise = getCachedSerializedProjectGraphPromise;
|
|
5
5
|
exports.addUpdatedAndDeletedFiles = addUpdatedAndDeletedFiles;
|
|
6
6
|
exports.registerProjectGraphRecomputationListener = registerProjectGraphRecomputationListener;
|
|
7
|
+
exports.invalidateGraphCache = invalidateGraphCache;
|
|
7
8
|
const perf_hooks_1 = require("perf_hooks");
|
|
8
9
|
const nx_json_1 = require("../../config/nx-json");
|
|
9
10
|
const file_hasher_1 = require("../../hasher/file-hasher");
|
|
10
11
|
const build_project_graph_1 = require("../../project-graph/build-project-graph");
|
|
12
|
+
const error_types_1 = require("../../project-graph/error-types");
|
|
11
13
|
const file_map_utils_1 = require("../../project-graph/file-map-utils");
|
|
12
14
|
const nx_deps_cache_1 = require("../../project-graph/nx-deps-cache");
|
|
15
|
+
const get_plugins_1 = require("../../project-graph/plugins/get-plugins");
|
|
13
16
|
const retrieve_workspace_files_1 = require("../../project-graph/utils/retrieve-workspace-files");
|
|
14
17
|
const fileutils_1 = require("../../utils/fileutils");
|
|
15
18
|
const workspace_context_1 = require("../../utils/workspace-context");
|
|
16
19
|
const workspace_root_1 = require("../../utils/workspace-root");
|
|
17
|
-
const
|
|
20
|
+
const logger_1 = require("../logger");
|
|
18
21
|
const file_change_events_1 = require("./file-watching/file-change-events");
|
|
22
|
+
const file_watcher_sockets_1 = require("./file-watching/file-watcher-sockets");
|
|
19
23
|
const project_graph_listener_sockets_1 = require("./project-graph-listener-sockets");
|
|
20
|
-
const logger_1 = require("../logger");
|
|
21
|
-
const error_types_1 = require("../../project-graph/error-types");
|
|
22
|
-
const get_plugins_1 = require("../../project-graph/plugins/get-plugins");
|
|
23
24
|
let cachedSerializedProjectGraphPromise;
|
|
24
25
|
// Maps file path to a version counter that increments on each modification.
|
|
25
26
|
// This lets us detect mid-flight re-modifications when clearing processed files.
|
|
@@ -86,9 +87,16 @@ async function getCachedSerializedProjectGraphPromise() {
|
|
|
86
87
|
const writeFn = graphWasRecomputed ? nx_deps_cache_1.writeCache : nx_deps_cache_1.writeCacheIfStale;
|
|
87
88
|
writeFn(result.projectFileMapCache, result.projectGraph, result.sourceMaps, errors);
|
|
88
89
|
}
|
|
90
|
+
if (errors?.length) {
|
|
91
|
+
cachedSerializedProjectGraphPromise = null;
|
|
92
|
+
}
|
|
89
93
|
return result;
|
|
90
94
|
}
|
|
91
95
|
catch (e) {
|
|
96
|
+
// We return the project graph, but we don't want to persist the cache to
|
|
97
|
+
// serve the same state, as it could cause issues if the error is caused by something
|
|
98
|
+
// transient
|
|
99
|
+
cachedSerializedProjectGraphPromise = null;
|
|
92
100
|
return {
|
|
93
101
|
error: e,
|
|
94
102
|
serializedProjectGraph: null,
|
|
@@ -180,6 +188,14 @@ async function processCollectedUpdatedAndDeletedFiles({ projects, externalNodes,
|
|
|
180
188
|
throw e;
|
|
181
189
|
}
|
|
182
190
|
}
|
|
191
|
+
function invalidateGraphCache() {
|
|
192
|
+
// Clear the cached promise so the next request triggers a fresh computation.
|
|
193
|
+
// We intentionally do NOT call getCachedSerializedProjectGraphPromise() here
|
|
194
|
+
// because assigning its return Promise to the module-level variable causes a
|
|
195
|
+
// deadlock: the async function resumes, sees the variable is non-null (pointing
|
|
196
|
+
// at its own Promise), takes the "reuse" branch, and awaits itself forever.
|
|
197
|
+
cachedSerializedProjectGraphPromise = null;
|
|
198
|
+
}
|
|
183
199
|
async function processFilesAndCreateAndSerializeProjectGraph(plugins) {
|
|
184
200
|
const myGeneration = ++recomputationGeneration;
|
|
185
201
|
// Helper to check if this recomputation is stale (a newer one has started)
|