@vzn/vx 0.0.650 → 0.0.652
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 +7 -23
- package/package.json +5 -5
- package/schemas/last.json +15 -0
- package/schemas/show.json +14 -20
- package/src/bin.ts +21 -31
- package/src/cache/archive.ts +1 -1
- package/src/cache/cache.ts +221 -30
- package/src/cache/file-hashes.ts +3 -0
- package/src/cache/git-inputs.ts +188 -39
- package/src/cache/history-stream.ts +134 -0
- package/src/cache/history-writer.ts +76 -0
- package/src/cache/index.ts +3 -0
- package/src/cache/inputs.ts +77 -14
- package/src/cache/layer.ts +17 -6
- package/src/cache/layered-cache.ts +4 -0
- package/src/cache/linked-inputs.ts +3 -0
- package/src/cache/lockfile-memo.ts +5 -3
- package/src/cache/output-index.ts +5 -2
- package/src/cache/remote-lane.ts +2 -1
- package/src/cache/run-history.ts +56 -17
- package/src/cache/schema.ts +15 -2
- package/src/cli/cache.ts +28 -18
- package/src/cli/completions.ts +4 -2
- package/src/cli/docs.ts +10 -11
- package/src/cli/help.ts +14 -25
- package/src/cli/index.ts +28 -9
- package/src/cli/info.ts +16 -8
- package/src/cli/init.ts +23 -15
- package/src/cli/last.ts +246 -204
- package/src/cli/lock.ts +55 -5
- package/src/cli/plan-format.ts +100 -118
- package/src/cli/plugin-commands.ts +8 -2
- package/src/cli/plugin-templates.ts +36 -45
- package/src/cli/run.ts +46 -27
- package/src/cli/select.ts +43 -5
- package/src/cli/show.ts +45 -52
- package/src/cli/task-verb.ts +22 -0
- package/src/cli/upgrade.ts +3 -1
- package/src/cli/watch-fs.ts +6 -1
- package/src/cli/watch-judge.ts +3 -2
- package/src/cli/watch-set.ts +4 -4
- package/src/cli/watch.ts +94 -52
- package/src/cli/why.ts +123 -89
- package/src/cli/workspace-config.ts +2 -1
- package/src/config.ts +47 -30
- package/src/exec/executor.ts +42 -2
- package/src/exec/index.ts +1 -0
- package/src/exec/kill-tree.ts +58 -5
- package/src/exec/local-executor.ts +1 -1
- package/src/exec/pipes.ts +152 -0
- package/src/exec/runner.ts +199 -182
- package/src/exec/sandbox-binds.ts +1 -1
- package/src/exec/sandbox-paths.ts +3 -1
- package/src/exec/sandbox-runtime.ts +317 -23
- package/src/exec/spawn-off.ts +154 -0
- package/src/exec/task-proxy.ts +93 -0
- package/src/exec/warm-shell.ts +146 -0
- package/src/graph/critical-path.ts +40 -28
- package/src/graph/definition.ts +16 -3
- package/src/graph/priorities.ts +98 -44
- package/src/graph/scheduler.ts +17 -11
- package/src/graph/task-graph.ts +51 -24
- package/src/handoff.ts +10 -7
- package/src/history/failure-mode.ts +24 -1
- package/src/history/history.ts +5 -0
- package/src/history/index.ts +1 -0
- package/src/history/metrics.ts +14 -6
- package/src/index.ts +7 -3
- package/src/orchestrator/admission.ts +1 -1
- package/src/orchestrator/command-windows.ts +1 -1
- package/src/orchestrator/deferred-outputs.ts +1 -1
- package/src/orchestrator/doctor.ts +1 -1
- package/src/orchestrator/download-policy.ts +5 -7
- package/src/orchestrator/excluded-keys.ts +1 -1
- package/src/orchestrator/execute-task.ts +67 -20
- package/src/orchestrator/graph-memo.ts +50 -1
- package/src/orchestrator/graph-stage.ts +6 -0
- package/src/orchestrator/hit-restore.ts +5 -6
- package/src/orchestrator/index.ts +3 -0
- package/src/orchestrator/keyed-projects.ts +28 -0
- package/src/orchestrator/live-usage.ts +16 -11
- package/src/orchestrator/local-shortcircuit.ts +2 -2
- package/src/orchestrator/locked-digests.ts +63 -0
- package/src/orchestrator/lockfile-claim.ts +108 -29
- package/src/orchestrator/miss-save.ts +58 -11
- package/src/orchestrator/persistent-task.ts +5 -1
- package/src/orchestrator/placement.ts +1 -1
- package/src/orchestrator/plan.ts +7 -3
- package/src/orchestrator/plugin-host.ts +67 -2
- package/src/orchestrator/plugin.ts +53 -2
- package/src/orchestrator/prepare.ts +16 -1
- package/src/orchestrator/projects.ts +4 -1
- package/src/orchestrator/remote-prefetch.ts +1 -1
- package/src/orchestrator/run-context.ts +29 -10
- package/src/orchestrator/run-failures.ts +62 -13
- package/src/orchestrator/run-keys.ts +1 -1
- package/src/orchestrator/run-records.ts +88 -59
- package/src/orchestrator/run-report.ts +1 -1
- package/src/orchestrator/run.ts +145 -41
- package/src/orchestrator/sandbox-request.ts +52 -9
- package/src/orchestrator/shell-verdict.ts +9 -0
- package/src/orchestrator/signals.ts +8 -5
- package/src/orchestrator/stable-keys.ts +17 -18
- package/src/orchestrator/task-artifacts.ts +1 -1
- package/src/orchestrator/task-hash.ts +21 -7
- package/src/orchestrator/telemetry.ts +5 -1
- package/src/report/events.ts +6 -14
- package/src/report/forecast.ts +10 -32
- package/src/report/framed-output.ts +283 -175
- package/src/report/index.ts +8 -3
- package/src/report/logger.ts +74 -39
- package/src/report/plain-output.ts +3 -1
- package/src/report/status-line.ts +49 -357
- package/src/report/summary.ts +105 -136
- package/src/settings.ts +8 -8
- package/src/ui/ansi.ts +48 -0
- package/src/ui/components.ts +506 -0
- package/src/ui/index.ts +79 -0
- package/src/ui/kit.ts +37 -0
- package/src/ui/live-region.ts +363 -0
- package/src/{util/refusal-notice.ts → ui/refusal.ts} +7 -5
- package/src/ui/terminal.ts +51 -0
- package/src/ui/theme.ts +224 -0
- package/src/ui/version-line.ts +28 -0
- package/src/util/config-frame.ts +191 -14
- package/src/util/edit-distance.ts +6 -1
- package/src/util/index.ts +2 -15
- package/src/util/paths.ts +21 -3
- package/src/util/secret-mask.ts +39 -3
- package/src/util/settle.ts +33 -1
- package/src/util/tail.ts +4 -1
- package/src/util/timing.ts +4 -16
- package/src/workspace/affected.ts +89 -30
- package/src/workspace/bracket-literal.ts +2 -2
- package/src/workspace/config-schema.ts +70 -63
- package/src/workspace/dependencies-lock.ts +191 -0
- package/src/workspace/filter.ts +36 -1
- package/src/workspace/index.ts +9 -0
- package/src/workspace/lockfile.ts +159 -6
- package/src/workspace/migration.ts +16 -9
- package/src/workspace/workspace.ts +3 -0
- package/src/util/colors.ts +0 -133
- package/src/util/report.ts +0 -44
- package/src/util/ui.ts +0 -258
- /package/src/{report/path-links.ts → ui/links.ts} +0 -0
- /package/src/{report → ui}/terminal-signals.ts +0 -0
package/src/cli/docs.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
// whole, best first.
|
|
6
6
|
|
|
7
7
|
import { VERSION } from '../version.js'
|
|
8
|
-
import {
|
|
8
|
+
import { parseDecimalInt } from '../util/index.js'
|
|
9
|
+
import * as ui from '../ui/index.js'
|
|
9
10
|
import { flagHint, formatValue, refuse, refusedWord, seeHelp } from './help.js'
|
|
10
11
|
|
|
11
12
|
const SITE = 'https://vznjs.github.io/vx/'
|
|
@@ -238,7 +239,7 @@ export async function docsCmd(
|
|
|
238
239
|
const hits = searchDocs(pages, parsed.terms, parsed.limit)
|
|
239
240
|
const query = parsed.terms.join(' ')
|
|
240
241
|
if (parsed.json) {
|
|
241
|
-
|
|
242
|
+
ui.data('out', `${JSON.stringify({ query, hits })}\n`)
|
|
242
243
|
return 0
|
|
243
244
|
}
|
|
244
245
|
if (hits.length === 0) {
|
|
@@ -249,15 +250,13 @@ export async function docsCmd(
|
|
|
249
250
|
)
|
|
250
251
|
return 0
|
|
251
252
|
}
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
)
|
|
260
|
-
.join('\n'),
|
|
253
|
+
// Each hit an excerpt of the page, its link under it: off colour the
|
|
254
|
+
// bare markdown, as a pipe copies it.
|
|
255
|
+
ui.print(
|
|
256
|
+
'out',
|
|
257
|
+
...hits.map((h) =>
|
|
258
|
+
ui.excerpt(`${h.page}.md${h.heading === '' ? '' : ` § ${h.heading}`} · ${h.url}`, h.text),
|
|
259
|
+
),
|
|
261
260
|
)
|
|
262
261
|
return 0
|
|
263
262
|
}
|
package/src/cli/help.ts
CHANGED
|
@@ -1,22 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
errorDocument,
|
|
5
|
-
maskedLine,
|
|
6
|
-
nearest,
|
|
7
|
-
paint,
|
|
8
|
-
refusalNotice,
|
|
9
|
-
ui,
|
|
10
|
-
wantsJson,
|
|
11
|
-
type ColorSupport,
|
|
12
|
-
} from '../util/index.js'
|
|
1
|
+
import { CORE_VERBS, errorDocument, maskedLine, nearest, wantsJson } from '../util/index.js'
|
|
2
|
+
import * as ui from '../ui/index.js'
|
|
3
|
+
import { detectColors, paint, refusalNotice, type ColorSupport } from '../ui/index.js'
|
|
13
4
|
|
|
14
5
|
export async function printHelp(
|
|
15
6
|
pluginCommands: readonly string[] = [],
|
|
16
7
|
verb?: string,
|
|
17
8
|
): Promise<void> {
|
|
18
9
|
const text = verb === undefined ? helpText(pluginCommands) : verbHelpText(verb)
|
|
19
|
-
|
|
10
|
+
// The reference a script greps: painted on a terminal only, and strips
|
|
11
|
+
// back to `text` exactly, so it goes out as written.
|
|
12
|
+
ui.data('out', paintHelp(text, helpColors(process.stdout, detectColors), paint))
|
|
20
13
|
}
|
|
21
14
|
|
|
22
15
|
/**
|
|
@@ -31,9 +24,6 @@ export function helpColors(
|
|
|
31
24
|
return { enabled: stream.isTTY === true && detect(stream as NodeJS.WriteStream).enabled }
|
|
32
25
|
}
|
|
33
26
|
|
|
34
|
-
const VERB = '#06b6d4' // cyan-500 — the orchestrator's accent
|
|
35
|
-
const TERM = '#22d3ee' // cyan-400 — a flag, a selector, an example
|
|
36
|
-
|
|
37
27
|
/**
|
|
38
28
|
* The reference with ANSI accents, line by line and never reflowed, so the
|
|
39
29
|
* painted text strips back to `text` exactly: section headings bold (their
|
|
@@ -48,13 +38,12 @@ export function paintHelp(text: string, colors: ColorSupport, paint: Paint): str
|
|
|
48
38
|
if (line === '') return line
|
|
49
39
|
if (i === 0) {
|
|
50
40
|
const [name, ...rest] = line.split(' ')
|
|
51
|
-
return [paint(
|
|
41
|
+
return [paint('info', name!, colors, true), ...rest].join(' ')
|
|
52
42
|
}
|
|
53
43
|
const heading = /^([A-Z][^:]*?)( \(for [^)]*\))?:$/.exec(line)
|
|
54
44
|
if (heading !== null) {
|
|
55
|
-
const qualifier =
|
|
56
|
-
|
|
57
|
-
return `${paint('', heading[1]!, colors, { bold: true })}${qualifier}${paint('', ':', colors, { bold: true })}`
|
|
45
|
+
const qualifier = heading[2] === undefined ? '' : paint('muted', heading[2], colors)
|
|
46
|
+
return `${paint('strong', heading[1]!, colors)}${qualifier}${paint('strong', ':', colors)}`
|
|
58
47
|
}
|
|
59
48
|
// ` term description`: a term is a flag, a `vx` form, a selector.
|
|
60
49
|
const row = /^(\s+)(\S(?:.*?\S)?)(\s{2,}\S.*)?$/.exec(line)
|
|
@@ -66,11 +55,11 @@ export function paintHelp(text: string, colors: ColorSupport, paint: Paint): str
|
|
|
66
55
|
if (description === '' && !(CORE_VERBS as readonly string[]).includes(verb)) return line
|
|
67
56
|
const head = `vx ${verb}`
|
|
68
57
|
const tail = term!.slice(head.length)
|
|
69
|
-
return `${indent}${paint(
|
|
58
|
+
return `${indent}${paint('info', head, colors, true)}${tail === '' ? '' : paint('term', tail, colors)}${description}`
|
|
70
59
|
}
|
|
71
60
|
if (description === '') return line
|
|
72
61
|
if (/^(-|\(|[\w-]+#)/.test(term!))
|
|
73
|
-
return `${indent}${paint(
|
|
62
|
+
return `${indent}${paint('term', term!, colors)}${description}`
|
|
74
63
|
return line
|
|
75
64
|
})
|
|
76
65
|
.join('\n')
|
|
@@ -215,9 +204,9 @@ export function helpText(pluginCommands: readonly string[] = []): string {
|
|
|
215
204
|
'Cache management:',
|
|
216
205
|
' vx cache clean --older-than 30d Evict entries last accessed > 30 days ago.',
|
|
217
206
|
' vx cache clean --max-size 1G Keep total cache under 1 GB (LRU eviction).',
|
|
218
|
-
" vx cache clean Clear .vx/cache and this
|
|
207
|
+
" vx cache clean Clear .vx/cache and this workspace's store",
|
|
219
208
|
' ~/.vx/<id>/cache.',
|
|
220
|
-
" --global Clear every
|
|
209
|
+
" --global Clear every workspace's store under ~/.vx.",
|
|
221
210
|
' --dry Say what the policy would reap; delete nothing.',
|
|
222
211
|
' --format <fmt> pretty (default) | json.',
|
|
223
212
|
' --cache-dir <path> The cache a run with the same flag uses (why,',
|
|
@@ -475,7 +464,7 @@ export function refuse(
|
|
|
475
464
|
): number {
|
|
476
465
|
const line = `vx ${verb}: ${message}`
|
|
477
466
|
ui.print('err', refusalNotice(`vx ${verb}`, message))
|
|
478
|
-
if (wantsJson(args))
|
|
467
|
+
if (wantsJson(args)) ui.data('out', errorDocument(code, maskedLine(line)))
|
|
479
468
|
return 1
|
|
480
469
|
}
|
|
481
470
|
|
package/src/cli/index.ts
CHANGED
|
@@ -5,21 +5,20 @@ import { VERSION } from '../version.js'
|
|
|
5
5
|
import { checkSettingsEnv } from '../settings.js'
|
|
6
6
|
import { CORE_VERBS, flagHint, printHelp, refuse, refusedWord, seeHelp } from './help.js'
|
|
7
7
|
import {
|
|
8
|
-
detectColors,
|
|
9
8
|
errorDocument,
|
|
9
|
+
hasControl,
|
|
10
10
|
hideEnvFromTasks,
|
|
11
|
-
sayNotice,
|
|
12
11
|
isFsRefusal,
|
|
13
12
|
isOutOfFds,
|
|
14
13
|
isUserError,
|
|
15
14
|
maskedLine,
|
|
16
15
|
nearest,
|
|
17
|
-
refusalNotice,
|
|
18
16
|
thrownMessage,
|
|
19
|
-
ui,
|
|
20
17
|
UserError,
|
|
21
18
|
wantsJson,
|
|
22
19
|
} from '../util/index.js'
|
|
20
|
+
import * as ui from '../ui/index.js'
|
|
21
|
+
import { sayNotice, refusalNotice } from '../ui/index.js'
|
|
23
22
|
|
|
24
23
|
// Every verb is imported when invoked, `run` included, and so is the
|
|
25
24
|
// plugin-verb lookup: each pulls in the orchestrator and the workspace
|
|
@@ -32,6 +31,7 @@ const plugins = () => import('./plugin-commands.js')
|
|
|
32
31
|
export async function run(argv: readonly string[]): Promise<number> {
|
|
33
32
|
refuseLossyArgs(argv)
|
|
34
33
|
const [command, ...rest] = argv
|
|
34
|
+
if (command !== undefined) refuseControlArgs(command, rest)
|
|
35
35
|
await hideEnvFromTasks()
|
|
36
36
|
|
|
37
37
|
// `vx <verb> --help` is the universal reflex, and every verb answered
|
|
@@ -71,6 +71,28 @@ function refuseLossyArgs(argv: readonly string[]): void {
|
|
|
71
71
|
)
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* No core verb's argument holds a control character, and a refusal echoing
|
|
76
|
+
* one raw broke its headline at a newline. A forwarded one (after `--`) is
|
|
77
|
+
* the task's, a `--sql` query may span lines, and a plugin verb owns its own.
|
|
78
|
+
*/
|
|
79
|
+
function refuseControlArgs(command: string, rest: readonly string[]): void {
|
|
80
|
+
if (!(CORE_VERBS as readonly string[]).includes(command)) return
|
|
81
|
+
for (let i = 0; i < rest.length; i++) {
|
|
82
|
+
const a = rest[i]!
|
|
83
|
+
if (a === '--') return
|
|
84
|
+
if (a === '--sql') {
|
|
85
|
+
i++
|
|
86
|
+
continue
|
|
87
|
+
}
|
|
88
|
+
if (a.startsWith('--sql=') || !hasControl(a)) continue
|
|
89
|
+
throw new UserError(
|
|
90
|
+
`argument ${i + 2} (${JSON.stringify(a)}) holds a control character, which no \`vx ${command}\` argument takes`,
|
|
91
|
+
'VX_E_USAGE',
|
|
92
|
+
)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
74
96
|
/**
|
|
75
97
|
* A crash from a hand-broken lock entry is that entry's fault: runs validate
|
|
76
98
|
* no entry, so it surfaced as a raw TypeError (2026-10-14). The lock is
|
|
@@ -163,9 +185,7 @@ async function dispatch(command: string | undefined, rest: string[]): Promise<nu
|
|
|
163
185
|
)
|
|
164
186
|
}
|
|
165
187
|
// Painted, and the same words piped: a script reads `vx <version>`.
|
|
166
|
-
|
|
167
|
-
`${ui.inline([ui.cmd('vx'), ' ', ui.tone('info', VERSION)], detectColors(process.stdout))}\n`,
|
|
168
|
-
)
|
|
188
|
+
ui.print('out', ui.line(ui.cmd('vx'), ' ', ui.tone('info', VERSION)))
|
|
169
189
|
return 0
|
|
170
190
|
}
|
|
171
191
|
case 'run':
|
|
@@ -238,8 +258,7 @@ async function dispatch(command: string | undefined, rest: string[]): Promise<nu
|
|
|
238
258
|
): number => {
|
|
239
259
|
sayNotice(tone, 'vx', text.replace(/^vx: /, '').trimEnd())
|
|
240
260
|
// `vx --format json` puts the flag where the verb goes.
|
|
241
|
-
if (wantsJson([command, ...rest]))
|
|
242
|
-
process.stdout.write(errorDocument(code, maskedLine(json)))
|
|
261
|
+
if (wantsJson([command, ...rest])) ui.data('out', errorDocument(code, maskedLine(json)))
|
|
243
262
|
return 1
|
|
244
263
|
}
|
|
245
264
|
const loadNote =
|
package/src/cli/info.ts
CHANGED
|
@@ -9,7 +9,9 @@ import { type FlakyTask } from '../history/index.js'
|
|
|
9
9
|
import { flagHint, formatValue, refuse, refusedWord, seeHelp } from './help.js'
|
|
10
10
|
import { namedCacheDir, parseCacheDirFlag, warnToStderr } from './workspace-config.js'
|
|
11
11
|
import { formatBytes } from './format.js'
|
|
12
|
-
import {
|
|
12
|
+
import { MIN_BUN } from '../util/index.js'
|
|
13
|
+
import * as ui from '../ui/index.js'
|
|
14
|
+
import { type ColorSupport } from '../ui/index.js'
|
|
13
15
|
import { envName } from '../settings.js'
|
|
14
16
|
|
|
15
17
|
interface InfoArgs {
|
|
@@ -55,15 +57,18 @@ export async function infoCmd(args: readonly string[]): Promise<number> {
|
|
|
55
57
|
...(parsed.cacheDir !== undefined ? { cacheDir: parsed.cacheDir } : {}),
|
|
56
58
|
warn: warnToStderr,
|
|
57
59
|
})
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
? `${JSON.stringify(facts)}\n`
|
|
61
|
-
: `${renderInfo(facts, detectColors(process.stdout))}\n`,
|
|
62
|
-
)
|
|
60
|
+
if (parsed.format === 'json') ui.data('out', `${JSON.stringify(facts)}\n`)
|
|
61
|
+
else ui.print('out', infoReport(facts))
|
|
63
62
|
return 0
|
|
64
63
|
}
|
|
65
64
|
|
|
65
|
+
/** `vx info` as text: the report's lines for `colors`. */
|
|
66
66
|
export function renderInfo(f: InfoFacts, colors: ColorSupport = { enabled: false }): string {
|
|
67
|
+
return infoReport(f).lines(colors).join('\n')
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** The `vx info` report: one field a fact. */
|
|
71
|
+
function infoReport(f: InfoFacts): ui.Block {
|
|
67
72
|
const rows: [string, string][] = [
|
|
68
73
|
[
|
|
69
74
|
'vx',
|
|
@@ -92,7 +97,7 @@ export function renderInfo(f: InfoFacts, colors: ColorSupport = { enabled: false
|
|
|
92
97
|
'cache store',
|
|
93
98
|
f.cacheStore === null
|
|
94
99
|
? 'none: the cache dir holds the entries'
|
|
95
|
-
: `${tildePath(f.cacheStore)} (${formatBytes(f.cacheStoreBytes ?? 0)}, shared by this
|
|
100
|
+
: `${tildePath(f.cacheStore)} (${formatBytes(f.cacheStoreBytes ?? 0)}, shared by this workspace's checkouts)`,
|
|
96
101
|
],
|
|
97
102
|
['cache versions', `keys ${f.cacheVersion} · index schema ${f.schemaVersion}`],
|
|
98
103
|
['cache entries', describeEntries(f)],
|
|
@@ -125,7 +130,7 @@ export function renderInfo(f: InfoFacts, colors: ColorSupport = { enabled: false
|
|
|
125
130
|
typeof f.lockError === 'string' ? `refused: ${f.lockError}` : f.lockfile ? 'yes' : 'no',
|
|
126
131
|
],
|
|
127
132
|
]
|
|
128
|
-
return ui.report('vx info', rows)
|
|
133
|
+
return ui.report('vx info', rows)
|
|
129
134
|
}
|
|
130
135
|
|
|
131
136
|
/** `812 (1.2 GB)`, or why the index cannot be read and its fix. */
|
|
@@ -195,6 +200,9 @@ function trimCores(n: number): string {
|
|
|
195
200
|
|
|
196
201
|
/** `2 — app#test (3 of 7 runs failed on unchanged inputs); api#e2e (1 of 4)`, or `none`. */
|
|
197
202
|
function describeProjects(f: InfoFacts): string {
|
|
203
|
+
// The count is the lock's: with none read, 0 would say the workspace has no project.
|
|
204
|
+
if (f.lockError != null) return '— (the lock is refused)'
|
|
205
|
+
if (!f.lockfile) return '— (no lock: `vx lock`)'
|
|
198
206
|
return `${f.projects} (${f.tasks} task${f.tasks === 1 ? '' : 's'})`
|
|
199
207
|
}
|
|
200
208
|
|
package/src/cli/init.ts
CHANGED
|
@@ -23,17 +23,14 @@ import {
|
|
|
23
23
|
} from './upgrade.js'
|
|
24
24
|
import { VERSION } from '../version.js'
|
|
25
25
|
import {
|
|
26
|
-
detectColors,
|
|
27
26
|
DOT_VX_GITATTRIBUTES,
|
|
28
27
|
DOT_VX_GITIGNORE,
|
|
29
|
-
paint,
|
|
30
28
|
refuseSymlink,
|
|
31
|
-
sayNotice,
|
|
32
|
-
SUCCESS,
|
|
33
|
-
ui,
|
|
34
29
|
UserError,
|
|
35
30
|
writeNoFollow,
|
|
36
31
|
} from '../util/index.js'
|
|
32
|
+
import * as ui from '../ui/index.js'
|
|
33
|
+
import { sayNotice } from '../ui/index.js'
|
|
37
34
|
import {
|
|
38
35
|
findWorkspaceRoot,
|
|
39
36
|
PROJECT_CONFIG_FILENAMES,
|
|
@@ -279,8 +276,9 @@ async function install(
|
|
|
279
276
|
let said = ''
|
|
280
277
|
const decoder = new TextDecoder()
|
|
281
278
|
for await (const chunk of proc.stderr) {
|
|
282
|
-
|
|
283
|
-
|
|
279
|
+
const text = decoder.decode(chunk, { stream: true })
|
|
280
|
+
ui.data('err', text)
|
|
281
|
+
said += text
|
|
284
282
|
}
|
|
285
283
|
const code = await proc.exited
|
|
286
284
|
if (code !== 0) {
|
|
@@ -351,13 +349,22 @@ async function scaffoldPlugin(seam: string, root: string, args: InitArgs): Promi
|
|
|
351
349
|
const factory = /^export function (\w+)/m.exec(template.plugin)![1]!
|
|
352
350
|
const workspaceFile =
|
|
353
351
|
WORKSPACE_CONFIG_FILENAMES.find((n) => existsSync(path.join(root, n))) ?? '.vx/workspace.ts'
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
352
|
+
const names = files.flatMap(([rel], i) => [...(i > 0 ? [' and '] : []), ui.strong(rel)])
|
|
353
|
+
ui.print('out', ui.line(ui.tone('ok', args.dry ? 'would write' : 'wrote', true), ' ', ...names))
|
|
354
|
+
ui.print(
|
|
355
|
+
'out',
|
|
356
|
+
ui.line(
|
|
357
|
+
'Declare it in ',
|
|
358
|
+
ui.path(workspaceFile),
|
|
359
|
+
': ',
|
|
360
|
+
ui.cmd(`import { ${factory} } from '../plugins/${seam}.ts'`),
|
|
361
|
+
', then ',
|
|
362
|
+
ui.cmd(`plugins: [${factory}(…)]`),
|
|
363
|
+
),
|
|
364
|
+
)
|
|
365
|
+
ui.print(
|
|
366
|
+
'out',
|
|
367
|
+
ui.line('Test it: ', ui.cmd(`bun test plugins/${seam}.test.ts`), ' (needs @vzn/vx installed)'),
|
|
361
368
|
)
|
|
362
369
|
return 0
|
|
363
370
|
}
|
|
@@ -460,7 +467,8 @@ async function starter(
|
|
|
460
467
|
const declare = `declare a task in ${kept.find((f) => f.startsWith('vx.config.')) ?? config}, then vx lock && vx run <task>`
|
|
461
468
|
const next = `${noGit ? 'git init, ' : ''}${hasScripts(pkgRoot) ? `bunx @vzn/vx-migrate${args.mjs ? ' --mjs' : ''} to make package.json scripts tasks, or ${declare}` : declare}`
|
|
462
469
|
if (args.json === true) {
|
|
463
|
-
|
|
470
|
+
ui.data(
|
|
471
|
+
'out',
|
|
464
472
|
`${JSON.stringify({ dry: true, source: 'no turbo.json or nx.json', files, kept, replaced, todos: [], notes: [], next, installs })}\n`,
|
|
465
473
|
)
|
|
466
474
|
return 0
|