@vzn/vx 0.0.538 → 0.0.540

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.538",
3
+ "version": "0.0.540",
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.538",
25
- "@vzn/vx-linux-arm64": "0.0.538",
26
- "@vzn/vx-darwin-x64": "0.0.538",
27
- "@vzn/vx-darwin-arm64": "0.0.538"
24
+ "@vzn/vx-linux-x64": "0.0.540",
25
+ "@vzn/vx-linux-arm64": "0.0.540",
26
+ "@vzn/vx-darwin-x64": "0.0.540",
27
+ "@vzn/vx-darwin-arm64": "0.0.540"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
@@ -183,6 +183,7 @@ export async function applyGraphHooks(
183
183
  for (const plugin of plugins) {
184
184
  if (plugin.graph === undefined) continue
185
185
  await safe(plugin, 'graph', () => plugin.graph!(nodes, ctx))
186
+ await safe(plugin, 'graph', () => checkNodeShapes(nodes))
186
187
  afterEach?.(plugin)
187
188
  last = plugin
188
189
  }
@@ -190,6 +191,24 @@ export async function applyGraphHooks(
190
191
  await safe(last, 'graph', () => checkGraph(nodes, ctx.workspaceRoot))
191
192
  }
192
193
 
194
+ /**
195
+ * A hook writes the graph as plain JS: `deps = null` surfaced as "null is
196
+ * not an object", naming no task (X-15). Checked per plugin, before its
197
+ * edits are read, so the refusal names the plugin that wrote them.
198
+ */
199
+ function checkNodeShapes(nodes: Map<string, TaskNode>): void {
200
+ const what = (v: unknown): string => (v === null ? 'null' : typeof v)
201
+ for (const [key, node] of nodes as Map<string, unknown>) {
202
+ if (typeof node !== 'object' || node === null) {
203
+ throw new Error(`'${key}' holds ${what(node)}, not a task`)
204
+ }
205
+ const deps = (node as { deps?: unknown }).deps
206
+ if (!Array.isArray(deps)) {
207
+ throw new Error(`${key}'s deps is ${what(deps)}, not an array of task ids`)
208
+ }
209
+ }
210
+ }
211
+
193
212
  /**
194
213
  * `key` stage: every plugin may add `{ name: value }` material to every
195
214
  * task. Stored on the node as sorted `[plugin/name, value]` pairs so the
@@ -45,6 +45,7 @@ import {
45
45
  buildTaskGraph,
46
46
  excludeDependencies,
47
47
  expandRequested,
48
+ isGroupTask,
48
49
  type TaskNode,
49
50
  undeclaredDepsError,
50
51
  unresolvedRequests,
@@ -627,6 +628,18 @@ export async function prepareRun(options: RunOptions, log: Logger): Promise<Prep
627
628
  },
628
629
  )
629
630
  }
631
+ // Args after `--` go to requested commands only; with none among them
632
+ // they reached nothing and the run passed, the `--watch` unheard.
633
+ if ((options.forwardArgs?.length ?? 0) > 0) {
634
+ const requestedNodes = [...nodes.values()].filter((n) => n.requested)
635
+ if (requestedNodes.length > 0 && requestedNodes.every(isGroupTask)) {
636
+ const ids = requestedNodes.map((n) => n.id)
637
+ const named = ids.length > 3 ? `${ids.slice(0, 3).join(', ')}, …` : ids.join(', ')
638
+ throw new UserError(
639
+ `args after \`--\` reach no task: ${named} ${ids.length === 1 ? 'has' : 'have'} no command (a group); name the task that runs one`,
640
+ )
641
+ }
642
+ }
630
643
  if (hasHook(plugins, 'key')) {
631
644
  await applyKeyHooks(plugins, nodes, { workspaceRoot, cacheDir, warn: (m) => log.status(m) })
632
645
  }