@vzn/vx 0.0.149 → 0.0.151
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 +5 -5
- package/src/cli/help.ts +6 -0
- package/src/orchestrator/placement.ts +11 -4
- package/src/orchestrator/plan.ts +5 -2
- package/src/workspace/filter.ts +24 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vzn/vx",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.151",
|
|
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.151",
|
|
21
|
+
"@vzn/vx-linux-arm64": "0.0.151",
|
|
22
|
+
"@vzn/vx-darwin-x64": "0.0.151",
|
|
23
|
+
"@vzn/vx-darwin-arm64": "0.0.151"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
26
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cli/help.ts
CHANGED
|
@@ -108,6 +108,12 @@ export function helpText(pluginCommands: readonly string[] = []): string {
|
|
|
108
108
|
' depends on none of them; a plain `vx run` never requires a plugin.',
|
|
109
109
|
' See the plugin guide: https://vznjs.github.io/vx/guides/plugins/',
|
|
110
110
|
'',
|
|
111
|
+
'Turbo and Nx spellings (for run):',
|
|
112
|
+
' What turbo run / nx run-many / nx affected take works here, or is refused',
|
|
113
|
+
' naming the vx spelling: -t build,test, -p app, --exclude docs, --parallel 4,',
|
|
114
|
+
' and --base main, --dry-run, --skip-nx-cache. `vx build` names `vx run build`.',
|
|
115
|
+
' Every flag: https://vznjs.github.io/vx/cli/#turbo-and-nx-flags',
|
|
116
|
+
'',
|
|
111
117
|
'Argument forwarding (for run):',
|
|
112
118
|
" Anything after `--` is forwarded (shell-quoted) to the task's exec",
|
|
113
119
|
' command. The forwarded args are folded into the cache key.',
|
|
@@ -144,8 +144,11 @@ export function placeTasks(
|
|
|
144
144
|
}
|
|
145
145
|
|
|
146
146
|
/**
|
|
147
|
-
* `executorOf` for `planRun`, or nothing.
|
|
148
|
-
* executor
|
|
147
|
+
* `executorOf` for `planRun`, or nothing. A remote-only task no remote
|
|
148
|
+
* executor takes is labelled `noop` whatever the executor count: the run
|
|
149
|
+
* does nothing for it, and a plan line without the label promises an
|
|
150
|
+
* execution. Otherwise declining plugins, a single executor, or a
|
|
151
|
+
* resolution error all yield nothing: `--dry` is an
|
|
149
152
|
* inspection command and must not fail over a label. The error is still
|
|
150
153
|
* said, on the status line, in the plugin's name: the run this plan
|
|
151
154
|
* previews would refuse on it, and a plan that hid that would read as
|
|
@@ -188,11 +191,15 @@ export async function planExecutorOf(
|
|
|
188
191
|
remoteOnly: placements.remoteOnly,
|
|
189
192
|
})
|
|
190
193
|
return {
|
|
191
|
-
...(executors.length < 2
|
|
194
|
+
...(executors.length < 2 && placements.remoteOnlyNoop.size === 0
|
|
192
195
|
? {}
|
|
193
196
|
: {
|
|
194
197
|
executorOf: (id: string) =>
|
|
195
|
-
placements.remoteOnlyNoop.has(id)
|
|
198
|
+
placements.remoteOnlyNoop.has(id)
|
|
199
|
+
? 'noop'
|
|
200
|
+
: executors.length < 2
|
|
201
|
+
? undefined
|
|
202
|
+
: placements.executors.get(id)?.name,
|
|
196
203
|
}),
|
|
197
204
|
...(download === undefined
|
|
198
205
|
? {}
|
package/src/orchestrator/plan.ts
CHANGED
|
@@ -40,7 +40,8 @@ export interface PlannedTask {
|
|
|
40
40
|
/**
|
|
41
41
|
* Name of the executor this task would be PLACED on. Attached only when
|
|
42
42
|
* the workspace declares more than one executor — with a single one every
|
|
43
|
-
* line would carry the same label and say nothing
|
|
43
|
+
* line would carry the same label and say nothing — except `'noop'`: a
|
|
44
|
+
* remote-only task no remote executor takes, which the run skips. Absent for group tasks
|
|
44
45
|
* and persistent tasks, which never reach an executor.
|
|
45
46
|
*/
|
|
46
47
|
executor?: string
|
|
@@ -105,7 +106,7 @@ export interface PlanArgs {
|
|
|
105
106
|
/** When provided, per-task p50s are attached and `RunPlan.predicted` is
|
|
106
107
|
* computed. Failing open: a history error yields a plan without them. */
|
|
107
108
|
history?: HistoryProvider
|
|
108
|
-
/** Placement lookup (`
|
|
109
|
+
/** Placement lookup (`placement.ts`): >1 executor declared, or a `noop` task. */
|
|
109
110
|
executorOf?: (id: string) => string | undefined
|
|
110
111
|
}
|
|
111
112
|
|
|
@@ -212,6 +213,8 @@ function downgradeField(args: PlanArgs): {
|
|
|
212
213
|
|
|
213
214
|
/** A task the plan expects to EXECUTE (a no-cache task executes every run). */
|
|
214
215
|
function wouldRun(t: PlannedTask): boolean {
|
|
216
|
+
// A `noop` task succeeds without running (execute-task.ts), whatever its key.
|
|
217
|
+
if (t.executor === 'noop') return false
|
|
215
218
|
return t.cacheStatus === 'miss' || t.cacheStatus === 'no-cache'
|
|
216
219
|
}
|
|
217
220
|
|
package/src/workspace/filter.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// <pattern> name glob, `*` = any characters (e.g. foo, @scope/*)
|
|
4
4
|
// ./<dir> the package at <dir>, else the packages under it (relative to workspace root)
|
|
5
5
|
// {<dir>} same as ./<dir>
|
|
6
|
+
// // the workspace-root project only (Turbo's name for the root)
|
|
6
7
|
// <pattern>... pattern + its transitive workspace dependencies
|
|
7
8
|
// ...<pattern> pattern + its transitive workspace dependents
|
|
8
9
|
// <pattern>^... only the transitive deps of pattern (excluding the matched package)
|
|
@@ -44,6 +45,8 @@ export interface ParsedFilter {
|
|
|
44
45
|
pathGlob?: Bun.Glob
|
|
45
46
|
/** The workspace root `pathGlob` is relative to. */
|
|
46
47
|
pathRoot?: string
|
|
48
|
+
/** `//`: the project at `matcher` itself, never the ones under it. */
|
|
49
|
+
exactDir?: true
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
export function parseFilter(raw: string, workspaceRoot: string): ParsedFilter {
|
|
@@ -102,6 +105,26 @@ export function parseFilter(raw: string, workspaceRoot: string): ParsedFilter {
|
|
|
102
105
|
// with one warning line (item 1030).
|
|
103
106
|
if (s === '') throw new UserError(`filter "${raw}" names no project`)
|
|
104
107
|
|
|
108
|
+
// `//` is Turbo's name for the root package (`--filter=//`, `//...`,
|
|
109
|
+
// `!//`, probed on 2.8.17). vx names the root project by its
|
|
110
|
+
// package.json name, so `//` is its directory, and only a project
|
|
111
|
+
// there: read as `.`, it would select every project when the root is
|
|
112
|
+
// none.
|
|
113
|
+
if (s === '//') {
|
|
114
|
+
return {
|
|
115
|
+
raw,
|
|
116
|
+
negate,
|
|
117
|
+
withDeps,
|
|
118
|
+
withDependents,
|
|
119
|
+
onlyDeps,
|
|
120
|
+
onlyDependents,
|
|
121
|
+
isPath: true,
|
|
122
|
+
matcher: path.resolve(workspaceRoot),
|
|
123
|
+
exactDir: true,
|
|
124
|
+
...(gitSince !== undefined ? { gitSince } : {}),
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
105
128
|
let isPath = false
|
|
106
129
|
let matcher = s
|
|
107
130
|
let pathGlob: Bun.Glob | undefined
|
|
@@ -164,6 +187,7 @@ function matchSelector(filter: ParsedFilter, projects: ProjectMeta[]): string[]
|
|
|
164
187
|
// A directory that is no project keeps the "at or under" reading.
|
|
165
188
|
const exact = projects.find((p) => p.dir === filter.matcher)
|
|
166
189
|
if (exact !== undefined) return [exact.name]
|
|
190
|
+
if (filter.exactDir === true) return out
|
|
167
191
|
const prefix = filter.matcher + path.sep
|
|
168
192
|
for (const p of projects) {
|
|
169
193
|
if (p.dir.startsWith(prefix)) out.push(p.name)
|