@vzn/vx 0.0.436 → 0.0.438

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.436",
3
+ "version": "0.0.438",
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.436",
25
- "@vzn/vx-linux-arm64": "0.0.436",
26
- "@vzn/vx-darwin-x64": "0.0.436",
27
- "@vzn/vx-darwin-arm64": "0.0.436"
24
+ "@vzn/vx-linux-x64": "0.0.438",
25
+ "@vzn/vx-linux-arm64": "0.0.438",
26
+ "@vzn/vx-darwin-x64": "0.0.438",
27
+ "@vzn/vx-darwin-arm64": "0.0.438"
28
28
  },
29
29
  "dependencies": {
30
30
  "@anthropic-ai/sandbox-runtime": "^0.0.76"
@@ -1,5 +1,5 @@
1
1
  import { constants, type Dirent } from 'node:fs'
2
- import { access, readdir, stat } from 'node:fs/promises'
2
+ import { access, readdir, realpath, stat } from 'node:fs/promises'
3
3
  import path from 'node:path'
4
4
  import type { ProjectConfig, WorkspaceConfig } from '../config.js'
5
5
  import {
@@ -675,7 +675,17 @@ export async function discoverProjects(
675
675
  }
676
676
  const projects: ProjectMeta[] = []
677
677
  const shared: string[] = []
678
- for (const [name, group] of byName) {
678
+ let rootReal: string | undefined
679
+ for (const [name, found] of byName) {
680
+ // One package reached by two paths (a member and a link to it) is one
681
+ // project, not a name two packages share: `apps/docs -> ../packages/docs`
682
+ // was refused as a duplicate and told to rename one (D-135). Resolved
683
+ // only here, so a workspace without a shared name pays nothing.
684
+ let group = found
685
+ if (group.length > 1) {
686
+ rootReal ??= await realpath(workspace.root)
687
+ group = await oneEntryPerPackage(group, workspace.root, rootReal)
688
+ }
679
689
  if (group.length === 1) {
680
690
  const { dir, pkg, configPath } = group[0]!
681
691
  projects.push({ name, dir, packageJson: pkg, configPath })
@@ -715,6 +725,32 @@ export async function discoverProjects(
715
725
  return projects.sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0))
716
726
  }
717
727
 
728
+ /**
729
+ * The entries of a name group, one per real directory. Of several paths to
730
+ * one package, the one that reaches it through no link inside the
731
+ * workspace is kept, else the first in path order.
732
+ */
733
+ async function oneEntryPerPackage<T extends { dir: string }>(
734
+ group: T[],
735
+ root: string,
736
+ rootReal: string,
737
+ ): Promise<T[]> {
738
+ const byReal = new Map<string, T[]>()
739
+ for (const entry of group) {
740
+ const real = await realpath(entry.dir)
741
+ const same = byReal.get(real)
742
+ if (same === undefined) byReal.set(real, [entry])
743
+ else same.push(entry)
744
+ }
745
+ if (byReal.size === group.length) return group
746
+ const kept: T[] = []
747
+ for (const [real, paths] of byReal) {
748
+ const direct = paths.find((e) => relPosix(root, e.dir) === relPosix(rootReal, real))
749
+ kept.push(direct ?? paths.sort((a, b) => (a.dir < b.dir ? -1 : 1))[0]!)
750
+ }
751
+ return kept
752
+ }
753
+
718
754
  /**
719
755
  * A directory a plugin's `discover` hook names, as a project meta; null
720
756
  * when `known` already holds it under that name. `by` names the plugin in