@vzn/vx 0.0.532 → 0.0.534

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.532",
3
+ "version": "0.0.534",
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.532",
25
- "@vzn/vx-linux-arm64": "0.0.532",
26
- "@vzn/vx-darwin-x64": "0.0.532",
27
- "@vzn/vx-darwin-arm64": "0.0.532"
24
+ "@vzn/vx-linux-x64": "0.0.534",
25
+ "@vzn/vx-linux-arm64": "0.0.534",
26
+ "@vzn/vx-darwin-x64": "0.0.534",
27
+ "@vzn/vx-darwin-arm64": "0.0.534"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
package/src/cli/select.ts CHANGED
@@ -21,11 +21,11 @@ import {
21
21
  parseFilter,
22
22
  type ProjectMeta,
23
23
  readLockfile,
24
- workspaceGlobsMatch,
25
24
  } from '../workspace/index.js'
26
25
  import type { ProjectConfig } from '../config.js'
27
26
  import type { ProjectEntry } from '../workspace/index.js'
28
27
  import { parseDependencySpec } from '../graph/index.js'
28
+ import { declaresInput } from '../cache/index.js'
29
29
  import { listed, maskedLine, nearest, UserError } from '../util/index.js'
30
30
  import {
31
31
  claimedAffected,
@@ -61,9 +61,9 @@ export async function workspaceGlobOwners(
61
61
  ): Promise<string[]> {
62
62
  const declaresMatch = (config: ProjectConfig): boolean => {
63
63
  for (const task of Object.values(config.tasks ?? {})) {
64
- const globs = task.cache?.inputs?.workspaceFiles
65
- if (globs === undefined) continue
66
- if (changed.some((rel) => workspaceGlobsMatch(globs, rel))) return true
64
+ const cache = task.cache
65
+ if (cache === undefined) continue
66
+ if (changed.some((rel) => declaresInput(cache, null, rel))) return true
67
67
  }
68
68
  return false
69
69
  }
package/src/cli/show.ts CHANGED
@@ -266,8 +266,11 @@ function renderProject(
266
266
  return `${JSON.stringify(JSON.parse(JSON.stringify({ name, dir, config: shown })), null, 2)}\n`
267
267
  }
268
268
  const tags = config?.tags ?? []
269
- const head = `${name} — ${dir}${tags.length > 0 ? `\n tags: ${tags.join(', ')}` : ''}`
270
269
  const tasks = Object.entries(config?.tasks ?? {})
270
+ const head = `${name} — ${dir}${tags.length > 0 ? `\n tags: ${tags.join(', ')}` : ''}${
271
+ // A config-less package a dependant reaches has the default `build` (X-9).
272
+ hasConfigFile || tasks.length === 0 ? '' : '\n (no vx config)'
273
+ }`
271
274
  if (tasks.length === 0)
272
275
  return `${head}\n ${hasConfigFile ? '(no tasks declared)' : '(no vx config)'}\n`
273
276
  const blocks = tasks.map(([taskName, task]) => taskBlock(taskName, task))
@@ -179,13 +179,16 @@ export async function loadProjects(args: LoadProjectsArgs): Promise<LoadedProjec
179
179
  // scripts mapped onto packages that never wrote a `vx.config.ts`). It
180
180
  // then loads as `{ tasks: {} }` — nothing to evaluate, nothing to freeze
181
181
  // — and the stage runs on that like on any loaded config. With no
182
- // `project` plugin a plain run never visits (or fences, or seeds) a
183
- // config-less package.
182
+ // `project` plugin a plain run never seeds (or fences) a config-less
183
+ // package, but loads one a loaded project's closure reaches: it gets the
184
+ // default `build`, so a dependant bundling its source is keyed on it
185
+ // behind `^build`. Left out, its edit replayed the dependant's stale
186
+ // output as a hit (X-9).
184
187
  const projectStage = hasHook(plugins, 'project')
185
188
  const configured = args.projectMetas.filter(
186
189
  (m) => projectStage || (typeof m.configPath === 'string' && m.configPath.length > 0),
187
190
  )
188
- const metaByName = new Map<string, ProjectMeta>(configured.map((m) => [m.name, m]))
191
+ const metaByName = new Map<string, ProjectMeta>(args.projectMetas.map((m) => [m.name, m]))
189
192
  const needed = new Set<string>()
190
193
  const pending: ProjectMeta[] = []
191
194
  // Counted, not read off `pending`: a round empties `pending`, and a guard
@@ -212,10 +215,11 @@ export async function loadProjects(args: LoadProjectsArgs): Promise<LoadedProjec
212
215
  walked.add(name)
213
216
  for (const dep of packageGraph.transitiveDeps(name)) consider(dep)
214
217
  }
215
- const seeds = args.seeds === 'all' ? metaByName.keys() : [...args.seeds]
218
+ const seedAll = (): Iterable<string> => configured.map((m) => m.name)
219
+ const seeds = args.seeds === 'all' ? seedAll() : [...args.seeds]
216
220
  for (const seed of seeds) consider(seed)
217
221
  if (graph !== null && pending.length < metaByName.size) {
218
- for (const seed of args.seeds === 'all' ? metaByName.keys() : seeds) {
222
+ for (const seed of args.seeds === 'all' ? seedAll() : seeds) {
219
223
  considerWithDeps(graph, seed)
220
224
  }
221
225
  }
@@ -10,14 +10,12 @@ import { realpathSync, statSync } from 'node:fs'
10
10
  import { realpath } from 'node:fs/promises'
11
11
  import path from 'node:path'
12
12
  import {
13
- asTrees,
14
13
  executablePath,
15
14
  UserError,
16
15
  gitSpawnRefusal,
17
16
  isExecutableMissing,
18
17
  isInstalledPath,
19
18
  relPosix,
20
- taskGlob,
21
19
  } from '../util/index.js'
22
20
  import { LOCKFILE_NAME } from './lockfile.js'
23
21
  import { configImportOwners } from './config-imports.js'
@@ -576,36 +574,6 @@ async function workspaceConfigChanged(
576
574
  return false
577
575
  }
578
576
 
579
- /**
580
- * Does any `cache.inputs.workspaceFiles` entry in `globs` match `rel`?
581
- *
582
- * Mirrors `resolveWorkspaceFiles`' partition: a leading `!` is an EXCLUDE, and
583
- * with no positive glob nothing matches. Paths are workspace-root-relative and
584
- * POSIX-separated, which is the form both git enumeration and the glob
585
- * resolver already speak.
586
- *
587
- * `asTrees` on BOTH sides, because the resolver runs it on both and this
588
- * has to answer the same question the KEY answers. It did not, and the
589
- * gap decided whether a changed file rebuilt anything: with
590
- * `workspaceFiles: ['./generated/**']` or the literal `['generated']` —
591
- * five spellings in all — the resolver folds `generated/x.txt` into the
592
- * project's key while a raw `Bun.Glob` matched none of them, so
593
- * `--affected` left the project out of a run its own key says is stale
594
- * (item 445). A mirror that normalizes differently from what it mirrors
595
- * is not a mirror.
596
- */
597
- export function workspaceGlobsMatch(globs: readonly string[], rel: string): boolean {
598
- const positive: string[] = []
599
- const negative: string[] = []
600
- for (const entry of globs) {
601
- if (entry.startsWith('!')) negative.push(entry.slice(1))
602
- else positive.push(entry)
603
- }
604
- if (positive.length === 0) return false
605
- if (!asTrees(positive).some((g) => taskGlob(g).match(rel))) return false
606
- return !asTrees(negative).some((g) => taskGlob(g).match(rel))
607
- }
608
-
609
577
  /**
610
578
  * The fingerprint files as workspace-root-relative paths. Read from the same
611
579
  * constant the fingerprint itself walks, so a new lockfile format cannot be
@@ -8,7 +8,6 @@ export {
8
8
  defaultAffectedBase,
9
9
  type FingerprintClaims,
10
10
  refIsHead,
11
- workspaceGlobsMatch,
12
11
  } from './affected.js'
13
12
  export { applyFilters, parseFilter } from './filter.js'
14
13
  export {