@vzn/vx 0.0.652 → 0.0.653
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 +2 -2
- package/launcher.sh +2 -1
- package/package.json +5 -5
- package/schemas/error.json +1 -1
- package/schemas/show.json +1 -0
- package/skills/vx/SKILL.md +3 -3
- package/src/bin.ts +25 -3
- package/src/cache/archive.ts +196 -31
- package/src/cache/cache.ts +863 -225
- package/src/cache/checkpointer.ts +102 -0
- package/src/cache/file-hashes.ts +2 -1
- package/src/cache/fold-memo.ts +24 -4
- package/src/cache/fs-clock.ts +26 -0
- package/src/cache/git-inputs.ts +188 -22
- package/src/cache/history-stream.ts +22 -5
- package/src/cache/index.ts +10 -1
- package/src/cache/inputs.ts +573 -152
- package/src/cache/key-fold.ts +1 -1
- package/src/cache/layer.ts +23 -10
- package/src/cache/layered-cache.ts +28 -7
- package/src/cache/output-index.ts +106 -44
- package/src/cache/plugin-cache.ts +2 -2
- package/src/cache/policy.ts +6 -2
- package/src/cache/remote-lane.ts +3 -1
- package/src/cache/run-history.ts +50 -10
- package/src/cache/schema.ts +42 -9
- package/src/cli/cache.ts +147 -34
- package/src/cli/completions.ts +2 -2
- package/src/cli/core-alias.ts +9 -2
- package/src/cli/docs.ts +4 -2
- package/src/cli/help.ts +25 -2
- package/src/cli/index.ts +38 -7
- package/src/cli/info.ts +4 -3
- package/src/cli/init.ts +55 -20
- package/src/cli/last.ts +184 -41
- package/src/cli/lock.ts +187 -24
- package/src/cli/plan-format.ts +24 -21
- package/src/cli/plugin-commands.ts +6 -1
- package/src/cli/plugin-templates.ts +1 -1
- package/src/cli/run.ts +68 -34
- package/src/cli/select.ts +160 -64
- package/src/cli/show.ts +63 -18
- package/src/cli/task-verb.ts +12 -7
- package/src/cli/upgrade.ts +210 -76
- package/src/cli/watch-filter.ts +88 -15
- package/src/cli/watch-fs.ts +34 -47
- package/src/cli/watch-judge.ts +72 -8
- package/src/cli/watch-set.ts +6 -4
- package/src/cli/watch.ts +179 -25
- package/src/cli/why.ts +107 -33
- package/src/cli/workspace-config.ts +11 -1
- package/src/config.ts +9 -0
- package/src/exec/env.ts +3 -1
- package/src/exec/executor.ts +76 -15
- package/src/exec/kill-tree.ts +7 -7
- package/src/exec/runner.ts +270 -108
- package/src/exec/sandbox-binds.ts +109 -18
- package/src/exec/sandbox-runtime.ts +134 -37
- package/src/exec/sandbox-violations.ts +250 -46
- package/src/exec/spawn-off.ts +10 -5
- package/src/exec/warm-shell.ts +29 -7
- package/src/graph/folds.ts +89 -16
- package/src/graph/index.ts +8 -0
- package/src/graph/priorities.ts +8 -5
- package/src/graph/scheduler.ts +173 -38
- package/src/graph/stand-ins.ts +36 -0
- package/src/graph/task-graph.ts +327 -141
- package/src/graph/task-status.ts +5 -1
- package/src/handoff.ts +45 -10
- package/src/history/failure-mode.ts +15 -5
- package/src/history/history.ts +103 -30
- package/src/history/index.ts +1 -0
- package/src/history/metrics.ts +189 -69
- package/src/index.ts +2 -1
- package/src/orchestrator/admission.ts +13 -9
- package/src/orchestrator/affected-tasks.ts +35 -13
- package/src/orchestrator/command-windows.ts +8 -5
- package/src/orchestrator/deferred-outputs.ts +41 -12
- package/src/orchestrator/doctor.ts +21 -9
- package/src/orchestrator/download-policy.ts +3 -3
- package/src/orchestrator/excluded-keys.ts +14 -2
- package/src/orchestrator/execute-args.ts +9 -2
- package/src/orchestrator/execute-task.ts +564 -123
- package/src/orchestrator/graph-memo.ts +26 -4
- package/src/orchestrator/graph-stage.ts +27 -4
- package/src/orchestrator/held-servers.ts +36 -14
- package/src/orchestrator/hit-restore.ts +136 -87
- package/src/orchestrator/index.ts +4 -1
- package/src/orchestrator/keyed-projects.ts +25 -0
- package/src/orchestrator/local-floor.ts +21 -3
- package/src/orchestrator/lockfile-claim.ts +30 -4
- package/src/orchestrator/miss-save.ts +33 -53
- package/src/orchestrator/options.ts +13 -0
- package/src/orchestrator/output-host.ts +16 -4
- package/src/orchestrator/output-log.ts +1 -54
- package/src/orchestrator/persistent-task.ts +31 -17
- package/src/orchestrator/persistent.ts +152 -15
- package/src/orchestrator/placement.ts +81 -15
- package/src/orchestrator/plan.ts +37 -15
- package/src/orchestrator/plugin-host.ts +232 -108
- package/src/orchestrator/plugin.ts +53 -27
- package/src/orchestrator/prepare.ts +194 -38
- package/src/orchestrator/projects.ts +89 -10
- package/src/orchestrator/read-only.ts +115 -0
- package/src/orchestrator/run-context.ts +6 -2
- package/src/orchestrator/run-failures.ts +43 -14
- package/src/orchestrator/run-id.ts +13 -2
- package/src/orchestrator/run-keys.ts +87 -28
- package/src/orchestrator/run-live.ts +16 -13
- package/src/orchestrator/run-lock.ts +27 -4
- package/src/orchestrator/run-records.ts +12 -10
- package/src/orchestrator/run-report.ts +2 -1
- package/src/orchestrator/run-stop.ts +17 -9
- package/src/orchestrator/run.ts +443 -107
- package/src/orchestrator/sandbox-fix.ts +40 -12
- package/src/orchestrator/sandbox-request.ts +286 -59
- package/src/orchestrator/save-lane.ts +24 -13
- package/src/orchestrator/shell-verdict.ts +20 -1
- package/src/orchestrator/signals.ts +103 -8
- package/src/orchestrator/stable-keys.ts +17 -9
- package/src/orchestrator/task-artifacts.ts +15 -2
- package/src/orchestrator/task-hash.ts +187 -30
- package/src/orchestrator/telemetry-host.ts +25 -6
- package/src/orchestrator/telemetry.ts +80 -12
- package/src/orchestrator/upstream.ts +3 -1
- package/src/report/events.ts +20 -3
- package/src/report/forecast.ts +103 -37
- package/src/report/framed-output.ts +165 -157
- package/src/report/index.ts +2 -1
- package/src/report/logger.ts +107 -30
- package/src/report/plain-output.ts +13 -9
- package/src/report/status-line.ts +28 -55
- package/src/report/summary.ts +57 -14
- package/src/settings.ts +42 -6
- package/src/ui/components.ts +36 -42
- package/src/ui/index.ts +3 -1
- package/src/ui/live-region.ts +67 -8
- package/src/ui/terminal.ts +12 -0
- package/src/ui/theme.ts +16 -1
- package/src/util/config-frame.ts +17 -3
- package/src/util/edit-distance.ts +17 -1
- package/src/util/errors.ts +23 -7
- package/src/util/foreign-cache-dir.ts +60 -0
- package/src/util/git-ignored.ts +59 -5
- package/src/util/index.ts +15 -1
- package/src/util/paths.ts +50 -6
- package/src/util/plain-text.ts +19 -0
- package/src/util/secret-mask.ts +57 -1
- package/src/util/settle.ts +16 -0
- package/src/util/size.ts +12 -2
- package/src/util/write-file.ts +86 -9
- package/src/workspace/affected.ts +225 -27
- package/src/workspace/config-bytecode.ts +23 -4
- package/src/workspace/config-eval.ts +90 -16
- package/src/workspace/config-imports.ts +96 -41
- package/src/workspace/config-schema.ts +126 -25
- package/src/workspace/dependencies-lock.ts +7 -14
- package/src/workspace/filter.ts +10 -1
- package/src/workspace/index.ts +3 -1
- package/src/workspace/json-data.ts +34 -8
- package/src/workspace/lockfile.ts +86 -37
- package/src/workspace/migration.ts +46 -25
- package/src/workspace/module-state.ts +62 -0
- package/src/workspace/nested-dirs.ts +8 -0
- package/src/workspace/project-loader.ts +276 -32
- package/src/workspace/repo-id.ts +29 -6
- package/src/workspace/workspace.ts +190 -30
package/src/cli/show.ts
CHANGED
|
@@ -6,11 +6,12 @@
|
|
|
6
6
|
// resolved config. `<pkg>#<task>`: one task. `<task>`: that task in every
|
|
7
7
|
// project declaring it.
|
|
8
8
|
|
|
9
|
+
import { existsSync } from 'node:fs'
|
|
9
10
|
import path from 'node:path'
|
|
10
11
|
import type { ProjectConfig, TaskConfig } from '../config.js'
|
|
11
12
|
import { declaredTask } from '../graph/index.js'
|
|
12
13
|
import { isDefaultBuild } from '../graph/index.js'
|
|
13
|
-
import { affectedTaskProjects } from '../orchestrator/index.js'
|
|
14
|
+
import { affectedTaskProjects, projectAtDir, unlockedDir } from '../orchestrator/index.js'
|
|
14
15
|
import { flagHint, formatValue, refuse, seeHelp } from './help.js'
|
|
15
16
|
import {
|
|
16
17
|
listed,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
} from '../util/index.js'
|
|
23
24
|
import * as ui from '../ui/index.js'
|
|
24
25
|
import { sayNotice } from '../ui/index.js'
|
|
25
|
-
import { affectedFilterFor, resolveFilters } from './select.js'
|
|
26
|
+
import { type AffectedFilter, affectedFilterFor, resolveFilters } from './select.js'
|
|
26
27
|
import {
|
|
27
28
|
discoverCliProjects,
|
|
28
29
|
loadCliProjects,
|
|
@@ -34,6 +35,7 @@ import {
|
|
|
34
35
|
buildPackageGraph,
|
|
35
36
|
EMPTY_LOCK,
|
|
36
37
|
findWorkspaceRoot,
|
|
38
|
+
PROJECT_CONFIG_FILENAMES,
|
|
37
39
|
type ProjectEntry,
|
|
38
40
|
type ProjectMeta,
|
|
39
41
|
} from '../workspace/index.js'
|
|
@@ -113,6 +115,22 @@ export async function showCmd(args: readonly string[]): Promise<number> {
|
|
|
113
115
|
}
|
|
114
116
|
parsed.target = `${rootMeta.name}${parsed.target.slice(2)}`
|
|
115
117
|
}
|
|
118
|
+
// A project's directory typed for its name: by edit distance, `p/a`
|
|
119
|
+
// hinted `p/b`, another project.
|
|
120
|
+
const atDir = (typed: string, suffix: string): string | undefined => {
|
|
121
|
+
const name = projectAtDir(typed, root, metas)
|
|
122
|
+
return name === undefined ? undefined : ` — did you mean ${name}${suffix}?`
|
|
123
|
+
}
|
|
124
|
+
// A directory whose config came after the lock: the line `vx run` gives,
|
|
125
|
+
// not "unknown project" and a guess.
|
|
126
|
+
const refuseUnlocked = async (typed: string): Promise<void> => {
|
|
127
|
+
const config = await unlockedDir(typed, metas, root)
|
|
128
|
+
if (config === undefined) return
|
|
129
|
+
throw new UserError(
|
|
130
|
+
`${parsed.target}: ${relPosix(root, config)} is not in the lock yet — run \`vx lock\``,
|
|
131
|
+
'VX_E_LOCK',
|
|
132
|
+
)
|
|
133
|
+
}
|
|
116
134
|
const hashAt = parsed.target?.indexOf('#') ?? -1
|
|
117
135
|
const projectName =
|
|
118
136
|
parsed.target === undefined
|
|
@@ -136,8 +154,9 @@ export async function showCmd(args: readonly string[]): Promise<number> {
|
|
|
136
154
|
}
|
|
137
155
|
if (projectName !== undefined && (taskName !== undefined || byName.has(projectName))) {
|
|
138
156
|
if (!byName.has(projectName)) {
|
|
157
|
+
await refuseUnlocked(projectName)
|
|
139
158
|
throw new UserError(
|
|
140
|
-
`vx show: unknown project: "${projectName}"${suggest(projectName, [...byName.keys()], '', 'projects')}`,
|
|
159
|
+
`vx show: unknown project: "${projectName}"${atDir(projectName, `#${taskName}`) ?? suggest(projectName, [...byName.keys()], '', 'projects')}`,
|
|
141
160
|
'VX_E_UNKNOWN_PROJECT',
|
|
142
161
|
)
|
|
143
162
|
}
|
|
@@ -161,16 +180,16 @@ export async function showCmd(args: readonly string[]): Promise<number> {
|
|
|
161
180
|
)
|
|
162
181
|
}
|
|
163
182
|
const raw = [...parsed.filters]
|
|
164
|
-
let affected:
|
|
183
|
+
let affected: AffectedFilter | undefined
|
|
165
184
|
if (parsed.affected !== undefined) {
|
|
166
185
|
const f = await affectedFilterFor(
|
|
167
186
|
process.cwd(),
|
|
168
187
|
parsed.affected,
|
|
169
188
|
'drop --affected to list them all',
|
|
170
189
|
)
|
|
171
|
-
if (
|
|
190
|
+
if ('error' in f) throw new UserError(`vx show: ${f.error}`, f.code ?? 'VX_E_USAGE')
|
|
172
191
|
affected = f
|
|
173
|
-
raw.unshift(f)
|
|
192
|
+
raw.unshift(f.filter)
|
|
174
193
|
}
|
|
175
194
|
const r = await resolveFilters(process.cwd(), raw, {}, affected, 'show')
|
|
176
195
|
if ('error' in r) throw new UserError(`vx show: ${r.error}`, r.code ?? 'VX_E_USAGE')
|
|
@@ -203,13 +222,14 @@ export async function showCmd(args: readonly string[]): Promise<number> {
|
|
|
203
222
|
declares(declaredTask(p.config, projectName!)),
|
|
204
223
|
)
|
|
205
224
|
if (declaring.length === 0) {
|
|
225
|
+
await refuseUnlocked(projectName!)
|
|
206
226
|
const names = new Set<string>()
|
|
207
227
|
for (const p of projects.values())
|
|
208
228
|
for (const [t, task] of Object.entries(p.config.tasks ?? {}))
|
|
209
229
|
if (declares(task)) names.add(t)
|
|
210
230
|
// `nx show projects` lists them; here a bare `vx show` does.
|
|
211
231
|
const nx = projectName === 'projects' ? ' (`nx show projects` is `vx show` here)' : ''
|
|
212
|
-
const unknown = `vx show: unknown project or task: "${projectName}"${nx}${suggest(projectName!, [...byName.keys(), ...names], '', 'projects and tasks')}`
|
|
232
|
+
const unknown = `vx show: unknown project or task: "${projectName}"${nx}${atDir(projectName!, '') ?? suggest(projectName!, [...byName.keys(), ...names], '', 'projects and tasks')}`
|
|
213
233
|
const base =
|
|
214
234
|
parsed.spacedBase === projectName
|
|
215
235
|
? `${unknown.endsWith('.') ? '' : '.'} \`--affected\` takes its base with '=': --affected=${projectName}`
|
|
@@ -258,7 +278,7 @@ export async function showCmd(args: readonly string[]): Promise<number> {
|
|
|
258
278
|
const dir = projectDir(root, meta)
|
|
259
279
|
|
|
260
280
|
if (taskName === undefined) {
|
|
261
|
-
emit(renderProject(meta.name, dir, config, meta
|
|
281
|
+
emit(renderProject(meta.name, dir, config, configNote(meta), parsed.format))
|
|
262
282
|
return 0
|
|
263
283
|
}
|
|
264
284
|
|
|
@@ -369,7 +389,9 @@ function renderList(
|
|
|
369
389
|
tags: projects.get(meta.name)?.config.tags ?? [],
|
|
370
390
|
tasks: Object.keys(tasks),
|
|
371
391
|
onlyDefault: Object.values(tasks).every((t) => isDefaultBuild(t)),
|
|
392
|
+
hasDefault: Object.values(tasks).some((t) => isDefaultBuild(t)),
|
|
372
393
|
configured: meta.configPath !== null,
|
|
394
|
+
note: configNote(meta),
|
|
373
395
|
}
|
|
374
396
|
})
|
|
375
397
|
if (format === 'json') {
|
|
@@ -383,23 +405,38 @@ function renderList(
|
|
|
383
405
|
// A package with no config file has only tasks a plugin gave it, or the
|
|
384
406
|
// default `build` a configured dependant's closure gave it.
|
|
385
407
|
const tasks = r.configured
|
|
386
|
-
?
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
408
|
+
? r.tasks.length > 0 && r.hasDefault
|
|
409
|
+
? `${count}, default build`
|
|
410
|
+
: count
|
|
411
|
+
: r.note !== null && r.note !== 'none'
|
|
412
|
+
? r.note
|
|
413
|
+
: n === 0
|
|
414
|
+
? 'no vx config'
|
|
415
|
+
: r.onlyDefault
|
|
416
|
+
? `${count}, default build (no vx config)`
|
|
417
|
+
: `${count} from plugins (no vx config)`
|
|
392
418
|
return [ui.id(r.name), r.dir, tasks, ...(anyTags ? [r.tags.join(', ')] : [])]
|
|
393
419
|
})
|
|
394
420
|
const columns = ['project', 'dir', 'tasks', ...(anyTags ? ['tags'] : [])]
|
|
395
421
|
return [ui.section('Projects', String(rows.length), ui.table(columns, cells))]
|
|
396
422
|
}
|
|
397
423
|
|
|
424
|
+
/**
|
|
425
|
+
* Null for a project the lock holds a config for; else `none`, or a config
|
|
426
|
+
* written after the lock: "no vx config" sent a user who had just written
|
|
427
|
+
* one looking for a typo.
|
|
428
|
+
*/
|
|
429
|
+
function configNote(meta: ProjectMeta): string | null {
|
|
430
|
+
if (meta.configPath !== null) return null
|
|
431
|
+
const file = PROJECT_CONFIG_FILENAMES.find((n) => existsSync(path.join(meta.dir, n)))
|
|
432
|
+
return file === undefined ? 'none' : `${file} not locked — run vx lock`
|
|
433
|
+
}
|
|
434
|
+
|
|
398
435
|
function renderProject(
|
|
399
436
|
name: string,
|
|
400
437
|
dir: string,
|
|
401
438
|
config: ProjectConfig | null,
|
|
402
|
-
|
|
439
|
+
note: string | null,
|
|
403
440
|
format: 'pretty' | 'json',
|
|
404
441
|
): Shown {
|
|
405
442
|
if (format === 'json') {
|
|
@@ -414,11 +451,16 @@ function renderProject(
|
|
|
414
451
|
['dir', dir],
|
|
415
452
|
...(tags.length > 0 ? [['tags', tags.join(', ')] as const] : []),
|
|
416
453
|
// A config-less package a dependant reaches has the default `build` (X-9).
|
|
417
|
-
...(
|
|
418
|
-
...(tasks.length === 0 &&
|
|
454
|
+
...(note === null ? [] : [['config', note] as const]),
|
|
455
|
+
...(tasks.length === 0 && note === null ? [['tasks', 'none declared'] as const] : []),
|
|
419
456
|
]
|
|
420
457
|
const blocks = tasks.map(([taskName, task]) =>
|
|
421
|
-
joined([
|
|
458
|
+
joined([
|
|
459
|
+
isDefaultBuild(task)
|
|
460
|
+
? ui.line(' ', ui.id(`${name}#${taskName}`), ui.dim(' default'))
|
|
461
|
+
: ui.text(ui.id(`${name}#${taskName}`)),
|
|
462
|
+
ui.fields(taskRows(task)),
|
|
463
|
+
]),
|
|
422
464
|
)
|
|
423
465
|
return [ui.section(name, ui.fields(head), ...blocks)]
|
|
424
466
|
}
|
|
@@ -516,5 +558,8 @@ function taskRows(raw: TaskConfig): ui.FieldRow[] {
|
|
|
516
558
|
add('outputs.workspaceFiles', list(outputs.workspaceFiles))
|
|
517
559
|
add('outputs.clean', outputs.clean === undefined ? undefined : outputs.clean ? 'yes' : 'no')
|
|
518
560
|
}
|
|
561
|
+
// The first question `vx why` raises ("declares no `cache: true`"), which
|
|
562
|
+
// only --format json answered.
|
|
563
|
+
if (task.cache === true) add('cache', 'yes')
|
|
519
564
|
return rows
|
|
520
565
|
}
|
package/src/cli/task-verb.ts
CHANGED
|
@@ -68,20 +68,25 @@ export async function nxTargetHint(tasks: readonly string[], cwd: string): Promi
|
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* The task names `vx run <task>` can take
|
|
72
|
-
*
|
|
73
|
-
*
|
|
71
|
+
* The task names `vx run <task>` can take in the asked scope (`asked`: the
|
|
72
|
+
* projects `--filter` / `--affected` selected, or `all`), else the cwd
|
|
73
|
+
* project's, else every project's, sorted; null when no workspace loads.
|
|
74
|
+
* What a run with no task and no terminal for the picker names instead of
|
|
75
|
+
* a guess.
|
|
74
76
|
*/
|
|
75
|
-
export async function taskNamesHere(
|
|
77
|
+
export async function taskNamesHere(
|
|
78
|
+
cwd: string,
|
|
79
|
+
asked?: ReadonlySet<string> | 'all',
|
|
80
|
+
): Promise<{ names: string[]; inProject: boolean } | null> {
|
|
76
81
|
const projects = await workspaceProjects(cwd)
|
|
77
82
|
if (projects === null) return null
|
|
78
|
-
const own = await findCwdProject(cwd)
|
|
83
|
+
const own = asked === undefined ? await findCwdProject(cwd) : null
|
|
79
84
|
const names = new Set<string>()
|
|
80
85
|
for (const p of projects.values())
|
|
81
|
-
if (own === null || p.name === own)
|
|
86
|
+
if (typeof asked === 'object' ? asked.has(p.name) : own === null || p.name === own)
|
|
82
87
|
for (const [t, task] of Object.entries(p.config.tasks ?? {}))
|
|
83
88
|
if (!isDefaultBuild(task)) names.add(t)
|
|
84
|
-
return [...names].sort()
|
|
89
|
+
return { names: [...names].sort(), inProject: own !== null }
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
/**
|