@vzn/vx 0.0.612 → 0.0.613
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.613",
|
|
4
4
|
"description": "The fastest 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.613",
|
|
25
|
+
"@vzn/vx-linux-arm64": "0.0.613",
|
|
26
|
+
"@vzn/vx-darwin-x64": "0.0.613",
|
|
27
|
+
"@vzn/vx-darwin-arm64": "0.0.613"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@anthropic-ai/sandbox-runtime": "^0.0.76"
|
|
@@ -34,7 +34,16 @@ function describeValue(v: unknown): string {
|
|
|
34
34
|
if (v === null) return 'null'
|
|
35
35
|
if (Array.isArray(v)) return 'an array'
|
|
36
36
|
const t = typeof v
|
|
37
|
-
|
|
37
|
+
if (t !== 'object') return `a ${t}`
|
|
38
|
+
const proto: unknown = Object.getPrototypeOf(v)
|
|
39
|
+
if (proto === Object.prototype || proto === null) return 'an object'
|
|
40
|
+
return `a ${(v as object).constructor?.name || 'class instance'}`
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function isRecord(v: unknown): v is Record<string, unknown> {
|
|
44
|
+
if (typeof v !== 'object' || v === null) return false
|
|
45
|
+
const proto: unknown = Object.getPrototypeOf(v)
|
|
46
|
+
return proto === Object.prototype || proto === null
|
|
38
47
|
}
|
|
39
48
|
|
|
40
49
|
/** Every method `CacheLayer` requires (the optional ones are probed with `?.`). */
|
|
@@ -197,7 +206,8 @@ export async function applyProjectHooks(
|
|
|
197
206
|
* against the LAST plugin that ran: usually the one whose edit made it so,
|
|
198
207
|
* but an earlier plugin's edit that a later one left in place is blamed on
|
|
199
208
|
* the later one, since the structure is not checked between plugins.
|
|
200
|
-
* Each node's task config is (`afterEach`),
|
|
209
|
+
* Each node's task config is re-validated after EACH plugin (`afterEach`),
|
|
210
|
+
* like the `project` stage's.
|
|
201
211
|
*/
|
|
202
212
|
export async function applyGraphHooks(
|
|
203
213
|
plugins: readonly VxPlugin[],
|
|
@@ -271,8 +281,10 @@ export async function applyKeyHooks(
|
|
|
271
281
|
if (material === undefined) continue
|
|
272
282
|
// `Object.entries` over a string yields its characters as string
|
|
273
283
|
// values, so a plugin returning `'v22'` used to fold parts named
|
|
274
|
-
// '0', '1', '2' into every key — silently, and permanently.
|
|
275
|
-
|
|
284
|
+
// '0', '1', '2' into every key — silently, and permanently. A Map or a
|
|
285
|
+
// class instance keeps its data off own enumerable keys, so
|
|
286
|
+
// `Object.entries` read it as no material at all: a silent miskey.
|
|
287
|
+
if (!isRecord(material)) {
|
|
276
288
|
throw new UserError(
|
|
277
289
|
`plugin '${plugin.name}' failed in key: returned ${describeValue(material)}, not a record of string values`,
|
|
278
290
|
)
|
|
@@ -254,12 +254,16 @@ export function validateWorkspace(config: WorkspaceConfig, configPath: string):
|
|
|
254
254
|
}
|
|
255
255
|
for (const cap of PLUGIN_FUNCTION_HOOKS) {
|
|
256
256
|
if (plug[cap] !== undefined && typeof plug[cap] !== 'function') {
|
|
257
|
-
throw new UserError(
|
|
257
|
+
throw new UserError(
|
|
258
|
+
`${configPath}: \`plugins[${i}].${cap}\` of plugin '${pkg}' must be a function`,
|
|
259
|
+
)
|
|
258
260
|
}
|
|
259
261
|
}
|
|
260
262
|
if (plug.commands !== undefined) {
|
|
261
263
|
if (plug.commands === null || typeof plug.commands !== 'object') {
|
|
262
|
-
throw new UserError(
|
|
264
|
+
throw new UserError(
|
|
265
|
+
`${configPath}: \`plugins[${i}].commands\` of plugin '${pkg}' must be an object`,
|
|
266
|
+
)
|
|
263
267
|
}
|
|
264
268
|
// A list of commands loaded as the verbs `0`, `1`, … that help listed.
|
|
265
269
|
if (Array.isArray(plug.commands)) {
|
|
@@ -276,7 +280,7 @@ export function validateWorkspace(config: WorkspaceConfig, configPath: string):
|
|
|
276
280
|
typeof c.description !== 'string'
|
|
277
281
|
) {
|
|
278
282
|
throw new UserError(
|
|
279
|
-
`${configPath}: \`plugins[${i}].commands.${verb}\` must be { description: string, run: function }`,
|
|
283
|
+
`${configPath}: \`plugins[${i}].commands.${verb}\` of plugin '${pkg}' must be { description: string, run: function }`,
|
|
280
284
|
)
|
|
281
285
|
}
|
|
282
286
|
// A verb the dispatcher would never reach is refused, not left
|
|
@@ -287,10 +291,12 @@ export function validateWorkspace(config: WorkspaceConfig, configPath: string):
|
|
|
287
291
|
// package: two plugins one package exports (`bun()` and `pnpm()`
|
|
288
292
|
// both carry `prune`) are one owner, and the first declared runs.
|
|
289
293
|
// `vx --version` and `vx ''` never reach a plugin: a flag is
|
|
290
|
-
// core's, and an empty word is no verb (X-21).
|
|
291
|
-
|
|
294
|
+
// core's, and an empty word is no verb (X-21). `vx completions`
|
|
295
|
+
// writes verbs unquoted into a shell script, so a space or a `$(`
|
|
296
|
+
// in one would break or inject into the user's rc.
|
|
297
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9:._-]*$/.test(verb)) {
|
|
292
298
|
throw new UserError(
|
|
293
|
-
`${configPath}: plugin '${plug.name}' declares command '${verb}', which
|
|
299
|
+
`${configPath}: plugin '${plug.name}' declares command '${verb}', which is not a word — a verb is a letter or digit, then letters, digits, ':', '.', '_' or '-'`,
|
|
294
300
|
)
|
|
295
301
|
}
|
|
296
302
|
if ((CORE_VERBS as readonly string[]).includes(verb)) {
|
|
@@ -317,7 +323,7 @@ export function validateWorkspace(config: WorkspaceConfig, configPath: string):
|
|
|
317
323
|
typeof claim.affected !== 'function'
|
|
318
324
|
) {
|
|
319
325
|
throw new UserError(
|
|
320
|
-
`${configPath}: \`plugins[${i}].fingerprint\` must be { files: [name, …], affected: function }`,
|
|
326
|
+
`${configPath}: \`plugins[${i}].fingerprint\` of plugin '${pkg}' must be { files: [name, …], affected: function }`,
|
|
321
327
|
)
|
|
322
328
|
}
|
|
323
329
|
for (const file of claim.files as unknown[]) {
|
|
@@ -357,7 +363,7 @@ export function validateWorkspace(config: WorkspaceConfig, configPath: string):
|
|
|
357
363
|
// — an empty `{ name }` object is a no-op authoring mistake.
|
|
358
364
|
if (PLUGIN_HOOKS.every((hook) => plug[hook] === undefined)) {
|
|
359
365
|
throw new UserError(
|
|
360
|
-
`${configPath}: \`plugins[${i}]\` must contribute at least one of ${PLUGIN_HOOKS.join('/')}`,
|
|
366
|
+
`${configPath}: \`plugins[${i}]\` (plugin '${pkg}') must contribute at least one of ${PLUGIN_HOOKS.join('/')}`,
|
|
361
367
|
)
|
|
362
368
|
}
|
|
363
369
|
}
|