@vzn/vx 0.0.241 → 0.0.242
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.242",
|
|
4
4
|
"description": "A fast, correct task runner and build cache for JavaScript monorepos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
19
|
"optionalDependencies": {
|
|
20
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
21
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
22
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
23
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
20
|
+
"@vzn/vx-linux-x64": "0.0.242",
|
|
21
|
+
"@vzn/vx-linux-arm64": "0.0.242",
|
|
22
|
+
"@vzn/vx-darwin-x64": "0.0.242",
|
|
23
|
+
"@vzn/vx-darwin-arm64": "0.0.242"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cache/git-inputs.ts
CHANGED
|
@@ -847,6 +847,11 @@ export interface GitEnumeration {
|
|
|
847
847
|
trusted: Map<string, string>
|
|
848
848
|
/** Whether the worktree had uncommitted changes; null when `git status` failed. */
|
|
849
849
|
dirty: boolean | null
|
|
850
|
+
/**
|
|
851
|
+
* What `git status` listed, workspace-relative: modified, staged or deleted
|
|
852
|
+
* paths (both sides of a rename) and untracked files. Null when it failed.
|
|
853
|
+
*/
|
|
854
|
+
changed: readonly string[] | null
|
|
850
855
|
/** Workspace-relative paths whose names are not UTF-8 (`decodeGitZ`). */
|
|
851
856
|
undecodable: readonly string[]
|
|
852
857
|
/** `Date.now()` before the spawns: what `trusted` says is true as of no earlier. */
|
|
@@ -1038,7 +1043,39 @@ export async function startGitEnumeration(
|
|
|
1038
1043
|
if (parsedStatus !== null && parsedStatus.undecodable.size > 0) {
|
|
1039
1044
|
undecodable.push(...stripPrefixFromSet(parsedStatus.undecodable, gitPrefix))
|
|
1040
1045
|
}
|
|
1041
|
-
return {
|
|
1046
|
+
return {
|
|
1047
|
+
all,
|
|
1048
|
+
trusted,
|
|
1049
|
+
dirty: worktreeDirty,
|
|
1050
|
+
changed: dirty === null ? null : [...dirty, ...untracked],
|
|
1051
|
+
undecodable,
|
|
1052
|
+
startedAtMs,
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
/** A run's whole-tree enumeration, started on its first ask and shared after. */
|
|
1057
|
+
export interface LazyGitEnumeration {
|
|
1058
|
+
start(): Promise<GitEnumeration>
|
|
1059
|
+
/** The enumeration, once something started it. */
|
|
1060
|
+
readonly started: Promise<GitEnumeration> | undefined
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
export function lazyGitEnumeration(workspaceRoot: string): LazyGitEnumeration {
|
|
1064
|
+
let started: Promise<GitEnumeration> | undefined
|
|
1065
|
+
return {
|
|
1066
|
+
start() {
|
|
1067
|
+
if (started === undefined) {
|
|
1068
|
+
started = startGitEnumeration(workspaceRoot, ['.'])
|
|
1069
|
+
// Its first reader may never await it (a config throws first); the
|
|
1070
|
+
// one that does still sees the error.
|
|
1071
|
+
started.catch(() => {})
|
|
1072
|
+
}
|
|
1073
|
+
return started
|
|
1074
|
+
},
|
|
1075
|
+
get started() {
|
|
1076
|
+
return started
|
|
1077
|
+
},
|
|
1078
|
+
}
|
|
1042
1079
|
}
|
|
1043
1080
|
|
|
1044
1081
|
/** The partition half of `populateGitFilesCache`: store per-project slices of one enumeration. */
|
package/src/cache/index.ts
CHANGED
|
@@ -259,6 +259,14 @@ export interface DiscoverContext extends WorkspaceHookContext {
|
|
|
259
259
|
readonly cacheDir: string
|
|
260
260
|
/** The projects found so far: core's, then earlier plugins'. */
|
|
261
261
|
readonly projects: readonly ProjectMeta[]
|
|
262
|
+
/**
|
|
263
|
+
* What `git status` lists in the workspace, workspace-relative: modified,
|
|
264
|
+
* staged or deleted paths (both sides of a rename) and untracked files;
|
|
265
|
+
* null outside a git worktree. It is the run's own enumeration, so a
|
|
266
|
+
* plugin whose answer depends on the worktree (nx()'s graph key) reads it
|
|
267
|
+
* here instead of walking the tree a second time.
|
|
268
|
+
*/
|
|
269
|
+
worktreeChanges(): Promise<readonly string[] | null>
|
|
262
270
|
}
|
|
263
271
|
|
|
264
272
|
export interface NamedProject {
|
|
@@ -21,7 +21,7 @@ import {
|
|
|
21
21
|
applyGitEnumeration,
|
|
22
22
|
gitPathspecs,
|
|
23
23
|
startGitEnumeration,
|
|
24
|
-
|
|
24
|
+
lazyGitEnumeration,
|
|
25
25
|
} from '../cache/index.js'
|
|
26
26
|
import {
|
|
27
27
|
buildPackageGraph,
|
|
@@ -54,6 +54,7 @@ import {
|
|
|
54
54
|
} from './plugin-host.js'
|
|
55
55
|
import {
|
|
56
56
|
discoverProjects,
|
|
57
|
+
gitOfDiscovery,
|
|
57
58
|
loadProjects,
|
|
58
59
|
loadWorkspacePlugins,
|
|
59
60
|
type LoadedProjects,
|
|
@@ -176,13 +177,15 @@ export async function prepareRun(options: RunOptions, log: Logger): Promise<Prep
|
|
|
176
177
|
// waits: its pathspecs depend on which projects the configs pull in.
|
|
177
178
|
const unscoped =
|
|
178
179
|
options.projects === undefined && options.tasks.some((spec) => spec.indexOf('#') <= 0)
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
//
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
180
|
+
// A `discover` hook that reads the worktree (nx()'s graph key) starts the
|
|
181
|
+
// whole-tree enumeration a scoped run would otherwise scope later, here or
|
|
182
|
+
// in the CLI's selection pass; the run reuses it instead of walking the
|
|
183
|
+
// tree twice (G-75).
|
|
184
|
+
const reused = options.discovered?.root === workspaceRoot ? options.discovered : undefined
|
|
185
|
+
const git =
|
|
186
|
+
(reused !== undefined ? gitOfDiscovery(reused.projects) : undefined) ??
|
|
187
|
+
lazyGitEnumeration(workspaceRoot)
|
|
188
|
+
if (unscoped) void git.start()
|
|
186
189
|
const workspace = await loadWorkspace(workspaceRoot, reads)
|
|
187
190
|
const { workspaceConfig, plugins } = await loadWorkspacePlugins(workspaceRoot, (m) =>
|
|
188
191
|
log.status(m),
|
|
@@ -194,9 +197,9 @@ export async function prepareRun(options: RunOptions, log: Logger): Promise<Prep
|
|
|
194
197
|
? path.resolve(options.cwd, options.cacheDir)
|
|
195
198
|
: resolveCacheDir(workspaceRoot, workspaceConfig)
|
|
196
199
|
const projectMetas =
|
|
197
|
-
|
|
198
|
-
?
|
|
199
|
-
: await discoverProjects(workspace, plugins, cacheDir, (m) => log.status(m))
|
|
200
|
+
reused !== undefined
|
|
201
|
+
? reused.projects
|
|
202
|
+
: await discoverProjects(workspace, plugins, cacheDir, (m) => log.status(m), git)
|
|
200
203
|
mark('discover projects')
|
|
201
204
|
|
|
202
205
|
// SCOPED config loading: configs are programs, and evaluating 1090
|
|
@@ -377,7 +380,7 @@ export async function prepareRun(options: RunOptions, log: Logger): Promise<Prep
|
|
|
377
380
|
),
|
|
378
381
|
)
|
|
379
382
|
const projectDirs = [...projects.values()].map((p) => p.dir)
|
|
380
|
-
const enumeration = await (
|
|
383
|
+
const enumeration = await (git.started ??
|
|
381
384
|
startGitEnumeration(
|
|
382
385
|
workspaceRoot,
|
|
383
386
|
gitPathspecs(workspaceRoot, projectDirs, usesWorkspaceInputs),
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
type Workspace,
|
|
19
19
|
} from '../workspace/index.js'
|
|
20
20
|
import type { WorkspaceConfig } from '../config.js'
|
|
21
|
-
import { Cache } from '../cache/index.js'
|
|
21
|
+
import { Cache, lazyGitEnumeration, type LazyGitEnumeration } from '../cache/index.js'
|
|
22
22
|
import { UserError } from '../util/index.js'
|
|
23
23
|
import {
|
|
24
24
|
buildPackageGraph,
|
|
@@ -56,6 +56,17 @@ export async function loadWorkspacePlugins(
|
|
|
56
56
|
return { workspaceConfig, plugins }
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* The enumeration a discovery's `discover` hooks shared, by the array it
|
|
61
|
+
* returned: a run handed that array (`RunOptions.discovered`, the CLI's
|
|
62
|
+
* `--filter` pass) reuses the walk a hook started instead of a second one.
|
|
63
|
+
*/
|
|
64
|
+
const discoveredGit = new WeakMap<readonly ProjectMeta[], LazyGitEnumeration>()
|
|
65
|
+
|
|
66
|
+
export function gitOfDiscovery(projects: readonly ProjectMeta[]): LazyGitEnumeration | undefined {
|
|
67
|
+
return discoveredGit.get(projects)
|
|
68
|
+
}
|
|
69
|
+
|
|
59
70
|
/**
|
|
60
71
|
* The workspace's projects: core's discovery, then the plugin `discover`
|
|
61
72
|
* stage. With no plugin declaring it, `listProjects` alone.
|
|
@@ -65,13 +76,21 @@ export async function discoverProjects(
|
|
|
65
76
|
plugins: readonly VxPlugin[],
|
|
66
77
|
cacheDir: string,
|
|
67
78
|
warn: (message: string) => void,
|
|
79
|
+
/** The run's enumeration, which `DiscoverContext.worktreeChanges` reads (and starts). */
|
|
80
|
+
git: LazyGitEnumeration = lazyGitEnumeration(workspace.root),
|
|
68
81
|
): Promise<ProjectMeta[]> {
|
|
69
82
|
const projects = await listProjects(workspace)
|
|
70
83
|
if (!hasHook(plugins, 'discover')) return projects
|
|
84
|
+
discoveredGit.set(projects, git)
|
|
85
|
+
const worktreeChanges = (): Promise<readonly string[] | null> =>
|
|
86
|
+
git.start().then(
|
|
87
|
+
(e) => e.changed,
|
|
88
|
+
() => null,
|
|
89
|
+
)
|
|
71
90
|
await applyDiscoverHooks(
|
|
72
91
|
plugins,
|
|
73
92
|
projects,
|
|
74
|
-
{ workspaceRoot: workspace.root, cacheDir, warn },
|
|
93
|
+
{ workspaceRoot: workspace.root, cacheDir, warn, worktreeChanges },
|
|
75
94
|
(named, plugin) => namedProject(workspace, projects, named, plugin.name),
|
|
76
95
|
)
|
|
77
96
|
return projects.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))
|