@vzn/vx 0.0.493 → 0.0.494

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.493",
3
+ "version": "0.0.494",
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.493",
25
- "@vzn/vx-linux-arm64": "0.0.493",
26
- "@vzn/vx-darwin-x64": "0.0.493",
27
- "@vzn/vx-darwin-arm64": "0.0.493"
24
+ "@vzn/vx-linux-x64": "0.0.494",
25
+ "@vzn/vx-linux-arm64": "0.0.494",
26
+ "@vzn/vx-darwin-x64": "0.0.494",
27
+ "@vzn/vx-darwin-arm64": "0.0.494"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
@@ -120,10 +120,14 @@ export async function pluginVerbs(cwd = process.cwd()): Promise<string[]> {
120
120
  export async function pluginCommandHelp(cwd = process.cwd()): Promise<string[]> {
121
121
  const ws = await workspacePlugins(cwd).catch(() => null)
122
122
  if (ws === null || 'loadError' in ws) return []
123
- // A verb has one owner: the workspace load refuses two plugins declaring it.
123
+ // A verb has one owner, a package: the workspace load refuses two packages
124
+ // declaring it, and of one package's plugins the first declared runs.
124
125
  const lines: string[] = []
126
+ const seen = new Set<string>()
125
127
  for (const plugin of ws.plugins) {
126
128
  for (const [verb, command] of Object.entries(plugin.commands ?? {})) {
129
+ if (seen.has(verb)) continue
130
+ seen.add(verb)
127
131
  lines.push(` vx ${verb.padEnd(17)} ${command.description} (${plugin.name})`)
128
132
  }
129
133
  }
package/src/util/verbs.ts CHANGED
@@ -29,7 +29,7 @@ export const MOVED_VERBS: Readonly<Record<string, string>> = {
29
29
  'vx migrate moved to @vzn/vx-migrate: run `bunx @vzn/vx-migrate` (turbo.json or an Nx ' +
30
30
  'project graph → vx.config.ts); `vx init` reads package.json scripts',
31
31
  prune:
32
- 'vx prune was removed (2026-09-11): the Docker-subset verb is not shipped; copy the ' +
33
- 'workspace and `--filter` the build instead',
32
+ 'vx prune comes from @vzn/vx-lockfile: declare pnpm(), bun(), npm() or yarn() in ' +
33
+ 'vx.workspace.ts',
34
34
  stats: 'vx stats was removed (H-19): run `vx info`, which prints the same report',
35
35
  }
@@ -204,14 +204,16 @@ export function validateWorkspace(config: WorkspaceConfig, configPath: string):
204
204
  // dead: core verbs are matched first, and two plugins on one verb
205
205
  // would run the first declared and hide the second. Here, in the
206
206
  // schema, so every loader of the file — a run, a reading verb, the
207
- // plugin-verb lookup — refuses it the same way.
207
+ // plugin-verb lookup — refuses it the same way. The owner is the
208
+ // package: two plugins one package exports (`bun()` and `pnpm()`
209
+ // both carry `prune`) are one owner, and the first declared runs.
208
210
  if ((CORE_VERBS as readonly string[]).includes(verb)) {
209
211
  throw new UserError(
210
212
  `${configPath}: plugin '${plug.name}' declares command '${verb}', a core verb — core verbs cannot be shadowed`,
211
213
  )
212
214
  }
213
215
  const owner = verbOwners.get(verb)
214
- if (owner !== undefined) {
216
+ if (owner !== undefined && owner !== plug.name) {
215
217
  throw new UserError(
216
218
  `${configPath}: plugins '${owner}' and '${plug.name}' both declare command '${verb}' — a verb has one owner`,
217
219
  )