@vzn/vx 0.0.550 → 0.0.552

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.550",
3
+ "version": "0.0.552",
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.550",
25
- "@vzn/vx-linux-arm64": "0.0.550",
26
- "@vzn/vx-darwin-x64": "0.0.550",
27
- "@vzn/vx-darwin-arm64": "0.0.550"
24
+ "@vzn/vx-linux-x64": "0.0.552",
25
+ "@vzn/vx-linux-arm64": "0.0.552",
26
+ "@vzn/vx-darwin-x64": "0.0.552",
27
+ "@vzn/vx-darwin-arm64": "0.0.552"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
package/src/cli/init.ts CHANGED
@@ -53,6 +53,12 @@ export function parseInitArgs(args: readonly string[]): InitArgs {
53
53
  return { ...out, error: `unknown flag: ${a}${flagHint('init', a)}${seeHelp('init')}` }
54
54
  else return { ...out, error: `unexpected argument: ${a}${seeHelp('init')}` }
55
55
  }
56
+ if (out.plugin !== undefined && out.mjs) {
57
+ return {
58
+ ...out,
59
+ error: '--mjs does not combine with --plugin: the plugin templates are TypeScript',
60
+ }
61
+ }
56
62
  return out
57
63
  }
58
64
 
@@ -139,9 +145,11 @@ async function scaffoldPlugin(seam: string, args: InitArgs): Promise<number> {
139
145
  for (const [rel, text] of files) await Bun.write(path.join(root, rel), text)
140
146
  }
141
147
  const factory = /^export function (\w+)/m.exec(template.plugin)![1]!
148
+ const workspaceFile =
149
+ WORKSPACE_CONFIG_FILENAMES.find((n) => existsSync(path.join(root, n))) ?? 'vx.workspace.ts'
142
150
  process.stdout.write(
143
151
  `${args.dry ? 'would write' : 'wrote'} ${files.map(([rel]) => rel).join(' and ')}\n` +
144
- `Declare it in vx.workspace.ts: import { ${factory} } from './plugins/${seam}.ts', then plugins: [${factory}(…)]\n` +
152
+ `Declare it in ${workspaceFile}: import { ${factory} } from './plugins/${seam}.ts', then plugins: [${factory}(…)]\n` +
145
153
  `Test it: bun test plugins/${seam}.test.ts (needs @vzn/vx installed)\n`,
146
154
  )
147
155
  return 0
@@ -670,11 +670,14 @@ export function migrateScripts(
670
670
  // insomnia's root is named as its `packages/insomnia`: a root config made
671
671
  // it a project, and every later run was refused for the duplicate (D-129).
672
672
  const clash = outsideName === undefined ? undefined : metas.find((m) => m.name === outsideName)
673
+ // A root with a config of its own is kept as written, and a run of `vx
674
+ // init` after the one that mapped it keeps it like a member's (X-27).
675
+ const rootKept = root !== undefined && root.configPath !== null
673
676
  const rootMeta: ProjectMeta | undefined =
674
677
  root !== undefined
675
- ? root.configPath === null
676
- ? root
677
- : undefined
678
+ ? rootKept
679
+ ? undefined
680
+ : root
678
681
  : outsideName !== undefined && outsideDir !== undefined && clash === undefined
679
682
  ? { name: outsideName, dir: outsideDir, packageJson: outside as never, configPath: null }
680
683
  : undefined
@@ -722,10 +725,9 @@ export function migrateScripts(
722
725
  Object.entries(scripts).filter(([n, v]) => typeof v === 'string' && !out.has(n)),
723
726
  )
724
727
  }
725
- const rootMapped =
726
- rootMeta === undefined
727
- ? 0
728
- : Object.keys(rootScripts(rootMeta)).filter((n) => !LIFECYCLE.test(n)).length
728
+ const mapsOf = (meta: ProjectMeta | undefined): number =>
729
+ meta === undefined ? 0 : Object.keys(rootScripts(meta)).filter((n) => !LIFECYCLE.test(n)).length
730
+ const rootMapped = mapsOf(rootMeta)
729
731
  const listed = (names: readonly string[]): string =>
730
732
  names.slice(0, 8).join(', ') + (names.length > 8 ? ` and ${names.length - 8} more` : '')
731
733
  const outsideScripts = outside?.['scripts']
@@ -750,14 +752,15 @@ export function migrateScripts(
750
752
  // Why a root mapped nothing: `eslint .` beside a member's `lint` runs
751
753
  // nothing of the workspace, and the note said it did.
752
754
  const rootLeftOut = (): string => {
753
- if (rootMeta === undefined) return 'run the workspace'
754
- const scripts = scriptsOf(rootMeta)
755
+ const judged = rootKept ? root : rootMeta
756
+ if (judged === undefined) return 'run the workspace'
757
+ const scripts = scriptsOf(judged)
755
758
  const named = Object.keys(scripts).filter(
756
759
  (n) => typeof scripts[n] === 'string' && scripts[n] !== '' && !LIFECYCLE.test(n),
757
760
  )
758
761
  const runs = runningMembers(
759
762
  scripts,
760
- rootMeta.dir,
763
+ judged.dir,
761
764
  metas.filter((m) => m !== root).map((m) => m.dir),
762
765
  )
763
766
  const shared = named.filter((n) => memberTasks.has(n) && !runs.has(n))
@@ -796,7 +799,7 @@ export function migrateScripts(
796
799
  notes.push(
797
800
  `package.json (the workspace root) not mapped: it has no "name", and vx names a project by it; give it one and run \`vx init\` again to map ${would.length} of its scripts (${would.slice(0, 8).join(', ')}${would.length > 8 ? ', …' : ''})`,
798
801
  )
799
- } else if (rootName !== undefined) {
802
+ } else if (rootName !== undefined && !(rootKept && mapsOf(root) > 0)) {
800
803
  // A nameless root's vx.config is skipped (vx names projects by their
801
804
  // manifest's name), so the hand-written one needs a name first (vuejs/core).
802
805
  notes.push(
@@ -276,6 +276,12 @@ export async function applyMigration(args: ApplyMigrationArgs): Promise<number>
276
276
  kept.push(relPosix(root, existing))
277
277
  return false
278
278
  })
279
+ // A plan never maps a workspace root that has a config (D-45), even
280
+ // under `--force`; its file stays, so it is named with the rest (X-27).
281
+ const rootConfig = metas.find((m) => m.dir === root)?.configPath
282
+ if (init && rootConfig && !projects.some((p) => p.dir === root && p.tasks.length > 0)) {
283
+ kept.push(relPosix(root, rootConfig))
284
+ }
279
285
  if (empty && !init) {
280
286
  throw new UserError(
281
287
  `nothing to migrate: no ${source === 'package.json scripts' ? 'package.json scripts in any workspace member' : 'tasks in ' + source}`,