@vzn/vx 0.0.596 → 0.0.597
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/launcher.cjs +7 -3
- package/package.json +5 -5
- package/src/cache/archive.ts +35 -6
- package/src/cache/cache.ts +31 -15
- package/src/cache/git-inputs.ts +23 -0
- package/src/cache/index.ts +2 -0
- package/src/cache/inputs.ts +87 -32
- package/src/cache/key-fold.ts +1 -1
- package/src/cache/layer.ts +2 -1
- package/src/cli/cache.ts +2 -2
- package/src/cli/foreign-flags.ts +56 -2
- package/src/cli/info.ts +1 -1
- package/src/cli/init.ts +2 -2
- package/src/cli/last.ts +6 -3
- package/src/cli/lock.ts +5 -3
- package/src/cli/plan-format.ts +4 -4
- package/src/cli/run.ts +42 -15
- package/src/cli/select.ts +6 -3
- package/src/cli/show.ts +8 -2
- package/src/cli/upgrade.ts +1 -1
- package/src/cli/watch-fs.ts +11 -3
- package/src/cli/watch.ts +14 -7
- package/src/cli/workspace-config.ts +3 -1
- package/src/config.ts +21 -0
- package/src/exec/executor.ts +1 -1
- package/src/exec/kill-tree.ts +89 -18
- package/src/exec/runner.ts +74 -36
- package/src/exec/sandbox-paths.ts +11 -0
- package/src/exec/sandbox-runtime.ts +168 -49
- package/src/exec/sandbox-violations.ts +59 -6
- package/src/graph/scheduler.ts +2 -2
- package/src/graph/task-graph.ts +145 -33
- package/src/orchestrator/affected-tasks.ts +6 -2
- package/src/orchestrator/deferred-outputs.ts +3 -2
- package/src/orchestrator/doctor.ts +2 -2
- package/src/orchestrator/excluded-keys.ts +2 -13
- package/src/orchestrator/execute-task.ts +49 -26
- package/src/orchestrator/failure-mode.ts +38 -29
- package/src/orchestrator/framed-output.ts +5 -5
- package/src/orchestrator/index.ts +0 -1
- package/src/orchestrator/keyed-projects.ts +6 -3
- package/src/orchestrator/logger.ts +10 -3
- package/src/orchestrator/miss-save.ts +7 -11
- package/src/orchestrator/plan.ts +4 -20
- package/src/orchestrator/run-artifacts.ts +2 -2
- package/src/orchestrator/run-lock.ts +25 -24
- package/src/orchestrator/run.ts +2 -1
- package/src/orchestrator/sandbox-request.ts +31 -9
- package/src/orchestrator/signals.ts +22 -4
- package/src/orchestrator/stable-keys.ts +3 -11
- package/src/orchestrator/summary.ts +5 -9
- package/src/orchestrator/task-hash.ts +13 -3
- package/src/orchestrator/upstream.ts +11 -0
- package/src/util/hangup.ts +42 -0
- package/src/util/index.ts +2 -0
- package/src/util/paths.ts +1 -1
- package/src/workspace/affected.ts +79 -42
- package/src/workspace/config-eval.ts +27 -6
- package/src/workspace/config-imports.ts +8 -55
- package/src/workspace/config-schema.ts +30 -6
- package/src/workspace/lockfile.ts +2 -1
- package/src/workspace/migrate-scripts.ts +1 -1
- package/src/workspace/project-loader.ts +15 -2
- package/src/workspace/workspace.ts +36 -14
|
@@ -847,7 +847,7 @@ export function migrateScripts(
|
|
|
847
847
|
const names = runnable.filter((n) => taskNameProblem(n) === null)
|
|
848
848
|
if (meta !== rootMeta && !('build' in scripts)) {
|
|
849
849
|
const hook = LIFECYCLE_BUILD_HOOKS.find(
|
|
850
|
-
(h) => typeof scripts[h] === 'string' && BUILDER.test(scripts[h]
|
|
850
|
+
(h) => typeof scripts[h] === 'string' && BUILDER.test(scripts[h]),
|
|
851
851
|
)
|
|
852
852
|
if (hook !== undefined) lifecycleBuilds.push([meta.name, hook, scripts[hook] as string])
|
|
853
853
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
CONFIG_EXIT,
|
|
10
10
|
evalBudgetMs,
|
|
11
11
|
evaluateConfigFresh,
|
|
12
|
+
thrownValueMessage,
|
|
12
13
|
WATCHED_BUILTIN_NAMES,
|
|
13
14
|
} from './config-eval.js'
|
|
14
15
|
import { hasEsmExport, unprovidedBareImports } from './config-imports.js'
|
|
@@ -191,7 +192,7 @@ async function loadDefaultExport(
|
|
|
191
192
|
if (err instanceof Error && err.stack !== undefined) {
|
|
192
193
|
err.stack = err.stack.replaceAll(specifier, configPath).replace(BUST_QUERY, '')
|
|
193
194
|
}
|
|
194
|
-
throw
|
|
195
|
+
throw loadFailure(err, configPath, kind)
|
|
195
196
|
} finally {
|
|
196
197
|
clearTimeout(deadline)
|
|
197
198
|
unguard()
|
|
@@ -341,6 +342,16 @@ export function configLoadError(err: unknown, configPath: string, kind: string):
|
|
|
341
342
|
return null
|
|
342
343
|
}
|
|
343
344
|
|
|
345
|
+
/** What a failed load throws: Bun's own errors and non-Error throws as user errors, the rest as thrown. */
|
|
346
|
+
function loadFailure(err: unknown, configPath: string, kind: string): unknown {
|
|
347
|
+
const user = configLoadError(err, configPath, kind)
|
|
348
|
+
if (user !== null) return user
|
|
349
|
+
if (err !== null && typeof err === 'object' && typeof (err as Error).message === 'string') {
|
|
350
|
+
return err
|
|
351
|
+
}
|
|
352
|
+
return new UserError(thrownValueMessage(kind, configPath, Bun.inspect(err, { compact: true })))
|
|
353
|
+
}
|
|
354
|
+
|
|
344
355
|
export interface LoadProjectConfigOptions {
|
|
345
356
|
/** Observe the CURRENT environment: no eval cache, even when `evalCache` is passed. */
|
|
346
357
|
fresh?: boolean
|
|
@@ -523,7 +534,7 @@ export async function loadProjectConfigs(
|
|
|
523
534
|
if (repeat) refuseUnprovidedImports(bytes!, configPath, 'Project')
|
|
524
535
|
const mod = repeat
|
|
525
536
|
? await evaluateConfigFresh(configPath).catch((err: unknown) => {
|
|
526
|
-
throw
|
|
537
|
+
throw loadFailure(err, configPath, 'Project')
|
|
527
538
|
})
|
|
528
539
|
: await loadDefaultExport(configPath, 'Project', bytes!)
|
|
529
540
|
// Before anything reads through them: a replaced `Array.prototype.includes`
|
|
@@ -812,6 +823,7 @@ const BUN_MEMBERS_VX_READS: readonly PropertyKey[] = [
|
|
|
812
823
|
'env',
|
|
813
824
|
'file',
|
|
814
825
|
'hash',
|
|
826
|
+
'inspect',
|
|
815
827
|
'main',
|
|
816
828
|
'nanoseconds',
|
|
817
829
|
'plugin',
|
|
@@ -820,6 +832,7 @@ const BUN_MEMBERS_VX_READS: readonly PropertyKey[] = [
|
|
|
820
832
|
'semver',
|
|
821
833
|
'serve',
|
|
822
834
|
'sleep',
|
|
835
|
+
'sleepSync',
|
|
823
836
|
'spawn',
|
|
824
837
|
'spawnSync',
|
|
825
838
|
'stderr',
|
|
@@ -290,13 +290,17 @@ async function readRootManifests(
|
|
|
290
290
|
)
|
|
291
291
|
}
|
|
292
292
|
if (ws === undefined || ws === null) return { globs: ['.'], catalogs }
|
|
293
|
+
// bun's `{ catalog }` and yarn's `{ nohoist }` name no members, and both
|
|
294
|
+
// managers run the root alone; vx refused them as no array (D-151).
|
|
295
|
+
if (typeof ws === 'object' && !Array.isArray(ws) && !('packages' in ws)) {
|
|
296
|
+
return { globs: ['.'], catalogs }
|
|
297
|
+
}
|
|
293
298
|
if (ws && typeof ws === 'object' && !Array.isArray(ws) && 'packages' in ws) {
|
|
294
|
-
const
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
)
|
|
299
|
-
return { globs, catalogs }
|
|
299
|
+
const packages = (ws as { packages?: unknown }).packages
|
|
300
|
+
// Yarn 1 and 4 run the root alone under `packages: null`; read as an
|
|
301
|
+
// empty list, the root was no project and every verb ran nothing (D-150).
|
|
302
|
+
if (packages === null) return { globs: ['.'], catalogs }
|
|
303
|
+
return { globs: assertGlobList(packages, pkgPath, 'workspaces.packages'), catalogs }
|
|
300
304
|
}
|
|
301
305
|
return { globs: assertGlobList(ws, pkgPath, 'workspaces'), catalogs }
|
|
302
306
|
}
|
|
@@ -454,13 +458,27 @@ function extglobRefusal(pattern: string, file: string, field: string): UserError
|
|
|
454
458
|
* to the workspace root.
|
|
455
459
|
*/
|
|
456
460
|
export function resolveCacheDir(root: string, config: WorkspaceConfig | null): string {
|
|
457
|
-
const
|
|
461
|
+
const env = process.env['VX_CACHE_DIR']
|
|
462
|
+
// `cacheDir: ' '` is refused at load (X-22); the variable made the same
|
|
463
|
+
// directory named in spaces at the root (D-160).
|
|
464
|
+
if (config?.cacheDir === undefined && env !== undefined && env !== '' && env.trim() === '') {
|
|
465
|
+
throw new UserError('VX_CACHE_DIR is only whitespace — name a directory, or unset it')
|
|
466
|
+
}
|
|
467
|
+
const rel = config?.cacheDir ?? (env || path.join('.vx', 'cache'))
|
|
468
|
+
const home = process.env['HOME'] || homedir()
|
|
458
469
|
// No shell expands `~` in a config string or a quoted variable, and
|
|
459
470
|
// `'~/.cache/vx'` made a directory named `~` in the workspace.
|
|
460
|
-
|
|
461
|
-
|
|
471
|
+
const dir =
|
|
472
|
+
rel === '~' || rel.startsWith('~/') ? path.join(home, rel.slice(1)) : path.resolve(root, rel)
|
|
473
|
+
// The cache writes a `*` .gitignore beside its index: a bare `~` made a
|
|
474
|
+
// directory named `~`, and expanded it would land in home itself (D-153).
|
|
475
|
+
if (path.resolve(dir) === path.resolve(home)) {
|
|
476
|
+
const source = config?.cacheDir !== undefined ? 'cacheDir' : 'VX_CACHE_DIR'
|
|
477
|
+
throw new UserError(
|
|
478
|
+
`${source} ${JSON.stringify(rel)} is the home directory itself, where the cache's \`*\` .gitignore and index would land — name a directory under it, like '~/.cache/vx'`,
|
|
479
|
+
)
|
|
462
480
|
}
|
|
463
|
-
return
|
|
481
|
+
return dir
|
|
464
482
|
}
|
|
465
483
|
|
|
466
484
|
/**
|
|
@@ -711,12 +729,17 @@ async function readManifest(root: string, dir: string, file: string): Promise<st
|
|
|
711
729
|
)
|
|
712
730
|
if (searchable) unreadable(err, file)
|
|
713
731
|
process.stderr.write(
|
|
714
|
-
`vx: ${
|
|
732
|
+
`vx: ${shownDir(root, dir)} is not readable by this user — skipped, with any project in it\n`,
|
|
715
733
|
)
|
|
716
734
|
return null
|
|
717
735
|
}
|
|
718
736
|
}
|
|
719
737
|
|
|
738
|
+
/** `dir` as a discovery line names it: the root's own path is '' (D-127, D-154). */
|
|
739
|
+
function shownDir(root: string, dir: string): string {
|
|
740
|
+
return relPosix(root, dir) || 'the workspace root'
|
|
741
|
+
}
|
|
742
|
+
|
|
720
743
|
export async function listProjects(workspace: Workspace): Promise<ProjectMeta[]> {
|
|
721
744
|
return discoverProjects(workspace)
|
|
722
745
|
}
|
|
@@ -769,7 +792,7 @@ export async function discoverProjects(
|
|
|
769
792
|
// same flight as the failed read, so naming it costs nothing.
|
|
770
793
|
if (configPath !== null) {
|
|
771
794
|
process.stderr.write(
|
|
772
|
-
`vx: ${
|
|
795
|
+
`vx: ${shownDir(workspace.root, dir)} has a vx config but no package.json — skipped: vx names a project by its package.json "name"\n`,
|
|
773
796
|
)
|
|
774
797
|
}
|
|
775
798
|
return null
|
|
@@ -800,9 +823,8 @@ export async function discoverProjects(
|
|
|
800
823
|
// fine for a dir that declares no tasks; a dir with a vx config was
|
|
801
824
|
// meant to run.
|
|
802
825
|
if (configPath !== null) {
|
|
803
|
-
const rel = relPosix(workspace.root, dir)
|
|
804
826
|
process.stderr.write(
|
|
805
|
-
`vx: ${
|
|
827
|
+
`vx: ${shownDir(workspace.root, dir)} has a vx config but its package.json has no "name" — skipped\n`,
|
|
806
828
|
)
|
|
807
829
|
}
|
|
808
830
|
continue
|