nx 23.3.0 → 24.0.0-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.
- package/README.md +3 -6
- package/dist/src/adapter/ngcli-adapter.js +1 -0
- package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +0 -12
- package/dist/src/command-line/graph/graph.js +3 -5
- package/dist/src/command-line/init/command-object.js +0 -12
- package/dist/src/command-line/init/init-v2.js +0 -2
- package/dist/src/command-line/nx-cloud/connect/connect-to-nx-cloud.js +17 -12
- package/dist/src/command-line/release/utils/remote-release-clients/github.js +5 -6
- package/dist/src/command-line/release/utils/remote-release-clients/gitlab.js +5 -6
- package/dist/src/command-line/run/executor-utils.js +1 -0
- package/dist/src/command-line/run/run-one.d.ts +20 -1
- package/dist/src/command-line/run/run-one.js +153 -5
- package/dist/src/command-line/show/show-target/utils.js +1 -0
- package/dist/src/command-line/watch/command-object.js +3 -22
- package/dist/src/command-line/watch/watch.d.ts +0 -7
- package/dist/src/command-line/watch/watch.js +1 -1
- package/dist/src/config/misc-interfaces.d.ts +12 -0
- package/dist/src/config/workspace-json-project-json.d.ts +5 -0
- package/dist/src/daemon/client/client.d.ts +9 -0
- package/dist/src/daemon/client/client.js +89 -37
- package/dist/src/daemon/server/shutdown-utils.js +0 -3
- package/dist/src/daemon/socket-utils.d.ts +9 -4
- package/dist/src/daemon/socket-utils.js +12 -49
- package/dist/src/daemon/tmp-dir.d.ts +19 -14
- package/dist/src/daemon/tmp-dir.js +142 -354
- package/dist/src/devkit-internals.d.ts +1 -1
- package/dist/src/devkit-internals.js +1 -0
- package/dist/src/hasher/file-hasher.js +9 -7
- package/dist/src/hasher/hash-task.js +4 -0
- package/dist/src/hasher/native-task-hasher-impl.js +1 -1
- package/dist/src/migrations/update-24-0-0/find-custom-hashers.d.ts +3 -0
- package/dist/src/migrations/update-24-0-0/find-custom-hashers.js +100 -0
- package/dist/src/migrations/update-24-0-0/find-custom-hashers.md +63 -0
- package/dist/src/migrations/update-24-0-0/move-custom-hashers-to-inputs.md +145 -0
- package/dist/src/native/index.d.ts +127 -8
- package/dist/src/native/native-bindings.js +5 -0
- package/dist/src/native/nx.wasi-browser.js +1 -0
- package/dist/src/native/nx.wasi.cjs +1 -0
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/nx-cloud/update-manager.d.ts +7 -0
- package/dist/src/nx-cloud/update-manager.js +237 -50
- package/dist/src/project-graph/affected/affected-tasks.js +1 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +7 -0
- package/dist/src/tasks-runner/create-task-graph.d.ts +10 -0
- package/dist/src/tasks-runner/create-task-graph.js +37 -2
- package/dist/src/tasks-runner/task-env.d.ts +10 -0
- package/dist/src/tasks-runner/task-env.js +26 -5
- package/dist/src/tasks-runner/task-orchestrator.d.ts +10 -4
- package/dist/src/tasks-runner/task-orchestrator.js +87 -53
- package/dist/src/tasks-runner/utils.d.ts +20 -5
- package/dist/src/tasks-runner/utils.js +80 -29
- package/dist/src/ultracache/overrides.js +4 -0
- package/dist/src/utils/owned-private-dir.d.ts +1 -17
- package/dist/src/utils/owned-private-dir.js +10 -62
- package/dist/src/utils/perf-hooks.d.ts +1 -0
- package/dist/src/utils/plugins/core-plugins.js +1 -1
- package/dist/src/utils/string-similarity.d.ts +38 -0
- package/dist/src/utils/string-similarity.js +108 -0
- package/migrations.json +7 -0
- package/package.json +11 -20
- package/readme-template.md +3 -3
- package/schemas/nx-schema.json +5 -0
- package/schemas/project-schema.json +5 -0
- package/dist/src/tasks-runner/legacy-depends-on-warning.d.ts +0 -18
- package/dist/src/tasks-runner/legacy-depends-on-warning.js +0 -109
|
@@ -98,7 +98,7 @@ function taskGraphFingerprint(taskGraph, ultracacheConfigurations) {
|
|
|
98
98
|
];
|
|
99
99
|
for (const id of Object.keys(taskGraph.tasks).sort()) {
|
|
100
100
|
const task = taskGraph.tasks[id];
|
|
101
|
-
parts.push(id, task.target.project, task.target.target, task.target.configuration ?? '', (task.outputs ?? []).join(','), (taskGraph.dependencies[id] ?? []).join(','), (taskGraph.continuousDependencies[id] ?? []).join(','));
|
|
101
|
+
parts.push(id, task.target.project, task.target.target, task.target.configuration ?? '', (task.outputs ?? []).join(','), (taskGraph.dependencies[id] ?? []).join(','), (taskGraph.continuousDependencies[id] ?? []).join(','), (taskGraph.continuousDependenciesWithoutInputs?.[id] ?? []).join(','));
|
|
102
102
|
}
|
|
103
103
|
return (0, native_1.hashArray)(parts);
|
|
104
104
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = findCustomHashers;
|
|
4
|
+
const glob_1 = require("../../generators/utils/glob");
|
|
5
|
+
const json_1 = require("../../utils/json");
|
|
6
|
+
const path_1 = require("../../utils/path");
|
|
7
|
+
const node_path_1 = require("node:path");
|
|
8
|
+
const DOCS_URL = 'https://nx.dev/docs/kb/local-executors#replace-a-custom-hasher-with-inputs';
|
|
9
|
+
async function findCustomHashers(tree) {
|
|
10
|
+
const hits = new Set();
|
|
11
|
+
const malformed = new Set();
|
|
12
|
+
const unparseable = [];
|
|
13
|
+
const visited = new Set();
|
|
14
|
+
for (const packageJsonPath of await (0, glob_1.globAsync)(tree, ['**/package.json'])) {
|
|
15
|
+
if (packageJsonPath.split('/').includes('node_modules')) {
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
const content = tree.read(packageJsonPath, 'utf-8');
|
|
19
|
+
if (!content.includes('"executors"') && !content.includes('"builders"')) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
const packageJson = tryParse(content);
|
|
23
|
+
if (!packageJson) {
|
|
24
|
+
unparseable.push(packageJsonPath);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const packageRoot = node_path_1.posix.dirname(packageJsonPath);
|
|
28
|
+
// A nameless local plugin is referenced by its relative path.
|
|
29
|
+
const pluginName = packageJson.name ?? (packageRoot === '.' ? '.' : `./${packageRoot}`);
|
|
30
|
+
for (const field of [packageJson.executors, packageJson.builders]) {
|
|
31
|
+
if (typeof field !== 'string') {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const executorsJsonPath = (0, path_1.joinPathFragments)(packageRoot, field);
|
|
35
|
+
if (visited.has(executorsJsonPath) || !tree.exists(executorsJsonPath)) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
visited.add(executorsJsonPath);
|
|
39
|
+
const executorsJson = tryParse(tree.read(executorsJsonPath, 'utf-8'));
|
|
40
|
+
if (!executorsJson) {
|
|
41
|
+
unparseable.push(executorsJsonPath);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const entries = [];
|
|
45
|
+
for (const map of [executorsJson.executors, executorsJson.builders]) {
|
|
46
|
+
if (map === undefined) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (!isPlainObject(map)) {
|
|
50
|
+
unparseable.push(executorsJsonPath);
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
entries.push(...Object.entries(map));
|
|
54
|
+
}
|
|
55
|
+
for (const [name, entry] of entries) {
|
|
56
|
+
if (typeof entry === 'string') {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (!isPlainObject(entry) || !isValidHasher(entry.hasher)) {
|
|
60
|
+
malformed.add(`Entry "${name}" in "${executorsJsonPath}" is not a valid executor entry. Check it by hand for a "hasher".`);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (entry.hasher === undefined) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const hasherPath = (0, path_1.joinPathFragments)(node_path_1.posix.dirname(executorsJsonPath), entry.hasher);
|
|
67
|
+
hits.add(`Executor "${pluginName}:${name}" declares a custom hasher at "${hasherPath}" in "${executorsJsonPath}".`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
if (hits.size === 0 && malformed.size === 0 && unparseable.length === 0) {
|
|
72
|
+
return { skipAgentic: true };
|
|
73
|
+
}
|
|
74
|
+
const manualNotes = [
|
|
75
|
+
...malformed,
|
|
76
|
+
...unparseable.map((path) => `Could not parse "${path}". Check it by hand for executors that declare a "hasher".`),
|
|
77
|
+
];
|
|
78
|
+
return {
|
|
79
|
+
nextSteps: [
|
|
80
|
+
`Custom hashers are deprecated and will be removed in Nx 25. Replace each one with target inputs, then remove "hasher" from executors.json. See ${DOCS_URL}`,
|
|
81
|
+
...hits,
|
|
82
|
+
...manualNotes,
|
|
83
|
+
],
|
|
84
|
+
agentContext: [...hits, ...manualNotes],
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function isPlainObject(value) {
|
|
88
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
89
|
+
}
|
|
90
|
+
function isValidHasher(hasher) {
|
|
91
|
+
return hasher === undefined || typeof hasher === 'string';
|
|
92
|
+
}
|
|
93
|
+
function tryParse(content) {
|
|
94
|
+
try {
|
|
95
|
+
return (0, json_1.parseJson)(content);
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
#### Move custom executor hashers to target inputs
|
|
2
|
+
|
|
3
|
+
Custom hashers are deprecated in Nx 24 and will be removed in Nx 25.
|
|
4
|
+
A custom hasher is the `hasher` property of an executor in `executors.json`, pointing at a module that computes the task hash in code.
|
|
5
|
+
Target `inputs` replace them.
|
|
6
|
+
|
|
7
|
+
This migration finds every local plugin in the workspace whose `executors.json` (or `builders.json`) declares a `hasher`.
|
|
8
|
+
It doesn't edit any files.
|
|
9
|
+
When it finds one, it lists the executor, the hasher module, and the `executors.json` file in the migration's next steps.
|
|
10
|
+
It also lists files and executor entries it can't read, so you can check those by hand.
|
|
11
|
+
Under `nx migrate` with an AI agent, the agent reads each hasher and writes `inputs` that hash the same things.
|
|
12
|
+
A target that declares its own `inputs` doesn't inherit them from `targetDefaults`, so the agent checks every target that uses the executor and adds the inputs where they're missing.
|
|
13
|
+
It removes the `hasher` only once every one of those targets is covered.
|
|
14
|
+
If something the hasher hashes can't be expressed as an input, the agent leaves the hasher in place and tells you why.
|
|
15
|
+
|
|
16
|
+
Packages installed in `node_modules` aren't scanned.
|
|
17
|
+
If a third-party plugin you use declares a hasher, Nx warns about it when it hashes one of its tasks.
|
|
18
|
+
|
|
19
|
+
#### Sample code changes
|
|
20
|
+
|
|
21
|
+
Given a local plugin whose `echo` executor hashes the project, its dependencies, and the `API_URL` environment variable:
|
|
22
|
+
|
|
23
|
+
##### Before
|
|
24
|
+
|
|
25
|
+
```json title="tools/my-plugin/executors.json"
|
|
26
|
+
{
|
|
27
|
+
"executors": {
|
|
28
|
+
"echo": {
|
|
29
|
+
"implementation": "./src/executors/echo/executor",
|
|
30
|
+
"hasher": "./src/executors/echo/hasher",
|
|
31
|
+
"schema": "./src/executors/echo/schema.json"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
##### After
|
|
38
|
+
|
|
39
|
+
```json title="nx.json"
|
|
40
|
+
{
|
|
41
|
+
"targetDefaults": {
|
|
42
|
+
"@acme/my-plugin:echo": {
|
|
43
|
+
"inputs": ["default", "^default", { "env": "API_URL" }]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```json title="tools/my-plugin/executors.json"
|
|
50
|
+
{
|
|
51
|
+
"executors": {
|
|
52
|
+
"echo": {
|
|
53
|
+
"implementation": "./src/executors/echo/executor",
|
|
54
|
+
"schema": "./src/executors/echo/schema.json"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
#### Reference
|
|
61
|
+
|
|
62
|
+
- [Replace a custom hasher with inputs](https://nx.dev/docs/kb/local-executors#replace-a-custom-hasher-with-inputs)
|
|
63
|
+
- [Inputs reference](https://nx.dev/docs/reference/inputs)
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Move custom executor hashers to target inputs
|
|
2
|
+
|
|
3
|
+
Custom hashers (the `hasher` property of an executor in `executors.json`) are
|
|
4
|
+
deprecated in Nx 24 and removed in Nx 25. Each one should become target `inputs`
|
|
5
|
+
that hash the same things, so the targets keep caching correctly once the hasher
|
|
6
|
+
is gone.
|
|
7
|
+
|
|
8
|
+
The generator half of this migration only scans. It edits no files, and it lists
|
|
9
|
+
every executor that declares a hasher in the advisory context, one line each,
|
|
10
|
+
with the executor name, the hasher path, and the `executors.json` path. Lines
|
|
11
|
+
starting with `Could not parse` name files the scan skipped, and lines starting
|
|
12
|
+
with `Entry` name executor entries it could not read.
|
|
13
|
+
|
|
14
|
+
Do not touch executors that declare no hasher, executors installed from
|
|
15
|
+
`node_modules`, or any other caching configuration.
|
|
16
|
+
|
|
17
|
+
## First, check whether there is anything to do
|
|
18
|
+
|
|
19
|
+
Confirm this before changing anything. If it fails, make no changes and stop:
|
|
20
|
+
|
|
21
|
+
1. The advisory context lists at least one executor that declares a custom
|
|
22
|
+
hasher, or at least one file or entry it could not read. Read each of those
|
|
23
|
+
yourself; if it declares no `hasher`, drop it from the list.
|
|
24
|
+
|
|
25
|
+
## Step 1: Read what each hasher hashes
|
|
26
|
+
|
|
27
|
+
Open the hasher module named in the advisory context. Work out every value it
|
|
28
|
+
feeds into the hash it returns:
|
|
29
|
+
|
|
30
|
+
- `context.hasher.hashTask(task, ...)` alone is Nx default hashing.
|
|
31
|
+
- Files it reads, globs it walks, or other projects it hashes.
|
|
32
|
+
- Environment variables it reads.
|
|
33
|
+
- Commands it runs, or data it fetches (a remote API, a registry lookup).
|
|
34
|
+
|
|
35
|
+
## Step 2: Write equivalent inputs
|
|
36
|
+
|
|
37
|
+
Map each value to an input:
|
|
38
|
+
|
|
39
|
+
| What the hasher hashes | Input |
|
|
40
|
+
| ----------------------------------------------------- | ------------------------------------------------------- |
|
|
41
|
+
| The project and its dependencies (Nx default hashing) | `"default"` and `"^default"` |
|
|
42
|
+
| Files of specific other projects | `{ "input": "default", "projects": ["shared-config"] }` |
|
|
43
|
+
| A subset of the files in the project | `{ "fileset": "{projectRoot}/src/**/*.graphql" }` |
|
|
44
|
+
| A file outside any project | `{ "fileset": "{workspaceRoot}/schema.json" }` |
|
|
45
|
+
| An environment variable | `{ "env": "API_URL" }` |
|
|
46
|
+
| The output of a command, such as a tool version | `{ "runtime": "node --version" }` |
|
|
47
|
+
|
|
48
|
+
If the workspace defines named inputs such as `production`, prefer them over
|
|
49
|
+
`default` where the hasher excluded test files.
|
|
50
|
+
|
|
51
|
+
### Find every target that uses the executor
|
|
52
|
+
|
|
53
|
+
Write the resolved project graph and list every target whose `executor` is the
|
|
54
|
+
executor name (`"@acme/my-plugin:echo"`):
|
|
55
|
+
|
|
56
|
+
```shell
|
|
57
|
+
npx nx graph --file=tmp/custom-hashers-graph.json
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Each target in `graph.nodes.<project>.data.targets` there is fully resolved: it
|
|
61
|
+
already reflects `targetDefaults` (including filtered array entries), inferred
|
|
62
|
+
targets, and project-level overrides. Record each consuming target's resolved
|
|
63
|
+
`inputs`. Every one of them must end up covered.
|
|
64
|
+
|
|
65
|
+
### Place the inputs
|
|
66
|
+
|
|
67
|
+
A target that declares its own `inputs` replaces the `inputs` from
|
|
68
|
+
`targetDefaults` rather than merging with them. So a `targetDefaults` edit alone
|
|
69
|
+
does not reach a target that already declares `inputs`.
|
|
70
|
+
|
|
71
|
+
1. Set the inputs in `nx.json` `targetDefaults` under the executor name. If that
|
|
72
|
+
key already exists, add `inputs` to it, and merge with any `inputs` it already
|
|
73
|
+
declares rather than replacing them. If its value is an array of filtered
|
|
74
|
+
entries, add the inputs to every entry that applies to a consuming target.
|
|
75
|
+
2. For every consuming target that declares its own `inputs`, add the
|
|
76
|
+
replacement inputs to that target as well, keeping the inputs it already has.
|
|
77
|
+
It is declared in `project.json`, in the `nx.targets` block of
|
|
78
|
+
`package.json`, or by the plugin that infers the target. For an inferred
|
|
79
|
+
target, set `inputs` in `project.json` to the full resolved list plus the
|
|
80
|
+
replacement inputs.
|
|
81
|
+
3. Write the graph again and confirm that every consuming target's resolved
|
|
82
|
+
`inputs` now contains every replacement input. Fix any that do not.
|
|
83
|
+
|
|
84
|
+
**Before:**
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
// tools/my-plugin/executors.json
|
|
88
|
+
{
|
|
89
|
+
"executors": {
|
|
90
|
+
"echo": {
|
|
91
|
+
"implementation": "./src/executors/echo/executor",
|
|
92
|
+
"hasher": "./src/executors/echo/hasher",
|
|
93
|
+
"schema": "./src/executors/echo/schema.json"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**After:**
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
// nx.json
|
|
103
|
+
{
|
|
104
|
+
"targetDefaults": {
|
|
105
|
+
"@acme/my-plugin:echo": {
|
|
106
|
+
"inputs": ["default", "^default", { "env": "API_URL" }]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```json
|
|
113
|
+
// tools/my-plugin/executors.json
|
|
114
|
+
{
|
|
115
|
+
"executors": {
|
|
116
|
+
"echo": {
|
|
117
|
+
"implementation": "./src/executors/echo/executor",
|
|
118
|
+
"schema": "./src/executors/echo/schema.json"
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Step 3: Remove the hasher only when the inputs cover it
|
|
125
|
+
|
|
126
|
+
Remove `hasher` from `executors.json` and delete the hasher module (and its
|
|
127
|
+
spec) only once the resolved inputs of every consuming target cover everything
|
|
128
|
+
the hasher hashed.
|
|
129
|
+
|
|
130
|
+
If a value has no file, environment variable, or project to point at, such as
|
|
131
|
+
data fetched from a remote service, use a `runtime` input whose command prints
|
|
132
|
+
that value. If no command can reproduce it, leave the hasher in place and tell
|
|
133
|
+
the user which value blocks the move and why.
|
|
134
|
+
|
|
135
|
+
## Post-Migration Validation
|
|
136
|
+
|
|
137
|
+
1. `npx nx show target <project>:<target>` for every consuming target found in
|
|
138
|
+
Step 2. Confirm each one lists the replacement inputs. After the hasher is
|
|
139
|
+
removed, `npx nx show target <project>:<target> inputs` also shows the files
|
|
140
|
+
and values those inputs resolve to.
|
|
141
|
+
2. `npx nx run-many -t <target>` twice for the targets that used the executor.
|
|
142
|
+
The second run should be a cache hit. Change a file the hasher used to hash
|
|
143
|
+
and confirm the next run is a cache miss.
|
|
144
|
+
3. `npx nx run-many -t build,test,lint -p <plugin project>` if you deleted hasher
|
|
145
|
+
files. Fix failures caused by this migration and re-run until green.
|
|
@@ -236,6 +236,10 @@ export declare class RunningTasksService {
|
|
|
236
236
|
constructor(db: ExternalObject<NxDbConnection>)
|
|
237
237
|
getRunningTasks(ids: Array<string>): Array<string>
|
|
238
238
|
addRunningTask(taskId: string): void
|
|
239
|
+
/**
|
|
240
|
+
* Release this process's claim on a task. A row another process has since
|
|
241
|
+
* taken over is left in place.
|
|
242
|
+
*/
|
|
239
243
|
removeRunningTask(taskId: string): void
|
|
240
244
|
}
|
|
241
245
|
|
|
@@ -282,14 +286,42 @@ export declare class TaskHasher {
|
|
|
282
286
|
hashPlansFor(hashPlans: ExternalObject<Record<string, Array<HashInstruction>>>, taskIds: Array<string>, perTaskEnvs: Record<string, Record<string, string>>, cwd: string, collectTaskInputs?: boolean | undefined | null): Record<string, HashDetails>
|
|
283
287
|
}
|
|
284
288
|
|
|
289
|
+
/**
|
|
290
|
+
* Tracks which tasks each Nx process in a nested process tree is running, so
|
|
291
|
+
* that a task which re-invokes itself can be reported instead of looping
|
|
292
|
+
* forever.
|
|
293
|
+
*
|
|
294
|
+
* Every process in the tree shares a `root_pid`, but sharing a root does not
|
|
295
|
+
* imply a parent/child relationship: sibling Nx processes are common and
|
|
296
|
+
* legitimate (N atomized e2e specs each spawning the same `serve-static` web
|
|
297
|
+
* server, or two parallel tasks that each shell out to `nx run lib:build`).
|
|
298
|
+
* Only an invocation belonging to an actual *ancestor* of this process is a
|
|
299
|
+
* loop, so the check is scoped to `ancestor_pids` rather than to the whole
|
|
300
|
+
* tree.
|
|
301
|
+
*/
|
|
285
302
|
export declare class TaskInvocationTracker {
|
|
286
|
-
constructor(db: ExternalObject<NxDbConnection>, rootPid: number)
|
|
287
|
-
/**
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
303
|
+
constructor(db: ExternalObject<NxDbConnection>, rootPid: number, ancestorPids: Array<number>)
|
|
304
|
+
/**
|
|
305
|
+
* Register a task as invoked by the process identified by `pid`.
|
|
306
|
+
*
|
|
307
|
+
* Returns the invocation chain when an ancestor process is already running
|
|
308
|
+
* this task, which is a genuine loop. The chain lists every task invoked
|
|
309
|
+
* along the ancestry path, outermost first. Returns `null` when the task
|
|
310
|
+
* was registered, including when a *sibling* process is already running it.
|
|
311
|
+
*
|
|
312
|
+
* An ancestor running this task with the *same* overrides is a loop
|
|
313
|
+
* immediately. An ancestor running it with different overrides is allowed
|
|
314
|
+
* up to `MAX_ANCESTOR_INVOCATIONS_PER_TASK`, which lets a terminating
|
|
315
|
+
* `app:build -> app:build --flag` chain through while still bounding a
|
|
316
|
+
* recursion whose forwarded arguments grow on every hop.
|
|
317
|
+
*/
|
|
318
|
+
registerTask(pid: number, taskId: string, overridesHash: string): Array<InvocationRecord> | null
|
|
319
|
+
/**
|
|
320
|
+
* Remove a task invocation record after the task completes. Scoped to the
|
|
321
|
+
* registering process so that a sibling finishing the same task does not
|
|
322
|
+
* drop this process's record.
|
|
323
|
+
*/
|
|
324
|
+
unregisterTask(pid: number, taskId: string): void
|
|
293
325
|
/** Clean up stale invocations older than 1 day (handles PID recycling). */
|
|
294
326
|
cleanupStale(): void
|
|
295
327
|
}
|
|
@@ -886,7 +918,7 @@ export declare function installNxConsole(): Promise<boolean>
|
|
|
886
918
|
export declare function installNxConsoleForEditor(editor: SupportedEditor): Promise<boolean>
|
|
887
919
|
|
|
888
920
|
export interface InvocationRecord {
|
|
889
|
-
|
|
921
|
+
pid: number
|
|
890
922
|
taskId: string
|
|
891
923
|
}
|
|
892
924
|
|
|
@@ -1012,6 +1044,14 @@ export interface NxWorkspaceFilesExternals {
|
|
|
1012
1044
|
ignoredIndex: ExternalObject<IgnoredIndexReader>
|
|
1013
1045
|
}
|
|
1014
1046
|
|
|
1047
|
+
/**
|
|
1048
|
+
* Open `url` in the user's default browser. Returns `true` if an opener
|
|
1049
|
+
* process was spawned, `false` if none could be (e.g. no `xdg-open`) or `url`
|
|
1050
|
+
* isn't `http(s)`, so the caller can tell the user instead of failing
|
|
1051
|
+
* silently. Never throws.
|
|
1052
|
+
*/
|
|
1053
|
+
export declare function openUrl(url: string): boolean
|
|
1054
|
+
|
|
1015
1055
|
/** A workspace-relative file with the stamp it was left with. */
|
|
1016
1056
|
export interface OutputFile {
|
|
1017
1057
|
path: string
|
|
@@ -1078,6 +1118,32 @@ export interface ProjectGraph {
|
|
|
1078
1118
|
|
|
1079
1119
|
export declare function remove(src: string): void
|
|
1080
1120
|
|
|
1121
|
+
/**
|
|
1122
|
+
* The daemon's own socket. Per run — the directory name hashes the pid, and
|
|
1123
|
+
* clients read the daemon's path back out of the process cache rather than
|
|
1124
|
+
* deriving it.
|
|
1125
|
+
*/
|
|
1126
|
+
export declare function resolveDaemonSocketPath(workspaceRoot: string, env?: Record<string, string> | undefined | null): SocketDirDetails
|
|
1127
|
+
|
|
1128
|
+
/** A forked task process's socket, in the daemon's per-run directory. */
|
|
1129
|
+
export declare function resolveForkedProcessSocketPath(workspaceRoot: string, id: string, env?: Record<string, string> | undefined | null): SocketDirDetails
|
|
1130
|
+
|
|
1131
|
+
/**
|
|
1132
|
+
* Where the Nx Console socket lives, for whoever binds or connects to it.
|
|
1133
|
+
*
|
|
1134
|
+
* `env` is for callers that load a workspace `.env` into a copy rather than
|
|
1135
|
+
* into their own environment, and `workspaceRoot` for callers that do not run
|
|
1136
|
+
* inside the workspace — Nx Console is both, since it runs in the editor's
|
|
1137
|
+
* extension host.
|
|
1138
|
+
*/
|
|
1139
|
+
export declare function resolveNxConsoleSocketPath(workspaceRoot: string, env?: Record<string, string> | undefined | null): SocketDirDetails
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* Plugin worker sockets get their own workspace-scoped directory rather than
|
|
1143
|
+
* sitting in the shared system temp dir, which cannot be locked down.
|
|
1144
|
+
*/
|
|
1145
|
+
export declare function resolvePluginSocketPath(workspaceRoot: string, id: string, env?: Record<string, string> | undefined | null): SocketDirDetails
|
|
1146
|
+
|
|
1081
1147
|
export declare function restoreTerminal(): void
|
|
1082
1148
|
|
|
1083
1149
|
export declare const enum RunMode {
|
|
@@ -1089,6 +1155,53 @@ export interface RuntimeInput {
|
|
|
1089
1155
|
runtime: string
|
|
1090
1156
|
}
|
|
1091
1157
|
|
|
1158
|
+
/**
|
|
1159
|
+
* One resolved socket location, and everything `daemon/tmp-dir.ts` needs to
|
|
1160
|
+
* explain it. Every user-facing sentence is rendered on the TypeScript side,
|
|
1161
|
+
* so this carries facts rather than prose.
|
|
1162
|
+
*/
|
|
1163
|
+
export interface SocketDirDetails {
|
|
1164
|
+
/** The socket itself, which on Windows is a named pipe rather than a path. */
|
|
1165
|
+
path: string
|
|
1166
|
+
/** The directory holding it, for the caller that deletes it on shutdown. */
|
|
1167
|
+
dir: string
|
|
1168
|
+
/**
|
|
1169
|
+
* Whether `path` exceeds what the platform will bind. Reported rather than
|
|
1170
|
+
* thrown because which advice is correct depends on the other fields.
|
|
1171
|
+
*/
|
|
1172
|
+
tooLong: boolean
|
|
1173
|
+
/**
|
|
1174
|
+
* Set when `path` is a directory Nx refuses to *be* the socket directory:
|
|
1175
|
+
* `shared-with-other-users`, `nx-managed`, or `os-temp-root`. The caller
|
|
1176
|
+
* throws on it rather than using `path`.
|
|
1177
|
+
*/
|
|
1178
|
+
invalidReason?: string
|
|
1179
|
+
/** The preferred root that was skipped, when a later tier was used. */
|
|
1180
|
+
demotedFrom?: string
|
|
1181
|
+
/**
|
|
1182
|
+
* The default-root directory Nx tried before falling back, when there was
|
|
1183
|
+
* one.
|
|
1184
|
+
*/
|
|
1185
|
+
attemptedDir?: string
|
|
1186
|
+
/**
|
|
1187
|
+
* The `NX_SOCKET_DIR` that was refused, when that is why this is a
|
|
1188
|
+
* fallback. Tracked apart from the other reasons so a later length error
|
|
1189
|
+
* stops telling someone to shorten a directory refused for another one.
|
|
1190
|
+
*/
|
|
1191
|
+
refusedConfiguredDir?: string
|
|
1192
|
+
/** Why that configured directory was refused. */
|
|
1193
|
+
refusalError?: string
|
|
1194
|
+
/**
|
|
1195
|
+
* Whether this landed in the workspace data dir, which the caller warns
|
|
1196
|
+
* about once per process.
|
|
1197
|
+
*/
|
|
1198
|
+
usedWorkspaceFallback: boolean
|
|
1199
|
+
/** Deduplicated advice for the refusals collected along the way. */
|
|
1200
|
+
remedies: Array<string>
|
|
1201
|
+
/** Every refusal as one sentence, for `--verbose`. */
|
|
1202
|
+
refusalDetails?: string
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1092
1205
|
export declare const enum SupportedEditor {
|
|
1093
1206
|
VSCode = 0,
|
|
1094
1207
|
VSCodeInsiders = 1,
|
|
@@ -1177,6 +1290,11 @@ export interface TaskGraph {
|
|
|
1177
1290
|
/** Map of Task IDs to IDs of tasks which the task depends on */
|
|
1178
1291
|
dependencies: Record<string, Array<string>>
|
|
1179
1292
|
continuousDependencies: Record<string, Array<string>>
|
|
1293
|
+
/**
|
|
1294
|
+
* The subset of `continuous_dependencies` from `dependsOn` entries with
|
|
1295
|
+
* `inputs: false`: still run, but their inputs are not hashed into the task.
|
|
1296
|
+
*/
|
|
1297
|
+
continuousDependenciesWithoutInputs?: Record<string, Array<string>>
|
|
1180
1298
|
}
|
|
1181
1299
|
|
|
1182
1300
|
/** Details about the composition of a task's hash */
|
|
@@ -1346,6 +1464,7 @@ export interface UltracacheDiagnostic {
|
|
|
1346
1464
|
export interface UltracacheEligibilityOptions {
|
|
1347
1465
|
/** Tasks whose executor ships a custom hasher. */
|
|
1348
1466
|
customHasherTaskIds?: Array<string>
|
|
1467
|
+
continuousTaskIds?: Array<string>
|
|
1349
1468
|
}
|
|
1350
1469
|
|
|
1351
1470
|
/**
|
|
@@ -638,8 +638,13 @@ module.exports.locateTouchedProjects = nativeBinding.locateTouchedProjects
|
|
|
638
638
|
module.exports.logDebug = nativeBinding.logDebug
|
|
639
639
|
module.exports.matchGlobPaths = nativeBinding.matchGlobPaths
|
|
640
640
|
module.exports.matchOutputPaths = nativeBinding.matchOutputPaths
|
|
641
|
+
module.exports.openUrl = nativeBinding.openUrl
|
|
641
642
|
module.exports.parseTaskStatus = nativeBinding.parseTaskStatus
|
|
642
643
|
module.exports.remove = nativeBinding.remove
|
|
644
|
+
module.exports.resolveDaemonSocketPath = nativeBinding.resolveDaemonSocketPath
|
|
645
|
+
module.exports.resolveForkedProcessSocketPath = nativeBinding.resolveForkedProcessSocketPath
|
|
646
|
+
module.exports.resolveNxConsoleSocketPath = nativeBinding.resolveNxConsoleSocketPath
|
|
647
|
+
module.exports.resolvePluginSocketPath = nativeBinding.resolvePluginSocketPath
|
|
643
648
|
module.exports.restoreTerminal = nativeBinding.restoreTerminal
|
|
644
649
|
module.exports.RunMode = nativeBinding.RunMode
|
|
645
650
|
module.exports.SupportedEditor = nativeBinding.SupportedEditor
|
|
@@ -124,6 +124,7 @@ export const installNxConsole = __napiModule.exports.installNxConsole
|
|
|
124
124
|
export const IS_WASM = __napiModule.exports.IS_WASM
|
|
125
125
|
export const isAiAgent = __napiModule.exports.isAiAgent
|
|
126
126
|
export const logDebug = __napiModule.exports.logDebug
|
|
127
|
+
export const openUrl = __napiModule.exports.openUrl
|
|
127
128
|
export const remove = __napiModule.exports.remove
|
|
128
129
|
export const testOnlyTransferFileMap = __napiModule.exports.testOnlyTransferFileMap
|
|
129
130
|
export const transferProjectGraph = __napiModule.exports.transferProjectGraph
|
|
@@ -154,6 +154,7 @@ module.exports.installNxConsole = __napiModule.exports.installNxConsole
|
|
|
154
154
|
module.exports.IS_WASM = __napiModule.exports.IS_WASM
|
|
155
155
|
module.exports.isAiAgent = __napiModule.exports.isAiAgent
|
|
156
156
|
module.exports.logDebug = __napiModule.exports.logDebug
|
|
157
|
+
module.exports.openUrl = __napiModule.exports.openUrl
|
|
157
158
|
module.exports.remove = __napiModule.exports.remove
|
|
158
159
|
module.exports.testOnlyTransferFileMap = __napiModule.exports.testOnlyTransferFileMap
|
|
159
160
|
module.exports.transferProjectGraph = __napiModule.exports.transferProjectGraph
|
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
import { HttpClient } from '../utils/http-client';
|
|
1
2
|
import type { CloudTaskRunnerOptions } from './nx-cloud-tasks-runner-shell';
|
|
2
3
|
import type { ReadUltracacheConfigurationsOptions, ReadUltracacheConfigurationsResult } from '../ultracache/fetch';
|
|
3
4
|
import { TasksRunner } from '../tasks-runner/tasks-runner';
|
|
4
5
|
import { RemoteCacheV2 } from '../tasks-runner/default-tasks-runner';
|
|
6
|
+
interface CloudBundleInstall {
|
|
7
|
+
version: string;
|
|
8
|
+
fullPath: string;
|
|
9
|
+
}
|
|
5
10
|
export declare class NxCloudEnterpriseOutdatedError extends Error {
|
|
6
11
|
constructor(url: string);
|
|
7
12
|
}
|
|
@@ -24,3 +29,5 @@ export declare function verifyOrUpdateNxCloudClient(options?: {
|
|
|
24
29
|
version: string;
|
|
25
30
|
} | null>;
|
|
26
31
|
export declare function getBundleInstallDefaultLocation(): string;
|
|
32
|
+
export declare function downloadAndExtractClientBundle(httpClient: HttpClient, version: string, url: string): Promise<CloudBundleInstall>;
|
|
33
|
+
export {};
|