@savvy-web/silk 3.8.0 → 3.8.2

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.
@@ -2335,7 +2335,7 @@ var GlobSet = class GlobSet extends effect.Schema.Class("GlobSet")(effect.Schema
2335
2335
  }
2336
2336
  };
2337
2337
  //#endregion
2338
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/BunExtension.js
2338
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/BunExtension.js
2339
2339
  /**
2340
2340
  * Extension data specific to bun lockfiles, attached to `Lockfile.extension`
2341
2341
  * when the format is `"bun"`.
@@ -4139,7 +4139,7 @@ input: effect.Schema.String }) {
4139
4139
  }
4140
4140
  };
4141
4141
  const CATALOG_PREFIX = "catalog:";
4142
- const WORKSPACE_PREFIX = "workspace:";
4142
+ const WORKSPACE_PREFIX$1 = "workspace:";
4143
4143
  const isBarePath = (value) => value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.startsWith("/");
4144
4144
  const isGitHubShorthand = (value) => !value.startsWith(".") && !value.startsWith("~") && !value.startsWith("/") && /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(#.*)?$/.test(value);
4145
4145
  const isGit = (value) => value.startsWith("git+") || value.startsWith("git://") || value.startsWith("github:") || value.startsWith("gist:") || value.startsWith("bitbucket:") || value.startsWith("gitlab:") || isGitHubShorthand(value);
@@ -4147,7 +4147,7 @@ const isLocal = (value) => value.startsWith("file:") || value.startsWith("link:"
4147
4147
  const isLink = (value) => value.startsWith("link:");
4148
4148
  const isPortal = (value) => value.startsWith("portal:");
4149
4149
  const isCatalog = (value) => value.startsWith(CATALOG_PREFIX);
4150
- const isWorkspace = (value) => value.startsWith(WORKSPACE_PREFIX);
4150
+ const isWorkspace = (value) => value.startsWith(WORKSPACE_PREFIX$1);
4151
4151
  const isUrl$1 = (value) => value.startsWith("http://") || value.startsWith("https://");
4152
4152
  const parseRange = (value) => {
4153
4153
  const exit = effect.Schema.decodeUnknownExit(Range$2.FromString)(value);
@@ -4156,7 +4156,7 @@ const parseRange = (value) => {
4156
4156
  const isRange = (value) => effect.Option.isSome(parseRange(value));
4157
4157
  const protocolOf = (value) => {
4158
4158
  if (value.startsWith(CATALOG_PREFIX)) return "catalog";
4159
- if (value.startsWith(WORKSPACE_PREFIX)) return "workspace";
4159
+ if (value.startsWith(WORKSPACE_PREFIX$1)) return "workspace";
4160
4160
  if (value.startsWith("link:")) return "link";
4161
4161
  if (value.startsWith("portal:")) return "portal";
4162
4162
  if (value.startsWith("file:") || isBarePath(value)) return "file";
@@ -5569,7 +5569,7 @@ var ReleaseAgeGate = class ReleaseAgeGate extends effect.Schema.Class("ReleaseAg
5569
5569
  }
5570
5570
  };
5571
5571
  //#endregion
5572
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/ImporterDependency.js
5572
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/ImporterDependency.js
5573
5573
  /**
5574
5574
  * One declared dependency of one workspace importer, as the lockfile records it.
5575
5575
  *
@@ -5607,7 +5607,7 @@ var ImporterDependency = class extends effect.Schema.Class("ImporterDependency")
5607
5607
  depType: DependencyField
5608
5608
  }) {};
5609
5609
  //#endregion
5610
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/LockfileImporter.js
5610
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/LockfileImporter.js
5611
5611
  /**
5612
5612
  * One workspace importer's declared dependencies, as the lockfile records them.
5613
5613
  *
@@ -5631,14 +5631,23 @@ var LockfileImporter = class extends effect.Schema.Class("LockfileImporter")({
5631
5631
  dependencies: effect.Schema.Array(ImporterDependency)
5632
5632
  }) {};
5633
5633
  //#endregion
5634
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/ResolvedPackage.js
5634
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/ResolvedPackage.js
5635
5635
  const EMPTY_DEPENDENCIES = {};
5636
+ const EMPTY_PEER_META = {};
5637
+ const EMPTY_EDGE_NAMES = [];
5636
5638
  /**
5637
5639
  * A package resolved from a lockfile.
5638
5640
  *
5639
5641
  * @remarks
5640
5642
  * The common shape every format's entries normalize into:
5641
5643
  *
5644
+ * - `instanceId` — the lockfile-native identity of this *instance*, verbatim:
5645
+ * pnpm's snapshot key (`react-dom@18.3.1(react@17.0.2)`), npm's full entry
5646
+ * key (`node_modules/express/node_modules/debug`), bun's `packages` key
5647
+ * (`@acme/lib/react-dom`) or yarn's locator (`react-dom@npm:18.3.1`). It is
5648
+ * **opaque** — no scheme is synthesized and none should be parsed by a
5649
+ * consumer; it exists so `resolved` can name an instance, and so two
5650
+ * peer-resolved variants of one `name@version` stay distinguishable.
5642
5651
  * - `name` — the resolved package name. For pnpm *workspace* packages
5643
5652
  * straight out of `Lockfile.parse` this is the importer path until
5644
5653
  * `Lockfile#withImporterNames` rewrites it.
@@ -5654,19 +5663,65 @@ const EMPTY_DEPENDENCIES = {};
5654
5663
  * packages, when the lockfile records one.
5655
5664
  * - `dependencies` — the package's own dependency map, defaulting to `{}`
5656
5665
  * both at construction and when decoding serialized data.
5666
+ * - `peerDependencies` — the package's *declared* peer ranges, keyed by peer
5667
+ * name. Every format records them (pnpm and npm as their own section, bun
5668
+ * inline in the package tuple's info object, yarn Berry as an entry
5669
+ * section), so this is populated across all four. Declarations only: what
5670
+ * the package *asks for*, never what actually resolved.
5671
+ * - `peerDependenciesMeta` — the per-peer flags, normalized to
5672
+ * `{ optional: boolean }`. bun spells optional peers as an `optionalPeers`
5673
+ * array of names rather than a meta object; that spelling is normalized
5674
+ * into this shape so one consumer algorithm serves every format. A peer
5675
+ * with no meta entry is required.
5676
+ * - `resolved` — this instance's *outgoing edges*: dependency (and, where the
5677
+ * format records it, peer) name → the `instanceId` that name actually
5678
+ * resolved to in this instance's context. This is the answer to "which
5679
+ * concrete version of P did X get", which `peerDependencies` deliberately
5680
+ * does not answer.
5681
+ *
5682
+ * Every entry is **verified**: an edge is emitted only when the composed or
5683
+ * walked-up identity matches a real instance in the same lockfile. An edge
5684
+ * that cannot be resolved honestly is *omitted*, never guessed — a wrong
5685
+ * resolved edge is a silent wrong answer, an absent one is a visible gap.
5686
+ * yarn records peer resolution virtually and is therefore dependency-edges
5687
+ * only.
5688
+ *
5689
+ * - `unresolvedEdges` — dependency names whose edge the lockfile **records**
5690
+ * but this model could not name: a `link:` target that is not a workspace
5691
+ * importer, a composed identity matching no instance. It is the companion
5692
+ * `resolved` needs to be honest, because an absent key in `resolved` would
5693
+ * otherwise mean two different things — "nothing is there" and "something is
5694
+ * there that I could not name" — and a consumer reading the first meaning
5695
+ * for the second turns this package's gap into its own false positive.
5696
+ *
5697
+ * A dependency the lockfile simply does not record is **not** an unresolved
5698
+ * edge; it is an absence, and must not appear here. npm and bun contribute
5699
+ * nothing at all: their sections are *declarations* resolved positionally, so
5700
+ * "the walk found nothing" is genuine absence. A fail-closed signal that is
5701
+ * always on is a signal nobody reads.
5702
+ *
5703
+ * All four record fields — `dependencies`, `peerDependencies`,
5704
+ * `peerDependenciesMeta` and `resolved` — default to `{}` at construction and
5705
+ * when decoding, and `unresolvedEdges` defaults to `[]`. An absent section is
5706
+ * therefore an empty collection, never `undefined`.
5657
5707
  *
5658
5708
  * @public
5659
5709
  */
5660
5710
  var ResolvedPackage = class extends effect.Schema.Class("ResolvedPackage")({
5661
5711
  name: effect.Schema.NonEmptyString,
5662
5712
  version: effect.Schema.String,
5713
+ instanceId: effect.Schema.NonEmptyString,
5663
5714
  integrity: effect.Schema.optionalKey(IntegrityHash),
5664
5715
  isWorkspace: effect.Schema.Boolean,
5665
5716
  relativePath: effect.Schema.optionalKey(effect.Schema.String),
5666
- dependencies: effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY_DEPENDENCIES)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY_DEPENDENCIES)))
5717
+ dependencies: effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY_DEPENDENCIES)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY_DEPENDENCIES))),
5718
+ peerDependencies: effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY_DEPENDENCIES)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY_DEPENDENCIES))),
5719
+ peerDependenciesMeta: effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ optional: effect.Schema.Boolean })).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY_PEER_META)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY_PEER_META))),
5720
+ resolved: effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY_DEPENDENCIES)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY_DEPENDENCIES))),
5721
+ unresolvedEdges: effect.Schema.Array(effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY_EDGE_NAMES)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY_EDGE_NAMES)))
5667
5722
  }) {};
5668
5723
  //#endregion
5669
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/WorkspaceDependency.js
5724
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/WorkspaceDependency.js
5670
5725
  /**
5671
5726
  * A directed dependency edge between two workspace packages as recorded in
5672
5727
  * the lockfile.
@@ -5688,7 +5743,7 @@ var WorkspaceDependency = class extends effect.Schema.Class("WorkspaceDependency
5688
5743
  constraint: effect.Schema.String
5689
5744
  }) {};
5690
5745
  //#endregion
5691
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/PnpmExtension.js
5746
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/PnpmExtension.js
5692
5747
  /**
5693
5748
  * Extension data specific to pnpm lockfiles, attached to `Lockfile.extension`
5694
5749
  * when the format is `"pnpm"`.
@@ -5713,10 +5768,10 @@ var PnpmExtension = class extends effect.Schema.Class("PnpmExtension")({
5713
5768
  }))
5714
5769
  }) {};
5715
5770
  //#endregion
5716
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/LockfileFormat.js
5771
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/LockfileFormat.js
5717
5772
  /**
5718
5773
  * The lockfile formats this package parses: bun's `bun.lock` (JSONC), npm's
5719
- * `package-lock.json` (v2/v3 JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
5774
+ * `package-lock.json` (JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
5720
5775
  * `yarn.lock` (both YAML).
5721
5776
  *
5722
5777
  * @remarks
@@ -5725,6 +5780,10 @@ var PnpmExtension = class extends effect.Schema.Class("PnpmExtension")({
5725
5780
  * Berry only; classic (v1) `yarn.lock` is not YAML and fails
5726
5781
  * `Lockfile.parse` with a typed `LockfileParseError`.
5727
5782
  *
5783
+ * The format literal says nothing about which *versions* of that format are
5784
+ * supported: pnpm `lockfileVersion` 9+ and npm `lockfileVersion` 3+ parse,
5785
+ * and older ones fail typed. See `Lockfile.parse`.
5786
+ *
5728
5787
  * @public
5729
5788
  */
5730
5789
  const LockfileFormat = effect.Schema.Literals([
@@ -5751,7 +5810,7 @@ const FILENAMES = {
5751
5810
  */
5752
5811
  const filenameFor = (format) => FILENAMES[format][0];
5753
5812
  //#endregion
5754
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/internal/shared.js
5813
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/internal/shared.js
5755
5814
  /**
5756
5815
  * The four dependency sections of a manifest, in a stable order — the shared
5757
5816
  * dependency-sections table (v3's `DEP_SECTIONS`). Each entry is both the
@@ -5862,6 +5921,79 @@ const importerDependencies = (entry, read) => {
5862
5921
  }
5863
5922
  return deps;
5864
5923
  };
5924
+ const EMPTY_PEERS = {
5925
+ peerDependencies: {},
5926
+ peerDependenciesMeta: {}
5927
+ };
5928
+ /**
5929
+ * Normalize one format's peer declarations into the unified pair.
5930
+ *
5931
+ * Every format records the ranges the same way (a name→range map), but the
5932
+ * optional flag has two spellings: a `peerDependenciesMeta` object (pnpm, npm,
5933
+ * yarn Berry) and bun's `optionalPeers` array of names. Both are accepted and
5934
+ * collapse to `{ optional: boolean }` per peer, so a consumer reads one shape
5935
+ * regardless of which manager wrote the lockfile.
5936
+ *
5937
+ * Absence yields empty records, never `undefined` — an absent section means
5938
+ * "declares no peers", which is a fact, not a gap. Records are built with
5939
+ * `Object.fromEntries` (own-property semantics), so a `__proto__` peer name
5940
+ * neither pollutes nor drops.
5941
+ *
5942
+ * @internal
5943
+ */
5944
+ const peerDeclarations = (peers, meta, optionalPeers) => {
5945
+ if (peers === void 0 && meta === void 0 && optionalPeers === void 0) return EMPTY_PEERS;
5946
+ const flags = /* @__PURE__ */ new Map();
5947
+ if (meta !== void 0) for (const [name, value] of Object.entries(meta)) flags.set(name, value?.optional === true);
5948
+ if (optionalPeers !== void 0) for (const name of optionalPeers) flags.set(name, true);
5949
+ return {
5950
+ peerDependencies: peers === void 0 ? {} : Object.fromEntries(Object.entries(peers)),
5951
+ peerDependenciesMeta: Object.fromEntries([...flags].map(([name, optional]) => [name, { optional }]))
5952
+ };
5953
+ };
5954
+ /**
5955
+ * The minimum lockfile-format version each gated format is parsed at.
5956
+ *
5957
+ * This is a deliberate narrowing of the supported input domain, not an
5958
+ * implementation detail: an older lockfile fails typed rather than parsing
5959
+ * into a model that cannot answer resolution questions. Note the gate is on
5960
+ * the **lockfile format version**, which is the only version a lockfile
5961
+ * records — the writing package manager's version is not recoverable from the
5962
+ * file, so no manager-version claim could be enforced here.
5963
+ *
5964
+ * @internal
5965
+ */
5966
+ const MINIMUM_LOCKFILE_VERSION = {
5967
+ pnpm: 9,
5968
+ npm: 3
5969
+ };
5970
+ /**
5971
+ * Fail typed when a lockfile predates the supported format version.
5972
+ *
5973
+ * Routed through {@link validationFailure} rather than {@link framingFailure}:
5974
+ * the document was located perfectly well, so this is a shape judgement about
5975
+ * a located document, not a framing problem. The cause is a structured record
5976
+ * rather than an engine error, so a consumer can tell "your lockfile is too
5977
+ * old" from "your lockfile is malformed" without parsing a message.
5978
+ *
5979
+ * A version that is not a number at all (`lockfileVersion: "next"`) is not a
5980
+ * supported version either, and fails the same way.
5981
+ *
5982
+ * @internal
5983
+ */
5984
+ const requireLockfileVersion = (format, raw) => {
5985
+ const minimum = MINIMUM_LOCKFILE_VERSION[format];
5986
+ const parsed = typeof raw === "number" ? raw : Number.parseFloat(raw);
5987
+ if (Number.isFinite(parsed) && parsed >= minimum) return effect.Effect.void;
5988
+ const cause = {
5989
+ _tag: "UnsupportedLockfileVersion",
5990
+ format,
5991
+ lockfileVersion: raw,
5992
+ minimumSupported: minimum,
5993
+ message: `${format} lockfileVersion ${JSON.stringify(raw)} is not supported: @effected/lockfiles parses ${format} lockfileVersion ${minimum} and newer`
5994
+ };
5995
+ return effect.Effect.fail(validationFailure(cause));
5996
+ };
5865
5997
  /** @internal */
5866
5998
  const syntaxFailure = (cause) => ({
5867
5999
  stage: "syntax",
@@ -7680,16 +7812,38 @@ var JsoncModifier = class {
7680
7812
  });
7681
7813
  };
7682
7814
  //#endregion
7683
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/internal/bun.js
7815
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/internal/bun.js
7684
7816
  const DepRecord$2 = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
7817
+ const OptionalPeers = effect.Schema.optionalKey(effect.Schema.Array(effect.Schema.String));
7685
7818
  const BunWorkspaceEntry = effect.Schema.Struct({
7686
7819
  name: effect.Schema.optionalKey(effect.Schema.String),
7687
7820
  version: effect.Schema.optionalKey(effect.Schema.String),
7688
7821
  dependencies: DepRecord$2,
7689
7822
  devDependencies: DepRecord$2,
7690
7823
  peerDependencies: DepRecord$2,
7691
- optionalDependencies: DepRecord$2
7824
+ optionalDependencies: DepRecord$2,
7825
+ optionalPeers: OptionalPeers
7826
+ });
7827
+ /**
7828
+ * The info object at package-tuple index 2. bun's tuple shape is
7829
+ * under-documented upstream, so it is read permissively and *out of band*: a
7830
+ * shape that does not decode is skipped (the package still lands, with no
7831
+ * peers) rather than failing the whole parse.
7832
+ *
7833
+ * @internal
7834
+ */
7835
+ const BunPackageInfo = effect.Schema.Struct({
7836
+ dependencies: DepRecord$2,
7837
+ devDependencies: DepRecord$2,
7838
+ optionalDependencies: DepRecord$2,
7839
+ peerDependencies: DepRecord$2,
7840
+ optionalPeers: OptionalPeers
7692
7841
  });
7842
+ const decodeBunPackageInfo = effect.Schema.decodeUnknownExit(BunPackageInfo);
7843
+ const readBunPackageInfo = (value) => {
7844
+ const exit = decodeBunPackageInfo(value);
7845
+ return effect.Exit.isSuccess(exit) ? exit.value : void 0;
7846
+ };
7693
7847
  const BunLockfileRaw = effect.Schema.Struct({
7694
7848
  lockfileVersion: effect.Schema.Number,
7695
7849
  workspaces: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, BunWorkspaceEntry)),
@@ -7712,8 +7866,60 @@ const parseBun = (content) => effect.Effect.gen(function* () {
7712
7866
  const validated = yield* effect.Schema.decodeUnknownEffect(BunLockfileRaw)(parsed).pipe(effect.Effect.mapError(validationFailure));
7713
7867
  return yield* toFields$3(validated);
7714
7868
  });
7869
+ /**
7870
+ * Resolve one entry's outgoing edges by replaying bun's own key scheme.
7871
+ *
7872
+ * bun encodes install position in the `packages` key: a nested install is
7873
+ * keyed `<parent-key>/<name>`, so `"react-dom/react"` is literally "the react
7874
+ * react-dom got". Package names are themselves slash-bearing when scoped, so
7875
+ * the parent chain is **not** computed by splitting on `/` — it is read off
7876
+ * the key space, taking those prefixes of the key that are themselves keys,
7877
+ * longest first. Deepest wins; the root (`<name>` alone) is tried last.
7878
+ *
7879
+ * Only keys that exist are emitted, so an edge bun did not record is omitted
7880
+ * rather than invented.
7881
+ *
7882
+ * @internal
7883
+ */
7884
+ const resolveBunEdges = (key, sections, keys) => {
7885
+ const names = /* @__PURE__ */ new Set();
7886
+ for (const section of sections) {
7887
+ if (!section) continue;
7888
+ for (const name of Object.keys(section)) if (name !== "") names.add(name);
7889
+ }
7890
+ if (names.size === 0) return {};
7891
+ const prefixes = [key];
7892
+ for (let i = key.indexOf("/"); i !== -1; i = key.indexOf("/", i + 1)) {
7893
+ const candidate = key.slice(0, i);
7894
+ if (keys.has(candidate)) prefixes.push(candidate);
7895
+ }
7896
+ prefixes.sort((a, b) => b.length - a.length);
7897
+ prefixes.push("");
7898
+ const edges = /* @__PURE__ */ new Map();
7899
+ for (const name of names) for (const prefix of prefixes) {
7900
+ const candidate = prefix === "" ? name : `${prefix}/${name}`;
7901
+ if (keys.has(candidate)) {
7902
+ edges.set(name, candidate);
7903
+ break;
7904
+ }
7905
+ }
7906
+ return Object.fromEntries(edges);
7907
+ };
7908
+ const infoSections = (info) => [
7909
+ info?.dependencies,
7910
+ info?.devDependencies,
7911
+ info?.optionalDependencies,
7912
+ info?.peerDependencies
7913
+ ];
7914
+ const workspaceSections = (entry) => [
7915
+ entry.dependencies,
7916
+ entry.devDependencies,
7917
+ entry.optionalDependencies,
7918
+ entry.peerDependencies
7919
+ ];
7715
7920
  const toFields$3 = (raw) => effect.Effect.gen(function* () {
7716
7921
  const packages = [];
7922
+ const keys = new Set(raw.packages ? Object.keys(raw.packages) : []);
7717
7923
  const workspaceNames = /* @__PURE__ */ new Set();
7718
7924
  const workspaceEntries = /* @__PURE__ */ new Map();
7719
7925
  const importers = [];
@@ -7726,11 +7932,16 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7726
7932
  if (wsPath === "") continue;
7727
7933
  const name = wsEntry.name === void 0 || wsEntry.name === "" ? wsPath : wsEntry.name;
7728
7934
  workspaceNames.add(name);
7935
+ const instanceId = keys.has(name) ? name : wsPath;
7936
+ if (instanceId === "") continue;
7729
7937
  packages.push(ResolvedPackage.make({
7730
7938
  name,
7731
7939
  version: wsEntry.version ?? "0.0.0",
7940
+ instanceId,
7732
7941
  isWorkspace: true,
7733
- relativePath: wsPath
7942
+ relativePath: wsPath,
7943
+ ...peerDeclarations(wsEntry.peerDependencies, void 0, wsEntry.optionalPeers),
7944
+ resolved: resolveBunEdges(instanceId, workspaceSections(wsEntry), keys)
7734
7945
  }));
7735
7946
  workspaceEntries.set(name, {
7736
7947
  ...wsEntry.dependencies ? { dependencies: wsEntry.dependencies } : {},
@@ -7740,7 +7951,8 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7740
7951
  });
7741
7952
  }
7742
7953
  }
7743
- if (raw.packages) for (const tuple of Object.values(raw.packages)) {
7954
+ if (raw.packages) for (const [key, tuple] of Object.entries(raw.packages)) {
7955
+ if (key === "") continue;
7744
7956
  if (tuple.length < 1) continue;
7745
7957
  const first = tuple[0];
7746
7958
  if (typeof first !== "string") continue;
@@ -7750,11 +7962,15 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7750
7962
  const version = first.slice(atIdx + 1);
7751
7963
  if (workspaceNames.has(name)) continue;
7752
7964
  const integrity = yield* toIntegrityHash(tuple.length >= 4 && typeof tuple[3] === "string" ? tuple[3] : void 0);
7965
+ const info = tuple.length >= 3 ? readBunPackageInfo(tuple[2]) : void 0;
7753
7966
  packages.push(ResolvedPackage.make({
7754
7967
  name,
7755
7968
  version,
7969
+ instanceId: key,
7756
7970
  ...integrity !== void 0 ? { integrity } : {},
7757
- isWorkspace: false
7971
+ isWorkspace: false,
7972
+ ...peerDeclarations(info?.peerDependencies, void 0, info?.optionalPeers),
7973
+ resolved: resolveBunEdges(key, infoSections(info), keys)
7758
7974
  }));
7759
7975
  }
7760
7976
  const workspaceDependencies = extractWorkspaceDeps(workspaceEntries, workspaceNames);
@@ -7773,8 +7989,9 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7773
7989
  };
7774
7990
  });
7775
7991
  //#endregion
7776
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/internal/npm.js
7992
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/internal/npm.js
7777
7993
  const DepRecord$1 = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
7994
+ const PeerMetaRecord = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ optional: effect.Schema.optionalKey(effect.Schema.Boolean) })));
7778
7995
  const NpmPackageEntry = effect.Schema.Struct({
7779
7996
  name: effect.Schema.optionalKey(effect.Schema.String),
7780
7997
  version: effect.Schema.optionalKey(effect.Schema.String),
@@ -7785,8 +8002,22 @@ const NpmPackageEntry = effect.Schema.Struct({
7785
8002
  dependencies: DepRecord$1,
7786
8003
  devDependencies: DepRecord$1,
7787
8004
  peerDependencies: DepRecord$1,
8005
+ peerDependenciesMeta: PeerMetaRecord,
7788
8006
  optionalDependencies: DepRecord$1
7789
8007
  });
8008
+ /**
8009
+ * The version gate's own input: `lockfileVersion` and nothing else.
8010
+ *
8011
+ * The gate has to read the version *before* the shape decode, because the
8012
+ * shape it would decode against is the shape of a supported version. `packages`
8013
+ * is a required key here and a v1 tree does not have one, so a shape-first
8014
+ * order reports npm v1 as **malformed** rather than as **too old** — losing
8015
+ * exactly the distinction the `UnsupportedLockfileVersion` cause exists to
8016
+ * carry.
8017
+ *
8018
+ * @internal
8019
+ */
8020
+ const NpmVersionProbe = effect.Schema.Struct({ lockfileVersion: effect.Schema.Union([effect.Schema.Number, effect.Schema.String]) });
7790
8021
  const NpmLockfileRaw = effect.Schema.Struct({
7791
8022
  name: effect.Schema.optionalKey(effect.Schema.String),
7792
8023
  version: effect.Schema.optionalKey(effect.Schema.String),
@@ -7795,10 +8026,73 @@ const NpmLockfileRaw = effect.Schema.Struct({
7795
8026
  packages: effect.Schema.Record(effect.Schema.String, NpmPackageEntry)
7796
8027
  });
7797
8028
  const NODE_MODULES_PREFIX = "node_modules/";
8029
+ const NESTED_NODE_MODULES = "/node_modules/";
8030
+ /**
8031
+ * Where a `packages` key's package name starts: after the **last**
8032
+ * `node_modules/` segment, not the first.
8033
+ *
8034
+ * npm encodes the whole install position in the key, so
8035
+ * `node_modules/express/node_modules/debug` is *debug*, nested under express —
8036
+ * and `packages/lib/node_modules/react` is *react*, nested under a workspace
8037
+ * directory and carrying no `node_modules/` prefix at all. Returns `-1` for a
8038
+ * key that is not a package position (the root `""` entry, a workspace path
8039
+ * entry), which the caller skips.
8040
+ *
8041
+ * @internal
8042
+ */
8043
+ const packageNameIndex = (key) => {
8044
+ const nested = key.lastIndexOf(NESTED_NODE_MODULES);
8045
+ if (nested !== -1) return nested + 14;
8046
+ return key.startsWith(NODE_MODULES_PREFIX) ? 13 : -1;
8047
+ };
7798
8048
  /**
7799
- * Parse npm `package-lock.json` (v2/v3) content into the unified field
7800
- * bundle. Native `JSON.parse` inside `Effect.try` its throw on hostile
7801
- * input (including V8's `RangeError` on pathological depth) lands typed as
8049
+ * Resolve one entry's outgoing edges by replaying node resolution over the key
8050
+ * space: from the depending package's own directory, try
8051
+ * `<prefix>/node_modules/<name>`, then strip one path segment and try again,
8052
+ * out to the root — **deepest first**, first hit wins. That order is the whole
8053
+ * algorithm: outermost-first would return the hoisted copy and silently
8054
+ * mis-report every shadowed dependency.
8055
+ *
8056
+ * Only keys that actually exist in the lockfile are emitted, so an edge npm
8057
+ * did not record is omitted rather than invented.
8058
+ *
8059
+ * @internal
8060
+ */
8061
+ const resolveNpmEdges = (start, sections, packages) => {
8062
+ const names = /* @__PURE__ */ new Set();
8063
+ for (const section of sections) {
8064
+ if (!section) continue;
8065
+ for (const name of Object.keys(section)) if (name !== "") names.add(name);
8066
+ }
8067
+ if (names.size === 0) return {};
8068
+ const prefixes = [];
8069
+ for (let prefix = start;;) {
8070
+ prefixes.push(prefix);
8071
+ if (prefix === "") break;
8072
+ const slash = prefix.lastIndexOf("/");
8073
+ prefix = slash === -1 ? "" : prefix.slice(0, slash);
8074
+ }
8075
+ const edges = /* @__PURE__ */ new Map();
8076
+ for (const name of names) for (const prefix of prefixes) {
8077
+ const candidate = prefix === "" ? `${NODE_MODULES_PREFIX}${name}` : `${prefix}${NESTED_NODE_MODULES}${name}`;
8078
+ if (Object.hasOwn(packages, candidate)) {
8079
+ edges.set(name, candidate);
8080
+ break;
8081
+ }
8082
+ }
8083
+ return Object.fromEntries(edges);
8084
+ };
8085
+ const entrySections = (entry) => [
8086
+ entry?.dependencies,
8087
+ entry?.devDependencies,
8088
+ entry?.optionalDependencies,
8089
+ entry?.peerDependencies
8090
+ ];
8091
+ /**
8092
+ * Parse npm `package-lock.json` content into the unified field bundle —
8093
+ * `lockfileVersion` 3 and newer; v2 and older fail typed at validation.
8094
+ * Native `JSON.parse` inside `Effect.try` — its throw on hostile input
8095
+ * (including V8's `RangeError` on pathological depth) lands typed as
7802
8096
  * `stage: "syntax"`.
7803
8097
  *
7804
8098
  * @internal
@@ -7808,6 +8102,8 @@ const parseNpm = (content) => effect.Effect.gen(function* () {
7808
8102
  try: () => JSON.parse(content),
7809
8103
  catch: syntaxFailure
7810
8104
  });
8105
+ const probe = yield* effect.Schema.decodeUnknownEffect(NpmVersionProbe)(raw).pipe(effect.Effect.mapError(validationFailure));
8106
+ yield* requireLockfileVersion("npm", probe.lockfileVersion);
7811
8107
  const validated = yield* effect.Schema.decodeUnknownEffect(NpmLockfileRaw)(raw).pipe(effect.Effect.mapError(validationFailure));
7812
8108
  return yield* toFields$2(validated);
7813
8109
  });
@@ -7821,22 +8117,30 @@ const toFields$2 = (raw) => effect.Effect.gen(function* () {
7821
8117
  path: ".",
7822
8118
  dependencies: importerDependencies(rootEntry, (s) => ({ specifier: s }))
7823
8119
  }));
7824
- for (const [key, entry] of Object.entries(raw.packages)) if (key.startsWith(NODE_MODULES_PREFIX) && entry.link === true) {
7825
- const name = (entry.resolved !== void 0 ? raw.packages[entry.resolved] : void 0)?.name ?? entry.name ?? key.slice(13);
7826
- if (name !== "") workspaceNames.add(name);
8120
+ for (const [key, entry] of Object.entries(raw.packages)) {
8121
+ const nameIndex = packageNameIndex(key);
8122
+ if (nameIndex !== -1 && entry.link === true) {
8123
+ const name = (entry.resolved !== void 0 ? raw.packages[entry.resolved] : void 0)?.name ?? entry.name ?? key.slice(nameIndex);
8124
+ if (name !== "") workspaceNames.add(name);
8125
+ }
7827
8126
  }
7828
8127
  for (const [key, entry] of Object.entries(raw.packages)) {
7829
8128
  if (key === "") continue;
7830
- if (key.startsWith(NODE_MODULES_PREFIX) && entry.link === true) {
8129
+ const nameIndex = packageNameIndex(key);
8130
+ if (nameIndex === -1) continue;
8131
+ if (entry.link === true) {
7831
8132
  const resolved = entry.resolved;
7832
8133
  const wsEntry = resolved !== void 0 ? raw.packages[resolved] : void 0;
7833
- const name = wsEntry?.name ?? entry.name ?? key.slice(13);
8134
+ const name = wsEntry?.name ?? entry.name ?? key.slice(nameIndex);
7834
8135
  if (name === "") continue;
7835
8136
  packages.push(ResolvedPackage.make({
7836
8137
  name,
7837
8138
  version: wsEntry?.version ?? "0.0.0",
8139
+ instanceId: key,
7838
8140
  isWorkspace: true,
7839
- ...resolved !== void 0 ? { relativePath: resolved } : {}
8141
+ ...resolved !== void 0 ? { relativePath: resolved } : {},
8142
+ ...peerDeclarations(wsEntry?.peerDependencies, wsEntry?.peerDependenciesMeta),
8143
+ resolved: resolveNpmEdges(resolved !== void 0 && resolved !== "" ? resolved : key, entrySections(wsEntry), raw.packages)
7840
8144
  }));
7841
8145
  if (wsEntry) workspaceEntries.set(name, {
7842
8146
  ...wsEntry.dependencies ? { dependencies: wsEntry.dependencies } : {},
@@ -7848,16 +8152,19 @@ const toFields$2 = (raw) => effect.Effect.gen(function* () {
7848
8152
  path: resolved,
7849
8153
  dependencies: wsEntry ? importerDependencies(wsEntry, (s) => ({ specifier: s })) : []
7850
8154
  }));
7851
- } else if (key.startsWith(NODE_MODULES_PREFIX)) {
7852
- const name = key.slice(13);
8155
+ } else {
8156
+ const name = key.slice(nameIndex);
7853
8157
  if (name !== "" && entry.version !== void 0) {
7854
8158
  const integrity = yield* toIntegrityHash(entry.integrity);
7855
8159
  packages.push(ResolvedPackage.make({
7856
8160
  name,
7857
8161
  version: entry.version,
8162
+ instanceId: key,
7858
8163
  ...integrity !== void 0 ? { integrity } : {},
7859
8164
  isWorkspace: false,
7860
- dependencies: entry.dependencies ?? {}
8165
+ dependencies: entry.dependencies ?? {},
8166
+ ...peerDeclarations(entry.peerDependencies, entry.peerDependenciesMeta),
8167
+ resolved: resolveNpmEdges(key, entrySections(entry), raw.packages)
7861
8168
  }));
7862
8169
  }
7863
8170
  }
@@ -15550,7 +15857,7 @@ function deepEqualValues(a, b) {
15550
15857
  return false;
15551
15858
  }
15552
15859
  //#endregion
15553
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/internal/documents.js
15860
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/internal/documents.js
15554
15861
  /**
15555
15862
  * An empty YAML document composes to `null` (`Yaml.parseAll("")` is `[null]`,
15556
15863
  * and the trailing document of an env-only `pnpm-lock.yaml` is `null` too).
@@ -15620,7 +15927,7 @@ const selectSoleDocument = (content) => effect.Effect.gen(function* () {
15620
15927
  };
15621
15928
  });
15622
15929
  //#endregion
15623
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/internal/pnpm.js
15930
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/internal/pnpm.js
15624
15931
  const PnpmImporterDeps = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({
15625
15932
  specifier: effect.Schema.String,
15626
15933
  version: effect.Schema.String
@@ -15631,6 +15938,18 @@ const PnpmImporter = effect.Schema.Struct({
15631
15938
  peerDependencies: PnpmImporterDeps,
15632
15939
  optionalDependencies: PnpmImporterDeps
15633
15940
  });
15941
+ /**
15942
+ * The version gate's own input: `lockfileVersion` and nothing else.
15943
+ *
15944
+ * The gate has to read the version *before* the shape decode, because the
15945
+ * shape it decodes against is the shape of a supported version. `importers` is
15946
+ * a required key here and a pre-v9 single-project lockfile has none — it
15947
+ * records its dependencies at the top level — so a shape-first order reports a
15948
+ * lockfile we reject for being too old as merely malformed instead.
15949
+ *
15950
+ * @internal
15951
+ */
15952
+ const PnpmVersionProbe = effect.Schema.Struct({ lockfileVersion: effect.Schema.Union([effect.Schema.String, effect.Schema.Number]) });
15634
15953
  const PnpmLockfileRaw = effect.Schema.Struct({
15635
15954
  lockfileVersion: effect.Schema.Union([effect.Schema.String, effect.Schema.Number]),
15636
15955
  settings: effect.Schema.optionalKey(effect.Schema.Struct({
@@ -15643,7 +15962,17 @@ const PnpmLockfileRaw = effect.Schema.Struct({
15643
15962
  version: effect.Schema.String
15644
15963
  })])))),
15645
15964
  importers: effect.Schema.Record(effect.Schema.String, PnpmImporter),
15646
- packages: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ resolution: effect.Schema.optionalKey(effect.Schema.Struct({ integrity: effect.Schema.optionalKey(effect.Schema.String) })) })))
15965
+ packages: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({
15966
+ resolution: effect.Schema.optionalKey(effect.Schema.Struct({ integrity: effect.Schema.optionalKey(effect.Schema.String) })),
15967
+ peerDependencies: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String)),
15968
+ peerDependenciesMeta: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ optional: effect.Schema.optionalKey(effect.Schema.Boolean) }))),
15969
+ dependencies: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String)),
15970
+ optionalDependencies: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String))
15971
+ }))),
15972
+ snapshots: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({
15973
+ dependencies: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String)),
15974
+ optionalDependencies: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String))
15975
+ })))
15647
15976
  });
15648
15977
  /**
15649
15978
  * Parse pnpm `pnpm-lock.yaml` content into the unified field bundle.
@@ -15663,10 +15992,142 @@ const PnpmLockfileRaw = effect.Schema.Struct({
15663
15992
  */
15664
15993
  const parsePnpm = (content) => effect.Effect.gen(function* () {
15665
15994
  const { document, documents } = yield* selectPnpmDocument(content);
15995
+ const probe = yield* effect.Schema.decodeUnknownEffect(PnpmVersionProbe)(document).pipe(effect.Effect.mapError(validationFailure));
15996
+ yield* requireLockfileVersion("pnpm", probe.lockfileVersion);
15666
15997
  const validated = yield* effect.Schema.decodeUnknownEffect(PnpmLockfileRaw)(document).pipe(effect.Effect.mapError(validationFailure));
15667
15998
  if (Object.keys(validated.importers).length === 0) return yield* effect.Effect.fail(framingFailure("noImporters", documents));
15668
15999
  return yield* toFields$1(validated);
15669
16000
  });
16001
+ /**
16002
+ * Resolve one instance's outgoing edges to instance ids.
16003
+ *
16004
+ * pnpm names a resolved dependency as `name` → `version`, where the version may
16005
+ * itself carry a peer suffix (`1.6.0(react@17.0.2)`); the referenced instance's
16006
+ * key is those two composed back together. The composition is *verified*
16007
+ * against the lockfile's own key set rather than trusted — the composed key is
16008
+ * v9's bare `name@version` and nothing else, because the format gate admits no
16009
+ * lockfile that spells keys the pre-v9 leading-slash way — and an edge that
16010
+ * matches nothing is **omitted**. That is what keeps a `link:`/`file:`
16011
+ * resolution, which names no instance in this lockfile, from becoming a
16012
+ * plausible lie.
16013
+ *
16014
+ * @internal
16015
+ */
16016
+ const resolveEdges = (sections, instanceIds) => {
16017
+ const edges = /* @__PURE__ */ new Map();
16018
+ const unnameable = /* @__PURE__ */ new Set();
16019
+ for (const section of sections) {
16020
+ if (!section) continue;
16021
+ for (const [name, version] of Object.entries(section)) {
16022
+ if (name === "") continue;
16023
+ if (version.startsWith(LINK_PREFIX)) {
16024
+ const target = resolveLinkTarget("", version.slice(LINK_PREFIX.length));
16025
+ if (target !== void 0 && instanceIds.has(target)) edges.set(name, target);
16026
+ else unnameable.add(name);
16027
+ continue;
16028
+ }
16029
+ const bare = `${name}@${version}`;
16030
+ if (instanceIds.has(bare)) edges.set(name, bare);
16031
+ else unnameable.add(name);
16032
+ }
16033
+ }
16034
+ return {
16035
+ resolved: Object.fromEntries(edges),
16036
+ unresolvedEdges: [...unnameable].sort()
16037
+ };
16038
+ };
16039
+ /** The protocol pnpm records a workspace-directory resolution under. @internal */
16040
+ const LINK_PREFIX = "link:";
16041
+ /**
16042
+ * Normalize a `link:` target against the linking importer's path, so a
16043
+ * workspace edge can name the workspace importer's instance id.
16044
+ * Total: a target that walks above the root yields `undefined`.
16045
+ *
16046
+ * @internal
16047
+ */
16048
+ const resolveLinkTarget = (importerPath, target) => {
16049
+ const segments = [];
16050
+ for (const segment of `${importerPath}/${target}`.split("/")) {
16051
+ if (segment === "" || segment === ".") continue;
16052
+ if (segment === "..") {
16053
+ if (segments.pop() === void 0) return void 0;
16054
+ continue;
16055
+ }
16056
+ segments.push(segment);
16057
+ }
16058
+ return segments.length === 0 ? void 0 : segments.join("/");
16059
+ };
16060
+ /** The specifier protocol pnpm resolves through the workspace itself. @internal */
16061
+ const WORKSPACE_PREFIX = "workspace:";
16062
+ /**
16063
+ * The importer a `link:` target lands INSIDE, longest path first.
16064
+ *
16065
+ * pnpm's `publishConfig.linkDirectory` makes a workspace link point at the
16066
+ * package's publish directory rather than its root — `link:../bundler/dist/dev/pkg`
16067
+ * where `packages/bundler` is the importer — so the target itself is a build
16068
+ * output that is no importer and never will be. The owning importer is the
16069
+ * longest ancestor of the target that IS one; longest-first so a nested importer
16070
+ * beats its parent.
16071
+ *
16072
+ * The root importer (`"."`) is deliberately unreachable here: it is an ancestor
16073
+ * of every path in the workspace, so admitting it would resolve every stray link
16074
+ * to the root rather than leaving it unnamed.
16075
+ *
16076
+ * @internal
16077
+ */
16078
+ const owningImporter = (target, importerPaths) => {
16079
+ const segments = target.split("/");
16080
+ for (let end = segments.length - 1; end > 0; end--) {
16081
+ const candidate = segments.slice(0, end).join("/");
16082
+ if (importerPaths.has(candidate)) return candidate;
16083
+ }
16084
+ };
16085
+ /**
16086
+ * Resolve one importer's outgoing edges. pnpm records `{ specifier, version }`
16087
+ * per importer dependency, where the version is either a registry version (the
16088
+ * instance-id composition {@link resolveEdges} performs) or a `link:` target
16089
+ * naming another importer — normalized against this importer's own path. Both
16090
+ * are checked against the lockfile's instance ids before being emitted.
16091
+ *
16092
+ * A `link:` target that is no importer gets one further chance, and only under
16093
+ * a `workspace:` SPECIFIER: pnpm resolved that edge through the workspace, so
16094
+ * the target directory is known to belong to a workspace package, and
16095
+ * {@link owningImporter} names it. The specifier is what makes this a
16096
+ * resolution rather than a guess — a hand-written `link:../vendor/stub`
16097
+ * specifier names a directory pnpm never claimed was a workspace package, and
16098
+ * attributing it to whichever importer happens to contain it would answer with
16099
+ * the wrong package's peers instead of admitting it could not name the edge.
16100
+ *
16101
+ * The snapshot path ({@link resolveEdges}) deliberately does NOT do this: a
16102
+ * snapshot body records `name: link:<path>` with no specifier beside it, so the
16103
+ * evidence this rule turns on is not available there.
16104
+ *
16105
+ * @internal
16106
+ */
16107
+ const resolveImporterEdges = (importer, importerPath, instanceIds, importerPaths) => {
16108
+ const edges = /* @__PURE__ */ new Map();
16109
+ const unnameable = /* @__PURE__ */ new Set();
16110
+ for (const group of importerDepGroups(importer)) {
16111
+ if (!group) continue;
16112
+ for (const [name, info] of Object.entries(group)) {
16113
+ if (name === "") continue;
16114
+ if (info.version.startsWith(LINK_PREFIX)) {
16115
+ const target = resolveLinkTarget(importerPath, info.version.slice(5));
16116
+ const owner = target === void 0 ? void 0 : instanceIds.has(target) ? target : info.specifier.startsWith(WORKSPACE_PREFIX) ? owningImporter(target, importerPaths) : void 0;
16117
+ if (owner !== void 0) edges.set(name, owner);
16118
+ else unnameable.add(name);
16119
+ continue;
16120
+ }
16121
+ const bare = `${name}@${info.version}`;
16122
+ if (instanceIds.has(bare)) edges.set(name, bare);
16123
+ else unnameable.add(name);
16124
+ }
16125
+ }
16126
+ return {
16127
+ resolved: Object.fromEntries(edges),
16128
+ unresolvedEdges: [...unnameable].sort()
16129
+ };
16130
+ };
15670
16131
  const toVersionMap = (deps) => {
15671
16132
  if (!deps) return void 0;
15672
16133
  return Object.fromEntries(Object.entries(deps).map(([name, info]) => [name, info.specifier]));
@@ -15707,28 +16168,51 @@ const toFields$1 = (raw) => effect.Effect.gen(function* () {
15707
16168
  }
15708
16169
  for (const path of Object.keys(raw.importers)) if (path !== "." && path !== "") workspaceNames.add(path);
15709
16170
  const packages = [];
15710
- for (const importerPath of Object.keys(raw.importers)) {
16171
+ const snapshots = raw.snapshots;
16172
+ const instanceIds = /* @__PURE__ */ new Set([
16173
+ ...snapshots ? Object.keys(snapshots) : [],
16174
+ ...raw.packages ? Object.keys(raw.packages) : [],
16175
+ ...Object.keys(raw.importers)
16176
+ ]);
16177
+ const importerPaths = new Set(Object.keys(raw.importers).filter((path) => path !== "." && path !== ""));
16178
+ const emitted = /* @__PURE__ */ new Set();
16179
+ for (const [importerPath, importer] of Object.entries(raw.importers)) {
15711
16180
  if (importerPath === "." || importerPath === "") continue;
15712
16181
  packages.push(ResolvedPackage.make({
15713
16182
  name: importerPath,
15714
16183
  version: "0.0.0",
16184
+ instanceId: importerPath,
15715
16185
  isWorkspace: true,
15716
- relativePath: importerPath
16186
+ relativePath: importerPath,
16187
+ ...resolveImporterEdges(importer, importerPath, instanceIds, importerPaths)
15717
16188
  }));
15718
16189
  }
15719
- if (raw.packages) for (const [key, pkg] of Object.entries(raw.packages)) {
15720
- const { plain: bare } = splitPeerSuffix(key);
16190
+ const emit = (instanceId, meta, edges) => effect.Effect.gen(function* () {
16191
+ const { plain: bare } = splitPeerSuffix(instanceId);
15721
16192
  const atIndex = bare.lastIndexOf("@");
15722
- if (atIndex <= 0) continue;
16193
+ if (atIndex <= 0) return;
15723
16194
  const name = bare.slice(0, atIndex);
15724
16195
  const version = bare.slice(atIndex + 1);
15725
- const integrity = yield* toIntegrityHash(pkg.resolution?.integrity);
16196
+ const integrity = yield* toIntegrityHash(meta?.resolution?.integrity);
16197
+ emitted.add(instanceId);
15726
16198
  packages.push(ResolvedPackage.make({
15727
16199
  name,
15728
16200
  version,
16201
+ instanceId,
15729
16202
  ...integrity !== void 0 ? { integrity } : {},
15730
- isWorkspace: false
16203
+ isWorkspace: false,
16204
+ ...peerDeclarations(meta?.peerDependencies, meta?.peerDependenciesMeta),
16205
+ ...resolveEdges(edges, instanceIds)
15731
16206
  }));
16207
+ });
16208
+ if (snapshots) for (const [key, snapshot] of Object.entries(snapshots)) {
16209
+ const plain = splitPeerSuffix(key).plain;
16210
+ yield* emit(key, raw.packages !== void 0 && Object.hasOwn(raw.packages, plain) ? raw.packages[plain] : void 0, [snapshot.dependencies, snapshot.optionalDependencies]);
16211
+ }
16212
+ const covered = new Set([...emitted].map((key) => splitPeerSuffix(key).plain));
16213
+ if (raw.packages) for (const [key, pkg] of Object.entries(raw.packages)) {
16214
+ if (covered.has(key)) continue;
16215
+ yield* emit(key, pkg, [pkg.dependencies, pkg.optionalDependencies]);
15732
16216
  }
15733
16217
  const workspaceDependencies = extractWorkspaceDeps(workspaceEntries, workspaceNames);
15734
16218
  const extension = PnpmExtension.make({
@@ -15745,7 +16229,7 @@ const toFields$1 = (raw) => effect.Effect.gen(function* () {
15745
16229
  };
15746
16230
  });
15747
16231
  //#endregion
15748
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/internal/yarn.js
16232
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/internal/yarn.js
15749
16233
  const YarnLockfileRaw = effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown);
15750
16234
  const DepRecord = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
15751
16235
  const YarnEntry = effect.Schema.Struct({
@@ -15754,6 +16238,7 @@ const YarnEntry = effect.Schema.Struct({
15754
16238
  dependencies: DepRecord,
15755
16239
  devDependencies: DepRecord,
15756
16240
  peerDependencies: DepRecord,
16241
+ peerDependenciesMeta: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ optional: effect.Schema.optionalKey(effect.Schema.Boolean) }))),
15757
16242
  optionalDependencies: DepRecord,
15758
16243
  checksum: effect.Schema.optionalKey(effect.Schema.String),
15759
16244
  languageName: effect.Schema.optionalKey(effect.Schema.String),
@@ -15787,6 +16272,13 @@ const toFields = (lockfileVersion, decoded) => effect.Effect.gen(function* () {
15787
16272
  const packages = [];
15788
16273
  const workspaceNames = /* @__PURE__ */ new Set();
15789
16274
  const workspaceEntries = /* @__PURE__ */ new Map();
16275
+ const locators = /* @__PURE__ */ new Map();
16276
+ for (const [key, entry] of decoded) {
16277
+ const descriptors = key.split(", ");
16278
+ const locator = entry.resolution ?? descriptors[0];
16279
+ if (locator === void 0 || locator === "") continue;
16280
+ for (const descriptor of descriptors) if (descriptor !== "") locators.set(descriptor, locator);
16281
+ }
15790
16282
  for (const [key, entry] of decoded) if (entry.linkType === "soft") {
15791
16283
  const name = extractYarnPackageName(key);
15792
16284
  if (name !== void 0) workspaceNames.add(name);
@@ -15797,12 +16289,17 @@ const toFields = (lockfileVersion, decoded) => effect.Effect.gen(function* () {
15797
16289
  const isWorkspace = entry.linkType === "soft";
15798
16290
  const relativePath = isWorkspace ? extractYarnWorkspacePath(key) : void 0;
15799
16291
  const integrity = yield* toIntegrityHash(entry.checksum);
16292
+ const instanceId = entry.resolution ?? key.split(", ")[0] ?? "";
16293
+ if (instanceId === "") continue;
15800
16294
  packages.push(ResolvedPackage.make({
15801
16295
  name,
15802
16296
  version: entry.version ?? "0.0.0",
16297
+ instanceId,
15803
16298
  ...integrity !== void 0 ? { integrity } : {},
15804
16299
  isWorkspace,
15805
- ...relativePath !== void 0 ? { relativePath } : {}
16300
+ ...relativePath !== void 0 ? { relativePath } : {},
16301
+ ...peerDeclarations(entry.peerDependencies, entry.peerDependenciesMeta),
16302
+ ...resolveYarnEdges(entry, locators)
15806
16303
  }));
15807
16304
  if (isWorkspace) {
15808
16305
  const deps = cleanYarnDeps(entry.dependencies);
@@ -15825,6 +16322,46 @@ const toFields = (lockfileVersion, decoded) => effect.Effect.gen(function* () {
15825
16322
  };
15826
16323
  });
15827
16324
  /**
16325
+ * Resolve one entry's outgoing edges through the descriptor→locator index.
16326
+ *
16327
+ * A yarn dependency value is a *descriptor* range (`"npm:5.3.0"`), and the
16328
+ * lockfile keys enumerate exactly which descriptors resolve to which locator,
16329
+ * so the lookup is exact rather than reconstructed.
16330
+ *
16331
+ * **`devDependencies` is not a section a Berry lockfile has.** yarn folds a
16332
+ * workspace's dev declarations into the entry's `dependencies` map — the
16333
+ * lockfile a project produces is byte-identical whether a dependency is
16334
+ * declared under `dependencies` or `devDependencies` (probed against yarn
16335
+ * 4.9.1). Dev edges are therefore already resolved here; iterating
16336
+ * `entry.devDependencies` would be dead code, and the schema keeps the field
16337
+ * only as permissive scaffolding for hand-edited input.
16338
+ *
16339
+ * **Dependency edges only.** yarn resolves peers virtually — a peer-bearing
16340
+ * package gets a `@virtual:` locator per consumer, and this lockfile shape does
16341
+ * not record which one satisfied which peer. Emitting a peer edge here would
16342
+ * mean guessing, so peers are left out: an absent edge is a true statement, a
16343
+ * plausible one would not be.
16344
+ *
16345
+ * @internal
16346
+ */
16347
+ const resolveYarnEdges = (entry, locators) => {
16348
+ const edges = /* @__PURE__ */ new Map();
16349
+ const unnameable = /* @__PURE__ */ new Set();
16350
+ for (const section of [entry.dependencies, entry.optionalDependencies]) {
16351
+ if (!section) continue;
16352
+ for (const [name, range] of Object.entries(section)) {
16353
+ if (name === "") continue;
16354
+ const locator = locators.get(`${name}@${range}`);
16355
+ if (locator !== void 0) edges.set(name, locator);
16356
+ else unnameable.add(name);
16357
+ }
16358
+ }
16359
+ return {
16360
+ resolved: Object.fromEntries(edges),
16361
+ unresolvedEdges: [...unnameable].sort()
16362
+ };
16363
+ };
16364
+ /**
15828
16365
  * Extract the package name from a yarn lockfile key. Handles compound keys
15829
16366
  * (`"a@workspace:*, a@workspace:packages/a"`) via the first descriptor and
15830
16367
  * `@patch:` descriptors (which embed `@npm:` inside). Total: malformed keys
@@ -15868,7 +16405,7 @@ const cleanYarnDeps = (deps) => {
15868
16405
  return Object.fromEntries(Object.entries(deps).map(([name, value]) => [name, value.startsWith("npm:") ? value.slice(4) : value]));
15869
16406
  };
15870
16407
  //#endregion
15871
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/Lockfile.js
16408
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/Lockfile.js
15872
16409
  const EMPTY_IMPORTERS = [];
15873
16410
  /**
15874
16411
  * Failure of `Lockfile.parse`: the given content is not a valid lockfile of
@@ -16040,10 +16577,15 @@ var Lockfile = class Lockfile extends effect.Schema.Class("Lockfile")({
16040
16577
  return ResolvedPackage.make({
16041
16578
  name: realName,
16042
16579
  version: pkg.version,
16580
+ instanceId: pkg.instanceId,
16043
16581
  ...pkg.integrity !== void 0 ? { integrity: pkg.integrity } : {},
16044
16582
  isWorkspace: pkg.isWorkspace,
16045
16583
  relativePath: pkg.relativePath,
16046
- dependencies: pkg.dependencies
16584
+ dependencies: pkg.dependencies,
16585
+ peerDependencies: pkg.peerDependencies,
16586
+ peerDependenciesMeta: pkg.peerDependenciesMeta,
16587
+ resolved: pkg.resolved,
16588
+ unresolvedEdges: pkg.unresolvedEdges
16047
16589
  });
16048
16590
  });
16049
16591
  const workspaceDependencies = this.workspaceDependencies.map((dep) => {
@@ -16112,7 +16654,7 @@ var Lockfile = class Lockfile extends effect.Schema.Class("Lockfile")({
16112
16654
  }
16113
16655
  };
16114
16656
  //#endregion
16115
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.5.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_d53253b32eb6a388ea04dc81d5e132f1/node_modules/@effected/lockfiles/LockfileIntegrity.js
16657
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.6.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__@effected+npm@0.11_b5e24f85b508eca09bd100b8bd2084bb/node_modules/@effected/lockfiles/LockfileIntegrity.js
16116
16658
  /**
16117
16659
  * The minimal manifest shape {@link LockfileIntegrity.compare} checks a
16118
16660
  * lockfile against: a package name plus the four optional dependency maps.
@@ -18925,7 +19467,7 @@ var Package = class Package extends effect.Schema.Class("Package")({
18925
19467
  }
18926
19468
  };
18927
19469
  //#endregion
18928
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspacePackage.js
19470
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspacePackage.js
18929
19471
  const EMPTY$1 = Object.freeze(Object.create(null));
18930
19472
  const EMPTY_MANIFEST = Object.freeze(Object.create(null));
18931
19473
  /**
@@ -19523,7 +20065,7 @@ var Walker$1 = class {
19523
20065
  static findRoot = findRoot$1;
19524
20066
  };
19525
20067
  //#endregion
19526
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceRoot.js
20068
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceRoot.js
19527
20069
  /**
19528
20070
  * The marker filenames {@link WorkspaceRoot} probes for, in priority order.
19529
20071
  *
@@ -19710,7 +20252,7 @@ var WorkspaceRoot = class WorkspaceRoot extends effect.Context.Service()("@effec
19710
20252
  static layerTest = (root) => effect.Layer.effect(WorkspaceRoot, WorkspaceRoot.makeTest(root)).pipe(effect.Layer.provide(effect.Path.layer));
19711
20253
  };
19712
20254
  //#endregion
19713
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/limits.js
20255
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/limits.js
19714
20256
  /**
19715
20257
  * Hard ceiling on directories the enumerator will visit for one pattern set.
19716
20258
  * Guards the pathological case a depth cap alone does not: a wide, shallow
@@ -19728,7 +20270,7 @@ const MAX_ENUMERATION_ENTRIES = 1e5;
19728
20270
  */
19729
20271
  const PRUNED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
19730
20272
  //#endregion
19731
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/traverse.js
20273
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/traverse.js
19732
20274
  /** Directory names never descended into. */
19733
20275
  const isPruned = (entry) => PRUNED_DIRECTORIES.has(entry);
19734
20276
  /** Join root-relative POSIX segments; `""` is the root itself. */
@@ -19818,7 +20360,7 @@ var Traversal = class {
19818
20360
  }
19819
20361
  };
19820
20362
  //#endregion
19821
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/enumerate.js
20363
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/enumerate.js
19822
20364
  /** Strip a trailing slash from `GlobPattern.enumerationPrefix` to get a relative directory. */
19823
20365
  const baseOf = (pattern) => pattern.enumerationPrefix.replace(/\/$/, "");
19824
20366
  /**
@@ -19835,6 +20377,8 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
19835
20377
  if (!isValidMaxDepth(maxDepth)) return yield* effect.Effect.die(/* @__PURE__ */ new Error(`enumerate: ${badMaxDepthMessage(maxDepth)}`));
19836
20378
  const isPackage = (absolute) => fs.exists(path.join(absolute, "package.json")).pipe(effect.Effect.orElseSucceed(() => false));
19837
20379
  const isDirectory = (absolute) => fs.stat(absolute).pipe(effect.Effect.map((info) => info.type === "Directory"), effect.Effect.orElseSucceed(() => false));
20380
+ const excludes = globs.excludes;
20381
+ const isExcluded = excludes.length === 0 ? (_) => false : (relative) => excludes.some((exclude) => exclude.matches(relative));
19838
20382
  const included = /* @__PURE__ */ new Map();
19839
20383
  /** A shared-traversal stop, materialized as this module's failure record. */
19840
20384
  const failureOf = (stop, pattern) => ({
@@ -19843,6 +20387,7 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
19843
20387
  detail: stop.detail
19844
20388
  });
19845
20389
  for (const literal of globs.literals) {
20390
+ if (isExcluded(literal)) continue;
19846
20391
  const absolute = path.join(root, literal);
19847
20392
  if (yield* isPackage(absolute)) included.set(literal, absolute);
19848
20393
  }
@@ -19870,25 +20415,22 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
19870
20415
  const absolute = path.join(frame.absolute, entry);
19871
20416
  if (!(yield* isDirectory(absolute))) continue;
19872
20417
  if (wildcard.crossesSegments && !traversal.admits(frame)) return yield* effect.Effect.fail(failureOf(traversal.depthStop(), wildcard.source));
19873
- if (wildcard.matches(relative) && (yield* isPackage(absolute))) included.set(relative, absolute);
20418
+ if (wildcard.matches(relative) && !isExcluded(relative) && (yield* isPackage(absolute))) included.set(relative, absolute);
19874
20419
  if (!wildcard.crossesSegments) continue;
19875
20420
  traversal.push(frame, relative, absolute);
19876
20421
  }
19877
20422
  }
19878
20423
  }
19879
20424
  const results = [];
19880
- for (const [relativePath, absolute] of included) {
19881
- if (globs.excludes.some((exclude) => exclude.matches(relativePath))) continue;
19882
- results.push({
19883
- relativePath,
19884
- path: absolute
19885
- });
19886
- }
20425
+ for (const [relativePath, absolute] of included) results.push({
20426
+ relativePath,
20427
+ path: absolute
20428
+ });
19887
20429
  results.sort((a, b) => a.relativePath < b.relativePath ? -1 : a.relativePath > b.relativePath ? 1 : 0);
19888
20430
  return results;
19889
20431
  });
19890
20432
  //#endregion
19891
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/patterns.js
20433
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/patterns.js
19892
20434
  const stringsOf = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : void 0;
19893
20435
  /** The `packages:` list of a `pnpm-workspace.yaml` document. Total on a parsed document. */
19894
20436
  const pnpmPatternsOf = (document) => {
@@ -19945,7 +20487,7 @@ const readPatterns = (root) => effect.Effect.gen(function* () {
19945
20487
  return manifestPatternsOf(manifest);
19946
20488
  });
19947
20489
  //#endregion
19948
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceDiscovery.js
20490
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceDiscovery.js
19949
20491
  /**
19950
20492
  * Raised when a workspace member's `package.json` cannot be read, parsed, or
19951
20493
  * used — it is missing, malformed, or lacks a `name` or `version`.
@@ -20401,7 +20943,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
20401
20943
  };
20402
20944
  const isStringRecord$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
20403
20945
  //#endregion
20404
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/DependencyGraph.js
20946
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/DependencyGraph.js
20405
20947
  /**
20406
20948
  * Raised when the workspace dependency graph cannot be topologically ordered
20407
20949
  * because it contains a cycle.
@@ -24097,7 +24639,7 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
24097
24639
  static layerTest = (overrides = {}) => effect.Layer.succeed(Git, Git.makeTest(overrides));
24098
24640
  };
24099
24641
  //#endregion
24100
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/ChangeDetector.js
24642
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/ChangeDetector.js
24101
24643
  /**
24102
24644
  * Which git refs to compare, and whether to fold in the working tree.
24103
24645
  *
@@ -24353,7 +24895,7 @@ function resolveFromCatalog(catalogs, wantedDependency) {
24353
24895
  };
24354
24896
  }
24355
24897
  //#endregion
24356
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/catalogs.js
24898
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/catalogs.js
24357
24899
  /** Project a pnpm-workspace manifest's `catalog` / `catalogs` fields into a `Catalogs` map. */
24358
24900
  const inlineCatalogs = (manifest) => {
24359
24901
  if (manifest.catalog === void 0 && manifest.catalogs === void 0) return {};
@@ -24416,8 +24958,12 @@ const rangeOf = (catalogs, dependency, specifier) => {
24416
24958
  unused: () => void 0
24417
24959
  });
24418
24960
  };
24419
- //#endregion
24420
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/ConfigDependencyHooks.js
24961
+ /** Internal alias, kept short at the many call sites in this module. */
24962
+ const NO_PEER_RULES = Object.freeze({
24963
+ allowedVersions: Object.freeze({}),
24964
+ ignoreMissing: Object.freeze([]),
24965
+ allowAny: Object.freeze([])
24966
+ });
24421
24967
  /** Whether `value` is a non-null, non-array object. */
24422
24968
  const isObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
24423
24969
  /**
@@ -24445,7 +24991,7 @@ const moduleNotFoundUrl = (cause) => isObject$2(cause) && cause.code === "ERR_MO
24445
24991
  */
24446
24992
  const hasTraversalSegment = (name) => name.split(/[/\\]/).includes("..");
24447
24993
  /** Turn the seed record into the pnpm hook config, with the default catalog split out under `catalog`. */
24448
- const seedToConfig = (seed) => {
24994
+ const seedToConfig = (seed, rules) => {
24449
24995
  const catalogs = {};
24450
24996
  let catalog = {};
24451
24997
  for (const [name, entries] of Object.entries(seed)) if (name === "default") catalog = { ...entries };
@@ -24454,7 +25000,8 @@ const seedToConfig = (seed) => {
24454
25000
  catalog,
24455
25001
  catalogs,
24456
25002
  minimumReleaseAge: void 0,
24457
- minimumReleaseAgeExclude: void 0
25003
+ minimumReleaseAgeExclude: void 0,
25004
+ peerDependencyRules: rules
24458
25005
  };
24459
25006
  };
24460
25007
  /** A finite number if `value` is one, else the prior threaded value — a garbage age is dropped, not fatal. */
@@ -24479,10 +25026,33 @@ const configOf = (value, fallback) => {
24479
25026
  catalog: isObject$2(value.catalog) ? value.catalog : fallback.catalog,
24480
25027
  catalogs: isObject$2(value.catalogs) ? value.catalogs : fallback.catalogs,
24481
25028
  minimumReleaseAge: finiteNumberOr(value.minimumReleaseAge, fallback.minimumReleaseAge),
24482
- minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude)
25029
+ minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude),
25030
+ peerDependencyRules: peerRulesOr(value.peerDependencyRules, fallback.peerDependencyRules)
24483
25031
  };
24484
25032
  };
24485
25033
  /**
25034
+ * A peer-rules block if `value` is one, else the prior threaded value — a
25035
+ * malformed block is dropped, not fatal, matching the other slices.
25036
+ *
25037
+ * Each axis is normalized independently: a hook that rewrites `allowedVersions`
25038
+ * and leaves `ignoreMissing` alone must not blank the latter.
25039
+ */
25040
+ const stringRecordOr = (value, fallback) => isObject$2(value) && Object.values(value).every((entry) => typeof entry === "string") ? value : fallback;
25041
+ const peerRulesOr = (value, fallback) => {
25042
+ if (!isObject$2(value)) return fallback;
25043
+ const allowed = stringRecordOr(value.allowedVersions, fallback?.allowedVersions);
25044
+ const ignoreMissing = stringArrayOr(value.ignoreMissing, fallback?.ignoreMissing);
25045
+ const allowAny = stringArrayOr(value.allowAny, fallback?.allowAny);
25046
+ if (allowed === void 0 && ignoreMissing === void 0 && allowAny === void 0) return fallback;
25047
+ return {
25048
+ allowedVersions: allowed ?? {},
25049
+ ignoreMissing: ignoreMissing ?? [],
25050
+ allowAny: allowAny ?? []
25051
+ };
25052
+ };
25053
+ /** Project the threaded config's rules into the slice, defaulting every axis to empty. */
25054
+ const peerRulesOf = (config) => config.peerDependencyRules ?? NO_PEER_RULES;
25055
+ /**
24486
25056
  * Project the threaded config's release-age keys into a partial gate
24487
25057
  * contribution, omitting a key the hooks never set (never an explicit
24488
25058
  * `undefined` — the fields are `optionalKey`).
@@ -24535,13 +25105,23 @@ const updateConfigOf = (mod) => {
24535
25105
  * noise on stdout.
24536
25106
  */
24537
25107
  const REPLAY_SCRIPT = `
24538
- const [root, seedJson, ...names] = process.argv.slice(1);
25108
+ const [root, seedJson, rulesJson, ...names] = process.argv.slice(1);
24539
25109
  const { pathToFileURL } = await import("node:url");
24540
25110
  const { join } = await import("node:path");
24541
25111
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
24542
25112
  const finiteNumberOr = (value, fallback) => (typeof value === "number" && Number.isFinite(value) ? value : fallback);
24543
25113
  const stringArrayOr = (value, fallback) =>
24544
25114
  Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : fallback;
25115
+ const stringRecordOr = (value, fallback) =>
25116
+ isObject(value) && Object.values(value).every((entry) => typeof entry === "string") ? value : fallback;
25117
+ const peerRulesOr = (value, fallback) => {
25118
+ if (!isObject(value)) return fallback;
25119
+ const allowed = stringRecordOr(value.allowedVersions, fallback && fallback.allowedVersions);
25120
+ const ignoreMissing = stringArrayOr(value.ignoreMissing, fallback && fallback.ignoreMissing);
25121
+ const allowAny = stringArrayOr(value.allowAny, fallback && fallback.allowAny);
25122
+ if (allowed === undefined && ignoreMissing === undefined && allowAny === undefined) return fallback;
25123
+ return { allowedVersions: allowed || {}, ignoreMissing: ignoreMissing || [], allowAny: allowAny || [] };
25124
+ };
24545
25125
  const configOf = (value, fallback) =>
24546
25126
  isObject(value)
24547
25127
  ? {
@@ -24549,6 +25129,7 @@ const configOf = (value, fallback) =>
24549
25129
  catalogs: isObject(value.catalogs) ? value.catalogs : fallback.catalogs,
24550
25130
  minimumReleaseAge: finiteNumberOr(value.minimumReleaseAge, fallback.minimumReleaseAge),
24551
25131
  minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude),
25132
+ peerDependencyRules: peerRulesOr(value.peerDependencyRules, fallback.peerDependencyRules),
24552
25133
  }
24553
25134
  : fallback;
24554
25135
  const failure = (name, cause) => ({
@@ -24564,7 +25145,13 @@ const replay = async () => {
24564
25145
  if (name === "default") catalog = { ...entries };
24565
25146
  else catalogs[name] = { ...entries };
24566
25147
  }
24567
- let config = { catalog, catalogs, minimumReleaseAge: undefined, minimumReleaseAgeExclude: undefined };
25148
+ let config = {
25149
+ catalog,
25150
+ catalogs,
25151
+ minimumReleaseAge: undefined,
25152
+ minimumReleaseAgeExclude: undefined,
25153
+ peerDependencyRules: JSON.parse(rulesJson),
25154
+ };
24568
25155
  for (const name of names) {
24569
25156
  let loaded;
24570
25157
  let found = false;
@@ -24665,9 +25252,10 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24665
25252
  * config dependency. The default {@link WorkspaceCatalogs} layer wires this, so
24666
25253
  * the default catalog path provably executes no config-dependency code.
24667
25254
  */
24668
- static layerNoop = effect.Layer.succeed(ConfigDependencyHooks, { inject: (_root, _configDependencies, seed) => effect.Effect.succeed({
25255
+ static layerNoop = effect.Layer.succeed(ConfigDependencyHooks, { inject: (_root, _configDependencies, seed, rules) => effect.Effect.succeed({
24669
25256
  catalogs: seed,
24670
- releaseAge: {}
25257
+ releaseAge: {},
25258
+ peerDependencyRules: rules ?? NO_PEER_RULES
24671
25259
  }) });
24672
25260
  /**
24673
25261
  * The live layer: dynamically imports each config dependency's `pnpmfile.cjs`
@@ -24685,13 +25273,14 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24685
25273
  * import, so this layer runs on either runtime. Only ever wired by
24686
25274
  * `WorkspaceCatalogs.layerWithConfigDependencies`.
24687
25275
  */
24688
- static layerLive = effect.Layer.succeed(ConfigDependencyHooks, { inject: (root, configDependencies, seed) => effect.Effect.gen(function* () {
25276
+ static layerLive = effect.Layer.succeed(ConfigDependencyHooks, { inject: (root, configDependencies, seed, rules) => effect.Effect.gen(function* () {
24689
25277
  const names = Object.keys(configDependencies);
24690
25278
  if (names.length === 0) return {
24691
25279
  catalogs: seed,
24692
- releaseAge: {}
25280
+ releaseAge: {},
25281
+ peerDependencyRules: rules ?? NO_PEER_RULES
24693
25282
  };
24694
- let config = seedToConfig(seed);
25283
+ let config = seedToConfig(seed, rules);
24695
25284
  for (const name of names) {
24696
25285
  if (hasTraversalSegment(name)) return yield* effect.Effect.fail(new CatalogAssemblyError({
24697
25286
  source: "hooks",
@@ -24737,7 +25326,8 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24737
25326
  }
24738
25327
  return {
24739
25328
  catalogs: configToEntries(config),
24740
- releaseAge: releaseAgeOf(config)
25329
+ releaseAge: releaseAgeOf(config),
25330
+ peerDependencyRules: peerRulesOf(config)
24741
25331
  };
24742
25332
  }) });
24743
25333
  /**
@@ -24793,11 +25383,12 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24793
25383
  */
24794
25384
  static layerSubprocess = effect.Layer.effect(ConfigDependencyHooks, effect.Effect.gen(function* () {
24795
25385
  const spawner = yield* effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner;
24796
- return { inject: (root, configDependencies, seed) => effect.Effect.gen(function* () {
25386
+ return { inject: (root, configDependencies, seed, rules) => effect.Effect.gen(function* () {
24797
25387
  const names = Object.keys(configDependencies);
24798
25388
  if (names.length === 0) return {
24799
25389
  catalogs: seed,
24800
- releaseAge: {}
25390
+ releaseAge: {},
25391
+ peerDependencyRules: rules ?? NO_PEER_RULES
24801
25392
  };
24802
25393
  for (const name of names) if (hasTraversalSegment(name)) return yield* effect.Effect.fail(new CatalogAssemblyError({
24803
25394
  source: "hooks",
@@ -24810,6 +25401,7 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24810
25401
  REPLAY_SCRIPT,
24811
25402
  root,
24812
25403
  JSON.stringify(seed),
25404
+ JSON.stringify(rules ?? NO_PEER_RULES),
24813
25405
  ...names
24814
25406
  ]);
24815
25407
  const payload = yield* Run.jsonLine(command, ReplayPayload, { timeout: REPLAY_TIMEOUT }).pipe(effect.Effect.provideService(effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner, spawner), effect.Effect.catch((cause) => effect.Effect.fail(new CatalogAssemblyError({
@@ -24822,16 +25414,17 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24822
25414
  path: payload.name ?? root,
24823
25415
  cause: replayFailureCause(payload)
24824
25416
  }));
24825
- const config = configOf(payload.config, seedToConfig(seed));
25417
+ const config = configOf(payload.config, seedToConfig(seed, rules));
24826
25418
  return {
24827
25419
  catalogs: configToEntries(config),
24828
- releaseAge: releaseAgeOf(config)
25420
+ releaseAge: releaseAgeOf(config),
25421
+ peerDependencyRules: peerRulesOf(config)
24829
25422
  };
24830
25423
  }) };
24831
25424
  }));
24832
25425
  };
24833
25426
  //#endregion
24834
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/PackageManagerName.js
25427
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/PackageManagerName.js
24835
25428
  /**
24836
25429
  * The four package managers this package understands.
24837
25430
  *
@@ -25206,7 +25799,7 @@ var PackageManagerDetector = class PackageManagerDetector extends effect.Context
25206
25799
  static layerTest = (overrides = {}) => effect.Layer.succeed(PackageManagerDetector, PackageManagerDetector.makeTest(overrides));
25207
25800
  };
25208
25801
  //#endregion
25209
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/LockfileReader.js
25802
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/LockfileReader.js
25210
25803
  /**
25211
25804
  * Raised when the workspace's lockfile cannot be read off disk.
25212
25805
  *
@@ -25386,7 +25979,7 @@ var LockfileReader = class LockfileReader extends effect.Context.Service()("@eff
25386
25979
  static layerTest = (overrides = {}) => effect.Layer.succeed(LockfileReader, LockfileReader.makeTest(overrides));
25387
25980
  };
25388
25981
  //#endregion
25389
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/Publishability.js
25982
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/Publishability.js
25390
25983
  /** The public npm registry, used when `publishConfig.registry` says nothing. */
25391
25984
  const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
25392
25985
  /**
@@ -25545,7 +26138,7 @@ var PublishabilityDetector = class extends effect.Context.Service()("@effected/w
25545
26138
  static layerNone = effect.Layer.succeed(this, this.none);
25546
26139
  };
25547
26140
  //#endregion
25548
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/importerVersions.js
26141
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/internal/importerVersions.js
25549
26142
  /**
25550
26143
  * Strip pnpm's peer-disambiguation suffix from a recorded importer version.
25551
26144
  *
@@ -25631,7 +26224,7 @@ const unanimousVersionOf = (index, dependency) => {
25631
26224
  return agreed;
25632
26225
  };
25633
26226
  //#endregion
25634
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceCatalogs.js
26227
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceCatalogs.js
25635
26228
  /**
25636
26229
  * An immutable, fully-normalized catalog collection — the one catalog
25637
26230
  * resolution semantic in the package.
@@ -25835,6 +26428,41 @@ const inlineReleaseAge = (document) => {
25835
26428
  cause
25836
26429
  })));
25837
26430
  };
26431
+ /**
26432
+ * The `peerDependencyRules` a `pnpm-workspace.yaml` declares inline — the half
26433
+ * `pnpm:export` materializes into the file, as opposed to the half a config
26434
+ * dependency injects at replay time.
26435
+ *
26436
+ * @remarks
26437
+ * **Tolerant, unlike the catalog blocks**, and the asymmetry is deliberate: a
26438
+ * malformed catalog block must hard-fail because a silently-empty catalog makes
26439
+ * every dependency look newly added, whereas a malformed rules block costs only
26440
+ * suppression — the failure mode is reporting a peer pnpm would have hidden,
26441
+ * which is visible and safe. Failing the whole assembly over it would take the
26442
+ * catalogs down with it.
26443
+ *
26444
+ * Every axis is read independently, so a malformed `ignoreMissing` does not
26445
+ * discard a well-formed `allowedVersions`.
26446
+ */
26447
+ const EMPTY_PEER_RULES = {
26448
+ allowedVersions: {},
26449
+ ignoreMissing: [],
26450
+ allowAny: []
26451
+ };
26452
+ const inlinePeerDependencyRules = (document) => {
26453
+ if (!isObject$1(document) || !isObject$1(document.peerDependencyRules)) return EMPTY_PEER_RULES;
26454
+ const block = document.peerDependencyRules;
26455
+ const allowedVersions = {};
26456
+ if (isObject$1(block.allowedVersions)) {
26457
+ for (const [key, value] of Object.entries(block.allowedVersions)) if (typeof value === "string") allowedVersions[key] = value;
26458
+ }
26459
+ const strings = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
26460
+ return {
26461
+ allowedVersions,
26462
+ ignoreMissing: strings(block.ignoreMissing),
26463
+ allowAny: strings(block.allowAny)
26464
+ };
26465
+ };
25838
26466
  /** A hard-fail catalog-assembly failure naming the malformed part of a `workspaces` field. */
25839
26467
  const malformed = (source, path, detail) => new CatalogAssemblyError({
25840
26468
  source,
@@ -25967,6 +26595,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
25967
26595
  let injected;
25968
26596
  let inlineGate = {};
25969
26597
  let hookGate = {};
26598
+ let peerDependencyRules = EMPTY_PEER_RULES;
25970
26599
  if (hasPnpmWorkspace) {
25971
26600
  const text = yield* fs.readFileString(workspaceYaml).pipe(effect.Effect.mapError((cause) => new CatalogAssemblyError({
25972
26601
  source: "manifest",
@@ -25981,15 +26610,17 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
25981
26610
  yield* validatePnpmWorkspaceCatalogs(document);
25982
26611
  inline = CatalogSet.fromCatalogs(inlineCatalogs(catalogBlocksOf(document)));
25983
26612
  inlineGate = yield* inlineReleaseAge(document);
25984
- const injection = yield* hooks.inject(root, configDependenciesOf(document), inline.entries);
26613
+ const injection = yield* hooks.inject(root, configDependenciesOf(document), inline.entries, inlinePeerDependencyRules(document));
25985
26614
  injected = CatalogSet.fromCatalogs(injection.catalogs);
25986
26615
  hookGate = injection.releaseAge;
26616
+ peerDependencyRules = injection.peerDependencyRules;
25987
26617
  } else {
25988
26618
  const manifestPath = path.join(root, "package.json");
25989
26619
  if (!(yield* probeExists(manifestPath))) return {
25990
26620
  catalogs: fromLockfile,
25991
26621
  releaseAgeGate: ReleaseAgeGate.combine(),
25992
- importerVersions
26622
+ importerVersions,
26623
+ peerDependencyRules: EMPTY_PEER_RULES
25993
26624
  };
25994
26625
  const text = yield* fs.readFileString(manifestPath).pipe(effect.Effect.mapError((cause) => new CatalogAssemblyError({
25995
26626
  source: "manifest",
@@ -26009,7 +26640,8 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
26009
26640
  return {
26010
26641
  catalogs: assembled,
26011
26642
  releaseAgeGate,
26012
- importerVersions
26643
+ importerVersions,
26644
+ peerDependencyRules
26013
26645
  };
26014
26646
  });
26015
26647
  const [resolveOnce, invalidate] = yield* effect.Effect.cachedInvalidateWithTTL(assemble, effect.Duration.infinity);
@@ -26021,6 +26653,9 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
26021
26653
  resolveSpecifier: effect.Effect.fn("WorkspaceCatalogs.resolveSpecifier")(function* (dependency, specifier) {
26022
26654
  return (yield* memo).catalogs.resolveSpecifier(dependency, specifier);
26023
26655
  }),
26656
+ peerDependencyRules: effect.Effect.fn("WorkspaceCatalogs.peerDependencyRules")(function* () {
26657
+ return (yield* memo).peerDependencyRules;
26658
+ }),
26024
26659
  releaseAgeGate: effect.Effect.fn("WorkspaceCatalogs.releaseAgeGate")(function* () {
26025
26660
  return (yield* memo).releaseAgeGate;
26026
26661
  }),
@@ -26107,6 +26742,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
26107
26742
  return {
26108
26743
  set: () => unstubbed$1("set"),
26109
26744
  resolveSpecifier: set !== void 0 ? (dependency, specifier) => effect.Effect.map(set(), (catalogs) => catalogs.resolveSpecifier(dependency, specifier)) : () => unstubbed$1("resolveSpecifier"),
26745
+ peerDependencyRules: () => unstubbed$1("peerDependencyRules"),
26110
26746
  releaseAgeGate: () => unstubbed$1("releaseAgeGate"),
26111
26747
  importerVersions: () => unstubbed$1("importerVersions"),
26112
26748
  ...overrides
@@ -26158,7 +26794,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
26158
26794
  }));
26159
26795
  };
26160
26796
  //#endregion
26161
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
26797
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
26162
26798
  const EMPTY = Object.freeze(Object.create(null));
26163
26799
  const DependencyMap = effect.Schema.Record(effect.Schema.String, effect.Schema.String).pipe(effect.Schema.withDecodingDefaultKey(effect.Effect.succeed(EMPTY)), effect.Schema.withConstructorDefault(effect.Effect.succeed(EMPTY)));
26164
26800
  /**
@@ -26381,7 +27017,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
26381
27017
  }
26382
27018
  };
26383
27019
  //#endregion
26384
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceSnapshots.js
27020
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/WorkspaceSnapshots.js
26385
27021
  /** Whether `value` is a non-null, non-array object. */
26386
27022
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
26387
27023
  /** Whether every value in a record is a string — a usable dependency map. */
@@ -26658,7 +27294,7 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends effect.Context.Service
26658
27294
  static layerTest = (overrides = {}) => effect.Layer.succeed(WorkspaceSnapshots, WorkspaceSnapshots.makeTest(overrides));
26659
27295
  };
26660
27296
  //#endregion
26661
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.14.2_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/Workspaces.js
27297
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.15.1_@effected+jsonc@0.7.0_effect@4.0.0-rc.109__effect@4.0.0-rc.109/node_modules/@effected/workspaces/Workspaces.js
26662
27298
  const compose = (options, catalogsFactory) => {
26663
27299
  const roots = WorkspaceRoot.layer;
26664
27300
  const detector = PackageManagerDetector.layer;