@vzn/vx 0.0.67 → 0.0.69

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.67",
3
+ "version": "0.0.69",
4
4
  "description": "An open, extensible monorepo task runner.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -17,10 +17,10 @@
17
17
  "node": ">=18"
18
18
  },
19
19
  "optionalDependencies": {
20
- "@vzn/vx-linux-x64": "0.0.67",
21
- "@vzn/vx-linux-arm64": "0.0.67",
22
- "@vzn/vx-darwin-x64": "0.0.67",
23
- "@vzn/vx-darwin-arm64": "0.0.67"
20
+ "@vzn/vx-linux-x64": "0.0.69",
21
+ "@vzn/vx-linux-arm64": "0.0.69",
22
+ "@vzn/vx-darwin-x64": "0.0.69",
23
+ "@vzn/vx-darwin-arm64": "0.0.69"
24
24
  },
25
25
  "dependencies": {
26
26
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
@@ -488,6 +488,19 @@ async function resolveRuntimeValues(
488
488
  */
489
489
  const OUTPUT_NEVER = ['**/.git/**', '**/.vx/**']
490
490
 
491
+ /**
492
+ * What a set of output globs may not reach: `OUTPUT_NEVER`, and every
493
+ * `node_modules` unless a glob names one. `**\/*.js` meant the build's
494
+ * files, and the clean before each run deleted every installed `.js`
495
+ * under `node_modules` with them (A-13); an install task declares
496
+ * `node_modules/**` and keeps it. Workspace outputs took none of this, not
497
+ * even `.git`.
498
+ */
499
+ function outputExcludes(outputs: readonly string[]): Bun.Glob[] {
500
+ const namesNodeModules = outputs.some((o) => normalizeGlob(o).split('/').includes('node_modules'))
501
+ return (namesNodeModules ? OUTPUT_NEVER : [...OUTPUT_NEVER, '**/node_modules/**']).map(globFor)
502
+ }
503
+
491
504
  /** Resolve declared output globs (project-relative) to actual produced files. */
492
505
  export async function resolveOutputs(args: {
493
506
  projectDir: string
@@ -495,7 +508,7 @@ export async function resolveOutputs(args: {
495
508
  nestedProjectDirs: string[]
496
509
  }): Promise<string[]> {
497
510
  if (args.outputs.length === 0) return []
498
- const excludeGlobs = OUTPUT_NEVER.map(globFor)
511
+ const excludeGlobs = outputExcludes(args.outputs)
499
512
  const scanned = [
500
513
  ...(await scanUnion(
501
514
  asTrees(args.outputs),
@@ -741,7 +754,9 @@ export async function resolveWorkspaceOutputs(args: {
741
754
  outputs: string[]
742
755
  }): Promise<string[]> {
743
756
  if (args.outputs.length === 0) return []
744
- const scanned = [...(await scanUnion(asTrees(args.outputs), [], args.workspaceRoot))]
757
+ const scanned = [
758
+ ...(await scanUnion(asTrees(args.outputs), outputExcludes(args.outputs), args.workspaceRoot)),
759
+ ]
745
760
  // Same containment as the project twin, anchored one level out. These globs
746
761
  // deliberately ignore PROJECT boundaries — that is the escape hatch — but
747
762
  // escaping the WORKSPACE was never part of it, and `cleanWorkspaceOutputs`
@@ -190,7 +190,8 @@ export interface TaskExecutor {
190
190
  /**
191
191
  * How many tasks this executor runs at once. Its tasks then occupy a pool
192
192
  * of this size instead of the local worker slots, so a remote pool is not
193
- * throttled by the local CPU count. Absent = the local pool.
193
+ * throttled by the local CPU count. A positive integer; anything else
194
+ * is refused when the executor is resolved. Absent = the local pool.
194
195
  */
195
196
  readonly capacity?: number
196
197
  /** Per-task opt-out at placement time. Absent = accepts every task it is offered. */
@@ -419,6 +419,13 @@ export async function resolveExecutors(
419
419
  if (typeof executor.name !== 'string' || executor.name.length === 0) {
420
420
  throw new UserError(`plugin '${plugin.name}' returned an executor with no name`)
421
421
  }
422
+ // The pool's room is `active < capacity`: 0 or NaN parks its tasks for good.
423
+ const capacity: unknown = executor.capacity
424
+ if (capacity !== undefined && !(Number.isInteger(capacity) && (capacity as number) > 0)) {
425
+ throw new UserError(
426
+ `plugin '${plugin.name}' returned executor '${executor.name}' with capacity ${typeof capacity === 'number' ? String(capacity) : JSON.stringify(capacity)}: it must be a positive integer`,
427
+ )
428
+ }
422
429
  executorPlugin.set(executor, plugin.name)
423
430
  executors.push(executor)
424
431
  }