@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.
@@ -2339,7 +2339,7 @@ var GlobSet = class GlobSet extends effect.Schema.Class("GlobSet")(effect.Schema
2339
2339
  }
2340
2340
  };
2341
2341
  //#endregion
2342
- //#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
2342
+ //#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
2343
2343
  /**
2344
2344
  * Extension data specific to bun lockfiles, attached to `Lockfile.extension`
2345
2345
  * when the format is `"bun"`.
@@ -4143,7 +4143,7 @@ input: effect.Schema.String }) {
4143
4143
  }
4144
4144
  };
4145
4145
  const CATALOG_PREFIX = "catalog:";
4146
- const WORKSPACE_PREFIX = "workspace:";
4146
+ const WORKSPACE_PREFIX$1 = "workspace:";
4147
4147
  const isBarePath = (value) => value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.startsWith("/");
4148
4148
  const isGitHubShorthand = (value) => !value.startsWith(".") && !value.startsWith("~") && !value.startsWith("/") && /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(#.*)?$/.test(value);
4149
4149
  const isGit = (value) => value.startsWith("git+") || value.startsWith("git://") || value.startsWith("github:") || value.startsWith("gist:") || value.startsWith("bitbucket:") || value.startsWith("gitlab:") || isGitHubShorthand(value);
@@ -4151,7 +4151,7 @@ const isLocal = (value) => value.startsWith("file:") || value.startsWith("link:"
4151
4151
  const isLink = (value) => value.startsWith("link:");
4152
4152
  const isPortal = (value) => value.startsWith("portal:");
4153
4153
  const isCatalog = (value) => value.startsWith(CATALOG_PREFIX);
4154
- const isWorkspace = (value) => value.startsWith(WORKSPACE_PREFIX);
4154
+ const isWorkspace = (value) => value.startsWith(WORKSPACE_PREFIX$1);
4155
4155
  const isUrl$1 = (value) => value.startsWith("http://") || value.startsWith("https://");
4156
4156
  const parseRange = (value) => {
4157
4157
  const exit = effect.Schema.decodeUnknownExit(Range$2.FromString)(value);
@@ -4160,7 +4160,7 @@ const parseRange = (value) => {
4160
4160
  const isRange = (value) => effect.Option.isSome(parseRange(value));
4161
4161
  const protocolOf = (value) => {
4162
4162
  if (value.startsWith(CATALOG_PREFIX)) return "catalog";
4163
- if (value.startsWith(WORKSPACE_PREFIX)) return "workspace";
4163
+ if (value.startsWith(WORKSPACE_PREFIX$1)) return "workspace";
4164
4164
  if (value.startsWith("link:")) return "link";
4165
4165
  if (value.startsWith("portal:")) return "portal";
4166
4166
  if (value.startsWith("file:") || isBarePath(value)) return "file";
@@ -5573,7 +5573,7 @@ var ReleaseAgeGate = class ReleaseAgeGate extends effect.Schema.Class("ReleaseAg
5573
5573
  }
5574
5574
  };
5575
5575
  //#endregion
5576
- //#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
5576
+ //#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
5577
5577
  /**
5578
5578
  * One declared dependency of one workspace importer, as the lockfile records it.
5579
5579
  *
@@ -5611,7 +5611,7 @@ var ImporterDependency = class extends effect.Schema.Class("ImporterDependency")
5611
5611
  depType: DependencyField
5612
5612
  }) {};
5613
5613
  //#endregion
5614
- //#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
5614
+ //#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
5615
5615
  /**
5616
5616
  * One workspace importer's declared dependencies, as the lockfile records them.
5617
5617
  *
@@ -5635,14 +5635,23 @@ var LockfileImporter = class extends effect.Schema.Class("LockfileImporter")({
5635
5635
  dependencies: effect.Schema.Array(ImporterDependency)
5636
5636
  }) {};
5637
5637
  //#endregion
5638
- //#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
5638
+ //#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
5639
5639
  const EMPTY_DEPENDENCIES = {};
5640
+ const EMPTY_PEER_META = {};
5641
+ const EMPTY_EDGE_NAMES = [];
5640
5642
  /**
5641
5643
  * A package resolved from a lockfile.
5642
5644
  *
5643
5645
  * @remarks
5644
5646
  * The common shape every format's entries normalize into:
5645
5647
  *
5648
+ * - `instanceId` — the lockfile-native identity of this *instance*, verbatim:
5649
+ * pnpm's snapshot key (`react-dom@18.3.1(react@17.0.2)`), npm's full entry
5650
+ * key (`node_modules/express/node_modules/debug`), bun's `packages` key
5651
+ * (`@acme/lib/react-dom`) or yarn's locator (`react-dom@npm:18.3.1`). It is
5652
+ * **opaque** — no scheme is synthesized and none should be parsed by a
5653
+ * consumer; it exists so `resolved` can name an instance, and so two
5654
+ * peer-resolved variants of one `name@version` stay distinguishable.
5646
5655
  * - `name` — the resolved package name. For pnpm *workspace* packages
5647
5656
  * straight out of `Lockfile.parse` this is the importer path until
5648
5657
  * `Lockfile#withImporterNames` rewrites it.
@@ -5658,19 +5667,65 @@ const EMPTY_DEPENDENCIES = {};
5658
5667
  * packages, when the lockfile records one.
5659
5668
  * - `dependencies` — the package's own dependency map, defaulting to `{}`
5660
5669
  * both at construction and when decoding serialized data.
5670
+ * - `peerDependencies` — the package's *declared* peer ranges, keyed by peer
5671
+ * name. Every format records them (pnpm and npm as their own section, bun
5672
+ * inline in the package tuple's info object, yarn Berry as an entry
5673
+ * section), so this is populated across all four. Declarations only: what
5674
+ * the package *asks for*, never what actually resolved.
5675
+ * - `peerDependenciesMeta` — the per-peer flags, normalized to
5676
+ * `{ optional: boolean }`. bun spells optional peers as an `optionalPeers`
5677
+ * array of names rather than a meta object; that spelling is normalized
5678
+ * into this shape so one consumer algorithm serves every format. A peer
5679
+ * with no meta entry is required.
5680
+ * - `resolved` — this instance's *outgoing edges*: dependency (and, where the
5681
+ * format records it, peer) name → the `instanceId` that name actually
5682
+ * resolved to in this instance's context. This is the answer to "which
5683
+ * concrete version of P did X get", which `peerDependencies` deliberately
5684
+ * does not answer.
5685
+ *
5686
+ * Every entry is **verified**: an edge is emitted only when the composed or
5687
+ * walked-up identity matches a real instance in the same lockfile. An edge
5688
+ * that cannot be resolved honestly is *omitted*, never guessed — a wrong
5689
+ * resolved edge is a silent wrong answer, an absent one is a visible gap.
5690
+ * yarn records peer resolution virtually and is therefore dependency-edges
5691
+ * only.
5692
+ *
5693
+ * - `unresolvedEdges` — dependency names whose edge the lockfile **records**
5694
+ * but this model could not name: a `link:` target that is not a workspace
5695
+ * importer, a composed identity matching no instance. It is the companion
5696
+ * `resolved` needs to be honest, because an absent key in `resolved` would
5697
+ * otherwise mean two different things — "nothing is there" and "something is
5698
+ * there that I could not name" — and a consumer reading the first meaning
5699
+ * for the second turns this package's gap into its own false positive.
5700
+ *
5701
+ * A dependency the lockfile simply does not record is **not** an unresolved
5702
+ * edge; it is an absence, and must not appear here. npm and bun contribute
5703
+ * nothing at all: their sections are *declarations* resolved positionally, so
5704
+ * "the walk found nothing" is genuine absence. A fail-closed signal that is
5705
+ * always on is a signal nobody reads.
5706
+ *
5707
+ * All four record fields — `dependencies`, `peerDependencies`,
5708
+ * `peerDependenciesMeta` and `resolved` — default to `{}` at construction and
5709
+ * when decoding, and `unresolvedEdges` defaults to `[]`. An absent section is
5710
+ * therefore an empty collection, never `undefined`.
5661
5711
  *
5662
5712
  * @public
5663
5713
  */
5664
5714
  var ResolvedPackage = class extends effect.Schema.Class("ResolvedPackage")({
5665
5715
  name: effect.Schema.NonEmptyString,
5666
5716
  version: effect.Schema.String,
5717
+ instanceId: effect.Schema.NonEmptyString,
5667
5718
  integrity: effect.Schema.optionalKey(IntegrityHash),
5668
5719
  isWorkspace: effect.Schema.Boolean,
5669
5720
  relativePath: effect.Schema.optionalKey(effect.Schema.String),
5670
- 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)))
5721
+ 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))),
5722
+ 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))),
5723
+ 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))),
5724
+ 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))),
5725
+ 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)))
5671
5726
  }) {};
5672
5727
  //#endregion
5673
- //#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
5728
+ //#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
5674
5729
  /**
5675
5730
  * A directed dependency edge between two workspace packages as recorded in
5676
5731
  * the lockfile.
@@ -5692,7 +5747,7 @@ var WorkspaceDependency = class extends effect.Schema.Class("WorkspaceDependency
5692
5747
  constraint: effect.Schema.String
5693
5748
  }) {};
5694
5749
  //#endregion
5695
- //#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
5750
+ //#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
5696
5751
  /**
5697
5752
  * Extension data specific to pnpm lockfiles, attached to `Lockfile.extension`
5698
5753
  * when the format is `"pnpm"`.
@@ -5717,10 +5772,10 @@ var PnpmExtension = class extends effect.Schema.Class("PnpmExtension")({
5717
5772
  }))
5718
5773
  }) {};
5719
5774
  //#endregion
5720
- //#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
5775
+ //#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
5721
5776
  /**
5722
5777
  * The lockfile formats this package parses: bun's `bun.lock` (JSONC), npm's
5723
- * `package-lock.json` (v2/v3 JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
5778
+ * `package-lock.json` (JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
5724
5779
  * `yarn.lock` (both YAML).
5725
5780
  *
5726
5781
  * @remarks
@@ -5729,6 +5784,10 @@ var PnpmExtension = class extends effect.Schema.Class("PnpmExtension")({
5729
5784
  * Berry only; classic (v1) `yarn.lock` is not YAML and fails
5730
5785
  * `Lockfile.parse` with a typed `LockfileParseError`.
5731
5786
  *
5787
+ * The format literal says nothing about which *versions* of that format are
5788
+ * supported: pnpm `lockfileVersion` 9+ and npm `lockfileVersion` 3+ parse,
5789
+ * and older ones fail typed. See `Lockfile.parse`.
5790
+ *
5732
5791
  * @public
5733
5792
  */
5734
5793
  const LockfileFormat = effect.Schema.Literals([
@@ -5755,7 +5814,7 @@ const FILENAMES = {
5755
5814
  */
5756
5815
  const filenameFor = (format) => FILENAMES[format][0];
5757
5816
  //#endregion
5758
- //#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
5817
+ //#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
5759
5818
  /**
5760
5819
  * The four dependency sections of a manifest, in a stable order — the shared
5761
5820
  * dependency-sections table (v3's `DEP_SECTIONS`). Each entry is both the
@@ -5866,6 +5925,79 @@ const importerDependencies = (entry, read) => {
5866
5925
  }
5867
5926
  return deps;
5868
5927
  };
5928
+ const EMPTY_PEERS = {
5929
+ peerDependencies: {},
5930
+ peerDependenciesMeta: {}
5931
+ };
5932
+ /**
5933
+ * Normalize one format's peer declarations into the unified pair.
5934
+ *
5935
+ * Every format records the ranges the same way (a name→range map), but the
5936
+ * optional flag has two spellings: a `peerDependenciesMeta` object (pnpm, npm,
5937
+ * yarn Berry) and bun's `optionalPeers` array of names. Both are accepted and
5938
+ * collapse to `{ optional: boolean }` per peer, so a consumer reads one shape
5939
+ * regardless of which manager wrote the lockfile.
5940
+ *
5941
+ * Absence yields empty records, never `undefined` — an absent section means
5942
+ * "declares no peers", which is a fact, not a gap. Records are built with
5943
+ * `Object.fromEntries` (own-property semantics), so a `__proto__` peer name
5944
+ * neither pollutes nor drops.
5945
+ *
5946
+ * @internal
5947
+ */
5948
+ const peerDeclarations = (peers, meta, optionalPeers) => {
5949
+ if (peers === void 0 && meta === void 0 && optionalPeers === void 0) return EMPTY_PEERS;
5950
+ const flags = /* @__PURE__ */ new Map();
5951
+ if (meta !== void 0) for (const [name, value] of Object.entries(meta)) flags.set(name, value?.optional === true);
5952
+ if (optionalPeers !== void 0) for (const name of optionalPeers) flags.set(name, true);
5953
+ return {
5954
+ peerDependencies: peers === void 0 ? {} : Object.fromEntries(Object.entries(peers)),
5955
+ peerDependenciesMeta: Object.fromEntries([...flags].map(([name, optional]) => [name, { optional }]))
5956
+ };
5957
+ };
5958
+ /**
5959
+ * The minimum lockfile-format version each gated format is parsed at.
5960
+ *
5961
+ * This is a deliberate narrowing of the supported input domain, not an
5962
+ * implementation detail: an older lockfile fails typed rather than parsing
5963
+ * into a model that cannot answer resolution questions. Note the gate is on
5964
+ * the **lockfile format version**, which is the only version a lockfile
5965
+ * records — the writing package manager's version is not recoverable from the
5966
+ * file, so no manager-version claim could be enforced here.
5967
+ *
5968
+ * @internal
5969
+ */
5970
+ const MINIMUM_LOCKFILE_VERSION = {
5971
+ pnpm: 9,
5972
+ npm: 3
5973
+ };
5974
+ /**
5975
+ * Fail typed when a lockfile predates the supported format version.
5976
+ *
5977
+ * Routed through {@link validationFailure} rather than {@link framingFailure}:
5978
+ * the document was located perfectly well, so this is a shape judgement about
5979
+ * a located document, not a framing problem. The cause is a structured record
5980
+ * rather than an engine error, so a consumer can tell "your lockfile is too
5981
+ * old" from "your lockfile is malformed" without parsing a message.
5982
+ *
5983
+ * A version that is not a number at all (`lockfileVersion: "next"`) is not a
5984
+ * supported version either, and fails the same way.
5985
+ *
5986
+ * @internal
5987
+ */
5988
+ const requireLockfileVersion = (format, raw) => {
5989
+ const minimum = MINIMUM_LOCKFILE_VERSION[format];
5990
+ const parsed = typeof raw === "number" ? raw : Number.parseFloat(raw);
5991
+ if (Number.isFinite(parsed) && parsed >= minimum) return effect.Effect.void;
5992
+ const cause = {
5993
+ _tag: "UnsupportedLockfileVersion",
5994
+ format,
5995
+ lockfileVersion: raw,
5996
+ minimumSupported: minimum,
5997
+ message: `${format} lockfileVersion ${JSON.stringify(raw)} is not supported: @effected/lockfiles parses ${format} lockfileVersion ${minimum} and newer`
5998
+ };
5999
+ return effect.Effect.fail(validationFailure(cause));
6000
+ };
5869
6001
  /** @internal */
5870
6002
  const syntaxFailure = (cause) => ({
5871
6003
  stage: "syntax",
@@ -7684,16 +7816,38 @@ var JsoncModifier = class {
7684
7816
  });
7685
7817
  };
7686
7818
  //#endregion
7687
- //#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
7819
+ //#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
7688
7820
  const DepRecord$2 = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
7821
+ const OptionalPeers = effect.Schema.optionalKey(effect.Schema.Array(effect.Schema.String));
7689
7822
  const BunWorkspaceEntry = effect.Schema.Struct({
7690
7823
  name: effect.Schema.optionalKey(effect.Schema.String),
7691
7824
  version: effect.Schema.optionalKey(effect.Schema.String),
7692
7825
  dependencies: DepRecord$2,
7693
7826
  devDependencies: DepRecord$2,
7694
7827
  peerDependencies: DepRecord$2,
7695
- optionalDependencies: DepRecord$2
7828
+ optionalDependencies: DepRecord$2,
7829
+ optionalPeers: OptionalPeers
7830
+ });
7831
+ /**
7832
+ * The info object at package-tuple index 2. bun's tuple shape is
7833
+ * under-documented upstream, so it is read permissively and *out of band*: a
7834
+ * shape that does not decode is skipped (the package still lands, with no
7835
+ * peers) rather than failing the whole parse.
7836
+ *
7837
+ * @internal
7838
+ */
7839
+ const BunPackageInfo = effect.Schema.Struct({
7840
+ dependencies: DepRecord$2,
7841
+ devDependencies: DepRecord$2,
7842
+ optionalDependencies: DepRecord$2,
7843
+ peerDependencies: DepRecord$2,
7844
+ optionalPeers: OptionalPeers
7696
7845
  });
7846
+ const decodeBunPackageInfo = effect.Schema.decodeUnknownExit(BunPackageInfo);
7847
+ const readBunPackageInfo = (value) => {
7848
+ const exit = decodeBunPackageInfo(value);
7849
+ return effect.Exit.isSuccess(exit) ? exit.value : void 0;
7850
+ };
7697
7851
  const BunLockfileRaw = effect.Schema.Struct({
7698
7852
  lockfileVersion: effect.Schema.Number,
7699
7853
  workspaces: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, BunWorkspaceEntry)),
@@ -7716,8 +7870,60 @@ const parseBun = (content) => effect.Effect.gen(function* () {
7716
7870
  const validated = yield* effect.Schema.decodeUnknownEffect(BunLockfileRaw)(parsed).pipe(effect.Effect.mapError(validationFailure));
7717
7871
  return yield* toFields$3(validated);
7718
7872
  });
7873
+ /**
7874
+ * Resolve one entry's outgoing edges by replaying bun's own key scheme.
7875
+ *
7876
+ * bun encodes install position in the `packages` key: a nested install is
7877
+ * keyed `<parent-key>/<name>`, so `"react-dom/react"` is literally "the react
7878
+ * react-dom got". Package names are themselves slash-bearing when scoped, so
7879
+ * the parent chain is **not** computed by splitting on `/` — it is read off
7880
+ * the key space, taking those prefixes of the key that are themselves keys,
7881
+ * longest first. Deepest wins; the root (`<name>` alone) is tried last.
7882
+ *
7883
+ * Only keys that exist are emitted, so an edge bun did not record is omitted
7884
+ * rather than invented.
7885
+ *
7886
+ * @internal
7887
+ */
7888
+ const resolveBunEdges = (key, sections, keys) => {
7889
+ const names = /* @__PURE__ */ new Set();
7890
+ for (const section of sections) {
7891
+ if (!section) continue;
7892
+ for (const name of Object.keys(section)) if (name !== "") names.add(name);
7893
+ }
7894
+ if (names.size === 0) return {};
7895
+ const prefixes = [key];
7896
+ for (let i = key.indexOf("/"); i !== -1; i = key.indexOf("/", i + 1)) {
7897
+ const candidate = key.slice(0, i);
7898
+ if (keys.has(candidate)) prefixes.push(candidate);
7899
+ }
7900
+ prefixes.sort((a, b) => b.length - a.length);
7901
+ prefixes.push("");
7902
+ const edges = /* @__PURE__ */ new Map();
7903
+ for (const name of names) for (const prefix of prefixes) {
7904
+ const candidate = prefix === "" ? name : `${prefix}/${name}`;
7905
+ if (keys.has(candidate)) {
7906
+ edges.set(name, candidate);
7907
+ break;
7908
+ }
7909
+ }
7910
+ return Object.fromEntries(edges);
7911
+ };
7912
+ const infoSections = (info) => [
7913
+ info?.dependencies,
7914
+ info?.devDependencies,
7915
+ info?.optionalDependencies,
7916
+ info?.peerDependencies
7917
+ ];
7918
+ const workspaceSections = (entry) => [
7919
+ entry.dependencies,
7920
+ entry.devDependencies,
7921
+ entry.optionalDependencies,
7922
+ entry.peerDependencies
7923
+ ];
7719
7924
  const toFields$3 = (raw) => effect.Effect.gen(function* () {
7720
7925
  const packages = [];
7926
+ const keys = new Set(raw.packages ? Object.keys(raw.packages) : []);
7721
7927
  const workspaceNames = /* @__PURE__ */ new Set();
7722
7928
  const workspaceEntries = /* @__PURE__ */ new Map();
7723
7929
  const importers = [];
@@ -7730,11 +7936,16 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7730
7936
  if (wsPath === "") continue;
7731
7937
  const name = wsEntry.name === void 0 || wsEntry.name === "" ? wsPath : wsEntry.name;
7732
7938
  workspaceNames.add(name);
7939
+ const instanceId = keys.has(name) ? name : wsPath;
7940
+ if (instanceId === "") continue;
7733
7941
  packages.push(ResolvedPackage.make({
7734
7942
  name,
7735
7943
  version: wsEntry.version ?? "0.0.0",
7944
+ instanceId,
7736
7945
  isWorkspace: true,
7737
- relativePath: wsPath
7946
+ relativePath: wsPath,
7947
+ ...peerDeclarations(wsEntry.peerDependencies, void 0, wsEntry.optionalPeers),
7948
+ resolved: resolveBunEdges(instanceId, workspaceSections(wsEntry), keys)
7738
7949
  }));
7739
7950
  workspaceEntries.set(name, {
7740
7951
  ...wsEntry.dependencies ? { dependencies: wsEntry.dependencies } : {},
@@ -7744,7 +7955,8 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7744
7955
  });
7745
7956
  }
7746
7957
  }
7747
- if (raw.packages) for (const tuple of Object.values(raw.packages)) {
7958
+ if (raw.packages) for (const [key, tuple] of Object.entries(raw.packages)) {
7959
+ if (key === "") continue;
7748
7960
  if (tuple.length < 1) continue;
7749
7961
  const first = tuple[0];
7750
7962
  if (typeof first !== "string") continue;
@@ -7754,11 +7966,15 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7754
7966
  const version = first.slice(atIdx + 1);
7755
7967
  if (workspaceNames.has(name)) continue;
7756
7968
  const integrity = yield* toIntegrityHash(tuple.length >= 4 && typeof tuple[3] === "string" ? tuple[3] : void 0);
7969
+ const info = tuple.length >= 3 ? readBunPackageInfo(tuple[2]) : void 0;
7757
7970
  packages.push(ResolvedPackage.make({
7758
7971
  name,
7759
7972
  version,
7973
+ instanceId: key,
7760
7974
  ...integrity !== void 0 ? { integrity } : {},
7761
- isWorkspace: false
7975
+ isWorkspace: false,
7976
+ ...peerDeclarations(info?.peerDependencies, void 0, info?.optionalPeers),
7977
+ resolved: resolveBunEdges(key, infoSections(info), keys)
7762
7978
  }));
7763
7979
  }
7764
7980
  const workspaceDependencies = extractWorkspaceDeps(workspaceEntries, workspaceNames);
@@ -7777,8 +7993,9 @@ const toFields$3 = (raw) => effect.Effect.gen(function* () {
7777
7993
  };
7778
7994
  });
7779
7995
  //#endregion
7780
- //#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
7996
+ //#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
7781
7997
  const DepRecord$1 = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
7998
+ const PeerMetaRecord = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ optional: effect.Schema.optionalKey(effect.Schema.Boolean) })));
7782
7999
  const NpmPackageEntry = effect.Schema.Struct({
7783
8000
  name: effect.Schema.optionalKey(effect.Schema.String),
7784
8001
  version: effect.Schema.optionalKey(effect.Schema.String),
@@ -7789,8 +8006,22 @@ const NpmPackageEntry = effect.Schema.Struct({
7789
8006
  dependencies: DepRecord$1,
7790
8007
  devDependencies: DepRecord$1,
7791
8008
  peerDependencies: DepRecord$1,
8009
+ peerDependenciesMeta: PeerMetaRecord,
7792
8010
  optionalDependencies: DepRecord$1
7793
8011
  });
8012
+ /**
8013
+ * The version gate's own input: `lockfileVersion` and nothing else.
8014
+ *
8015
+ * The gate has to read the version *before* the shape decode, because the
8016
+ * shape it would decode against is the shape of a supported version. `packages`
8017
+ * is a required key here and a v1 tree does not have one, so a shape-first
8018
+ * order reports npm v1 as **malformed** rather than as **too old** — losing
8019
+ * exactly the distinction the `UnsupportedLockfileVersion` cause exists to
8020
+ * carry.
8021
+ *
8022
+ * @internal
8023
+ */
8024
+ const NpmVersionProbe = effect.Schema.Struct({ lockfileVersion: effect.Schema.Union([effect.Schema.Number, effect.Schema.String]) });
7794
8025
  const NpmLockfileRaw = effect.Schema.Struct({
7795
8026
  name: effect.Schema.optionalKey(effect.Schema.String),
7796
8027
  version: effect.Schema.optionalKey(effect.Schema.String),
@@ -7799,10 +8030,73 @@ const NpmLockfileRaw = effect.Schema.Struct({
7799
8030
  packages: effect.Schema.Record(effect.Schema.String, NpmPackageEntry)
7800
8031
  });
7801
8032
  const NODE_MODULES_PREFIX = "node_modules/";
8033
+ const NESTED_NODE_MODULES = "/node_modules/";
8034
+ /**
8035
+ * Where a `packages` key's package name starts: after the **last**
8036
+ * `node_modules/` segment, not the first.
8037
+ *
8038
+ * npm encodes the whole install position in the key, so
8039
+ * `node_modules/express/node_modules/debug` is *debug*, nested under express —
8040
+ * and `packages/lib/node_modules/react` is *react*, nested under a workspace
8041
+ * directory and carrying no `node_modules/` prefix at all. Returns `-1` for a
8042
+ * key that is not a package position (the root `""` entry, a workspace path
8043
+ * entry), which the caller skips.
8044
+ *
8045
+ * @internal
8046
+ */
8047
+ const packageNameIndex = (key) => {
8048
+ const nested = key.lastIndexOf(NESTED_NODE_MODULES);
8049
+ if (nested !== -1) return nested + 14;
8050
+ return key.startsWith(NODE_MODULES_PREFIX) ? 13 : -1;
8051
+ };
7802
8052
  /**
7803
- * Parse npm `package-lock.json` (v2/v3) content into the unified field
7804
- * bundle. Native `JSON.parse` inside `Effect.try` its throw on hostile
7805
- * input (including V8's `RangeError` on pathological depth) lands typed as
8053
+ * Resolve one entry's outgoing edges by replaying node resolution over the key
8054
+ * space: from the depending package's own directory, try
8055
+ * `<prefix>/node_modules/<name>`, then strip one path segment and try again,
8056
+ * out to the root — **deepest first**, first hit wins. That order is the whole
8057
+ * algorithm: outermost-first would return the hoisted copy and silently
8058
+ * mis-report every shadowed dependency.
8059
+ *
8060
+ * Only keys that actually exist in the lockfile are emitted, so an edge npm
8061
+ * did not record is omitted rather than invented.
8062
+ *
8063
+ * @internal
8064
+ */
8065
+ const resolveNpmEdges = (start, sections, packages) => {
8066
+ const names = /* @__PURE__ */ new Set();
8067
+ for (const section of sections) {
8068
+ if (!section) continue;
8069
+ for (const name of Object.keys(section)) if (name !== "") names.add(name);
8070
+ }
8071
+ if (names.size === 0) return {};
8072
+ const prefixes = [];
8073
+ for (let prefix = start;;) {
8074
+ prefixes.push(prefix);
8075
+ if (prefix === "") break;
8076
+ const slash = prefix.lastIndexOf("/");
8077
+ prefix = slash === -1 ? "" : prefix.slice(0, slash);
8078
+ }
8079
+ const edges = /* @__PURE__ */ new Map();
8080
+ for (const name of names) for (const prefix of prefixes) {
8081
+ const candidate = prefix === "" ? `${NODE_MODULES_PREFIX}${name}` : `${prefix}${NESTED_NODE_MODULES}${name}`;
8082
+ if (Object.hasOwn(packages, candidate)) {
8083
+ edges.set(name, candidate);
8084
+ break;
8085
+ }
8086
+ }
8087
+ return Object.fromEntries(edges);
8088
+ };
8089
+ const entrySections = (entry) => [
8090
+ entry?.dependencies,
8091
+ entry?.devDependencies,
8092
+ entry?.optionalDependencies,
8093
+ entry?.peerDependencies
8094
+ ];
8095
+ /**
8096
+ * Parse npm `package-lock.json` content into the unified field bundle —
8097
+ * `lockfileVersion` 3 and newer; v2 and older fail typed at validation.
8098
+ * Native `JSON.parse` inside `Effect.try` — its throw on hostile input
8099
+ * (including V8's `RangeError` on pathological depth) lands typed as
7806
8100
  * `stage: "syntax"`.
7807
8101
  *
7808
8102
  * @internal
@@ -7812,6 +8106,8 @@ const parseNpm = (content) => effect.Effect.gen(function* () {
7812
8106
  try: () => JSON.parse(content),
7813
8107
  catch: syntaxFailure
7814
8108
  });
8109
+ const probe = yield* effect.Schema.decodeUnknownEffect(NpmVersionProbe)(raw).pipe(effect.Effect.mapError(validationFailure));
8110
+ yield* requireLockfileVersion("npm", probe.lockfileVersion);
7815
8111
  const validated = yield* effect.Schema.decodeUnknownEffect(NpmLockfileRaw)(raw).pipe(effect.Effect.mapError(validationFailure));
7816
8112
  return yield* toFields$2(validated);
7817
8113
  });
@@ -7825,22 +8121,30 @@ const toFields$2 = (raw) => effect.Effect.gen(function* () {
7825
8121
  path: ".",
7826
8122
  dependencies: importerDependencies(rootEntry, (s) => ({ specifier: s }))
7827
8123
  }));
7828
- for (const [key, entry] of Object.entries(raw.packages)) if (key.startsWith(NODE_MODULES_PREFIX) && entry.link === true) {
7829
- const name = (entry.resolved !== void 0 ? raw.packages[entry.resolved] : void 0)?.name ?? entry.name ?? key.slice(13);
7830
- if (name !== "") workspaceNames.add(name);
8124
+ for (const [key, entry] of Object.entries(raw.packages)) {
8125
+ const nameIndex = packageNameIndex(key);
8126
+ if (nameIndex !== -1 && entry.link === true) {
8127
+ const name = (entry.resolved !== void 0 ? raw.packages[entry.resolved] : void 0)?.name ?? entry.name ?? key.slice(nameIndex);
8128
+ if (name !== "") workspaceNames.add(name);
8129
+ }
7831
8130
  }
7832
8131
  for (const [key, entry] of Object.entries(raw.packages)) {
7833
8132
  if (key === "") continue;
7834
- if (key.startsWith(NODE_MODULES_PREFIX) && entry.link === true) {
8133
+ const nameIndex = packageNameIndex(key);
8134
+ if (nameIndex === -1) continue;
8135
+ if (entry.link === true) {
7835
8136
  const resolved = entry.resolved;
7836
8137
  const wsEntry = resolved !== void 0 ? raw.packages[resolved] : void 0;
7837
- const name = wsEntry?.name ?? entry.name ?? key.slice(13);
8138
+ const name = wsEntry?.name ?? entry.name ?? key.slice(nameIndex);
7838
8139
  if (name === "") continue;
7839
8140
  packages.push(ResolvedPackage.make({
7840
8141
  name,
7841
8142
  version: wsEntry?.version ?? "0.0.0",
8143
+ instanceId: key,
7842
8144
  isWorkspace: true,
7843
- ...resolved !== void 0 ? { relativePath: resolved } : {}
8145
+ ...resolved !== void 0 ? { relativePath: resolved } : {},
8146
+ ...peerDeclarations(wsEntry?.peerDependencies, wsEntry?.peerDependenciesMeta),
8147
+ resolved: resolveNpmEdges(resolved !== void 0 && resolved !== "" ? resolved : key, entrySections(wsEntry), raw.packages)
7844
8148
  }));
7845
8149
  if (wsEntry) workspaceEntries.set(name, {
7846
8150
  ...wsEntry.dependencies ? { dependencies: wsEntry.dependencies } : {},
@@ -7852,16 +8156,19 @@ const toFields$2 = (raw) => effect.Effect.gen(function* () {
7852
8156
  path: resolved,
7853
8157
  dependencies: wsEntry ? importerDependencies(wsEntry, (s) => ({ specifier: s })) : []
7854
8158
  }));
7855
- } else if (key.startsWith(NODE_MODULES_PREFIX)) {
7856
- const name = key.slice(13);
8159
+ } else {
8160
+ const name = key.slice(nameIndex);
7857
8161
  if (name !== "" && entry.version !== void 0) {
7858
8162
  const integrity = yield* toIntegrityHash(entry.integrity);
7859
8163
  packages.push(ResolvedPackage.make({
7860
8164
  name,
7861
8165
  version: entry.version,
8166
+ instanceId: key,
7862
8167
  ...integrity !== void 0 ? { integrity } : {},
7863
8168
  isWorkspace: false,
7864
- dependencies: entry.dependencies ?? {}
8169
+ dependencies: entry.dependencies ?? {},
8170
+ ...peerDeclarations(entry.peerDependencies, entry.peerDependenciesMeta),
8171
+ resolved: resolveNpmEdges(key, entrySections(entry), raw.packages)
7865
8172
  }));
7866
8173
  }
7867
8174
  }
@@ -15554,7 +15861,7 @@ function deepEqualValues(a, b) {
15554
15861
  return false;
15555
15862
  }
15556
15863
  //#endregion
15557
- //#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
15864
+ //#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
15558
15865
  /**
15559
15866
  * An empty YAML document composes to `null` (`Yaml.parseAll("")` is `[null]`,
15560
15867
  * and the trailing document of an env-only `pnpm-lock.yaml` is `null` too).
@@ -15624,7 +15931,7 @@ const selectSoleDocument = (content) => effect.Effect.gen(function* () {
15624
15931
  };
15625
15932
  });
15626
15933
  //#endregion
15627
- //#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
15934
+ //#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
15628
15935
  const PnpmImporterDeps = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({
15629
15936
  specifier: effect.Schema.String,
15630
15937
  version: effect.Schema.String
@@ -15635,6 +15942,18 @@ const PnpmImporter = effect.Schema.Struct({
15635
15942
  peerDependencies: PnpmImporterDeps,
15636
15943
  optionalDependencies: PnpmImporterDeps
15637
15944
  });
15945
+ /**
15946
+ * The version gate's own input: `lockfileVersion` and nothing else.
15947
+ *
15948
+ * The gate has to read the version *before* the shape decode, because the
15949
+ * shape it decodes against is the shape of a supported version. `importers` is
15950
+ * a required key here and a pre-v9 single-project lockfile has none — it
15951
+ * records its dependencies at the top level — so a shape-first order reports a
15952
+ * lockfile we reject for being too old as merely malformed instead.
15953
+ *
15954
+ * @internal
15955
+ */
15956
+ const PnpmVersionProbe = effect.Schema.Struct({ lockfileVersion: effect.Schema.Union([effect.Schema.String, effect.Schema.Number]) });
15638
15957
  const PnpmLockfileRaw = effect.Schema.Struct({
15639
15958
  lockfileVersion: effect.Schema.Union([effect.Schema.String, effect.Schema.Number]),
15640
15959
  settings: effect.Schema.optionalKey(effect.Schema.Struct({
@@ -15647,7 +15966,17 @@ const PnpmLockfileRaw = effect.Schema.Struct({
15647
15966
  version: effect.Schema.String
15648
15967
  })])))),
15649
15968
  importers: effect.Schema.Record(effect.Schema.String, PnpmImporter),
15650
- 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) })) })))
15969
+ packages: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({
15970
+ resolution: effect.Schema.optionalKey(effect.Schema.Struct({ integrity: effect.Schema.optionalKey(effect.Schema.String) })),
15971
+ peerDependencies: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String)),
15972
+ peerDependenciesMeta: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ optional: effect.Schema.optionalKey(effect.Schema.Boolean) }))),
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
+ }))),
15976
+ snapshots: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({
15977
+ dependencies: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String)),
15978
+ optionalDependencies: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String))
15979
+ })))
15651
15980
  });
15652
15981
  /**
15653
15982
  * Parse pnpm `pnpm-lock.yaml` content into the unified field bundle.
@@ -15667,10 +15996,142 @@ const PnpmLockfileRaw = effect.Schema.Struct({
15667
15996
  */
15668
15997
  const parsePnpm = (content) => effect.Effect.gen(function* () {
15669
15998
  const { document, documents } = yield* selectPnpmDocument(content);
15999
+ const probe = yield* effect.Schema.decodeUnknownEffect(PnpmVersionProbe)(document).pipe(effect.Effect.mapError(validationFailure));
16000
+ yield* requireLockfileVersion("pnpm", probe.lockfileVersion);
15670
16001
  const validated = yield* effect.Schema.decodeUnknownEffect(PnpmLockfileRaw)(document).pipe(effect.Effect.mapError(validationFailure));
15671
16002
  if (Object.keys(validated.importers).length === 0) return yield* effect.Effect.fail(framingFailure("noImporters", documents));
15672
16003
  return yield* toFields$1(validated);
15673
16004
  });
16005
+ /**
16006
+ * Resolve one instance's outgoing edges to instance ids.
16007
+ *
16008
+ * pnpm names a resolved dependency as `name` → `version`, where the version may
16009
+ * itself carry a peer suffix (`1.6.0(react@17.0.2)`); the referenced instance's
16010
+ * key is those two composed back together. The composition is *verified*
16011
+ * against the lockfile's own key set rather than trusted — the composed key is
16012
+ * v9's bare `name@version` and nothing else, because the format gate admits no
16013
+ * lockfile that spells keys the pre-v9 leading-slash way — and an edge that
16014
+ * matches nothing is **omitted**. That is what keeps a `link:`/`file:`
16015
+ * resolution, which names no instance in this lockfile, from becoming a
16016
+ * plausible lie.
16017
+ *
16018
+ * @internal
16019
+ */
16020
+ const resolveEdges = (sections, instanceIds) => {
16021
+ const edges = /* @__PURE__ */ new Map();
16022
+ const unnameable = /* @__PURE__ */ new Set();
16023
+ for (const section of sections) {
16024
+ if (!section) continue;
16025
+ for (const [name, version] of Object.entries(section)) {
16026
+ if (name === "") continue;
16027
+ if (version.startsWith(LINK_PREFIX)) {
16028
+ const target = resolveLinkTarget("", version.slice(LINK_PREFIX.length));
16029
+ if (target !== void 0 && instanceIds.has(target)) edges.set(name, target);
16030
+ else unnameable.add(name);
16031
+ continue;
16032
+ }
16033
+ const bare = `${name}@${version}`;
16034
+ if (instanceIds.has(bare)) edges.set(name, bare);
16035
+ else unnameable.add(name);
16036
+ }
16037
+ }
16038
+ return {
16039
+ resolved: Object.fromEntries(edges),
16040
+ unresolvedEdges: [...unnameable].sort()
16041
+ };
16042
+ };
16043
+ /** The protocol pnpm records a workspace-directory resolution under. @internal */
16044
+ const LINK_PREFIX = "link:";
16045
+ /**
16046
+ * Normalize a `link:` target against the linking importer's path, so a
16047
+ * workspace edge can name the workspace importer's instance id.
16048
+ * Total: a target that walks above the root yields `undefined`.
16049
+ *
16050
+ * @internal
16051
+ */
16052
+ const resolveLinkTarget = (importerPath, target) => {
16053
+ const segments = [];
16054
+ for (const segment of `${importerPath}/${target}`.split("/")) {
16055
+ if (segment === "" || segment === ".") continue;
16056
+ if (segment === "..") {
16057
+ if (segments.pop() === void 0) return void 0;
16058
+ continue;
16059
+ }
16060
+ segments.push(segment);
16061
+ }
16062
+ return segments.length === 0 ? void 0 : segments.join("/");
16063
+ };
16064
+ /** The specifier protocol pnpm resolves through the workspace itself. @internal */
16065
+ const WORKSPACE_PREFIX = "workspace:";
16066
+ /**
16067
+ * The importer a `link:` target lands INSIDE, longest path first.
16068
+ *
16069
+ * pnpm's `publishConfig.linkDirectory` makes a workspace link point at the
16070
+ * package's publish directory rather than its root — `link:../bundler/dist/dev/pkg`
16071
+ * where `packages/bundler` is the importer — so the target itself is a build
16072
+ * output that is no importer and never will be. The owning importer is the
16073
+ * longest ancestor of the target that IS one; longest-first so a nested importer
16074
+ * beats its parent.
16075
+ *
16076
+ * The root importer (`"."`) is deliberately unreachable here: it is an ancestor
16077
+ * of every path in the workspace, so admitting it would resolve every stray link
16078
+ * to the root rather than leaving it unnamed.
16079
+ *
16080
+ * @internal
16081
+ */
16082
+ const owningImporter = (target, importerPaths) => {
16083
+ const segments = target.split("/");
16084
+ for (let end = segments.length - 1; end > 0; end--) {
16085
+ const candidate = segments.slice(0, end).join("/");
16086
+ if (importerPaths.has(candidate)) return candidate;
16087
+ }
16088
+ };
16089
+ /**
16090
+ * Resolve one importer's outgoing edges. pnpm records `{ specifier, version }`
16091
+ * per importer dependency, where the version is either a registry version (the
16092
+ * instance-id composition {@link resolveEdges} performs) or a `link:` target
16093
+ * naming another importer — normalized against this importer's own path. Both
16094
+ * are checked against the lockfile's instance ids before being emitted.
16095
+ *
16096
+ * A `link:` target that is no importer gets one further chance, and only under
16097
+ * a `workspace:` SPECIFIER: pnpm resolved that edge through the workspace, so
16098
+ * the target directory is known to belong to a workspace package, and
16099
+ * {@link owningImporter} names it. The specifier is what makes this a
16100
+ * resolution rather than a guess — a hand-written `link:../vendor/stub`
16101
+ * specifier names a directory pnpm never claimed was a workspace package, and
16102
+ * attributing it to whichever importer happens to contain it would answer with
16103
+ * the wrong package's peers instead of admitting it could not name the edge.
16104
+ *
16105
+ * The snapshot path ({@link resolveEdges}) deliberately does NOT do this: a
16106
+ * snapshot body records `name: link:<path>` with no specifier beside it, so the
16107
+ * evidence this rule turns on is not available there.
16108
+ *
16109
+ * @internal
16110
+ */
16111
+ const resolveImporterEdges = (importer, importerPath, instanceIds, importerPaths) => {
16112
+ const edges = /* @__PURE__ */ new Map();
16113
+ const unnameable = /* @__PURE__ */ new Set();
16114
+ for (const group of importerDepGroups(importer)) {
16115
+ if (!group) continue;
16116
+ for (const [name, info] of Object.entries(group)) {
16117
+ if (name === "") continue;
16118
+ if (info.version.startsWith(LINK_PREFIX)) {
16119
+ const target = resolveLinkTarget(importerPath, info.version.slice(5));
16120
+ const owner = target === void 0 ? void 0 : instanceIds.has(target) ? target : info.specifier.startsWith(WORKSPACE_PREFIX) ? owningImporter(target, importerPaths) : void 0;
16121
+ if (owner !== void 0) edges.set(name, owner);
16122
+ else unnameable.add(name);
16123
+ continue;
16124
+ }
16125
+ const bare = `${name}@${info.version}`;
16126
+ if (instanceIds.has(bare)) edges.set(name, bare);
16127
+ else unnameable.add(name);
16128
+ }
16129
+ }
16130
+ return {
16131
+ resolved: Object.fromEntries(edges),
16132
+ unresolvedEdges: [...unnameable].sort()
16133
+ };
16134
+ };
15674
16135
  const toVersionMap = (deps) => {
15675
16136
  if (!deps) return void 0;
15676
16137
  return Object.fromEntries(Object.entries(deps).map(([name, info]) => [name, info.specifier]));
@@ -15711,28 +16172,51 @@ const toFields$1 = (raw) => effect.Effect.gen(function* () {
15711
16172
  }
15712
16173
  for (const path of Object.keys(raw.importers)) if (path !== "." && path !== "") workspaceNames.add(path);
15713
16174
  const packages = [];
15714
- for (const importerPath of Object.keys(raw.importers)) {
16175
+ const snapshots = raw.snapshots;
16176
+ const instanceIds = /* @__PURE__ */ new Set([
16177
+ ...snapshots ? Object.keys(snapshots) : [],
16178
+ ...raw.packages ? Object.keys(raw.packages) : [],
16179
+ ...Object.keys(raw.importers)
16180
+ ]);
16181
+ const importerPaths = new Set(Object.keys(raw.importers).filter((path) => path !== "." && path !== ""));
16182
+ const emitted = /* @__PURE__ */ new Set();
16183
+ for (const [importerPath, importer] of Object.entries(raw.importers)) {
15715
16184
  if (importerPath === "." || importerPath === "") continue;
15716
16185
  packages.push(ResolvedPackage.make({
15717
16186
  name: importerPath,
15718
16187
  version: "0.0.0",
16188
+ instanceId: importerPath,
15719
16189
  isWorkspace: true,
15720
- relativePath: importerPath
16190
+ relativePath: importerPath,
16191
+ ...resolveImporterEdges(importer, importerPath, instanceIds, importerPaths)
15721
16192
  }));
15722
16193
  }
15723
- if (raw.packages) for (const [key, pkg] of Object.entries(raw.packages)) {
15724
- const { plain: bare } = splitPeerSuffix(key);
16194
+ const emit = (instanceId, meta, edges) => effect.Effect.gen(function* () {
16195
+ const { plain: bare } = splitPeerSuffix(instanceId);
15725
16196
  const atIndex = bare.lastIndexOf("@");
15726
- if (atIndex <= 0) continue;
16197
+ if (atIndex <= 0) return;
15727
16198
  const name = bare.slice(0, atIndex);
15728
16199
  const version = bare.slice(atIndex + 1);
15729
- const integrity = yield* toIntegrityHash(pkg.resolution?.integrity);
16200
+ const integrity = yield* toIntegrityHash(meta?.resolution?.integrity);
16201
+ emitted.add(instanceId);
15730
16202
  packages.push(ResolvedPackage.make({
15731
16203
  name,
15732
16204
  version,
16205
+ instanceId,
15733
16206
  ...integrity !== void 0 ? { integrity } : {},
15734
- isWorkspace: false
16207
+ isWorkspace: false,
16208
+ ...peerDeclarations(meta?.peerDependencies, meta?.peerDependenciesMeta),
16209
+ ...resolveEdges(edges, instanceIds)
15735
16210
  }));
16211
+ });
16212
+ if (snapshots) for (const [key, snapshot] of Object.entries(snapshots)) {
16213
+ const plain = splitPeerSuffix(key).plain;
16214
+ yield* emit(key, raw.packages !== void 0 && Object.hasOwn(raw.packages, plain) ? raw.packages[plain] : void 0, [snapshot.dependencies, snapshot.optionalDependencies]);
16215
+ }
16216
+ const covered = new Set([...emitted].map((key) => splitPeerSuffix(key).plain));
16217
+ if (raw.packages) for (const [key, pkg] of Object.entries(raw.packages)) {
16218
+ if (covered.has(key)) continue;
16219
+ yield* emit(key, pkg, [pkg.dependencies, pkg.optionalDependencies]);
15736
16220
  }
15737
16221
  const workspaceDependencies = extractWorkspaceDeps(workspaceEntries, workspaceNames);
15738
16222
  const extension = PnpmExtension.make({
@@ -15749,7 +16233,7 @@ const toFields$1 = (raw) => effect.Effect.gen(function* () {
15749
16233
  };
15750
16234
  });
15751
16235
  //#endregion
15752
- //#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
16236
+ //#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
15753
16237
  const YarnLockfileRaw = effect.Schema.Record(effect.Schema.String, effect.Schema.Unknown);
15754
16238
  const DepRecord = effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.String));
15755
16239
  const YarnEntry = effect.Schema.Struct({
@@ -15758,6 +16242,7 @@ const YarnEntry = effect.Schema.Struct({
15758
16242
  dependencies: DepRecord,
15759
16243
  devDependencies: DepRecord,
15760
16244
  peerDependencies: DepRecord,
16245
+ peerDependenciesMeta: effect.Schema.optionalKey(effect.Schema.Record(effect.Schema.String, effect.Schema.Struct({ optional: effect.Schema.optionalKey(effect.Schema.Boolean) }))),
15761
16246
  optionalDependencies: DepRecord,
15762
16247
  checksum: effect.Schema.optionalKey(effect.Schema.String),
15763
16248
  languageName: effect.Schema.optionalKey(effect.Schema.String),
@@ -15791,6 +16276,13 @@ const toFields = (lockfileVersion, decoded) => effect.Effect.gen(function* () {
15791
16276
  const packages = [];
15792
16277
  const workspaceNames = /* @__PURE__ */ new Set();
15793
16278
  const workspaceEntries = /* @__PURE__ */ new Map();
16279
+ const locators = /* @__PURE__ */ new Map();
16280
+ for (const [key, entry] of decoded) {
16281
+ const descriptors = key.split(", ");
16282
+ const locator = entry.resolution ?? descriptors[0];
16283
+ if (locator === void 0 || locator === "") continue;
16284
+ for (const descriptor of descriptors) if (descriptor !== "") locators.set(descriptor, locator);
16285
+ }
15794
16286
  for (const [key, entry] of decoded) if (entry.linkType === "soft") {
15795
16287
  const name = extractYarnPackageName(key);
15796
16288
  if (name !== void 0) workspaceNames.add(name);
@@ -15801,12 +16293,17 @@ const toFields = (lockfileVersion, decoded) => effect.Effect.gen(function* () {
15801
16293
  const isWorkspace = entry.linkType === "soft";
15802
16294
  const relativePath = isWorkspace ? extractYarnWorkspacePath(key) : void 0;
15803
16295
  const integrity = yield* toIntegrityHash(entry.checksum);
16296
+ const instanceId = entry.resolution ?? key.split(", ")[0] ?? "";
16297
+ if (instanceId === "") continue;
15804
16298
  packages.push(ResolvedPackage.make({
15805
16299
  name,
15806
16300
  version: entry.version ?? "0.0.0",
16301
+ instanceId,
15807
16302
  ...integrity !== void 0 ? { integrity } : {},
15808
16303
  isWorkspace,
15809
- ...relativePath !== void 0 ? { relativePath } : {}
16304
+ ...relativePath !== void 0 ? { relativePath } : {},
16305
+ ...peerDeclarations(entry.peerDependencies, entry.peerDependenciesMeta),
16306
+ ...resolveYarnEdges(entry, locators)
15810
16307
  }));
15811
16308
  if (isWorkspace) {
15812
16309
  const deps = cleanYarnDeps(entry.dependencies);
@@ -15829,6 +16326,46 @@ const toFields = (lockfileVersion, decoded) => effect.Effect.gen(function* () {
15829
16326
  };
15830
16327
  });
15831
16328
  /**
16329
+ * Resolve one entry's outgoing edges through the descriptor→locator index.
16330
+ *
16331
+ * A yarn dependency value is a *descriptor* range (`"npm:5.3.0"`), and the
16332
+ * lockfile keys enumerate exactly which descriptors resolve to which locator,
16333
+ * so the lookup is exact rather than reconstructed.
16334
+ *
16335
+ * **`devDependencies` is not a section a Berry lockfile has.** yarn folds a
16336
+ * workspace's dev declarations into the entry's `dependencies` map — the
16337
+ * lockfile a project produces is byte-identical whether a dependency is
16338
+ * declared under `dependencies` or `devDependencies` (probed against yarn
16339
+ * 4.9.1). Dev edges are therefore already resolved here; iterating
16340
+ * `entry.devDependencies` would be dead code, and the schema keeps the field
16341
+ * only as permissive scaffolding for hand-edited input.
16342
+ *
16343
+ * **Dependency edges only.** yarn resolves peers virtually — a peer-bearing
16344
+ * package gets a `@virtual:` locator per consumer, and this lockfile shape does
16345
+ * not record which one satisfied which peer. Emitting a peer edge here would
16346
+ * mean guessing, so peers are left out: an absent edge is a true statement, a
16347
+ * plausible one would not be.
16348
+ *
16349
+ * @internal
16350
+ */
16351
+ const resolveYarnEdges = (entry, locators) => {
16352
+ const edges = /* @__PURE__ */ new Map();
16353
+ const unnameable = /* @__PURE__ */ new Set();
16354
+ for (const section of [entry.dependencies, entry.optionalDependencies]) {
16355
+ if (!section) continue;
16356
+ for (const [name, range] of Object.entries(section)) {
16357
+ if (name === "") continue;
16358
+ const locator = locators.get(`${name}@${range}`);
16359
+ if (locator !== void 0) edges.set(name, locator);
16360
+ else unnameable.add(name);
16361
+ }
16362
+ }
16363
+ return {
16364
+ resolved: Object.fromEntries(edges),
16365
+ unresolvedEdges: [...unnameable].sort()
16366
+ };
16367
+ };
16368
+ /**
15832
16369
  * Extract the package name from a yarn lockfile key. Handles compound keys
15833
16370
  * (`"a@workspace:*, a@workspace:packages/a"`) via the first descriptor and
15834
16371
  * `@patch:` descriptors (which embed `@npm:` inside). Total: malformed keys
@@ -15872,7 +16409,7 @@ const cleanYarnDeps = (deps) => {
15872
16409
  return Object.fromEntries(Object.entries(deps).map(([name, value]) => [name, value.startsWith("npm:") ? value.slice(4) : value]));
15873
16410
  };
15874
16411
  //#endregion
15875
- //#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
16412
+ //#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
15876
16413
  const EMPTY_IMPORTERS = [];
15877
16414
  /**
15878
16415
  * Failure of `Lockfile.parse`: the given content is not a valid lockfile of
@@ -16044,10 +16581,15 @@ var Lockfile = class Lockfile extends effect.Schema.Class("Lockfile")({
16044
16581
  return ResolvedPackage.make({
16045
16582
  name: realName,
16046
16583
  version: pkg.version,
16584
+ instanceId: pkg.instanceId,
16047
16585
  ...pkg.integrity !== void 0 ? { integrity: pkg.integrity } : {},
16048
16586
  isWorkspace: pkg.isWorkspace,
16049
16587
  relativePath: pkg.relativePath,
16050
- dependencies: pkg.dependencies
16588
+ dependencies: pkg.dependencies,
16589
+ peerDependencies: pkg.peerDependencies,
16590
+ peerDependenciesMeta: pkg.peerDependenciesMeta,
16591
+ resolved: pkg.resolved,
16592
+ unresolvedEdges: pkg.unresolvedEdges
16051
16593
  });
16052
16594
  });
16053
16595
  const workspaceDependencies = this.workspaceDependencies.map((dep) => {
@@ -16116,7 +16658,7 @@ var Lockfile = class Lockfile extends effect.Schema.Class("Lockfile")({
16116
16658
  }
16117
16659
  };
16118
16660
  //#endregion
16119
- //#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
16661
+ //#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
16120
16662
  /**
16121
16663
  * The minimal manifest shape {@link LockfileIntegrity.compare} checks a
16122
16664
  * lockfile against: a package name plus the four optional dependency maps.
@@ -18929,7 +19471,7 @@ var Package = class Package extends effect.Schema.Class("Package")({
18929
19471
  }
18930
19472
  };
18931
19473
  //#endregion
18932
- //#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
19474
+ //#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
18933
19475
  const EMPTY$1 = Object.freeze(Object.create(null));
18934
19476
  const EMPTY_MANIFEST = Object.freeze(Object.create(null));
18935
19477
  /**
@@ -19527,7 +20069,7 @@ var Walker$1 = class {
19527
20069
  static findRoot = findRoot$1;
19528
20070
  };
19529
20071
  //#endregion
19530
- //#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
20072
+ //#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
19531
20073
  /**
19532
20074
  * The marker filenames {@link WorkspaceRoot} probes for, in priority order.
19533
20075
  *
@@ -19714,7 +20256,7 @@ var WorkspaceRoot = class WorkspaceRoot extends effect.Context.Service()("@effec
19714
20256
  static layerTest = (root) => effect.Layer.effect(WorkspaceRoot, WorkspaceRoot.makeTest(root)).pipe(effect.Layer.provide(effect.Path.layer));
19715
20257
  };
19716
20258
  //#endregion
19717
- //#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
20259
+ //#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
19718
20260
  /**
19719
20261
  * Hard ceiling on directories the enumerator will visit for one pattern set.
19720
20262
  * Guards the pathological case a depth cap alone does not: a wide, shallow
@@ -19732,7 +20274,7 @@ const MAX_ENUMERATION_ENTRIES = 1e5;
19732
20274
  */
19733
20275
  const PRUNED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
19734
20276
  //#endregion
19735
- //#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
20277
+ //#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
19736
20278
  /** Directory names never descended into. */
19737
20279
  const isPruned = (entry) => PRUNED_DIRECTORIES.has(entry);
19738
20280
  /** Join root-relative POSIX segments; `""` is the root itself. */
@@ -19822,7 +20364,7 @@ var Traversal = class {
19822
20364
  }
19823
20365
  };
19824
20366
  //#endregion
19825
- //#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
20367
+ //#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
19826
20368
  /** Strip a trailing slash from `GlobPattern.enumerationPrefix` to get a relative directory. */
19827
20369
  const baseOf = (pattern) => pattern.enumerationPrefix.replace(/\/$/, "");
19828
20370
  /**
@@ -19839,6 +20381,8 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
19839
20381
  if (!isValidMaxDepth(maxDepth)) return yield* effect.Effect.die(/* @__PURE__ */ new Error(`enumerate: ${badMaxDepthMessage(maxDepth)}`));
19840
20382
  const isPackage = (absolute) => fs.exists(path.join(absolute, "package.json")).pipe(effect.Effect.orElseSucceed(() => false));
19841
20383
  const isDirectory = (absolute) => fs.stat(absolute).pipe(effect.Effect.map((info) => info.type === "Directory"), effect.Effect.orElseSucceed(() => false));
20384
+ const excludes = globs.excludes;
20385
+ const isExcluded = excludes.length === 0 ? (_) => false : (relative) => excludes.some((exclude) => exclude.matches(relative));
19842
20386
  const included = /* @__PURE__ */ new Map();
19843
20387
  /** A shared-traversal stop, materialized as this module's failure record. */
19844
20388
  const failureOf = (stop, pattern) => ({
@@ -19847,6 +20391,7 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
19847
20391
  detail: stop.detail
19848
20392
  });
19849
20393
  for (const literal of globs.literals) {
20394
+ if (isExcluded(literal)) continue;
19850
20395
  const absolute = path.join(root, literal);
19851
20396
  if (yield* isPackage(absolute)) included.set(literal, absolute);
19852
20397
  }
@@ -19874,25 +20419,22 @@ const enumerate = (root, globs, options) => effect.Effect.gen(function* () {
19874
20419
  const absolute = path.join(frame.absolute, entry);
19875
20420
  if (!(yield* isDirectory(absolute))) continue;
19876
20421
  if (wildcard.crossesSegments && !traversal.admits(frame)) return yield* effect.Effect.fail(failureOf(traversal.depthStop(), wildcard.source));
19877
- if (wildcard.matches(relative) && (yield* isPackage(absolute))) included.set(relative, absolute);
20422
+ if (wildcard.matches(relative) && !isExcluded(relative) && (yield* isPackage(absolute))) included.set(relative, absolute);
19878
20423
  if (!wildcard.crossesSegments) continue;
19879
20424
  traversal.push(frame, relative, absolute);
19880
20425
  }
19881
20426
  }
19882
20427
  }
19883
20428
  const results = [];
19884
- for (const [relativePath, absolute] of included) {
19885
- if (globs.excludes.some((exclude) => exclude.matches(relativePath))) continue;
19886
- results.push({
19887
- relativePath,
19888
- path: absolute
19889
- });
19890
- }
20429
+ for (const [relativePath, absolute] of included) results.push({
20430
+ relativePath,
20431
+ path: absolute
20432
+ });
19891
20433
  results.sort((a, b) => a.relativePath < b.relativePath ? -1 : a.relativePath > b.relativePath ? 1 : 0);
19892
20434
  return results;
19893
20435
  });
19894
20436
  //#endregion
19895
- //#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
20437
+ //#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
19896
20438
  const stringsOf = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : void 0;
19897
20439
  /** The `packages:` list of a `pnpm-workspace.yaml` document. Total on a parsed document. */
19898
20440
  const pnpmPatternsOf = (document) => {
@@ -19949,7 +20491,7 @@ const readPatterns = (root) => effect.Effect.gen(function* () {
19949
20491
  return manifestPatternsOf(manifest);
19950
20492
  });
19951
20493
  //#endregion
19952
- //#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
20494
+ //#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
19953
20495
  /**
19954
20496
  * Raised when a workspace member's `package.json` cannot be read, parsed, or
19955
20497
  * used — it is missing, malformed, or lacks a `name` or `version`.
@@ -20405,7 +20947,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends effect.Context.Service
20405
20947
  };
20406
20948
  const isStringRecord$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
20407
20949
  //#endregion
20408
- //#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
20950
+ //#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
20409
20951
  /**
20410
20952
  * Raised when the workspace dependency graph cannot be topologically ordered
20411
20953
  * because it contains a cycle.
@@ -24101,7 +24643,7 @@ var Git = class Git extends effect.Context.Service()("@effected/git/Git") {
24101
24643
  static layerTest = (overrides = {}) => effect.Layer.succeed(Git, Git.makeTest(overrides));
24102
24644
  };
24103
24645
  //#endregion
24104
- //#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
24646
+ //#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
24105
24647
  /**
24106
24648
  * Which git refs to compare, and whether to fold in the working tree.
24107
24649
  *
@@ -24357,7 +24899,7 @@ function resolveFromCatalog(catalogs, wantedDependency) {
24357
24899
  };
24358
24900
  }
24359
24901
  //#endregion
24360
- //#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
24902
+ //#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
24361
24903
  /** Project a pnpm-workspace manifest's `catalog` / `catalogs` fields into a `Catalogs` map. */
24362
24904
  const inlineCatalogs = (manifest) => {
24363
24905
  if (manifest.catalog === void 0 && manifest.catalogs === void 0) return {};
@@ -24420,8 +24962,12 @@ const rangeOf = (catalogs, dependency, specifier) => {
24420
24962
  unused: () => void 0
24421
24963
  });
24422
24964
  };
24423
- //#endregion
24424
- //#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
24965
+ /** Internal alias, kept short at the many call sites in this module. */
24966
+ const NO_PEER_RULES = Object.freeze({
24967
+ allowedVersions: Object.freeze({}),
24968
+ ignoreMissing: Object.freeze([]),
24969
+ allowAny: Object.freeze([])
24970
+ });
24425
24971
  /** Whether `value` is a non-null, non-array object. */
24426
24972
  const isObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
24427
24973
  /**
@@ -24449,7 +24995,7 @@ const moduleNotFoundUrl = (cause) => isObject$2(cause) && cause.code === "ERR_MO
24449
24995
  */
24450
24996
  const hasTraversalSegment = (name) => name.split(/[/\\]/).includes("..");
24451
24997
  /** Turn the seed record into the pnpm hook config, with the default catalog split out under `catalog`. */
24452
- const seedToConfig = (seed) => {
24998
+ const seedToConfig = (seed, rules) => {
24453
24999
  const catalogs = {};
24454
25000
  let catalog = {};
24455
25001
  for (const [name, entries] of Object.entries(seed)) if (name === "default") catalog = { ...entries };
@@ -24458,7 +25004,8 @@ const seedToConfig = (seed) => {
24458
25004
  catalog,
24459
25005
  catalogs,
24460
25006
  minimumReleaseAge: void 0,
24461
- minimumReleaseAgeExclude: void 0
25007
+ minimumReleaseAgeExclude: void 0,
25008
+ peerDependencyRules: rules
24462
25009
  };
24463
25010
  };
24464
25011
  /** A finite number if `value` is one, else the prior threaded value — a garbage age is dropped, not fatal. */
@@ -24483,10 +25030,33 @@ const configOf = (value, fallback) => {
24483
25030
  catalog: isObject$2(value.catalog) ? value.catalog : fallback.catalog,
24484
25031
  catalogs: isObject$2(value.catalogs) ? value.catalogs : fallback.catalogs,
24485
25032
  minimumReleaseAge: finiteNumberOr(value.minimumReleaseAge, fallback.minimumReleaseAge),
24486
- minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude)
25033
+ minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude),
25034
+ peerDependencyRules: peerRulesOr(value.peerDependencyRules, fallback.peerDependencyRules)
24487
25035
  };
24488
25036
  };
24489
25037
  /**
25038
+ * A peer-rules block if `value` is one, else the prior threaded value — a
25039
+ * malformed block is dropped, not fatal, matching the other slices.
25040
+ *
25041
+ * Each axis is normalized independently: a hook that rewrites `allowedVersions`
25042
+ * and leaves `ignoreMissing` alone must not blank the latter.
25043
+ */
25044
+ const stringRecordOr = (value, fallback) => isObject$2(value) && Object.values(value).every((entry) => typeof entry === "string") ? value : fallback;
25045
+ const peerRulesOr = (value, fallback) => {
25046
+ if (!isObject$2(value)) return fallback;
25047
+ const allowed = stringRecordOr(value.allowedVersions, fallback?.allowedVersions);
25048
+ const ignoreMissing = stringArrayOr(value.ignoreMissing, fallback?.ignoreMissing);
25049
+ const allowAny = stringArrayOr(value.allowAny, fallback?.allowAny);
25050
+ if (allowed === void 0 && ignoreMissing === void 0 && allowAny === void 0) return fallback;
25051
+ return {
25052
+ allowedVersions: allowed ?? {},
25053
+ ignoreMissing: ignoreMissing ?? [],
25054
+ allowAny: allowAny ?? []
25055
+ };
25056
+ };
25057
+ /** Project the threaded config's rules into the slice, defaulting every axis to empty. */
25058
+ const peerRulesOf = (config) => config.peerDependencyRules ?? NO_PEER_RULES;
25059
+ /**
24490
25060
  * Project the threaded config's release-age keys into a partial gate
24491
25061
  * contribution, omitting a key the hooks never set (never an explicit
24492
25062
  * `undefined` — the fields are `optionalKey`).
@@ -24539,13 +25109,23 @@ const updateConfigOf = (mod) => {
24539
25109
  * noise on stdout.
24540
25110
  */
24541
25111
  const REPLAY_SCRIPT = `
24542
- const [root, seedJson, ...names] = process.argv.slice(1);
25112
+ const [root, seedJson, rulesJson, ...names] = process.argv.slice(1);
24543
25113
  const { pathToFileURL } = await import("node:url");
24544
25114
  const { join } = await import("node:path");
24545
25115
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
24546
25116
  const finiteNumberOr = (value, fallback) => (typeof value === "number" && Number.isFinite(value) ? value : fallback);
24547
25117
  const stringArrayOr = (value, fallback) =>
24548
25118
  Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : fallback;
25119
+ const stringRecordOr = (value, fallback) =>
25120
+ isObject(value) && Object.values(value).every((entry) => typeof entry === "string") ? value : fallback;
25121
+ const peerRulesOr = (value, fallback) => {
25122
+ if (!isObject(value)) return fallback;
25123
+ const allowed = stringRecordOr(value.allowedVersions, fallback && fallback.allowedVersions);
25124
+ const ignoreMissing = stringArrayOr(value.ignoreMissing, fallback && fallback.ignoreMissing);
25125
+ const allowAny = stringArrayOr(value.allowAny, fallback && fallback.allowAny);
25126
+ if (allowed === undefined && ignoreMissing === undefined && allowAny === undefined) return fallback;
25127
+ return { allowedVersions: allowed || {}, ignoreMissing: ignoreMissing || [], allowAny: allowAny || [] };
25128
+ };
24549
25129
  const configOf = (value, fallback) =>
24550
25130
  isObject(value)
24551
25131
  ? {
@@ -24553,6 +25133,7 @@ const configOf = (value, fallback) =>
24553
25133
  catalogs: isObject(value.catalogs) ? value.catalogs : fallback.catalogs,
24554
25134
  minimumReleaseAge: finiteNumberOr(value.minimumReleaseAge, fallback.minimumReleaseAge),
24555
25135
  minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude),
25136
+ peerDependencyRules: peerRulesOr(value.peerDependencyRules, fallback.peerDependencyRules),
24556
25137
  }
24557
25138
  : fallback;
24558
25139
  const failure = (name, cause) => ({
@@ -24568,7 +25149,13 @@ const replay = async () => {
24568
25149
  if (name === "default") catalog = { ...entries };
24569
25150
  else catalogs[name] = { ...entries };
24570
25151
  }
24571
- let config = { catalog, catalogs, minimumReleaseAge: undefined, minimumReleaseAgeExclude: undefined };
25152
+ let config = {
25153
+ catalog,
25154
+ catalogs,
25155
+ minimumReleaseAge: undefined,
25156
+ minimumReleaseAgeExclude: undefined,
25157
+ peerDependencyRules: JSON.parse(rulesJson),
25158
+ };
24572
25159
  for (const name of names) {
24573
25160
  let loaded;
24574
25161
  let found = false;
@@ -24669,9 +25256,10 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24669
25256
  * config dependency. The default {@link WorkspaceCatalogs} layer wires this, so
24670
25257
  * the default catalog path provably executes no config-dependency code.
24671
25258
  */
24672
- static layerNoop = effect.Layer.succeed(ConfigDependencyHooks, { inject: (_root, _configDependencies, seed) => effect.Effect.succeed({
25259
+ static layerNoop = effect.Layer.succeed(ConfigDependencyHooks, { inject: (_root, _configDependencies, seed, rules) => effect.Effect.succeed({
24673
25260
  catalogs: seed,
24674
- releaseAge: {}
25261
+ releaseAge: {},
25262
+ peerDependencyRules: rules ?? NO_PEER_RULES
24675
25263
  }) });
24676
25264
  /**
24677
25265
  * The live layer: dynamically imports each config dependency's `pnpmfile.cjs`
@@ -24689,13 +25277,14 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24689
25277
  * import, so this layer runs on either runtime. Only ever wired by
24690
25278
  * `WorkspaceCatalogs.layerWithConfigDependencies`.
24691
25279
  */
24692
- static layerLive = effect.Layer.succeed(ConfigDependencyHooks, { inject: (root, configDependencies, seed) => effect.Effect.gen(function* () {
25280
+ static layerLive = effect.Layer.succeed(ConfigDependencyHooks, { inject: (root, configDependencies, seed, rules) => effect.Effect.gen(function* () {
24693
25281
  const names = Object.keys(configDependencies);
24694
25282
  if (names.length === 0) return {
24695
25283
  catalogs: seed,
24696
- releaseAge: {}
25284
+ releaseAge: {},
25285
+ peerDependencyRules: rules ?? NO_PEER_RULES
24697
25286
  };
24698
- let config = seedToConfig(seed);
25287
+ let config = seedToConfig(seed, rules);
24699
25288
  for (const name of names) {
24700
25289
  if (hasTraversalSegment(name)) return yield* effect.Effect.fail(new CatalogAssemblyError({
24701
25290
  source: "hooks",
@@ -24741,7 +25330,8 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24741
25330
  }
24742
25331
  return {
24743
25332
  catalogs: configToEntries(config),
24744
- releaseAge: releaseAgeOf(config)
25333
+ releaseAge: releaseAgeOf(config),
25334
+ peerDependencyRules: peerRulesOf(config)
24745
25335
  };
24746
25336
  }) });
24747
25337
  /**
@@ -24797,11 +25387,12 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24797
25387
  */
24798
25388
  static layerSubprocess = effect.Layer.effect(ConfigDependencyHooks, effect.Effect.gen(function* () {
24799
25389
  const spawner = yield* effect_unstable_process.ChildProcessSpawner.ChildProcessSpawner;
24800
- return { inject: (root, configDependencies, seed) => effect.Effect.gen(function* () {
25390
+ return { inject: (root, configDependencies, seed, rules) => effect.Effect.gen(function* () {
24801
25391
  const names = Object.keys(configDependencies);
24802
25392
  if (names.length === 0) return {
24803
25393
  catalogs: seed,
24804
- releaseAge: {}
25394
+ releaseAge: {},
25395
+ peerDependencyRules: rules ?? NO_PEER_RULES
24805
25396
  };
24806
25397
  for (const name of names) if (hasTraversalSegment(name)) return yield* effect.Effect.fail(new CatalogAssemblyError({
24807
25398
  source: "hooks",
@@ -24814,6 +25405,7 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24814
25405
  REPLAY_SCRIPT,
24815
25406
  root,
24816
25407
  JSON.stringify(seed),
25408
+ JSON.stringify(rules ?? NO_PEER_RULES),
24817
25409
  ...names
24818
25410
  ]);
24819
25411
  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({
@@ -24826,16 +25418,17 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends effect.Context.S
24826
25418
  path: payload.name ?? root,
24827
25419
  cause: replayFailureCause(payload)
24828
25420
  }));
24829
- const config = configOf(payload.config, seedToConfig(seed));
25421
+ const config = configOf(payload.config, seedToConfig(seed, rules));
24830
25422
  return {
24831
25423
  catalogs: configToEntries(config),
24832
- releaseAge: releaseAgeOf(config)
25424
+ releaseAge: releaseAgeOf(config),
25425
+ peerDependencyRules: peerRulesOf(config)
24833
25426
  };
24834
25427
  }) };
24835
25428
  }));
24836
25429
  };
24837
25430
  //#endregion
24838
- //#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
25431
+ //#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
24839
25432
  /**
24840
25433
  * The four package managers this package understands.
24841
25434
  *
@@ -25210,7 +25803,7 @@ var PackageManagerDetector = class PackageManagerDetector extends effect.Context
25210
25803
  static layerTest = (overrides = {}) => effect.Layer.succeed(PackageManagerDetector, PackageManagerDetector.makeTest(overrides));
25211
25804
  };
25212
25805
  //#endregion
25213
- //#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
25806
+ //#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
25214
25807
  /**
25215
25808
  * Raised when the workspace's lockfile cannot be read off disk.
25216
25809
  *
@@ -25390,7 +25983,7 @@ var LockfileReader = class LockfileReader extends effect.Context.Service()("@eff
25390
25983
  static layerTest = (overrides = {}) => effect.Layer.succeed(LockfileReader, LockfileReader.makeTest(overrides));
25391
25984
  };
25392
25985
  //#endregion
25393
- //#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
25986
+ //#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
25394
25987
  /** The public npm registry, used when `publishConfig.registry` says nothing. */
25395
25988
  const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
25396
25989
  /**
@@ -25549,7 +26142,7 @@ var PublishabilityDetector = class extends effect.Context.Service()("@effected/w
25549
26142
  static layerNone = effect.Layer.succeed(this, this.none);
25550
26143
  };
25551
26144
  //#endregion
25552
- //#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
26145
+ //#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
25553
26146
  /**
25554
26147
  * Strip pnpm's peer-disambiguation suffix from a recorded importer version.
25555
26148
  *
@@ -25635,7 +26228,7 @@ const unanimousVersionOf = (index, dependency) => {
25635
26228
  return agreed;
25636
26229
  };
25637
26230
  //#endregion
25638
- //#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
26231
+ //#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
25639
26232
  /**
25640
26233
  * An immutable, fully-normalized catalog collection — the one catalog
25641
26234
  * resolution semantic in the package.
@@ -25839,6 +26432,41 @@ const inlineReleaseAge = (document) => {
25839
26432
  cause
25840
26433
  })));
25841
26434
  };
26435
+ /**
26436
+ * The `peerDependencyRules` a `pnpm-workspace.yaml` declares inline — the half
26437
+ * `pnpm:export` materializes into the file, as opposed to the half a config
26438
+ * dependency injects at replay time.
26439
+ *
26440
+ * @remarks
26441
+ * **Tolerant, unlike the catalog blocks**, and the asymmetry is deliberate: a
26442
+ * malformed catalog block must hard-fail because a silently-empty catalog makes
26443
+ * every dependency look newly added, whereas a malformed rules block costs only
26444
+ * suppression — the failure mode is reporting a peer pnpm would have hidden,
26445
+ * which is visible and safe. Failing the whole assembly over it would take the
26446
+ * catalogs down with it.
26447
+ *
26448
+ * Every axis is read independently, so a malformed `ignoreMissing` does not
26449
+ * discard a well-formed `allowedVersions`.
26450
+ */
26451
+ const EMPTY_PEER_RULES = {
26452
+ allowedVersions: {},
26453
+ ignoreMissing: [],
26454
+ allowAny: []
26455
+ };
26456
+ const inlinePeerDependencyRules = (document) => {
26457
+ if (!isObject$1(document) || !isObject$1(document.peerDependencyRules)) return EMPTY_PEER_RULES;
26458
+ const block = document.peerDependencyRules;
26459
+ const allowedVersions = {};
26460
+ if (isObject$1(block.allowedVersions)) {
26461
+ for (const [key, value] of Object.entries(block.allowedVersions)) if (typeof value === "string") allowedVersions[key] = value;
26462
+ }
26463
+ const strings = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : [];
26464
+ return {
26465
+ allowedVersions,
26466
+ ignoreMissing: strings(block.ignoreMissing),
26467
+ allowAny: strings(block.allowAny)
26468
+ };
26469
+ };
25842
26470
  /** A hard-fail catalog-assembly failure naming the malformed part of a `workspaces` field. */
25843
26471
  const malformed = (source, path, detail) => new CatalogAssemblyError({
25844
26472
  source,
@@ -25971,6 +26599,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
25971
26599
  let injected;
25972
26600
  let inlineGate = {};
25973
26601
  let hookGate = {};
26602
+ let peerDependencyRules = EMPTY_PEER_RULES;
25974
26603
  if (hasPnpmWorkspace) {
25975
26604
  const text = yield* fs.readFileString(workspaceYaml).pipe(effect.Effect.mapError((cause) => new CatalogAssemblyError({
25976
26605
  source: "manifest",
@@ -25985,15 +26614,17 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
25985
26614
  yield* validatePnpmWorkspaceCatalogs(document);
25986
26615
  inline = CatalogSet.fromCatalogs(inlineCatalogs(catalogBlocksOf(document)));
25987
26616
  inlineGate = yield* inlineReleaseAge(document);
25988
- const injection = yield* hooks.inject(root, configDependenciesOf(document), inline.entries);
26617
+ const injection = yield* hooks.inject(root, configDependenciesOf(document), inline.entries, inlinePeerDependencyRules(document));
25989
26618
  injected = CatalogSet.fromCatalogs(injection.catalogs);
25990
26619
  hookGate = injection.releaseAge;
26620
+ peerDependencyRules = injection.peerDependencyRules;
25991
26621
  } else {
25992
26622
  const manifestPath = path.join(root, "package.json");
25993
26623
  if (!(yield* probeExists(manifestPath))) return {
25994
26624
  catalogs: fromLockfile,
25995
26625
  releaseAgeGate: ReleaseAgeGate.combine(),
25996
- importerVersions
26626
+ importerVersions,
26627
+ peerDependencyRules: EMPTY_PEER_RULES
25997
26628
  };
25998
26629
  const text = yield* fs.readFileString(manifestPath).pipe(effect.Effect.mapError((cause) => new CatalogAssemblyError({
25999
26630
  source: "manifest",
@@ -26013,7 +26644,8 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
26013
26644
  return {
26014
26645
  catalogs: assembled,
26015
26646
  releaseAgeGate,
26016
- importerVersions
26647
+ importerVersions,
26648
+ peerDependencyRules
26017
26649
  };
26018
26650
  });
26019
26651
  const [resolveOnce, invalidate] = yield* effect.Effect.cachedInvalidateWithTTL(assemble, effect.Duration.infinity);
@@ -26025,6 +26657,9 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
26025
26657
  resolveSpecifier: effect.Effect.fn("WorkspaceCatalogs.resolveSpecifier")(function* (dependency, specifier) {
26026
26658
  return (yield* memo).catalogs.resolveSpecifier(dependency, specifier);
26027
26659
  }),
26660
+ peerDependencyRules: effect.Effect.fn("WorkspaceCatalogs.peerDependencyRules")(function* () {
26661
+ return (yield* memo).peerDependencyRules;
26662
+ }),
26028
26663
  releaseAgeGate: effect.Effect.fn("WorkspaceCatalogs.releaseAgeGate")(function* () {
26029
26664
  return (yield* memo).releaseAgeGate;
26030
26665
  }),
@@ -26111,6 +26746,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
26111
26746
  return {
26112
26747
  set: () => unstubbed$1("set"),
26113
26748
  resolveSpecifier: set !== void 0 ? (dependency, specifier) => effect.Effect.map(set(), (catalogs) => catalogs.resolveSpecifier(dependency, specifier)) : () => unstubbed$1("resolveSpecifier"),
26749
+ peerDependencyRules: () => unstubbed$1("peerDependencyRules"),
26114
26750
  releaseAgeGate: () => unstubbed$1("releaseAgeGate"),
26115
26751
  importerVersions: () => unstubbed$1("importerVersions"),
26116
26752
  ...overrides
@@ -26162,7 +26798,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends effect.Context.Service()
26162
26798
  }));
26163
26799
  };
26164
26800
  //#endregion
26165
- //#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
26801
+ //#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
26166
26802
  const EMPTY = Object.freeze(Object.create(null));
26167
26803
  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)));
26168
26804
  /**
@@ -26385,7 +27021,7 @@ var WorkspaceStateSnapshot = class extends effect.Schema.Class("WorkspaceStateSn
26385
27021
  }
26386
27022
  };
26387
27023
  //#endregion
26388
- //#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
27024
+ //#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
26389
27025
  /** Whether `value` is a non-null, non-array object. */
26390
27026
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
26391
27027
  /** Whether every value in a record is a string — a usable dependency map. */
@@ -26662,7 +27298,7 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends effect.Context.Service
26662
27298
  static layerTest = (overrides = {}) => effect.Layer.succeed(WorkspaceSnapshots, WorkspaceSnapshots.makeTest(overrides));
26663
27299
  };
26664
27300
  //#endregion
26665
- //#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
27301
+ //#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
26666
27302
  const compose = (options, catalogsFactory) => {
26667
27303
  const roots = WorkspaceRoot.layer;
26668
27304
  const detector = PackageManagerDetector.layer;