@vzn/vx 0.0.342 → 0.0.344
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.344",
|
|
4
4
|
"description": "A fast, correct task runner and build cache for JavaScript monorepos.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -21,10 +21,10 @@
|
|
|
21
21
|
"node": ">=18"
|
|
22
22
|
},
|
|
23
23
|
"optionalDependencies": {
|
|
24
|
-
"@vzn/vx-linux-x64": "0.0.
|
|
25
|
-
"@vzn/vx-linux-arm64": "0.0.
|
|
26
|
-
"@vzn/vx-darwin-x64": "0.0.
|
|
27
|
-
"@vzn/vx-darwin-arm64": "0.0.
|
|
24
|
+
"@vzn/vx-linux-x64": "0.0.344",
|
|
25
|
+
"@vzn/vx-linux-arm64": "0.0.344",
|
|
26
|
+
"@vzn/vx-darwin-x64": "0.0.344",
|
|
27
|
+
"@vzn/vx-darwin-arm64": "0.0.344"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
package/src/cache/inputs.ts
CHANGED
|
@@ -1223,6 +1223,7 @@ async function scanUnion(
|
|
|
1223
1223
|
// `/`: `{dist,lib/esm}/**` saved an empty artifact, and a hit restored
|
|
1224
1224
|
// nothing over a cleaned tree (A-10). Expanded here, as discovery does.
|
|
1225
1225
|
for (const pattern of positive.flatMap(slashBraceExpansions)) {
|
|
1226
|
+
if (absentPrefix(cwd, pattern)) continue
|
|
1226
1227
|
const glob = globFor(pattern)
|
|
1227
1228
|
for (const rel of glob.scanSync({ cwd, onlyFiles: false, followSymlinks: false, dot: true })) {
|
|
1228
1229
|
if (nested(rel) || excludeGlobs.some((g) => g.match(rel))) continue
|
|
@@ -1235,6 +1236,23 @@ async function scanUnion(
|
|
|
1235
1236
|
return matches
|
|
1236
1237
|
}
|
|
1237
1238
|
|
|
1239
|
+
/**
|
|
1240
|
+
* True when `pattern`'s static directory is not on disk, so nothing can
|
|
1241
|
+
* match under it. A restore into a tree without its outputs scans each
|
|
1242
|
+
* glob twice (the check, then the clean), and a scan of a missing `dist`
|
|
1243
|
+
* cost ~58 µs where the lstat costs a few. Anything this cannot read
|
|
1244
|
+
* plainly (no prefix, an escape, an absolute path, a refused stat) scans.
|
|
1245
|
+
*/
|
|
1246
|
+
function absentPrefix(cwd: string, pattern: string): boolean {
|
|
1247
|
+
const prefix = staticPrefix(pattern)
|
|
1248
|
+
if (prefix === '.' || prefix.includes('\\') || path.isAbsolute(prefix)) return false
|
|
1249
|
+
try {
|
|
1250
|
+
return lstatSync(path.join(cwd, prefix), { throwIfNoEntry: false }) === undefined
|
|
1251
|
+
} catch {
|
|
1252
|
+
return false
|
|
1253
|
+
}
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1238
1256
|
// Compiled once per pattern string for the life of the process: a `Bun.Glob`
|
|
1239
1257
|
// is immutable, and the same handful of declared globs are compiled again
|
|
1240
1258
|
// for every task otherwise (three sites, up to thousands of times per run).
|
|
@@ -1012,7 +1012,7 @@ export async function wrapSandboxedCommand(
|
|
|
1012
1012
|
let wrapped = await wrapForTask(
|
|
1013
1013
|
SandboxManager,
|
|
1014
1014
|
inner,
|
|
1015
|
-
customConfig,
|
|
1015
|
+
process.platform === 'linux' ? literalReadPaths(customConfig) : customConfig,
|
|
1016
1016
|
ports.length > 0 || asksUnixSockets(args.config),
|
|
1017
1017
|
args.config.gitConfig === true,
|
|
1018
1018
|
)
|
|
@@ -1148,6 +1148,30 @@ function asksUnixSockets(c: Pick<ResolvedSandboxConfig, 'unixSockets'>): boolean
|
|
|
1148
1148
|
return c.unixSockets === true || (c.unixSockets !== undefined && c.unixSockets.length > 0)
|
|
1149
1149
|
}
|
|
1150
1150
|
|
|
1151
|
+
/**
|
|
1152
|
+
* Linux: the read paths as SRT must be handed them to take each as the
|
|
1153
|
+
* name it is. vx has expanded every grant by then, so each is a path,
|
|
1154
|
+
* but SRT reads any holding `[` as a glob, where a bracket opens a class:
|
|
1155
|
+
* a route granted as `pages/\[id\].tsx` was never mounted (its denial
|
|
1156
|
+
* unreported, a listed grant), and a workspace under `[ws]/` was never
|
|
1157
|
+
* walled. `[[]` is a class of one `[`; a lone `]` is plain text to it.
|
|
1158
|
+
*/
|
|
1159
|
+
function literalReadPaths(
|
|
1160
|
+
config: Parameters<SrtModule['SandboxManager']['wrapWithSandbox']>[2],
|
|
1161
|
+
): Parameters<SrtModule['SandboxManager']['wrapWithSandbox']>[2] {
|
|
1162
|
+
const fs = config?.filesystem
|
|
1163
|
+
if (fs === undefined) return config
|
|
1164
|
+
const escape = (paths: readonly string[]): string[] => paths.map((p) => p.replaceAll('[', '[[]'))
|
|
1165
|
+
return {
|
|
1166
|
+
...config,
|
|
1167
|
+
filesystem: {
|
|
1168
|
+
...fs,
|
|
1169
|
+
denyRead: escape(fs.denyRead),
|
|
1170
|
+
...(fs.allowRead !== undefined ? { allowRead: escape(fs.allowRead) } : {}),
|
|
1171
|
+
},
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1151
1175
|
/** SRT's wrap, with the socket lift and the git-config grant this task asked for, or none (L-6, B-41). */
|
|
1152
1176
|
function wrapForTask(
|
|
1153
1177
|
SandboxManager: SrtModule['SandboxManager'],
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
import { readFileSync, statSync } from 'node:fs'
|
|
13
13
|
import path from 'node:path'
|
|
14
|
-
import { FILE_HASH_RACY_MS } from '../cache/index.js'
|
|
14
|
+
import { FILE_HASH_RACY_MS, racyWindowMs } from '../cache/index.js'
|
|
15
15
|
import { WORKSPACE_FINGERPRINT_FILES, type WorkspaceFingerprints } from '../workspace/index.js'
|
|
16
16
|
import type { Logger } from './logger.js'
|
|
17
17
|
|
|
@@ -56,7 +56,10 @@ export class FingerprintWatch {
|
|
|
56
56
|
if (before !== undefined) moved.push(f)
|
|
57
57
|
continue
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
// A whole-second stamp widens the window by that second (A-2): a
|
|
60
|
+
// rewrite 400 ms after the read was stamped before it (C-59).
|
|
61
|
+
if (before !== undefined && ctimeMs < this.at - racyWindowMs(ctimeMs, FILE_HASH_RACY_MS))
|
|
62
|
+
continue
|
|
60
63
|
let now: Uint8Array | undefined
|
|
61
64
|
try {
|
|
62
65
|
now = readFileSync(abs)
|
|
@@ -38,7 +38,7 @@ export const WORKSPACE_FINGERPRINT_FILES = [
|
|
|
38
38
|
'bunfig.toml',
|
|
39
39
|
]
|
|
40
40
|
|
|
41
|
-
// DELIBERATELY ABSENT: `vx.workspace.{ts,mts,js,mjs}`. Everything it can
|
|
41
|
+
// DELIBERATELY ABSENT: `vx.workspace.{ts,mts,js,mjs,cts,cjs}`. Everything it can
|
|
42
42
|
// declare — `concurrency`, `cacheDir`, `timeout`, and the
|
|
43
43
|
// plugin list — is placement, storage or observability, never what a
|
|
44
44
|
// command produces; core's three seams may change WHERE a task runs, not
|
|
@@ -23,6 +23,10 @@ export const WORKSPACE_CONFIG_FILENAMES = [
|
|
|
23
23
|
'vx.workspace.mts',
|
|
24
24
|
'vx.workspace.js',
|
|
25
25
|
'vx.workspace.mjs',
|
|
26
|
+
// A CommonJS config (`module.exports = …`), as Vite and TS name theirs: it
|
|
27
|
+
// was ignored without a word (D-86).
|
|
28
|
+
'vx.workspace.cts',
|
|
29
|
+
'vx.workspace.cjs',
|
|
26
30
|
]
|
|
27
31
|
|
|
28
32
|
/** Project configs already loaded in this process, by absolute path. */
|
|
@@ -660,7 +664,7 @@ async function refuseStaleWorkspaceImports(configPath: string, since: number): P
|
|
|
660
664
|
}
|
|
661
665
|
|
|
662
666
|
/**
|
|
663
|
-
* Find and load `vx.workspace.{ts,mts,js,mjs}` from the workspace
|
|
667
|
+
* Find and load `vx.workspace.{ts,mts,js,mjs,cts,cjs}` from the workspace
|
|
664
668
|
* root. Returns `null` if no such file exists (the common case;
|
|
665
669
|
* the schema is fully optional). Validates the shape and throws
|
|
666
670
|
* a `UserError` on malformed input.
|
|
@@ -35,7 +35,7 @@ export interface ProjectMeta {
|
|
|
35
35
|
/** Absolute path to the project directory. */
|
|
36
36
|
dir: string
|
|
37
37
|
packageJson: PackageJson
|
|
38
|
-
/** Absolute path to vx.config.{ts,mts,js,mjs} or null. */
|
|
38
|
+
/** Absolute path to vx.config.{ts,mts,js,mjs,cts,cjs} or null. */
|
|
39
39
|
configPath: string | null
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -51,6 +51,10 @@ export const PROJECT_CONFIG_FILENAMES = [
|
|
|
51
51
|
'vx.config.mts',
|
|
52
52
|
'vx.config.js',
|
|
53
53
|
'vx.config.mjs',
|
|
54
|
+
// A CommonJS config (`module.exports = …`), as Vite and TS name theirs: it
|
|
55
|
+
// was ignored without a word (D-86).
|
|
56
|
+
'vx.config.cts',
|
|
57
|
+
'vx.config.cjs',
|
|
54
58
|
]
|
|
55
59
|
|
|
56
60
|
const decoder = new TextDecoder()
|