nx 23.1.1 → 23.1.3
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/release/changelog-renderer/index.js +4 -5
- package/dist/release/index.d.ts +1 -1
- package/dist/src/command-line/add/add.js +5 -0
- package/dist/src/command-line/affected/affected.js +1 -0
- package/dist/src/command-line/configure-ai-agents/configure-ai-agents.js +2 -2
- package/dist/src/command-line/import/import.js +1 -2
- package/dist/src/command-line/init/init-v2.js +4 -5
- package/dist/src/command-line/migrate/migrate.d.ts +4 -0
- package/dist/src/command-line/migrate/migrate.js +89 -26
- package/dist/src/command-line/release/changelog.js +5 -0
- package/dist/src/command-line/release/index.d.ts +1 -1
- package/dist/src/command-line/release/utils/git.js +1 -1
- package/dist/src/command-line/release/utils/release-graph.d.ts +17 -0
- package/dist/src/command-line/release/utils/release-graph.js +71 -19
- package/dist/src/command-line/release/utils/remote-release-clients/github.js +6 -0
- package/dist/src/command-line/release/version/release-group-processor.d.ts +24 -0
- package/dist/src/command-line/release/version/release-group-processor.js +80 -6
- package/dist/src/command-line/release/version/version-actions.d.ts +27 -2
- package/dist/src/command-line/release/version/version-actions.js +9 -1
- package/dist/src/command-line/release/version.js +9 -5
- package/dist/src/command-line/reset/reset.js +6 -1
- package/dist/src/command-line/run/run-one.js +1 -0
- package/dist/src/command-line/run-many/run-many.js +1 -0
- package/dist/src/command-line/watch/watch.js +13 -0
- package/dist/src/core/graph/main.js +1 -1
- package/dist/src/core/graph/styles.js +1 -1
- package/dist/src/daemon/client/client.d.ts +52 -1
- package/dist/src/daemon/client/client.js +160 -36
- package/dist/src/daemon/client/daemon-environment.d.ts +17 -0
- package/dist/src/daemon/client/daemon-environment.js +110 -2
- package/dist/src/daemon/client/daemon-socket-messenger.js +4 -0
- package/dist/src/daemon/message-types/daemon-message.d.ts +33 -0
- package/dist/src/daemon/message-types/daemon-message.js +48 -0
- package/dist/src/daemon/server/file-watching/file-watcher-sockets.d.ts +5 -0
- package/dist/src/daemon/server/file-watching/file-watcher-sockets.js +16 -0
- package/dist/src/daemon/server/latest-nx.js +5 -2
- package/dist/src/daemon/server/server.js +24 -0
- package/dist/src/daemon/server/shutdown-utils.d.ts +5 -0
- package/dist/src/daemon/server/shutdown-utils.js +11 -4
- package/dist/src/daemon/socket-utils.d.ts +1 -0
- package/dist/src/daemon/socket-utils.js +24 -3
- package/dist/src/daemon/tmp-dir.d.ts +43 -3
- package/dist/src/daemon/tmp-dir.js +437 -15
- package/dist/src/devkit-internals.d.ts +94 -4
- package/dist/src/devkit-internals.js +194 -5
- package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.d.ts +5 -0
- package/dist/src/generators/internal-utils/format-changed-files-with-prettier-if-available.js +9 -2
- package/dist/src/generators/tree.d.ts +4 -2
- package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.d.ts +12 -0
- package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.js +250 -0
- package/dist/src/migrations/update-23-2-0/set-cache-on-executor-target-defaults.md +50 -0
- package/dist/src/native/index.d.ts +10 -0
- package/dist/src/native/index.js +71 -28
- package/dist/src/native/native-bindings.js +1 -0
- package/dist/src/native/native-file-cache-location.d.ts +17 -1
- package/dist/src/native/native-file-cache-location.js +86 -12
- 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/utilities/get-cloud-options.js +5 -2
- package/dist/src/nx-cloud/utilities/onboarding.js +5 -2
- package/dist/src/plugins/js/lock-file/bun-parser.js +43 -10
- package/dist/src/plugins/js/lock-file/pnpm-parser.js +60 -0
- package/dist/src/plugins/js/lock-file/project-graph-pruning.js +14 -8
- package/dist/src/plugins/js/project-graph/affected/npm-packages.js +51 -20
- package/dist/src/plugins/js/project-graph/build-dependencies/target-project-locator.js +2 -0
- package/dist/src/project-graph/affected/affected-project-graph-models.d.ts +1 -1
- package/dist/src/project-graph/affected/affected-project-graph.d.ts +1 -1
- package/dist/src/project-graph/affected/affected-project-graph.js +2 -2
- package/dist/src/project-graph/affected/locators/project-glob-changes.js +5 -2
- package/dist/src/project-graph/error-types.d.ts +12 -1
- package/dist/src/project-graph/error-types.js +27 -2
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +1 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +18 -1
- package/dist/src/project-graph/plugins/isolation/messaging.d.ts +16 -3
- package/dist/src/project-graph/plugins/isolation/messaging.js +3 -0
- package/dist/src/project-graph/plugins/isolation/plugin-worker.js +58 -8
- package/dist/src/project-graph/project-graph.js +20 -0
- package/dist/src/project-graph/utils/project-configuration/project-nodes-manager.js +5 -1
- package/dist/src/project-graph/utils/project-configuration/target-normalization.js +133 -3
- package/dist/src/tasks-runner/task-env.js +5 -2
- package/dist/src/tasks-runner/utils.js +2 -6
- package/dist/src/utils/assert-workspace-validity.js +7 -2
- package/dist/src/utils/fileutils.d.ts +5 -0
- package/dist/src/utils/fileutils.js +7 -2
- package/dist/src/utils/git-worktrees.d.ts +30 -0
- package/dist/src/utils/git-worktrees.js +212 -0
- package/dist/src/utils/ignore.d.ts +128 -1
- package/dist/src/utils/ignore.js +182 -12
- package/dist/src/utils/long-running-target.d.ts +10 -0
- package/dist/src/utils/long-running-target.js +19 -0
- package/dist/src/utils/min-release-age/behavior/bun.js +7 -11
- package/dist/src/utils/min-release-age/behavior/npm.js +5 -2
- package/dist/src/utils/min-release-age/packument.js +1 -1
- package/dist/src/utils/nx-tmp-dir.d.ts +18 -0
- package/dist/src/utils/nx-tmp-dir.js +40 -0
- package/dist/src/utils/owned-private-dir.d.ts +132 -0
- package/dist/src/utils/owned-private-dir.js +323 -0
- package/dist/src/utils/package-manager-config/bunfig.d.ts +14 -0
- package/dist/src/utils/package-manager-config/bunfig.js +49 -0
- package/dist/src/utils/package-manager-config/npmrc.d.ts +23 -0
- package/dist/src/utils/package-manager-config/npmrc.js +124 -0
- package/dist/src/utils/package-manager-config/pnpm-config.d.ts +17 -0
- package/dist/src/utils/package-manager-config/pnpm-config.js +60 -0
- package/dist/src/utils/package-manager.d.ts +21 -2
- package/dist/src/utils/package-manager.js +244 -47
- package/dist/src/utils/provenance.js +6 -14
- package/dist/src/utils/registry-config/bun.d.ts +2 -0
- package/dist/src/utils/registry-config/bun.js +257 -0
- package/dist/src/utils/registry-config/index.d.ts +13 -0
- package/dist/src/utils/registry-config/index.js +102 -0
- package/dist/src/utils/registry-config/pnpm.d.ts +2 -0
- package/dist/src/utils/registry-config/pnpm.js +1551 -0
- package/dist/src/utils/registry-config/utils.d.ts +195 -0
- package/dist/src/utils/registry-config/utils.js +496 -0
- package/dist/src/utils/registry-config/yarn-berry.d.ts +2 -0
- package/dist/src/utils/registry-config/yarn-berry.js +612 -0
- package/dist/src/utils/registry-config/yarn-classic.d.ts +2 -0
- package/dist/src/utils/registry-config/yarn-classic.js +1001 -0
- package/dist/src/utils/safe-spawn.d.ts +24 -0
- package/dist/src/utils/safe-spawn.js +104 -0
- package/dist/src/utils/shell-quoting.d.ts +15 -0
- package/dist/src/utils/shell-quoting.js +35 -0
- package/dist/src/utils/wait-for-socket-connection.d.ts +11 -0
- package/dist/src/utils/wait-for-socket-connection.js +14 -8
- package/migrations.json +6 -0
- package/package.json +12 -12
- package/dist/src/utils/min-release-age/npmrc.d.ts +0 -15
- package/dist/src/utils/min-release-age/npmrc.js +0 -45
package/dist/src/utils/ignore.js
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.getIgnoreObject = getIgnoreObject;
|
|
4
|
-
exports.
|
|
4
|
+
exports.createIgnoreChainResolver = createIgnoreChainResolver;
|
|
5
|
+
exports.isIgnoredByChain = isIgnoredByChain;
|
|
6
|
+
exports.isAlwaysIgnored = isAlwaysIgnored;
|
|
7
|
+
exports.createGitIgnoreChecker = createGitIgnoreChecker;
|
|
8
|
+
exports.createPrettierIgnoreChecker = createPrettierIgnoreChecker;
|
|
9
|
+
exports.posixDirname = posixDirname;
|
|
5
10
|
exports.addEntryToGitIgnore = addEntryToGitIgnore;
|
|
6
11
|
const ignore = require("ignore");
|
|
12
|
+
const index_1 = require("../native/index");
|
|
7
13
|
const fileutils_1 = require("./fileutils");
|
|
8
14
|
const workspace_root_1 = require("./workspace-root");
|
|
9
15
|
function getIgnoreObject(root = workspace_root_1.workspaceRoot) {
|
|
@@ -12,18 +18,182 @@ function getIgnoreObject(root = workspace_root_1.workspaceRoot) {
|
|
|
12
18
|
ig.add((0, fileutils_1.readFileIfExisting)(`${root}/.nxignore`));
|
|
13
19
|
return ig;
|
|
14
20
|
}
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Resolves the ignore files that apply to a directory: its own and every one
|
|
23
|
+
* above it, up to the workspace root.
|
|
24
|
+
*
|
|
25
|
+
* Ignore files cascade - a `.gitignore` covers its own directory and below, and
|
|
26
|
+
* its patterns are relative to *itself*, not to the workspace root. Reading only
|
|
27
|
+
* the root file, which is what `getIgnoreObject` does, silently misses every
|
|
28
|
+
* nested one.
|
|
29
|
+
*
|
|
30
|
+
* A directory's answer is its own files plus its parent's, so every directory on
|
|
31
|
+
* the way up is memoized rather than only the one asked for: sibling leaves
|
|
32
|
+
* share the whole trunk, and a later walk stops at the first directory already
|
|
33
|
+
* known.
|
|
34
|
+
*
|
|
35
|
+
* `read` decides where the files come from - `tree.read` for a generator, disk
|
|
36
|
+
* for a caller with no tree - and returns an empty string or null when there is
|
|
37
|
+
* no such file. Paths handed to it are workspace-relative POSIX.
|
|
38
|
+
*
|
|
39
|
+
* `merge` decides how the files *within one directory* relate, and the two
|
|
40
|
+
* consumers genuinely need different rules:
|
|
41
|
+
*
|
|
42
|
+
* - `false` is prettier's: one matcher per file, any of them excluding wins, and
|
|
43
|
+
* a negation counts only if none excluded. `createIsIgnoredFunction` builds an
|
|
44
|
+
* ignorer per `--ignore-path` and ORs them, so a `!x` in `.prettierignore`
|
|
45
|
+
* cannot re-include an `x` that `.gitignore` excluded.
|
|
46
|
+
* - `true` is git's and the native walker's: all files in one matcher, so
|
|
47
|
+
* `.nxignore`'s `!x` removes `.gitignore`'s exclusion of `x` outright. It has
|
|
48
|
+
* to be a merge rather than a precedence check between separate matchers,
|
|
49
|
+
* because a lone `!x` in its own matcher reports an opinion on `x/` but *none*
|
|
50
|
+
* on `x/a.ts` (measured), so the exclusion would still reach the children.
|
|
51
|
+
* The merge only removes the exclusion within that one directory - a negation
|
|
52
|
+
* in a nested file still loses to an ancestor's exclusion.
|
|
53
|
+
*
|
|
54
|
+
* When `merge` is true, `filenames` order matters: they go into one matcher in
|
|
55
|
+
* order and the last matching pattern decides, so list them lowest-authority
|
|
56
|
+
* first.
|
|
57
|
+
*/
|
|
58
|
+
function createIgnoreChainResolver(read, filenames, merge) {
|
|
59
|
+
const cache = new Map();
|
|
60
|
+
const resolve = (dir) => {
|
|
61
|
+
const cached = cache.get(dir);
|
|
62
|
+
if (cached) {
|
|
63
|
+
return cached;
|
|
64
|
+
}
|
|
65
|
+
const contents = filenames
|
|
66
|
+
.map((name) => read(dir ? `${dir}/${name}` : name))
|
|
67
|
+
.filter((c) => !!c);
|
|
68
|
+
const matchers = merge
|
|
69
|
+
? contents.length > 0
|
|
70
|
+
? [contents.reduce((m, c) => m.add(c), ignore())]
|
|
71
|
+
: []
|
|
72
|
+
: contents.map((c) => ignore().add(c));
|
|
73
|
+
const inherited = dir === '' ? [] : resolve(posixDirname(dir));
|
|
74
|
+
const chain = matchers.length > 0 ? [{ dir, matchers }, ...inherited] : inherited;
|
|
75
|
+
cache.set(dir, chain);
|
|
76
|
+
return chain;
|
|
77
|
+
};
|
|
78
|
+
return resolve;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* True when the file is ignored, resolving the chain nearest file first.
|
|
82
|
+
*
|
|
83
|
+
* Each matcher is tested against the path relative to its own directory, which
|
|
84
|
+
* is what makes a nested pattern like `/build` mean that directory's `build`
|
|
85
|
+
* rather than the workspace's.
|
|
86
|
+
*
|
|
87
|
+
* Nearest directory with an *opinion* wins, not the first match: a nested
|
|
88
|
+
* `!keep.log` must override the root's `*.log`, which is git's rule for files.
|
|
89
|
+
* A nested negation of a *directory* does not reach its children - see the
|
|
90
|
+
* `merge` note on `createIgnoreChainResolver`.
|
|
91
|
+
*
|
|
92
|
+
* How the files of one directory relate is decided when the chain is built - see
|
|
93
|
+
* that same note. Here they are simply the entry's matchers: any one excluding
|
|
94
|
+
* wins, and a negation counts only if none excluded.
|
|
95
|
+
*
|
|
96
|
+
* Two preconditions, both satisfied by a pruning walk and neither enforced:
|
|
97
|
+
*
|
|
98
|
+
* - `filePath` is workspace-relative POSIX and must sit under every `dir` in the
|
|
99
|
+
* chain, which holds when the chain came from that file's own directory.
|
|
100
|
+
* - No ancestor directory of `filePath` may itself be ignored. git refuses to
|
|
101
|
+
* re-include a file inside an excluded directory, and this does not implement
|
|
102
|
+
* that rule: asked directly about `dist/keep.ts` with a root `dist/` and a
|
|
103
|
+
* nested `dist/.gitignore` holding `!keep.ts`, it answers "not ignored" where
|
|
104
|
+
* git says ignored (measured). `visitNotIgnoredFiles` never asks, because it
|
|
105
|
+
* prunes `dist/` before descending - which is what makes its answers match
|
|
106
|
+
* git, and why that pruning is load-bearing for correctness rather than speed.
|
|
107
|
+
*/
|
|
108
|
+
function isIgnoredByChain(chain, filePath) {
|
|
109
|
+
for (const { dir, matchers } of chain) {
|
|
110
|
+
const relative = dir === '' ? filePath : filePath.slice(dir.length + 1);
|
|
111
|
+
let unignored = false;
|
|
112
|
+
for (const matcher of matchers) {
|
|
113
|
+
const result = matcher.test(relative);
|
|
114
|
+
if (result.ignored) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
unignored ||= result.unignored;
|
|
118
|
+
}
|
|
119
|
+
if (unignored) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
25
122
|
}
|
|
26
|
-
return
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
let alwaysIgnored;
|
|
126
|
+
/**
|
|
127
|
+
* Directories that should never be walked, whatever the workspace's own ignore
|
|
128
|
+
* files say - `node_modules`, `.git`, the nx caches.
|
|
129
|
+
*
|
|
130
|
+
* The list comes from the native walker rather than a second copy here, so a
|
|
131
|
+
* filesystem walk and a tree walk cannot drift apart.
|
|
132
|
+
*
|
|
133
|
+
* Checked ahead of the cascading chain rather than folded into it: these are not
|
|
134
|
+
* re-includable, and as ordinary patterns a nested negation could resurrect
|
|
135
|
+
* `node_modules`.
|
|
136
|
+
*/
|
|
137
|
+
function isAlwaysIgnored(path) {
|
|
138
|
+
alwaysIgnored ??= ignore().add((0, index_1.getHardcodedIgnorePatterns)());
|
|
139
|
+
return alwaysIgnored.ignores(path);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* What git ignores, which is also what the native walker ignores.
|
|
143
|
+
*
|
|
144
|
+
* `.nxignore` outranks `.gitignore` - `walker.rs` registers it with
|
|
145
|
+
* `add_custom_ignore_filename` - which a merge with `.nxignore` last reproduces.
|
|
146
|
+
* git itself does not read it.
|
|
147
|
+
*
|
|
148
|
+
* Reads from the tree rather than disk because a generator can create or amend
|
|
149
|
+
* an ignore file in the same run, which would leave the on-disk copy stale.
|
|
150
|
+
*/
|
|
151
|
+
function createGitIgnoreChecker(tree) {
|
|
152
|
+
return createTreeIgnoreChecker(tree, {
|
|
153
|
+
filenames: ['.gitignore', '.nxignore'],
|
|
154
|
+
cascade: true,
|
|
155
|
+
merge: true,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* What prettier ignores: the workspace root only, and one ignorer per
|
|
160
|
+
* `--ignore-path` ORed rather than merged (both measured), so a `!` in
|
|
161
|
+
* `.prettierignore` cannot re-include what `.gitignore` excluded. That is the
|
|
162
|
+
* CLI `nx format:check` shells out to.
|
|
163
|
+
*
|
|
164
|
+
* Not an exact match for that command: `isAlwaysIgnored` is wider than
|
|
165
|
+
* prettier's built-ins, and `format.ts` filters its own patterns through
|
|
166
|
+
* `.nxignore`, which this does not read.
|
|
167
|
+
*
|
|
168
|
+
* Reads from the tree rather than disk, as above.
|
|
169
|
+
*/
|
|
170
|
+
function createPrettierIgnoreChecker(tree) {
|
|
171
|
+
return createTreeIgnoreChecker(tree, {
|
|
172
|
+
filenames: ['.gitignore', '.prettierignore'],
|
|
173
|
+
cascade: false,
|
|
174
|
+
merge: false,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
function createTreeIgnoreChecker(tree, { filenames, cascade, merge }) {
|
|
178
|
+
const resolve = createIgnoreChainResolver((path) => tree.read(path, 'utf-8'), filenames, merge);
|
|
179
|
+
// `probe` may carry a trailing slash; `path` never does. The chain is keyed by
|
|
180
|
+
// real directories, and `posixDirname('dist/')` is `'dist'` rather than the
|
|
181
|
+
// parent, so the lookup always uses the slash-less form.
|
|
182
|
+
const check = (path, probe) => isAlwaysIgnored(probe) ||
|
|
183
|
+
isIgnoredByChain(resolve(cascade ? posixDirname(path) : ''), probe);
|
|
184
|
+
return {
|
|
185
|
+
isIgnoredFile: (path) => check(path, path),
|
|
186
|
+
isIgnoredDirectory: (path) => check(path, `${path}/`),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* `path.dirname` for the workspace-relative POSIX paths the chain is keyed by,
|
|
191
|
+
* except that the workspace root is `''` rather than `.` - that is the key
|
|
192
|
+
* `createIgnoreChainResolver` terminates on.
|
|
193
|
+
*/
|
|
194
|
+
function posixDirname(relativePath) {
|
|
195
|
+
const separator = relativePath.lastIndexOf('/');
|
|
196
|
+
return separator === -1 ? '' : relativePath.slice(0, separator);
|
|
27
197
|
}
|
|
28
198
|
/**
|
|
29
199
|
* Adds an entry to a .gitignore file if it's not already covered by existing patterns.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Target names the pre-23 `longRunningTask` guard excluded from caching. Shared
|
|
3
|
+
* between that guard and the deprecated target-name cache fallback so the two
|
|
4
|
+
* cannot drift apart.
|
|
5
|
+
*
|
|
6
|
+
* The copy in `migrations/update-23-2-0/set-cache-on-executor-target-defaults.ts`
|
|
7
|
+
* deliberately does not use this: a migration's decision has to freeze at the
|
|
8
|
+
* semantics it shipped with.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isLongRunningTargetName(targetName: string): boolean;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isLongRunningTargetName = isLongRunningTargetName;
|
|
4
|
+
/**
|
|
5
|
+
* Target names the pre-23 `longRunningTask` guard excluded from caching. Shared
|
|
6
|
+
* between that guard and the deprecated target-name cache fallback so the two
|
|
7
|
+
* cannot drift apart.
|
|
8
|
+
*
|
|
9
|
+
* The copy in `migrations/update-23-2-0/set-cache-on-executor-target-defaults.ts`
|
|
10
|
+
* deliberately does not use this: a migration's decision has to freeze at the
|
|
11
|
+
* semantics it shipped with.
|
|
12
|
+
*/
|
|
13
|
+
function isLongRunningTargetName(targetName) {
|
|
14
|
+
return (targetName.endsWith(':watch') ||
|
|
15
|
+
targetName.endsWith('-watch') ||
|
|
16
|
+
targetName === 'serve' ||
|
|
17
|
+
targetName === 'dev' ||
|
|
18
|
+
targetName === 'start');
|
|
19
|
+
}
|
|
@@ -2,10 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.readBunPolicy = readBunPolicy;
|
|
4
4
|
exports.pickBunVersion = pickBunVersion;
|
|
5
|
-
const fs_1 = require("fs");
|
|
6
5
|
const path_1 = require("path");
|
|
7
6
|
const semver_1 = require("semver");
|
|
8
|
-
const
|
|
7
|
+
const bunfig_1 = require("../../package-manager-config/bunfig");
|
|
9
8
|
const constants_1 = require("../constants");
|
|
10
9
|
const errors_1 = require("../errors");
|
|
11
10
|
const pick_1 = require("../pick");
|
|
@@ -82,23 +81,20 @@ function readLocalBunInstall(root) {
|
|
|
82
81
|
return readBunInstall((0, path_1.join)(root, 'bunfig.toml'));
|
|
83
82
|
}
|
|
84
83
|
function readGlobalBunInstall() {
|
|
85
|
-
const
|
|
86
|
-
const base = xdg || process.env.HOME;
|
|
84
|
+
const base = (0, bunfig_1.getBunGlobalConfigBase)(process.env);
|
|
87
85
|
if (!base) {
|
|
88
86
|
return {};
|
|
89
87
|
}
|
|
90
88
|
return readBunInstall((0, path_1.join)(base, '.bunfig.toml'));
|
|
91
89
|
}
|
|
92
90
|
function readBunInstall(path) {
|
|
93
|
-
|
|
91
|
+
const parsed = (0, bunfig_1.readBunfigRaw)(path);
|
|
92
|
+
// bun skips a bunfig it cannot read and resolves on, so its settings do not
|
|
93
|
+
// apply. Only a parse failure kills the install.
|
|
94
|
+
if (parsed === null || parsed === 'unreadable') {
|
|
94
95
|
return {};
|
|
95
96
|
}
|
|
96
|
-
|
|
97
|
-
try {
|
|
98
|
-
parsed = (0, smol_toml_1.parse)((0, fs_1.readFileSync)(path, 'utf-8'));
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
// Unparseable bunfig makes bun's install die; treat as a hard error.
|
|
97
|
+
if (parsed === 'invalid') {
|
|
102
98
|
return 'error';
|
|
103
99
|
}
|
|
104
100
|
const install = parsed.install;
|
|
@@ -8,7 +8,7 @@ const path_1 = require("path");
|
|
|
8
8
|
const semver_1 = require("semver");
|
|
9
9
|
const constants_1 = require("../constants");
|
|
10
10
|
const errors_1 = require("../errors");
|
|
11
|
-
const npmrc_1 = require("
|
|
11
|
+
const npmrc_1 = require("../../package-manager-config/npmrc");
|
|
12
12
|
const pick_1 = require("../pick");
|
|
13
13
|
const RANK_UNKNOWN = 0; // global/builtin/default - not detectable here
|
|
14
14
|
const RANK_USER = 1;
|
|
@@ -116,7 +116,10 @@ function detectSurfaces(root, env) {
|
|
|
116
116
|
}
|
|
117
117
|
function readNpmrcKeys(override, fallback) {
|
|
118
118
|
const present = { minReleaseAge: false, before: false };
|
|
119
|
-
|
|
119
|
+
// npm silently treats an .npmrc it cannot read as absent, so both non-array
|
|
120
|
+
// states scan nothing.
|
|
121
|
+
const entries = (0, npmrc_1.readNpmrcEntries)(override ?? fallback);
|
|
122
|
+
for (const { key } of Array.isArray(entries) ? entries : []) {
|
|
120
123
|
if (key === 'min-release-age') {
|
|
121
124
|
present.minReleaseAge = true;
|
|
122
125
|
}
|
|
@@ -16,7 +16,7 @@ function toArray(value) {
|
|
|
16
16
|
* `dist-tags` carries a hyphen.
|
|
17
17
|
*/
|
|
18
18
|
async function fetchRegistryMetadata(pkg) {
|
|
19
|
-
const raw = await (0, package_manager_1.packageRegistryView)(pkg, '', '--json');
|
|
19
|
+
const raw = await (0, package_manager_1.packageRegistryView)(pkg, '', ['--json']);
|
|
20
20
|
const parsed = JSON.parse(raw);
|
|
21
21
|
const time = parsed.time ?? null;
|
|
22
22
|
if (time) {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable root for Nx runtime artifacts that need an OS tmp location. On POSIX a
|
|
3
|
+
* literal `/tmp`, not `os.tmpdir()`, which honours `$TMPDIR` — per-user on
|
|
4
|
+
* macOS, rewritten by sandboxes, stripped from the daemon env, so client and
|
|
5
|
+
* daemon would disagree. Windows has no `/tmp`, and `%TMP%` is already per-user
|
|
6
|
+
* and stable, so it keeps `os.tmpdir()`.
|
|
7
|
+
*
|
|
8
|
+
* Consumed by the native binding loader, so keep this file limited to local
|
|
9
|
+
* helpers that themselves use Node builtins only.
|
|
10
|
+
*/
|
|
11
|
+
export declare const NX_TMP_DIR: string;
|
|
12
|
+
/**
|
|
13
|
+
* Owner-only runtime root for the current user. No user segment on Windows —
|
|
14
|
+
* `%TMP%` is already per-account, and the segment would only cost path length.
|
|
15
|
+
*/
|
|
16
|
+
export declare const NX_USER_TMP_DIR: string;
|
|
17
|
+
/** Runtime root under the user's home, used when the shared container cannot be established. */
|
|
18
|
+
export declare const NX_HOME_TMP_DIR: string;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NX_HOME_TMP_DIR = exports.NX_USER_TMP_DIR = exports.NX_TMP_DIR = void 0;
|
|
4
|
+
const node_os_1 = require("node:os");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const owned_private_dir_1 = require("./owned-private-dir");
|
|
7
|
+
/**
|
|
8
|
+
* Stable root for Nx runtime artifacts that need an OS tmp location. On POSIX a
|
|
9
|
+
* literal `/tmp`, not `os.tmpdir()`, which honours `$TMPDIR` — per-user on
|
|
10
|
+
* macOS, rewritten by sandboxes, stripped from the daemon env, so client and
|
|
11
|
+
* daemon would disagree. Windows has no `/tmp`, and `%TMP%` is already per-user
|
|
12
|
+
* and stable, so it keeps `os.tmpdir()`.
|
|
13
|
+
*
|
|
14
|
+
* Consumed by the native binding loader, so keep this file limited to local
|
|
15
|
+
* helpers that themselves use Node builtins only.
|
|
16
|
+
*/
|
|
17
|
+
exports.NX_TMP_DIR = (0, node_os_1.platform)() === 'win32' ? (0, node_path_1.join)((0, node_os_1.tmpdir)(), '.nx') : '/tmp/.nx';
|
|
18
|
+
/**
|
|
19
|
+
* Owner-only runtime root for the current user. No user segment on Windows —
|
|
20
|
+
* `%TMP%` is already per-account, and the segment would only cost path length.
|
|
21
|
+
*/
|
|
22
|
+
exports.NX_USER_TMP_DIR = (0, node_os_1.platform)() === 'win32' ? exports.NX_TMP_DIR : (0, node_path_1.join)(exports.NX_TMP_DIR, (0, owned_private_dir_1.getUserSegment)());
|
|
23
|
+
/** Runtime root under the user's home, used when the shared container cannot be established. */
|
|
24
|
+
exports.NX_HOME_TMP_DIR = resolveHomeTmpDir();
|
|
25
|
+
/**
|
|
26
|
+
* Absolute, not merely non-empty: a relative `$HOME` would make `join` return
|
|
27
|
+
* `.nx`, putting sockets under the cwd and aiming `removeSocketDir`'s recursive
|
|
28
|
+
* delete at it. A rootless container has no `$HOME` and no passwd entry, so
|
|
29
|
+
* `homedir()` throws or returns empty — caught here because this runs at module
|
|
30
|
+
* scope and the native binding loader imports this file.
|
|
31
|
+
*/
|
|
32
|
+
function resolveHomeTmpDir() {
|
|
33
|
+
try {
|
|
34
|
+
const home = (0, node_os_1.homedir)();
|
|
35
|
+
return home && (0, node_path_1.isAbsolute)(home) ? (0, node_path_1.join)(home, '.nx') : undefined;
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
declare const safeSharedRootBrand: unique symbol;
|
|
2
|
+
declare const sharedRootEstablishedBrand: unique symbol;
|
|
3
|
+
declare const ownedRealDirBrand: unique symbol;
|
|
4
|
+
declare const ownedPrivateDirBrand: unique symbol;
|
|
5
|
+
/** Verified safe to keep an owner-only directory under. Not created. */
|
|
6
|
+
export type SafeSharedRoot = string & {
|
|
7
|
+
readonly [safeSharedRootBrand]: true;
|
|
8
|
+
};
|
|
9
|
+
/** Created if absent, then verified safe as above. */
|
|
10
|
+
export type EstablishedSharedRoot = string & {
|
|
11
|
+
readonly [sharedRootEstablishedBrand]: true;
|
|
12
|
+
};
|
|
13
|
+
/** An existing real directory owned by us. Mode is *not* checked. */
|
|
14
|
+
export type OwnedRealDir = string & {
|
|
15
|
+
readonly [ownedRealDirBrand]: true;
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* POSIX: created if absent, owned by us, and carrying no group or other bits —
|
|
19
|
+
* re-locked first if it was looser. The mode is checked on whichever branch
|
|
20
|
+
* produced it, so the brand does not depend on who created the directory.
|
|
21
|
+
*
|
|
22
|
+
* Windows: only *is a real directory*. `getuid` is unavailable there, so
|
|
23
|
+
* neither ownership nor mode is checked; `%TMP%` is already per-account.
|
|
24
|
+
*/
|
|
25
|
+
export type OwnedPrivateDir = string & {
|
|
26
|
+
readonly [ownedPrivateDirBrand]: true;
|
|
27
|
+
};
|
|
28
|
+
/** Why a guard refused a directory. Data, not a sentence: `remedyFor` decides on it. */
|
|
29
|
+
export type DirRefusal = {
|
|
30
|
+
kind: 'not-created';
|
|
31
|
+
dir: string;
|
|
32
|
+
code?: string;
|
|
33
|
+
} | {
|
|
34
|
+
kind: 'not-inspectable';
|
|
35
|
+
dir: string;
|
|
36
|
+
code?: string;
|
|
37
|
+
} | {
|
|
38
|
+
kind: 'not-a-directory';
|
|
39
|
+
dir: string;
|
|
40
|
+
symlink?: true;
|
|
41
|
+
} | {
|
|
42
|
+
kind: 'foreign-owner';
|
|
43
|
+
dir: string;
|
|
44
|
+
uid: number;
|
|
45
|
+
} | {
|
|
46
|
+
kind: 'foreign-shared-container';
|
|
47
|
+
dir: string;
|
|
48
|
+
uid: number;
|
|
49
|
+
} | {
|
|
50
|
+
kind: 'not-tightenable';
|
|
51
|
+
dir: string;
|
|
52
|
+
mode: number;
|
|
53
|
+
} | {
|
|
54
|
+
kind: 'peer-writable-not-sticky';
|
|
55
|
+
dir: string;
|
|
56
|
+
mode: number;
|
|
57
|
+
};
|
|
58
|
+
/** A guard's verdict. */
|
|
59
|
+
export type GuardResult<T> = {
|
|
60
|
+
status: 'ok';
|
|
61
|
+
path: T;
|
|
62
|
+
} | {
|
|
63
|
+
status: 'refused';
|
|
64
|
+
refusal: DirRefusal;
|
|
65
|
+
};
|
|
66
|
+
/** The user-facing sentence for a refusal. The only place wording is decided. */
|
|
67
|
+
export declare function describeRefusal(r: DirRefusal): string;
|
|
68
|
+
/** What the user can do about a refusal, or `undefined` when there is nothing. */
|
|
69
|
+
export declare function remedyFor(r: DirRefusal): string | undefined;
|
|
70
|
+
/** One refusal as an `Error`, so several can travel in an `AggregateError`. */
|
|
71
|
+
export declare class DirectoryRefusedError extends Error {
|
|
72
|
+
readonly refusal: DirRefusal;
|
|
73
|
+
constructor(refusal: DirRefusal);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Whether a shared container is safe to keep an owner-only directory under.
|
|
77
|
+
*
|
|
78
|
+
* On POSIX, a container writable by other users must be sticky, and it must be
|
|
79
|
+
* owned by either root or the current user. Windows short-circuits after the
|
|
80
|
+
* directory test — the OS temp root is already scoped to one account, so there
|
|
81
|
+
* is no shared level whose ownership could matter.
|
|
82
|
+
*
|
|
83
|
+
* Sticky directories still let the directory's own owner rename entries, so a
|
|
84
|
+
* container owned by another unprivileged user could replace a previously
|
|
85
|
+
* verified private directory beneath it.
|
|
86
|
+
*/
|
|
87
|
+
export declare function isSafeSharedRoot(dir: string): GuardResult<SafeSharedRoot>;
|
|
88
|
+
/**
|
|
89
|
+
* Whether other users on this machine can write into `dir`. Gates whether a
|
|
90
|
+
* refusal message may cite other users, so it must not over-report: `false` on
|
|
91
|
+
* Windows, where libuv synthesizes `st_mode` from the READONLY attribute and
|
|
92
|
+
* reports an ordinary per-account directory as `0666`, and `false` on a path
|
|
93
|
+
* that cannot be inspected.
|
|
94
|
+
*
|
|
95
|
+
* `statSync`, not `lstatSync`: the question is about the directory that will be
|
|
96
|
+
* used, not the link pointing at it. Link modes mislead in both directions —
|
|
97
|
+
* Linux creates symlinks `0777`, macOS applies the umask. Nothing here decides
|
|
98
|
+
* whether a path is accepted, so following the link costs nothing the guards
|
|
99
|
+
* do not already re-check.
|
|
100
|
+
*/
|
|
101
|
+
export declare function isPeerWritable(dir: string): boolean;
|
|
102
|
+
/**
|
|
103
|
+
* Create a shared container as sticky + world-writable if it does not exist,
|
|
104
|
+
* and report whether the resulting path is safe for the current user.
|
|
105
|
+
*
|
|
106
|
+
* **A container that already exists is never modified — only judged.** Do not
|
|
107
|
+
* chmod before deciding trust: `CAP_FOWNER` (root's default in Docker and most
|
|
108
|
+
* CI images) can chmod a directory it does not own, so a peer-owned root would
|
|
109
|
+
* be widened to `1777` and then refused, and an operator who deliberately
|
|
110
|
+
* tightened this root would have it re-widened on every `nx` process.
|
|
111
|
+
*/
|
|
112
|
+
export declare function ensureSafeSharedRoot(dir: string): GuardResult<EstablishedSharedRoot>;
|
|
113
|
+
/**
|
|
114
|
+
* Whether `dir` is an existing real directory owned by us. Unlike
|
|
115
|
+
* `ensureOwnedPrivateDir` it creates nothing and repairs nothing — for callers
|
|
116
|
+
* that only want to know whether a path is safe to act on, such as deleting.
|
|
117
|
+
*/
|
|
118
|
+
export declare function isOwnedRealDirectory(dir: string): OwnedRealDir | null;
|
|
119
|
+
/** The path segment separating one user's Nx runtime state from another's. */
|
|
120
|
+
export declare function getUserSegment(): string;
|
|
121
|
+
/**
|
|
122
|
+
* Ensure `dir` exists, is a real directory owned by us, and carries no group or
|
|
123
|
+
* other bits at all — read and search alone reach a socket inside it, so 0755 is
|
|
124
|
+
* re-locked rather than accepted. A `refused` status carries which check said
|
|
125
|
+
* no — usually `foreign-owner` for a directory another user planted, but also
|
|
126
|
+
* `not-created`/`not-inspectable` for a filesystem error, `not-a-directory`, or
|
|
127
|
+
* `not-tightenable` when the re-lock did not land.
|
|
128
|
+
*
|
|
129
|
+
* Node builtins only: reached from the native binding loader.
|
|
130
|
+
*/
|
|
131
|
+
export declare function ensureOwnedPrivateDir(dir: string): GuardResult<OwnedPrivateDir>;
|
|
132
|
+
export {};
|