@savvy-web/silk 3.4.1 → 3.4.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.
@@ -1,5 +1,5 @@
1
1
  import { builtinModules, createRequire } from "node:module";
2
- import { Context, Data, Duration, Effect, Equal, Exit, FileSystem, Function, Hash, HashMap, Layer, Option, Order, Path, Pipeable, PlatformError, Predicate, Result, Schema, SchemaIssue, SchemaTransformation, Stream } from "effect";
2
+ import { Context, Data, Duration, Effect, Equal, Exit, FileSystem, Function, Hash, HashMap, Layer, Option, Order, Path, Pipeable, PlatformError, Predicate, Redacted, Ref, Result, Schema, SchemaIssue, SchemaTransformation, Stdio, Stream } from "effect";
3
3
  import * as path$1 from "node:path";
4
4
  import { basename, delimiter, dirname, isAbsolute, join, normalize, relative, resolve } from "node:path";
5
5
  import { ChildProcess, ChildProcessSpawner } from "effect/unstable/process";
@@ -2352,7 +2352,7 @@ var GlobSet = class GlobSet extends Schema.Class("GlobSet")(Schema.Struct({ patt
2352
2352
  };
2353
2353
 
2354
2354
  //#endregion
2355
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/BunExtension.js
2355
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/BunExtension.js
2356
2356
  /**
2357
2357
  * Extension data specific to bun lockfiles, attached to `Lockfile.extension`
2358
2358
  * when the format is `"bun"`.
@@ -2374,7 +2374,7 @@ var BunExtension = class extends Schema.Class("BunExtension")({
2374
2374
  }) {};
2375
2375
 
2376
2376
  //#endregion
2377
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogResolver.js
2377
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogResolver.js
2378
2378
  /**
2379
2379
  * Contract for resolving pnpm `catalog:` dependency specifiers to concrete
2380
2380
  * version ranges.
@@ -2410,7 +2410,7 @@ var BunExtension = class extends Schema.Class("BunExtension")({
2410
2410
  *
2411
2411
  * @public
2412
2412
  */
2413
- var CatalogResolver = class CatalogResolver extends Context.Service()("@effected/npm/CatalogResolver") {
2413
+ var CatalogResolver$1 = class CatalogResolver extends Context.Service()("@effected/npm/CatalogResolver") {
2414
2414
  /**
2415
2415
  * No-op default: `rangeOf` always succeeds with `Option.none()`, never
2416
2416
  * consulting an actual catalog. A pure `Layer.succeed`, bound to a const
@@ -2421,7 +2421,7 @@ var CatalogResolver = class CatalogResolver extends Context.Service()("@effected
2421
2421
  };
2422
2422
 
2423
2423
  //#endregion
2424
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/WorkspaceResolver.js
2424
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/WorkspaceResolver.js
2425
2425
  /**
2426
2426
  * Raised when a `catalog:` or `workspace:` specifier cannot be resolved
2427
2427
  * because the resolution mechanism itself failed — not for an ordinary
@@ -2435,7 +2435,7 @@ var CatalogResolver = class CatalogResolver extends Context.Service()("@effected
2435
2435
  *
2436
2436
  * @public
2437
2437
  */
2438
- var DependencyResolutionError = class extends Schema.TaggedErrorClass()("DependencyResolutionError", {
2438
+ var DependencyResolutionError$1 = class extends Schema.TaggedErrorClass()("DependencyResolutionError", {
2439
2439
  specifier: Schema.String,
2440
2440
  cause: Schema.Defect()
2441
2441
  }) {
@@ -2473,7 +2473,7 @@ var DependencyResolutionError = class extends Schema.TaggedErrorClass()("Depende
2473
2473
  *
2474
2474
  * @public
2475
2475
  */
2476
- var WorkspaceResolver = class WorkspaceResolver extends Context.Service()("@effected/npm/WorkspaceResolver") {
2476
+ var WorkspaceResolver$1 = class WorkspaceResolver extends Context.Service()("@effected/npm/WorkspaceResolver") {
2477
2477
  /**
2478
2478
  * No-op default: `versionOf` always succeeds with `Option.none()`, never
2479
2479
  * consulting an actual workspace. A pure `Layer.succeed`, bound to a
@@ -2483,7 +2483,7 @@ var WorkspaceResolver = class WorkspaceResolver extends Context.Service()("@effe
2483
2483
  };
2484
2484
 
2485
2485
  //#endregion
2486
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogAssemblyError.js
2486
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogAssemblyError.js
2487
2487
  /**
2488
2488
  * Raised when a workspace's catalogs cannot be assembled — a `pnpm-workspace.yaml`
2489
2489
  * that is unreadable or not valid YAML, a root `package.json` `workspaces` field
@@ -2528,14 +2528,14 @@ var CatalogAssemblyError = class extends Schema.TaggedErrorClass()("CatalogAssem
2528
2528
  };
2529
2529
 
2530
2530
  //#endregion
2531
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySection.js
2531
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySection.js
2532
2532
  /**
2533
2533
  * The short dependency kind: which dependency map an entry came from, named the
2534
2534
  * way consumers branch on it.
2535
2535
  *
2536
2536
  * @public
2537
2537
  */
2538
- const DependencyKind = Schema.Literals([
2538
+ const DependencyKind$1 = Schema.Literals([
2539
2539
  "prod",
2540
2540
  "dev",
2541
2541
  "peer",
@@ -2547,19 +2547,19 @@ const DependencyKind = Schema.Literals([
2547
2547
  *
2548
2548
  * @public
2549
2549
  */
2550
- const DependencyField = Schema.Literals([
2550
+ const DependencyField$1 = Schema.Literals([
2551
2551
  "dependencies",
2552
2552
  "devDependencies",
2553
2553
  "peerDependencies",
2554
2554
  "optionalDependencies"
2555
2555
  ]);
2556
- const KIND_TO_FIELD = {
2556
+ const KIND_TO_FIELD$1 = {
2557
2557
  prod: "dependencies",
2558
2558
  dev: "devDependencies",
2559
2559
  peer: "peerDependencies",
2560
2560
  optional: "optionalDependencies"
2561
2561
  };
2562
- const FIELD_TO_KIND = Object.fromEntries(Object.entries(KIND_TO_FIELD).map(([kind, field]) => [field, kind]));
2562
+ const FIELD_TO_KIND$1 = Object.fromEntries(Object.entries(KIND_TO_FIELD$1).map(([kind, field]) => [field, kind]));
2563
2563
 
2564
2564
  //#endregion
2565
2565
  //#region ../../node_modules/.pnpm/@effected+semver@0.3.2_effect@4.0.0-beta.101/node_modules/@effected/semver/internal/desugar.js
@@ -2937,7 +2937,7 @@ const parseRangeComparators = (s) => {
2937
2937
  * Parse a range expression into comparator sets (OR of ANDs). The empty
2938
2938
  * string parses as the match-all range.
2939
2939
  */
2940
- const parseRange$1 = (raw) => {
2940
+ const parseRange$2 = (raw) => {
2941
2941
  const trimmed = raw.trim();
2942
2942
  if (trimmed.length === 0) return {
2943
2943
  ok: true,
@@ -3841,7 +3841,7 @@ sets: Schema.Array(Schema.Array(Comparator)) }) {
3841
3841
  */
3842
3842
  static FromString = Schema.String.pipe(Schema.decodeTo(Range, SchemaTransformation.transformOrFail({
3843
3843
  decode: (input) => {
3844
- const result = parseRange$1(input);
3844
+ const result = parseRange$2(input);
3845
3845
  return result.ok ? Effect.succeed({ sets: normalizeSets(result.value) }) : Effect.fail(new SchemaIssue.InvalidValue(Option.some(input), { message: `Invalid range expression: "${result.input}" at position ${result.position}` }));
3846
3846
  },
3847
3847
  encode: (parts) => Effect.succeed(formatRange(parts.sets))
@@ -3872,7 +3872,7 @@ sets: Schema.Array(Schema.Array(Comparator)) }) {
3872
3872
  * with {@link InvalidRangeError}.
3873
3873
  */
3874
3874
  static parseResult(input) {
3875
- const result = parseRange$1(input);
3875
+ const result = parseRange$2(input);
3876
3876
  if (!result.ok) return Result.fail(new InvalidRangeError({
3877
3877
  input: result.input,
3878
3878
  position: result.position
@@ -4152,7 +4152,7 @@ const isComparatorSetSubset = (sub, sup) => {
4152
4152
  };
4153
4153
 
4154
4154
  //#endregion
4155
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySpecifier.js
4155
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySpecifier.js
4156
4156
  /**
4157
4157
  * Indicates that a string could not be parsed as a valid dependency specifier.
4158
4158
  *
@@ -4161,50 +4161,50 @@ const isComparatorSetSubset = (sub, sup) => {
4161
4161
  *
4162
4162
  * @public
4163
4163
  */
4164
- var InvalidDependencySpecifierError = class extends Schema.TaggedErrorClass()("InvalidDependencySpecifierError", {
4164
+ var InvalidDependencySpecifierError$1 = class extends Schema.TaggedErrorClass()("InvalidDependencySpecifierError", {
4165
4165
  /** The raw input string that failed validation. */
4166
4166
  input: Schema.String }) {
4167
4167
  get message() {
4168
4168
  return `Invalid dependency specifier "${this.input}": not a recognized specifier`;
4169
4169
  }
4170
4170
  };
4171
- const CATALOG_PREFIX = "catalog:";
4172
- const WORKSPACE_PREFIX = "workspace:";
4173
- const isBarePath = (value) => value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.startsWith("/");
4174
- const isGitHubShorthand = (value) => !value.startsWith(".") && !value.startsWith("~") && !value.startsWith("/") && /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(#.*)?$/.test(value);
4175
- const isGit = (value) => value.startsWith("git+") || value.startsWith("git://") || value.startsWith("github:") || value.startsWith("gist:") || value.startsWith("bitbucket:") || value.startsWith("gitlab:") || isGitHubShorthand(value);
4176
- const isLocal = (value) => value.startsWith("file:") || value.startsWith("link:") || value.startsWith("portal:") || isBarePath(value);
4177
- const isLink = (value) => value.startsWith("link:");
4178
- const isPortal = (value) => value.startsWith("portal:");
4179
- const isCatalog = (value) => value.startsWith(CATALOG_PREFIX);
4180
- const isWorkspace = (value) => value.startsWith(WORKSPACE_PREFIX);
4181
- const isUrl$1 = (value) => value.startsWith("http://") || value.startsWith("https://");
4182
- const parseRange = (value) => {
4171
+ const CATALOG_PREFIX$1 = "catalog:";
4172
+ const WORKSPACE_PREFIX$1 = "workspace:";
4173
+ const isBarePath$1 = (value) => value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.startsWith("/");
4174
+ const isGitHubShorthand$1 = (value) => !value.startsWith(".") && !value.startsWith("~") && !value.startsWith("/") && /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(#.*)?$/.test(value);
4175
+ const isGit$1 = (value) => value.startsWith("git+") || value.startsWith("git://") || value.startsWith("github:") || value.startsWith("gist:") || value.startsWith("bitbucket:") || value.startsWith("gitlab:") || isGitHubShorthand$1(value);
4176
+ const isLocal$1 = (value) => value.startsWith("file:") || value.startsWith("link:") || value.startsWith("portal:") || isBarePath$1(value);
4177
+ const isLink$1 = (value) => value.startsWith("link:");
4178
+ const isPortal$1 = (value) => value.startsWith("portal:");
4179
+ const isCatalog$1 = (value) => value.startsWith(CATALOG_PREFIX$1);
4180
+ const isWorkspace$1 = (value) => value.startsWith(WORKSPACE_PREFIX$1);
4181
+ const isUrl$2 = (value) => value.startsWith("http://") || value.startsWith("https://");
4182
+ const parseRange$1 = (value) => {
4183
4183
  const exit = Schema.decodeUnknownExit(Range$1.FromString)(value);
4184
4184
  return Exit.isSuccess(exit) ? Option.some(exit.value) : Option.none();
4185
4185
  };
4186
- const isRange = (value) => Option.isSome(parseRange(value));
4187
- const protocolOf = (value) => {
4188
- if (value.startsWith(CATALOG_PREFIX)) return "catalog";
4189
- if (value.startsWith(WORKSPACE_PREFIX)) return "workspace";
4186
+ const isRange$1 = (value) => Option.isSome(parseRange$1(value));
4187
+ const protocolOf$1 = (value) => {
4188
+ if (value.startsWith(CATALOG_PREFIX$1)) return "catalog";
4189
+ if (value.startsWith(WORKSPACE_PREFIX$1)) return "workspace";
4190
4190
  if (value.startsWith("link:")) return "link";
4191
4191
  if (value.startsWith("portal:")) return "portal";
4192
- if (value.startsWith("file:") || isBarePath(value)) return "file";
4192
+ if (value.startsWith("file:") || isBarePath$1(value)) return "file";
4193
4193
  if (value.startsWith("npm:")) return "npm";
4194
- if (isGit(value)) return "git";
4195
- if (isUrl$1(value)) return "url";
4196
- if (isRange(value)) return "range";
4194
+ if (isGit$1(value)) return "git";
4195
+ if (isUrl$2(value)) return "url";
4196
+ if (isRange$1(value)) return "range";
4197
4197
  if (/^[a-zA-Z][a-zA-Z0-9._-]*$/.test(value)) return "tag";
4198
4198
  return "unknown";
4199
4199
  };
4200
- const isTag = (value) => protocolOf(value) === "tag";
4201
- const catalogNameOf$1 = (specifier) => {
4202
- if (!isCatalog(specifier)) return Option.none();
4200
+ const isTag$1 = (value) => protocolOf$1(value) === "tag";
4201
+ const catalogNameOf$2 = (specifier) => {
4202
+ if (!isCatalog$1(specifier)) return Option.none();
4203
4203
  const rest = specifier.slice(8).trim();
4204
4204
  return rest.length === 0 ? Option.none() : Option.some(rest);
4205
4205
  };
4206
- const projectRangeModifier = (range, version) => range === "*" || range === "" ? version : range === "~" ? `~${version}` : range === "^" ? `^${version}` : range;
4207
- const splitWorkspaceRest = (rest) => {
4206
+ const projectRangeModifier$1 = (range, version) => range === "*" || range === "" ? version : range === "~" ? `~${version}` : range === "^" ? `^${version}` : range;
4207
+ const splitWorkspaceRest$1 = (rest) => {
4208
4208
  const at = rest.lastIndexOf("@");
4209
4209
  return at > 0 ? {
4210
4210
  target: rest.slice(0, at),
@@ -4214,15 +4214,15 @@ const splitWorkspaceRest = (rest) => {
4214
4214
  range: rest
4215
4215
  };
4216
4216
  };
4217
- const projectWorkspaceRange = (rest, version) => {
4218
- const { target, range } = splitWorkspaceRest(rest);
4219
- const projected = projectRangeModifier(range, version);
4217
+ const projectWorkspaceRange$1 = (rest, version) => {
4218
+ const { target, range } = splitWorkspaceRest$1(rest);
4219
+ const projected = projectRangeModifier$1(range, version);
4220
4220
  return target === void 0 ? projected : `npm:${target}@${projected}`;
4221
4221
  };
4222
- const resolveWorkspace = (specifier, version) => isWorkspace(specifier) ? projectWorkspaceRange(specifier.slice(10), version) : specifier;
4223
- const workspaceTargetOf = (specifier) => {
4224
- if (!isWorkspace(specifier)) return Option.none();
4225
- const { target } = splitWorkspaceRest(specifier.slice(10));
4222
+ const resolveWorkspace$1 = (specifier, version) => isWorkspace$1(specifier) ? projectWorkspaceRange$1(specifier.slice(10), version) : specifier;
4223
+ const workspaceTargetOf$1 = (specifier) => {
4224
+ if (!isWorkspace$1(specifier)) return Option.none();
4225
+ const { target } = splitWorkspaceRest$1(specifier.slice(10));
4226
4226
  return target === void 0 ? Option.none() : Option.some(target);
4227
4227
  };
4228
4228
  /**
@@ -4232,14 +4232,14 @@ const workspaceTargetOf = (specifier) => {
4232
4232
  *
4233
4233
  * @public
4234
4234
  */
4235
- const isValidDependencySpecifier = (value) => value.length > 0 && protocolOf(value) !== "unknown";
4235
+ const isValidDependencySpecifier$1 = (value) => value.length > 0 && protocolOf$1(value) !== "unknown";
4236
4236
  /**
4237
4237
  * A `catalog:` reference. `name` carries the catalog name, or `Option.none()`
4238
4238
  * for the default catalog (`catalog:`).
4239
4239
  *
4240
4240
  * @public
4241
4241
  */
4242
- var CatalogSpecifier = class extends Schema.TaggedClass()("catalog", {
4242
+ var CatalogSpecifier$1 = class extends Schema.TaggedClass()("catalog", {
4243
4243
  /** The original specifier string. */
4244
4244
  raw: Schema.String,
4245
4245
  /** The catalog name, or `Option.none()` for the default catalog. */
@@ -4251,7 +4251,7 @@ var CatalogSpecifier = class extends Schema.TaggedClass()("catalog", {
4251
4251
  *
4252
4252
  * @public
4253
4253
  */
4254
- var WorkspaceSpecifier = class extends Schema.TaggedClass()("workspace", {
4254
+ var WorkspaceSpecifier$1 = class extends Schema.TaggedClass()("workspace", {
4255
4255
  /** The original specifier string. */
4256
4256
  raw: Schema.String,
4257
4257
  /** The part after `workspace:` (e.g. `*`, `^1.2.3`, or an alias form). */
@@ -4275,7 +4275,7 @@ var WorkspaceSpecifier = class extends Schema.TaggedClass()("workspace", {
4275
4275
  * specifier points at (the alias target's version for the alias form).
4276
4276
  */
4277
4277
  resolve(version) {
4278
- return projectWorkspaceRange(this.range, version);
4278
+ return projectWorkspaceRange$1(this.range, version);
4279
4279
  }
4280
4280
  };
4281
4281
  /**
@@ -4283,7 +4283,7 @@ var WorkspaceSpecifier = class extends Schema.TaggedClass()("workspace", {
4283
4283
  *
4284
4284
  * @public
4285
4285
  */
4286
- var RangeSpecifier = class extends Schema.TaggedClass()("range", {
4286
+ var RangeSpecifier$1 = class extends Schema.TaggedClass()("range", {
4287
4287
  /** The original specifier string. */
4288
4288
  raw: Schema.String }) {};
4289
4289
  /**
@@ -4291,7 +4291,7 @@ raw: Schema.String }) {};
4291
4291
  *
4292
4292
  * @public
4293
4293
  */
4294
- var DistTagSpecifier = class extends Schema.TaggedClass()("dist-tag", {
4294
+ var DistTagSpecifier$1 = class extends Schema.TaggedClass()("dist-tag", {
4295
4295
  /** The original specifier string (also the tag name). */
4296
4296
  raw: Schema.String }) {};
4297
4297
  /**
@@ -4300,35 +4300,35 @@ raw: Schema.String }) {};
4300
4300
  *
4301
4301
  * @public
4302
4302
  */
4303
- var RawSpecifier = class extends Schema.TaggedClass()("raw", {
4303
+ var RawSpecifier$1 = class extends Schema.TaggedClass()("raw", {
4304
4304
  /** The original specifier string. */
4305
4305
  raw: Schema.String }) {};
4306
- const Classified = Schema.Union([
4307
- CatalogSpecifier,
4308
- WorkspaceSpecifier,
4309
- RangeSpecifier,
4310
- DistTagSpecifier,
4311
- RawSpecifier
4306
+ const Classified$1 = Schema.Union([
4307
+ CatalogSpecifier$1,
4308
+ WorkspaceSpecifier$1,
4309
+ RangeSpecifier$1,
4310
+ DistTagSpecifier$1,
4311
+ RawSpecifier$1
4312
4312
  ]);
4313
- const classify$1 = (value) => {
4314
- if (isCatalog(value)) return CatalogSpecifier.make({
4313
+ const classify$2 = (value) => {
4314
+ if (isCatalog$1(value)) return CatalogSpecifier$1.make({
4315
4315
  raw: value,
4316
- name: catalogNameOf$1(value)
4316
+ name: catalogNameOf$2(value)
4317
4317
  });
4318
- if (isWorkspace(value)) return WorkspaceSpecifier.make({
4318
+ if (isWorkspace$1(value)) return WorkspaceSpecifier$1.make({
4319
4319
  raw: value,
4320
4320
  range: value.slice(10)
4321
4321
  });
4322
- if (isRange(value)) return RangeSpecifier.make({ raw: value });
4323
- if (isTag(value)) return DistTagSpecifier.make({ raw: value });
4324
- return RawSpecifier.make({ raw: value });
4322
+ if (isRange$1(value)) return RangeSpecifier$1.make({ raw: value });
4323
+ if (isTag$1(value)) return DistTagSpecifier$1.make({ raw: value });
4324
+ return RawSpecifier$1.make({ raw: value });
4325
4325
  };
4326
- const fromString = Schema.String.pipe(Schema.decodeTo(Classified, SchemaTransformation.transformOrFail({
4327
- decode: (input) => isValidDependencySpecifier(input) ? Effect.succeed(classify$1(input)) : Effect.fail(new SchemaIssue.InvalidValue(Option.some(input), { message: `Invalid dependency specifier: "${input}"` })),
4326
+ const fromString$1 = Schema.String.pipe(Schema.decodeTo(Classified$1, SchemaTransformation.transformOrFail({
4327
+ decode: (input) => isValidDependencySpecifier$1(input) ? Effect.succeed(classify$2(input)) : Effect.fail(new SchemaIssue.InvalidValue(Option.some(input), { message: `Invalid dependency specifier: "${input}"` })),
4328
4328
  encode: (classified) => Effect.succeed(classified.raw)
4329
4329
  })));
4330
- const brandedSpecifier = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => isValidDependencySpecifier(value) ? void 0 : "Expected a valid dependency specifier")), Schema.brand("DependencySpecifier"));
4331
- const decode$3 = (input) => Schema.decodeUnknownEffect(brandedSpecifier)(input).pipe(Effect.mapError(() => new InvalidDependencySpecifierError({ input })));
4330
+ const brandedSpecifier$1 = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => isValidDependencySpecifier$1(value) ? void 0 : "Expected a valid dependency specifier")), Schema.brand("DependencySpecifier"));
4331
+ const decode$5 = (input) => Schema.decodeUnknownEffect(brandedSpecifier$1)(input).pipe(Effect.mapError(() => new InvalidDependencySpecifierError$1({ input })));
4332
4332
  /**
4333
4333
  * A valid dependency version specifier, carrying the protocol taxonomy statics
4334
4334
  * (`DependencySpecifier.protocolOf` and friends) that classify any specifier
@@ -4339,44 +4339,44 @@ const decode$3 = (input) => Schema.decodeUnknownEffect(brandedSpecifier)(input).
4339
4339
  *
4340
4340
  * @public
4341
4341
  */
4342
- const DependencySpecifier = Object.assign(brandedSpecifier, {
4343
- protocolOf,
4344
- parseRange,
4345
- isRange,
4346
- isTag,
4347
- isGit,
4348
- isUrl: isUrl$1,
4349
- isLocal,
4350
- isLink,
4351
- isPortal,
4352
- isCatalog,
4353
- isWorkspace,
4354
- catalogNameOf: catalogNameOf$1,
4355
- resolveWorkspace,
4356
- workspaceTargetOf,
4357
- isValid: isValidDependencySpecifier,
4358
- decode: decode$3,
4359
- FromString: fromString
4342
+ const DependencySpecifier$1 = Object.assign(brandedSpecifier$1, {
4343
+ protocolOf: protocolOf$1,
4344
+ parseRange: parseRange$1,
4345
+ isRange: isRange$1,
4346
+ isTag: isTag$1,
4347
+ isGit: isGit$1,
4348
+ isUrl: isUrl$2,
4349
+ isLocal: isLocal$1,
4350
+ isLink: isLink$1,
4351
+ isPortal: isPortal$1,
4352
+ isCatalog: isCatalog$1,
4353
+ isWorkspace: isWorkspace$1,
4354
+ catalogNameOf: catalogNameOf$2,
4355
+ resolveWorkspace: resolveWorkspace$1,
4356
+ workspaceTargetOf: workspaceTargetOf$1,
4357
+ isValid: isValidDependencySpecifier$1,
4358
+ decode: decode$5,
4359
+ FromString: fromString$1
4360
4360
  });
4361
4361
 
4362
4362
  //#endregion
4363
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/IntegrityHash.js
4364
- const SRI_RE = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
4365
- const COREPACK_RE = /^(sha1|sha224|sha256|sha384|sha512)\.[0-9a-f]+$/;
4366
- const YARN_RE = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
4367
- const isSri = (value) => SRI_RE.test(value);
4368
- const isCorepack = (value) => COREPACK_RE.test(value);
4369
- const isYarnChecksum = (value) => YARN_RE.test(value);
4363
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/IntegrityHash.js
4364
+ const SRI_RE$1 = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
4365
+ const COREPACK_RE$1 = /^(sha1|sha224|sha256|sha384|sha512)\.[0-9a-f]+$/;
4366
+ const YARN_RE$1 = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
4367
+ const isSri$1 = (value) => SRI_RE$1.test(value);
4368
+ const isCorepack$1 = (value) => COREPACK_RE$1.test(value);
4369
+ const isYarnChecksum$1 = (value) => YARN_RE$1.test(value);
4370
4370
  /**
4371
4371
  * Whether a string is a valid integrity hash in the SRI (`<algo>-<base64>`),
4372
4372
  * corepack (`<algo>.<hex>`) or yarn (`<cachekey>/<hex>`) form.
4373
4373
  *
4374
4374
  * @public
4375
4375
  */
4376
- const isValidIntegrityHash = (value) => isSri(value) || isCorepack(value) || isYarnChecksum(value);
4377
- const algorithmOf = (value) => {
4378
- if (isSri(value)) return Option.some(value.slice(0, value.indexOf("-")));
4379
- if (isCorepack(value)) return Option.some(value.slice(0, value.indexOf(".")));
4376
+ const isValidIntegrityHash$1 = (value) => isSri$1(value) || isCorepack$1(value) || isYarnChecksum$1(value);
4377
+ const algorithmOf$1 = (value) => {
4378
+ if (isSri$1(value)) return Option.some(value.slice(0, value.indexOf("-")));
4379
+ if (isCorepack$1(value)) return Option.some(value.slice(0, value.indexOf(".")));
4380
4380
  return Option.none();
4381
4381
  };
4382
4382
  /**
@@ -4387,15 +4387,15 @@ const algorithmOf = (value) => {
4387
4387
  *
4388
4388
  * @public
4389
4389
  */
4390
- var InvalidIntegrityHashError = class extends Schema.TaggedErrorClass()("InvalidIntegrityHashError", {
4390
+ var InvalidIntegrityHashError$1 = class extends Schema.TaggedErrorClass()("InvalidIntegrityHashError", {
4391
4391
  /** The raw input string that failed validation. */
4392
4392
  input: Schema.String }) {
4393
4393
  get message() {
4394
4394
  return `Invalid integrity hash "${this.input}": expected an SRI (<algo>-<base64>), corepack (<algo>.<hex>) or yarn (<cachekey>/<hex>) form`;
4395
4395
  }
4396
4396
  };
4397
- const brandedIntegrity = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => isValidIntegrityHash(value) ? void 0 : "Expected an SRI, corepack or yarn integrity hash")), Schema.brand("IntegrityHash"));
4398
- const decode$2 = (input) => Schema.decodeUnknownEffect(brandedIntegrity)(input).pipe(Effect.mapError(() => new InvalidIntegrityHashError({ input })));
4397
+ const brandedIntegrity$1 = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => isValidIntegrityHash$1(value) ? void 0 : "Expected an SRI, corepack or yarn integrity hash")), Schema.brand("IntegrityHash"));
4398
+ const decode$4 = (input) => Schema.decodeUnknownEffect(brandedIntegrity$1)(input).pipe(Effect.mapError(() => new InvalidIntegrityHashError$1({ input })));
4399
4399
  /**
4400
4400
  * A subresource-integrity hash, covering the SRI (`sha512-<base64>`), corepack
4401
4401
  * (`sha512.<hex>`) and yarn (`10c0/<hex>`) textual forms, carrying taxonomy
@@ -4404,13 +4404,13 @@ const decode$2 = (input) => Schema.decodeUnknownEffect(brandedIntegrity)(input).
4404
4404
  *
4405
4405
  * @public
4406
4406
  */
4407
- const IntegrityHash = Object.assign(brandedIntegrity, {
4408
- isSri,
4409
- isCorepack,
4410
- isYarnChecksum,
4411
- isValid: isValidIntegrityHash,
4412
- algorithmOf,
4413
- decode: decode$2
4407
+ const IntegrityHash$1 = Object.assign(brandedIntegrity$1, {
4408
+ isSri: isSri$1,
4409
+ isCorepack: isCorepack$1,
4410
+ isYarnChecksum: isYarnChecksum$1,
4411
+ isValid: isValidIntegrityHash$1,
4412
+ algorithmOf: algorithmOf$1,
4413
+ decode: decode$4
4414
4414
  });
4415
4415
  /**
4416
4416
  * {@link (IntegrityHash:variable)} narrowed to the corepack `<algo>.<hex>` form
@@ -4463,10 +4463,10 @@ const IntegrityHash = Object.assign(brandedIntegrity, {
4463
4463
  *
4464
4464
  * @public
4465
4465
  */
4466
- const CorepackIntegrityHash = brandedIntegrity.pipe(Schema.check(Schema.makeFilter((value) => isCorepack(value) ? void 0 : "Expected a corepack (<algo>.<hex>) integrity hash")));
4466
+ const CorepackIntegrityHash$1 = brandedIntegrity$1.pipe(Schema.check(Schema.makeFilter((value) => isCorepack$1(value) ? void 0 : "Expected a corepack (<algo>.<hex>) integrity hash")));
4467
4467
 
4468
4468
  //#endregion
4469
- //#region ../../node_modules/.pnpm/@effected+commands@0.2.1_effect@4.0.0-beta.101/node_modules/@effected/commands/LocalExec.js
4469
+ //#region ../../node_modules/.pnpm/@effected+commands@0.3.1_effect@4.0.0-beta.101/node_modules/@effected/commands/LocalExec.js
4470
4470
  /**
4471
4471
  * The package managers whose project-local exec argv this package knows.
4472
4472
  *
@@ -4675,723 +4675,1397 @@ var LocalExec = class LocalExec extends Context.Service()("@effected/commands/Lo
4675
4675
  };
4676
4676
 
4677
4677
  //#endregion
4678
- //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/ReleaseAgeGate.js
4679
- const MS_PER_MINUTE = 6e4;
4678
+ //#region ../../node_modules/.pnpm/@effected+commands@0.3.1_effect@4.0.0-beta.101/node_modules/@effected/commands/Redaction.js
4680
4679
  /**
4681
- * A source's partial contribution to a {@link ReleaseAgeGate}: the effective
4682
- * gate is assembled from more than one place (inline `pnpm-workspace.yaml`
4683
- * keys, replayed `updateConfig` hooks, `pnpm config get` output), and each
4684
- * source may set the age, the exclude list, both, or neither. Absent fields
4685
- * contribute nothing to the combination.
4680
+ * Argument tokens whose *following* positional (or `=`-joined value) is a
4681
+ * secret. Lowercase; matching is case-insensitive.
4686
4682
  *
4687
- * Deliberately permissive: unlike {@link ReleaseAgeGate} it does not constrain
4688
- * `ageMinutes` to be non-negative, because the raw values arrive from arbitrary
4689
- * config sources and {@link ReleaseAgeGate.combine} is the single authority
4690
- * that clamps them.
4683
+ * @remarks
4684
+ * This is the heuristic backstop, not the primary mechanism it can only know
4685
+ * about flags someone thought to list. The primary mechanism is
4686
+ * {@link Redaction.applyArgs}, which redacts by **value**: the caller says what
4687
+ * its secrets are and every occurrence goes, whatever flag carried it.
4691
4688
  *
4692
4689
  * @public
4693
4690
  */
4694
- const PartialReleaseAgeGate = Schema.Struct({
4695
- /** Minutes a release must age; absent means this source sets no age. */
4696
- ageMinutes: Schema.optionalKey(Schema.Number),
4697
- /** Exempt package-name patterns; absent means this source adds no exemptions. */
4698
- exclude: Schema.optionalKey(Schema.Array(Schema.String))
4699
- });
4700
- const AgeMinutes = Schema.Number.check(Schema.isGreaterThanOrEqualTo(0), Schema.isFinite());
4701
- const matchesPattern = (name, pattern) => {
4702
- if (pattern === name) return true;
4703
- if (!pattern.includes("*")) return false;
4704
- let nameIndex = 0;
4705
- let patternIndex = 0;
4706
- let starIndex = -1;
4707
- let retryNameIndex = 0;
4708
- while (nameIndex < name.length) if (pattern[patternIndex] === "*") {
4709
- starIndex = patternIndex;
4710
- patternIndex += 1;
4711
- retryNameIndex = nameIndex;
4712
- } else if (pattern[patternIndex] === name[nameIndex]) {
4713
- patternIndex += 1;
4714
- nameIndex += 1;
4715
- } else if (starIndex !== -1) {
4716
- patternIndex = starIndex + 1;
4717
- retryNameIndex += 1;
4718
- nameIndex = retryNameIndex;
4719
- } else return false;
4720
- while (pattern[patternIndex] === "*") patternIndex += 1;
4721
- return patternIndex === pattern.length;
4722
- };
4723
- const matchesExclude = (name, patterns) => patterns.some((pattern) => matchesPattern(name, pattern));
4691
+ const SECRET_FLAGS = /* @__PURE__ */ new Set([
4692
+ "--access-token",
4693
+ "--api-key",
4694
+ "--auth",
4695
+ "--auth-token",
4696
+ "--otp",
4697
+ "--password",
4698
+ "--registry-token",
4699
+ "--token"
4700
+ ]);
4724
4701
  /**
4725
- * pnpm's publish-time release-age gate: the number of minutes a published
4726
- * version must age before it is eligible, and the set of package-name patterns
4727
- * exempt from the gate. Mirrors pnpm's `minimumReleaseAge` /
4728
- * `minimumReleaseAgeExclude` config so a resolver can drop too-young candidate
4729
- * versions before picking, avoiding `ERR_PNPM_NO_MATURE_MATCHING_VERSION`.
4730
- *
4731
- * `ageMinutes` is constrained non-negative and finite; a `ReleaseAgeGate` with
4732
- * `ageMinutes <= 0` is an inert gate that filters nothing. Assemble a gate from
4733
- * multiple config sources with {@link ReleaseAgeGate.combine}, and apply it to
4734
- * a package's candidate versions with {@link ReleaseAgeGate.filterVersions}.
4735
- *
4736
- * @example
4737
- * ```ts
4738
- * import { ReleaseAgeGate } from "@effected/npm";
4702
+ * npm config keys whose value is a credential (`//registry/:_authToken`,
4703
+ * `//registry/:_password`).
4704
+ */
4705
+ const AUTH_KEY = /:(?:_authtoken|_password)$/i;
4706
+ /**
4707
+ * The distinct, non-empty secret values, longest first.
4739
4708
  *
4740
- * const gate = ReleaseAgeGate.combine(
4741
- * { ageMinutes: 1440 },
4742
- * { exclude: ["@my-scope/*"] },
4743
- * );
4744
- * // gate.ageMinutes === 1440, gate.exclude === ["@my-scope/*"]
4709
+ * @remarks
4710
+ * Longest-first is load-bearing: redacting `"ab"` before `"abcd"` rewrites
4711
+ * `"abcd"` to `"***cd"`, leaking `"cd"` — a fragment of the longer secret.
4712
+ * Empty values are dropped because `"abc".split("").join("***")` would insert
4713
+ * the placeholder between every character.
4714
+ */
4715
+ const prepare = (secrets) => [...new Set(secrets.map(Redacted.value))].filter((value) => value.length > 0).sort((a, b) => b.length - a.length);
4716
+ /** Replaces each prepared value with {@link REDACTED}, literally (never as a pattern). */
4717
+ const replaceAll = (text, values) => {
4718
+ let out = text;
4719
+ for (const value of values) out = out.split(value).join("***");
4720
+ return out;
4721
+ };
4722
+ const apply = (text, secrets) => secrets.length === 0 ? text : replaceAll(text, prepare(secrets));
4723
+ const applyArgs = (args, secrets) => {
4724
+ if (secrets.length === 0) return args;
4725
+ const values = prepare(secrets);
4726
+ return args.map((arg) => replaceAll(arg, values));
4727
+ };
4728
+ /** Whether `name` introduces a credential value. */
4729
+ const isSecretName = (name, extra) => {
4730
+ const lower = name.toLowerCase();
4731
+ return SECRET_FLAGS.has(lower) || extra.has(lower) || AUTH_KEY.test(name);
4732
+ };
4733
+ const scrubArgs = (args, options) => {
4734
+ const extra = new Set((options?.flags ?? []).map((flag) => flag.toLowerCase()));
4735
+ const out = [];
4736
+ for (let index = 0; index < args.length; index++) {
4737
+ const arg = args[index] ?? "";
4738
+ const equals = arg.indexOf("=");
4739
+ if (equals > 0 && isSecretName(arg.slice(0, equals), extra)) {
4740
+ out.push(`${arg.slice(0, equals)}=***`);
4741
+ continue;
4742
+ }
4743
+ out.push(arg);
4744
+ if (isSecretName(arg, extra) && index + 1 < args.length) {
4745
+ out.push("***");
4746
+ index++;
4747
+ }
4748
+ }
4749
+ return out;
4750
+ };
4751
+ /**
4752
+ * Secret scrubbing for command arguments and captured output.
4745
4753
  *
4746
- * const eligible = gate.filterVersions(
4747
- * ["1.0.0", "1.0.1"],
4748
- * { "1.0.0": "2020-01-01T00:00:00Z", "1.0.1": "2026-07-21T00:00:00Z" },
4749
- * "prettier",
4750
- * Date.now(),
4751
- * );
4752
- * ```
4754
+ * @remarks
4755
+ * Two mechanisms, deliberately layered. {@link Redaction.apply} and
4756
+ * {@link Redaction.applyArgs} redact **by value** — the caller declares its
4757
+ * secrets as `Redacted` and every occurrence is removed wherever it appears.
4758
+ * {@link Redaction.scrubArgs} is a **flag heuristic** that runs in addition, for
4759
+ * the secrets a caller forgot to declare.
4753
4760
  *
4754
4761
  * @public
4755
4762
  */
4756
- var ReleaseAgeGate = class ReleaseAgeGate extends Schema.Class("ReleaseAgeGate")({
4757
- /** Minutes a published version must age before it is eligible (non-negative, finite). */
4758
- ageMinutes: AgeMinutes,
4759
- /** Package-name patterns exempt from the gate (exact names or `*`-globs). */
4760
- exclude: Schema.Array(Schema.String)
4761
- }) {
4762
- /**
4763
- * Combine partial contributions from multiple sources into one effective
4764
- * gate: **strictest age wins** (the maximum of the contributed ages,
4765
- * clamped to be non-negative) and the exclude sets **union** (deduplicated,
4766
- * lexicographically sorted — a canonical wire form, so the combined gate is
4767
- * deterministic regardless of the order contributions arrive in). A
4768
- * contribution's absent field adds nothing; a
4769
- * negative or non-finite contributed age is ignored by the clamp. With no
4770
- * contributions (or only empty ones) the result is the inert zero gate
4771
- * (`ageMinutes: 0`, `exclude: []`).
4772
- *
4773
- * `combine` is total — it never throws on a fractional, negative, or
4774
- * non-finite contribution — which is why {@link (PartialReleaseAgeGate:variable)}
4775
- * does not constrain its `ageMinutes` and this method owns the clamp.
4776
- *
4777
- * @param contributions - the partial gates to merge, one per source.
4778
- */
4779
- static combine(...contributions) {
4780
- const ages = contributions.map((contribution) => contribution.ageMinutes).filter((age) => typeof age === "number" && Number.isFinite(age));
4781
- const ageMinutes = ages.length > 0 ? Math.max(0, ...ages) : 0;
4782
- const exclude = [...new Set(contributions.flatMap((contribution) => contribution.exclude ?? []))].sort();
4783
- return ReleaseAgeGate.make({
4784
- ageMinutes,
4785
- exclude
4786
- });
4787
- }
4763
+ var Redaction = class {
4764
+ constructor() {}
4788
4765
  /**
4789
- * Whether a package name matches any of `patterns`, using pnpm's
4790
- * `@pnpm/matcher` semantics: an exact-name match, or a `*`-glob where `*`
4791
- * matches any run of characters **including `/`** — so a bare `*` matches a
4792
- * scoped name like `@scope/pkg`, and `@scope/*` matches every package in a
4793
- * scope.
4766
+ * Replaces every occurrence of every secret's value in `text` with
4767
+ * {@link REDACTED}.
4794
4768
  *
4795
4769
  * @remarks
4796
- * This is deliberately **NOT** `@effected/glob`'s minimatch dialect, in
4797
- * which `*` refuses to cross `/` (there `*` matches `pkg` but not
4798
- * `@scope/pkg`, and you would need `**`). pnpm treats the package name as a
4799
- * flat string, so this matcher does too. Do not "fix" this to route through
4800
- * `@effected/glob`: it would silently change which packages a gate exempts
4801
- * and diverge from pnpm's own behavior.
4770
+ * Exact, literal matching no pattern compilation, no encoding-aware search. A
4771
+ * secret that reaches the text base64-encoded, URL-encoded, or split across a
4772
+ * line break is **not** found; declare the encoded form as a secret too if that
4773
+ * is a real risk.
4802
4774
  *
4803
- * @param name - the package name to test.
4804
- * @param patterns - the exclude patterns (exact names or `*`-globs).
4775
+ * A secret composed only of the placeholder's own characters (`*`, `**`, `***`)
4776
+ * cannot be fully removed, because the replacement reintroduces it. That is a
4777
+ * documented limitation, not a defect.
4805
4778
  */
4806
- static matchesExclude(name, patterns) {
4807
- return matchesExclude(name, patterns);
4808
- }
4779
+ static apply = apply;
4809
4780
  /**
4810
- * Whether this gate exempts the given package name from the release-age
4811
- * check `ReleaseAgeGate.matchesExclude(name, this.exclude)`.
4812
- *
4813
- * @param name - the package name to test.
4781
+ * {@link Redaction.apply} over each entry of an argv array. An entry is
4782
+ * redacted whether it *is* a secret or merely *contains* one
4783
+ * (`--url=https://u:s3cr3t@host`).
4814
4784
  */
4815
- isExcluded(name) {
4816
- return matchesExclude(name, this.exclude);
4817
- }
4785
+ static applyArgs = applyArgs;
4818
4786
  /**
4819
- * Filter a package's candidate versions to those old enough to pass the
4820
- * gate, given each version's publish timestamp and a caller-supplied `now`.
4821
- *
4822
- * A version is kept when it has a parseable publish timestamp at or before
4823
- * the cutoff (`now - ageMinutes * 60000`). A version with a **missing or
4824
- * unparseable** timestamp in `times` is **dropped** — matching pnpm's strict
4825
- * posture: a version whose age cannot be established is treated as too young.
4826
- * The clock is the caller's; this method reads no wall clock.
4787
+ * Heuristic backstop: redact any argv value that is introduced by a known
4788
+ * secret-bearing flag or npm auth key, in either the separated
4789
+ * (`--token abc`) or inline (`--token=abc`) form.
4827
4790
  *
4828
- * Returns all versions unchanged (a no-op) when the gate is inert
4829
- * (`ageMinutes <= 0`) or the package name is excluded.
4830
- *
4831
- * @param versions - the candidate version strings.
4832
- * @param times - a map from version string to its ISO-8601 publish date.
4833
- * @param name - the package name (checked against the gate's `exclude` list).
4834
- * @param now - the current time in epoch milliseconds (the caller's clock).
4791
+ * @remarks
4792
+ * This catches secrets the caller forgot to declare; it cannot catch a flag
4793
+ * nobody listed. Prefer {@link Redaction.applyArgs} with the actual
4794
+ * `Redacted` values this runs *in addition*, never instead.
4835
4795
  */
4836
- filterVersions(versions, times, name, now) {
4837
- if (this.ageMinutes <= 0 || this.isExcluded(name)) return versions;
4838
- const cutoff = now - this.ageMinutes * MS_PER_MINUTE;
4839
- return versions.filter((version) => {
4840
- const time = times[version];
4841
- if (time === void 0) return false;
4842
- const published = Date.parse(time);
4843
- return Number.isFinite(published) && published <= cutoff;
4844
- });
4845
- }
4796
+ static scrubArgs = scrubArgs;
4797
+ /** Flags treated as secret-bearing by {@link Redaction.scrubArgs}. See {@link SECRET_FLAGS}. */
4798
+ static SECRET_FLAGS = SECRET_FLAGS;
4846
4799
  };
4847
4800
 
4848
4801
  //#endregion
4849
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/ImporterDependency.js
4802
+ //#region ../../node_modules/.pnpm/@effected+commands@0.3.1_effect@4.0.0-beta.101/node_modules/@effected/commands/internal/capture.js
4850
4803
  /**
4851
- * One declared dependency of one workspace importer, as the lockfile records it.
4804
+ * Raised when a captured stream exceeds its byte budget.
4852
4805
  *
4853
4806
  * @remarks
4854
- * - `name` the dependency's package name.
4855
- * - `specifier` the declared range, typed through `@effected/npm`'s
4856
- * `DependencySpecifier.FromString` codec: the decoded value is a tag-matchable
4857
- * `ClassifiedSpecifier` (`catalog:` / `workspace:` / range / dist-tag / raw),
4858
- * while encoding round-trips the **exact original string byte-for-byte** — the
4859
- * guarantee a before/after lockfile diff relies on.
4860
- * - `version` — the concrete resolved version, **populated by pnpm only**:
4861
- * comparable across refs and printable. pnpm records `{ specifier, version }`
4862
- * per importer dependency, and the parser splits pnpm's peer-disambiguation
4863
- * suffix off into `peerSuffix`, so `version` is always the plain version — or
4864
- * a non-registry resolution (`link:../utils`, `file:...`), passed through
4865
- * verbatim. bun and npm record resolved versions on their package entries
4866
- * instead, so for those formats `version` is absent and a consumer joins by
4867
- * `name` against `Lockfile.packages`.
4868
- * - `peerSuffix` — pnpm's peer-disambiguation context: the raw parenthesized
4869
- * chain the lockfile recorded after the version, e.g.
4870
- * `(effect@4.0.0-beta.101)(ioredis@5.11.1(supports-color@8.1.1))`. Present
4871
- * only when the lockfile recorded one — never for suffix-free pnpm entries,
4872
- * and never for the other formats, which do not record peer context per
4873
- * importer dependency.
4874
- * - `depType` — which dependency map declared it, spelled with `@effected/npm`'s
4875
- * kit-wide `DependencyField` vocabulary.
4876
- *
4877
- * @public
4807
+ * Internal and never exported from the package: `Run` maps it to the public
4808
+ * `CommandOutputError`. `Data.TaggedError` is appropriate precisely because it
4809
+ * never escapes it is an in-process signal, not a contract.
4878
4810
  */
4879
- var ImporterDependency = class extends Schema.Class("ImporterDependency")({
4880
- name: Schema.NonEmptyString,
4881
- specifier: DependencySpecifier.FromString,
4882
- version: Schema.optionalKey(Schema.String),
4883
- peerSuffix: Schema.optionalKey(Schema.String),
4884
- depType: DependencyField
4885
- }) {};
4886
-
4887
- //#endregion
4888
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/LockfileImporter.js
4811
+ var OutputTooLarge = class extends Data.TaggedError("OutputTooLarge") {};
4889
4812
  /**
4890
- * One workspace importer's declared dependencies, as the lockfile records them.
4813
+ * Collects a byte stream into a string, failing once more than `limit` bytes
4814
+ * have arrived.
4891
4815
  *
4892
4816
  * @remarks
4893
- * - `path` the importer path relative to the workspace root, `"."` for the
4894
- * root package (never empty a `NonEmptyString`) the same keys as
4895
- * `WorkspaceDiscovery.importerMap()` in
4896
- * `@effected/workspaces`. This is the stable join key: `Lockfile#importer`
4897
- * looks importers up by it, and `Lockfile#withImporterNames` deliberately
4898
- * leaves importers untouched because the path — not a package name — keys
4899
- * them.
4900
- * - `dependencies` each declared dependency as an {@link ImporterDependency}.
4901
- *
4902
- * Populated by the pnpm, bun and npm parsers. yarn does not record importers,
4903
- * so a yarn lockfile always yields an empty `importers` array.
4904
- *
4905
- * @public
4906
- */
4907
- var LockfileImporter = class extends Schema.Class("LockfileImporter")({
4908
- path: Schema.NonEmptyString,
4909
- dependencies: Schema.Array(ImporterDependency)
4910
- }) {};
4817
+ * The budget is enforced **during** accumulation, not after: checking the
4818
+ * length of an already-collected string would mean the memory was already
4819
+ * spent, which is the exact failure the budget exists to prevent. Counting is
4820
+ * on raw bytes, before decoding, because bytes are what the process actually
4821
+ * produced.
4822
+ */
4823
+ const collectBounded = (stream, limit) => Effect.gen(function* () {
4824
+ const seen = yield* Ref.make(0);
4825
+ const bounded = Stream.mapEffect(stream, (chunk) => Effect.flatMap(Ref.updateAndGet(seen, (total) => total + chunk.length), (total) => total > limit ? Effect.fail(new OutputTooLarge({ limit })) : Effect.succeed(chunk)));
4826
+ return yield* Stream.mkString(Stream.decodeText(bounded));
4827
+ });
4911
4828
 
4912
4829
  //#endregion
4913
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/ResolvedPackage.js
4914
- const EMPTY_DEPENDENCIES = {};
4830
+ //#region ../../node_modules/.pnpm/@effected+commands@0.3.1_effect@4.0.0-beta.101/node_modules/@effected/commands/Run.js
4915
4831
  /**
4916
- * A package resolved from a lockfile.
4832
+ * Default ceiling on captured bytes per stream (16 MiB).
4917
4833
  *
4918
4834
  * @remarks
4919
- * The common shape every format's entries normalize into:
4920
- *
4921
- * - `name` — the resolved package name. For pnpm *workspace* packages
4922
- * straight out of `Lockfile.parse` this is the importer path until
4923
- * `Lockfile#withImporterNames` rewrites it.
4924
- * - `version` — the resolved version string (pnpm workspace packages carry
4925
- * `"0.0.0"`; the lockfile does not record their real versions).
4926
- * - `integrity` — optional `@effected/npm` `IntegrityHash`, covering npm/pnpm
4927
- * `sha512-...` SRI and yarn Berry's `10c0/...` cache checksums (the yarn
4928
- * textual form). An *absent* integrity is omitted, so a `ResolvedPackage` may
4929
- * carry none; a *present but unparseable* integrity fails the parse typed at
4930
- * validation rather than being silently dropped.
4931
- * - `isWorkspace` — `true` for workspace-local packages.
4932
- * - `relativePath` — the workspace-relative directory for workspace
4933
- * packages, when the lockfile records one.
4934
- * - `dependencies` — the package's own dependency map, defaulting to `{}`
4935
- * both at construction and when decoding serialized data.
4835
+ * Collecting a child's output without a bound is a memory-exhaustion vector.
4836
+ * Output genuinely larger than this belongs on {@link Run.stream}, which never
4837
+ * accumulates.
4936
4838
  *
4937
4839
  * @public
4938
4840
  */
4939
- var ResolvedPackage = class extends Schema.Class("ResolvedPackage")({
4940
- name: Schema.NonEmptyString,
4941
- version: Schema.String,
4942
- integrity: Schema.optionalKey(IntegrityHash),
4943
- isWorkspace: Schema.Boolean,
4944
- relativePath: Schema.optionalKey(Schema.String),
4945
- dependencies: Schema.Record(Schema.String, Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed(EMPTY_DEPENDENCIES)), Schema.withConstructorDefault(Effect.succeed(EMPTY_DEPENDENCIES)))
4946
- }) {};
4947
-
4948
- //#endregion
4949
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/WorkspaceDependency.js
4841
+ const DEFAULT_MAX_OUTPUT_BYTES = 16777216;
4842
+ /** Characters shown from the tail of captured output in an error message. */
4843
+ const MAX_MESSAGE_CHARS = 2e3;
4950
4844
  /**
4951
- * A directed dependency edge between two workspace packages as recorded in
4952
- * the lockfile.
4953
- *
4954
- * @remarks
4955
- * - `from` — the workspace package declaring the dependency. For pnpm this
4956
- * is the importer path until `Lockfile#withImporterNames` rewrites it.
4957
- * - `to` — the workspace package depended upon.
4958
- * - `depType` — which dependency map holds the edge, spelled with
4959
- * `@effected/npm`'s kit-wide `DependencyField` vocabulary.
4960
- * - `constraint` — the declared specifier (e.g. `"workspace:*"`, `"^1.0.0"`).
4845
+ * What one completed run produced.
4961
4846
  *
4962
4847
  * @public
4963
4848
  */
4964
- var WorkspaceDependency = class extends Schema.Class("WorkspaceDependency")({
4965
- from: Schema.NonEmptyString,
4966
- to: Schema.NonEmptyString,
4967
- depType: DependencyField,
4968
- constraint: Schema.String
4969
- }) {};
4970
-
4971
- //#endregion
4972
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/PnpmExtension.js
4849
+ var CommandOutput = class extends Schema.Class("CommandOutput")({
4850
+ /** Captured standard output, redacted. */
4851
+ stdout: Schema.String,
4852
+ /** Captured standard error, redacted. */
4853
+ stderr: Schema.String,
4854
+ /** The process exit code. A non-zero value is NOT an error at this level. */
4855
+ exitCode: Schema.Number
4856
+ }) {
4857
+ /** Whether the process exited zero. */
4858
+ get succeeded() {
4859
+ return this.exitCode === 0;
4860
+ }
4861
+ };
4862
+ /** The executable and argv an error should report for `command`. */
4863
+ const describeCommand = (command) => {
4864
+ if (ChildProcess.isStandardCommand(command)) return {
4865
+ command: command.command,
4866
+ args: command.args
4867
+ };
4868
+ const left = describeCommand(command.left);
4869
+ const right = describeCommand(command.right);
4870
+ return {
4871
+ command: `${left.command} | ${right.command}`,
4872
+ args: []
4873
+ };
4874
+ };
4875
+ /** argv as an error should store it: declared secrets removed, then the flag heuristic. */
4876
+ const safeArgs = (args, secrets) => Redaction.scrubArgs(Redaction.applyArgs(args, secrets ?? []));
4877
+ /** Captured text as an error should store it. */
4878
+ const safeText = (text, secrets) => Redaction.apply(text, secrets ?? []);
4879
+ /** Tail-bounded rendering: tools write warnings first and the real error last. */
4880
+ const tail = (text) => {
4881
+ const trimmed = text.trim();
4882
+ if (trimmed.length <= MAX_MESSAGE_CHARS) return trimmed;
4883
+ return `...[${trimmed.length - MAX_MESSAGE_CHARS} chars truncated from head]...\n${trimmed.slice(-2e3)}`;
4884
+ };
4973
4885
  /**
4974
- * Extension data specific to pnpm lockfiles, attached to `Lockfile.extension`
4975
- * when the format is `"pnpm"`.
4886
+ * A command that could not be run, or that ran and failed.
4976
4887
  *
4977
4888
  * @remarks
4978
- * - `catalogs` pnpm catalog definitions ({@link PnpmCatalogs}).
4979
- * - `overrides` the version override map recorded in the lockfile header.
4980
- * - `settings` pnpm settings recorded in the lockfile header.
4889
+ * `kind` is the routing surface, never the message: `"nonZero"` (the process
4890
+ * ran and exited non-zero), `"spawn"` (it never started the executable is
4891
+ * missing, or the platform refused), `"timeout"` (a caller-supplied ceiling
4892
+ * elapsed). Composed retry and fallback logic branches on `kind`; nothing in
4893
+ * this package asks a caller to match on prose.
4894
+ *
4895
+ * `args` is **always** stored redacted.
4981
4896
  *
4982
4897
  * @public
4983
4898
  */
4984
- var PnpmExtension = class extends Schema.Class("PnpmExtension")({
4985
- _tag: Schema.tag("pnpm"),
4986
- catalogs: Schema.optionalKey(Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Union([Schema.String, Schema.Struct({
4987
- specifier: Schema.String,
4988
- version: Schema.String
4989
- })])))),
4990
- overrides: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
4991
- settings: Schema.optionalKey(Schema.Struct({
4992
- autoInstallPeers: Schema.optionalKey(Schema.Boolean),
4993
- excludeLinksFromLockfile: Schema.optionalKey(Schema.Boolean)
4994
- }))
4995
- }) {};
4996
-
4997
- //#endregion
4998
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/LockfileFormat.js
4899
+ var CommandFailedError = class CommandFailedError extends Schema.TaggedErrorClass()("CommandFailedError", {
4900
+ /** Why it failed. */
4901
+ kind: Schema.Literals([
4902
+ "nonZero",
4903
+ "spawn",
4904
+ "timeout"
4905
+ ]),
4906
+ /** The executable (or `"a | b"` for a pipeline). */
4907
+ command: Schema.String,
4908
+ /** argv, redacted. */
4909
+ args: Schema.Array(Schema.String),
4910
+ /** The exit code, when the process ran. */
4911
+ exitCode: Schema.optionalKey(Schema.Number),
4912
+ /** Captured standard error, redacted, when the process ran. */
4913
+ stderr: Schema.optionalKey(Schema.String),
4914
+ /** Captured standard output, redacted, when the process ran. */
4915
+ stdout: Schema.optionalKey(Schema.String),
4916
+ /** The absorbed platform failure, for `"spawn"`. */
4917
+ cause: Schema.optionalKey(Schema.Defect())
4918
+ }) {
4919
+ /** The process ran and exited non-zero. */
4920
+ static nonZero = (command, output, secrets) => {
4921
+ const described = describeCommand(command);
4922
+ return new CommandFailedError({
4923
+ kind: "nonZero",
4924
+ command: described.command,
4925
+ args: safeArgs(described.args, secrets),
4926
+ exitCode: output.exitCode,
4927
+ stderr: output.stderr,
4928
+ stdout: output.stdout
4929
+ });
4930
+ };
4931
+ /** The process never started. */
4932
+ static spawn = (command, cause, secrets) => {
4933
+ const described = describeCommand(command);
4934
+ return new CommandFailedError({
4935
+ kind: "spawn",
4936
+ command: described.command,
4937
+ args: safeArgs(described.args, secrets),
4938
+ cause
4939
+ });
4940
+ };
4941
+ /** A caller-supplied ceiling elapsed; the child was killed with its scope. */
4942
+ static timedOut = (command, secrets) => {
4943
+ const described = describeCommand(command);
4944
+ return new CommandFailedError({
4945
+ kind: "timeout",
4946
+ command: described.command,
4947
+ args: safeArgs(described.args, secrets)
4948
+ });
4949
+ };
4950
+ /**
4951
+ * Whether this is a spawn failure caused by the executable not existing —
4952
+ * the structural "tool is not installed" signal.
4953
+ */
4954
+ get notFound() {
4955
+ return this.kind === "spawn" && this.cause instanceof PlatformError.PlatformError && this.cause.reason._tag === "NotFound";
4956
+ }
4957
+ /** Names the command and surfaces the tail of whichever stream carries the cause. */
4958
+ get message() {
4959
+ const parts = [`Command "${this.args.length > 0 ? `${this.command} ${this.args.join(" ")}` : this.command}" failed`];
4960
+ if (this.kind === "timeout") parts.push("(timed out)");
4961
+ if (this.exitCode !== void 0) parts.push(`(exit ${this.exitCode})`);
4962
+ const stream = this.stderr?.trim() ? this.stderr : this.stdout?.trim() ? this.stdout : void 0;
4963
+ if (stream !== void 0) parts.push(`:\n${tail(stream)}`);
4964
+ return parts.join(" ");
4965
+ }
4966
+ };
4999
4967
  /**
5000
- * The lockfile formats this package parses: bun's `bun.lock` (JSONC), npm's
5001
- * `package-lock.json` (v2/v3 JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
5002
- * `yarn.lock` (both YAML).
4968
+ * A command ran, but its output could not be used.
5003
4969
  *
5004
4970
  * @remarks
5005
- * The literal names the *lockfile format*, not the package manager that
5006
- * happens to write it this package models lockfiles. Yarn support is
5007
- * Berry only; classic (v1) `yarn.lock` is not YAML and fails
5008
- * `Lockfile.parse` with a typed `LockfileParseError`.
4971
+ * Separate from {@link CommandFailedError} because the process itself
4972
+ * succeeded: `"notJson"` (stdout is not JSON), `"schema"` (it is JSON but does
4973
+ * not decode), `"tooLarge"` (capture exceeded its byte budget). Keeping the two
4974
+ * distinguishable is the point — a schema drift and a crashed tool call for
4975
+ * different responses.
4976
+ *
4977
+ * The context fields (`exitCode`, `stderr`, `stdout`) are populated by
4978
+ * {@link Run.jsonLine}, whose payload framing parses regardless of exit code —
4979
+ * when no payload arrives, the exit code and captured streams are the only
4980
+ * evidence of what actually went wrong. Both streams are **always** stored
4981
+ * redacted.
5009
4982
  *
5010
4983
  * @public
5011
4984
  */
5012
- const LockfileFormat = Schema.Literals([
5013
- "bun",
5014
- "npm",
5015
- "pnpm",
5016
- "yarn"
5017
- ]);
5018
- const FILENAMES = {
5019
- bun: ["bun.lock", "bun.lockb"],
5020
- npm: ["package-lock.json", "npm-shrinkwrap.json"],
5021
- pnpm: ["pnpm-lock.yaml"],
5022
- yarn: ["yarn.lock"]
4985
+ var CommandOutputError = class extends Schema.TaggedErrorClass()("CommandOutputError", {
4986
+ /** Which way the output was unusable. */
4987
+ kind: Schema.Literals([
4988
+ "notJson",
4989
+ "schema",
4990
+ "tooLarge"
4991
+ ]),
4992
+ /** The executable that produced it. */
4993
+ command: Schema.String,
4994
+ /** The underlying parse or decode failure. */
4995
+ cause: Schema.optionalKey(Schema.Defect()),
4996
+ /** The exit code, when the combinator parses independently of it. */
4997
+ exitCode: Schema.optionalKey(Schema.Number),
4998
+ /** Captured standard error, redacted, when the process ran. */
4999
+ stderr: Schema.optionalKey(Schema.String),
5000
+ /** Captured standard output, redacted, when the process ran. */
5001
+ stdout: Schema.optionalKey(Schema.String)
5002
+ }) {
5003
+ get message() {
5004
+ const parts = [];
5005
+ if (this.kind === "notJson") parts.push(`Command "${this.command}" did not produce JSON`);
5006
+ else if (this.kind === "schema") parts.push(`Command "${this.command}" produced JSON that did not match the expected schema`);
5007
+ else parts.push(`Command "${this.command}" produced more output than the configured limit`);
5008
+ if (this.exitCode !== void 0) parts.push(`(exit ${this.exitCode})`);
5009
+ if (this.stderr !== void 0 && this.stderr.trim().length > 0) parts.push(`:\n${tail(this.stderr)}`);
5010
+ return parts.join(" ");
5011
+ }
5012
+ };
5013
+ /** Spawns, collects both streams concurrently, and awaits exit. */
5014
+ const collectRaw = (command, options, tee) => Effect.scoped(Effect.gen(function* () {
5015
+ const handle = yield* (yield* ChildProcessSpawner.ChildProcessSpawner).spawn(command);
5016
+ const limit = options?.maxOutputBytes ?? 16777216;
5017
+ const out = tee === void 0 ? handle.stdout : Stream.tapSink(handle.stdout, tee.stdout());
5018
+ const err = tee === void 0 ? handle.stderr : Stream.tapSink(handle.stderr, tee.stderr());
5019
+ const [stdout, stderr, exitCode] = yield* Effect.all([
5020
+ collectBounded(out, limit),
5021
+ collectBounded(err, limit),
5022
+ handle.exitCode
5023
+ ], { concurrency: "unbounded" });
5024
+ const secrets = options?.redact;
5025
+ return CommandOutput.make({
5026
+ stdout: safeText(stdout, secrets),
5027
+ stderr: safeText(stderr, secrets),
5028
+ exitCode: Number(exitCode)
5029
+ });
5030
+ }));
5031
+ /** Maps the raw failure modes onto this package's taxonomy, and applies any ceiling. */
5032
+ const collectClassified = (command, options, tee) => {
5033
+ const described = describeCommand(command);
5034
+ const classified = collectRaw(command, options, tee).pipe(Effect.catch((error) => Effect.fail(error instanceof OutputTooLarge ? new CommandOutputError({
5035
+ kind: "tooLarge",
5036
+ command: described.command,
5037
+ cause: error
5038
+ }) : CommandFailedError.spawn(command, error, options?.redact))));
5039
+ return options?.timeout === void 0 ? classified : Effect.timeoutOrElse(classified, {
5040
+ duration: options.timeout,
5041
+ orElse: () => Effect.fail(CommandFailedError.timedOut(command, options.redact))
5042
+ });
5023
5043
  };
5044
+ /** Fails a run whose process exited non-zero. */
5045
+ const requireZero = (command, output, options) => output.succeeded ? Effect.succeed(output) : Effect.fail(CommandFailedError.nonZero(command, output, options?.redact));
5046
+ /** Span attributes: what ran and how many arguments — never the arguments. */
5047
+ const annotate = (command) => {
5048
+ const described = describeCommand(command);
5049
+ return Effect.annotateCurrentSpan({
5050
+ command: described.command,
5051
+ argc: described.args.length
5052
+ });
5053
+ };
5054
+ const collect = Effect.fn("Run.collect")(function* (command, options) {
5055
+ yield* annotate(command);
5056
+ return yield* collectClassified(command, options, void 0);
5057
+ });
5058
+ const collectTee = Effect.fn("Run.collectTee")(function* (command, options) {
5059
+ yield* annotate(command);
5060
+ const stdio = yield* Stdio.Stdio;
5061
+ return yield* collectClassified(command, options, stdio);
5062
+ });
5063
+ const text$4 = Effect.fn("Run.text")(function* (command, options) {
5064
+ yield* annotate(command);
5065
+ const output = yield* collectClassified(command, options, void 0);
5066
+ return (yield* requireZero(command, output, options)).stdout.trim();
5067
+ });
5068
+ const lines = Effect.fn("Run.lines")(function* (command, options) {
5069
+ yield* annotate(command);
5070
+ const output = yield* collectClassified(command, options, void 0);
5071
+ return (yield* requireZero(command, output, options)).stdout.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
5072
+ });
5073
+ const json = Effect.fn("Run.json")(function* (command, schema, options) {
5074
+ yield* annotate(command);
5075
+ const described = describeCommand(command);
5076
+ const output = yield* collectClassified(command, options, void 0);
5077
+ const checked = yield* requireZero(command, output, options);
5078
+ const parsed = yield* Effect.try({
5079
+ try: () => JSON.parse(checked.stdout),
5080
+ catch: (cause) => new CommandOutputError({
5081
+ kind: "notJson",
5082
+ command: described.command,
5083
+ cause
5084
+ })
5085
+ });
5086
+ return yield* Schema.decodeUnknownEffect(schema)(parsed).pipe(Effect.catch((cause) => Effect.fail(new CommandOutputError({
5087
+ kind: "schema",
5088
+ command: described.command,
5089
+ cause
5090
+ }))));
5091
+ });
5092
+ const jsonLine = Effect.fn("Run.jsonLine")(function* (command, schema, options) {
5093
+ yield* annotate(command);
5094
+ const described = describeCommand(command);
5095
+ const output = yield* collectClassified(command, options, void 0);
5096
+ const context = {
5097
+ exitCode: output.exitCode,
5098
+ stderr: output.stderr,
5099
+ stdout: output.stdout
5100
+ };
5101
+ const candidates = output.stdout.split(/\r?\n/).filter((candidate) => candidate.trim().length > 0);
5102
+ if (candidates.length === 0) return yield* Effect.fail(new CommandOutputError({
5103
+ kind: "notJson",
5104
+ command: described.command,
5105
+ cause: /* @__PURE__ */ new Error("stdout carried no non-empty line"),
5106
+ ...context
5107
+ }));
5108
+ let notJsonCause;
5109
+ let schemaCause;
5110
+ for (let index = candidates.length - 1; index >= 0; index--) {
5111
+ const candidate = candidates[index];
5112
+ if (candidate === void 0) continue;
5113
+ let parsed;
5114
+ try {
5115
+ parsed = JSON.parse(candidate);
5116
+ } catch (cause) {
5117
+ notJsonCause ??= cause;
5118
+ continue;
5119
+ }
5120
+ const decoded = yield* Effect.result(Schema.decodeUnknownEffect(schema)(parsed));
5121
+ if (Result.isSuccess(decoded)) return decoded.success;
5122
+ schemaCause ??= decoded.failure;
5123
+ }
5124
+ return yield* Effect.fail(schemaCause !== void 0 ? new CommandOutputError({
5125
+ kind: "schema",
5126
+ command: described.command,
5127
+ cause: schemaCause,
5128
+ ...context
5129
+ }) : new CommandOutputError({
5130
+ kind: "notJson",
5131
+ command: described.command,
5132
+ cause: notJsonCause,
5133
+ ...context
5134
+ }));
5135
+ });
5136
+ const exitCode = Effect.fn("Run.exitCode")(function* (command, options) {
5137
+ yield* annotate(command);
5138
+ return (yield* collectClassified(command, options, void 0)).exitCode;
5139
+ });
5140
+ const succeeds = Effect.fn("Run.succeeds")(function* (command, options) {
5141
+ yield* annotate(command);
5142
+ return yield* collectClassified(command, options, void 0).pipe(Effect.map((output) => output.succeeded), Effect.catch(() => Effect.succeed(false)));
5143
+ });
5144
+ const detach = Effect.fn("Run.detach")(function* (command) {
5145
+ yield* annotate(command);
5146
+ return yield* Effect.scoped(Effect.gen(function* () {
5147
+ const handle = yield* (yield* ChildProcessSpawner.ChildProcessSpawner).spawn(command);
5148
+ yield* handle.unref;
5149
+ return handle.pid;
5150
+ })).pipe(Effect.catch((error) => Effect.fail(CommandFailedError.spawn(command, error))));
5151
+ });
5152
+ const stream = (command, options) => Stream.unwrap(Effect.map(ChildProcessSpawner.ChildProcessSpawner, (spawner) => spawner.streamLines(command, { includeStderr: options?.includeStderr ?? false }))).pipe(Stream.mapError((error) => CommandFailedError.spawn(command, error)));
5153
+ const extendEnv = Function.dual(2, (self, env) => {
5154
+ if (ChildProcess.isStandardCommand(self)) {
5155
+ const merged = self.options.env === void 0 ? env : {
5156
+ ...self.options.env,
5157
+ ...env
5158
+ };
5159
+ return ChildProcess.make(self.command, self.args, {
5160
+ ...self.options,
5161
+ env: merged,
5162
+ extendEnv: true
5163
+ });
5164
+ }
5165
+ return ChildProcess.pipeTo(extendEnv(self.left, env), extendEnv(self.right, env), self.options);
5166
+ });
5024
5167
  /**
5025
- * The conventional lockfile filename for a format: `"bun.lock"`,
5026
- * `"package-lock.json"`, `"pnpm-lock.yaml"` or `"yarn.lock"`.
5168
+ * Structured running of core `ChildProcess.Command` values.
5027
5169
  *
5028
5170
  * @remarks
5029
- * The primary name only the first element of {@link filenamesFor}, which is
5030
- * what detection that must also see the genuine alternates should use.
5171
+ * These are free functions over core's contract, **not** a service: core's
5172
+ * `ChildProcessSpawner` already is the subprocess service, and wrapping it in a
5173
+ * second one is the re-declaration this package exists not to repeat. Tests
5174
+ * stub the spawner (`ChildProcessSpawner.make(mockSpawn)`), not these.
5175
+ *
5176
+ * A non-zero exit is a *result* for {@link Run.collect}, {@link Run.exitCode},
5177
+ * {@link Run.succeeds} and {@link Run.jsonLine}, and a typed *failure* for
5178
+ * {@link Run.text}, {@link Run.lines} and {@link Run.json} — the split is
5179
+ * deliberate, matching core (where a non-zero exit is a success) at the
5180
+ * reporting level while giving the interpreting helpers the ergonomics callers
5181
+ * actually want.
5182
+ *
5183
+ * The interpreting helpers also **trim**: {@link Run.text} strips leading and
5184
+ * trailing whitespace from the whole result — not just a trailing newline —
5185
+ * and {@link Run.lines} trims each line. Fixed-column output whose first
5186
+ * column can be whitespace (`git status --porcelain`) silently loses that
5187
+ * column through either, producing plausible wrong values rather than an
5188
+ * error. Parse that kind of output from the untrimmed `stdout` of
5189
+ * {@link Run.collect}'s {@link CommandOutput} instead.
5031
5190
  *
5032
5191
  * @public
5033
5192
  */
5034
- const filenameFor = (format) => FILENAMES[format][0];
5035
-
5036
- //#endregion
5037
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/shared.js
5038
- /**
5039
- * The four dependency sections of a manifest, in a stable order — the shared
5040
- * dependency-sections table (v3's `DEP_SECTIONS`). Each entry is both the
5041
- * manifest field name to read and the `@effected/npm` `DependencyField` it maps
5042
- * to, since the two coincide. Consumed by `extractWorkspaceDeps` and by the
5043
- * pnpm/bun/npm importer builders.
5044
- *
5045
- * @internal
5046
- */
5047
- const DEP_TYPES = [
5048
- "dependencies",
5049
- "devDependencies",
5050
- "peerDependencies",
5051
- "optionalDependencies"
5052
- ];
5053
- /**
5054
- * Coerce a raw lockfile integrity string to the `@effected/npm` `IntegrityHash`
5055
- * brand, which recognizes the SRI (`<algo>-<base64>`), corepack (`<algo>.<hex>`)
5056
- * and yarn (`<cachekey>/<hex>`) textual forms.
5057
- *
5058
- * Absence and corruption are treated differently, and the distinction is the
5059
- * point. An *absent* integrity (input `undefined`) succeeds with `undefined`,
5060
- * so the caller omits the field a lockfile that records no integrity is
5061
- * legitimate. A *present but unparseable* integrity fails through the same
5062
- * validation channel the shape checks use ({@link validationFailure}), so
5063
- * `Lockfile.parse` surfaces it as a `LockfileParseError` with
5064
- * `stage: "validation"` rather than silently dropping a corrupt value. Never a
5065
- * defect. yarn's `10c0/<hex>` cache checksums are a recognized form, so real
5066
- * yarn/npm/pnpm/bun integrity all still parses; only genuine corruption fails.
5067
- *
5068
- * @internal
5069
- */
5070
- const toIntegrityHash = (raw) => {
5071
- if (raw === void 0) return Effect.succeed(void 0);
5072
- return Schema.decodeUnknownEffect(IntegrityHash)(raw).pipe(Effect.mapError(validationFailure));
5073
- };
5074
- const decodeSpecifier = Schema.decodeUnknownExit(DependencySpecifier.FromString);
5075
- /**
5076
- * Split pnpm's peer-disambiguation suffix off a recorded string: everything
5077
- * from the first `(` on is suffix, since package names and versions never
5078
- * contain `(`. Handles both shapes pnpm records — a bare version
5079
- * (`"1.0.0(effect@4.0.0)"`, importer entries) and a `name@version` snapshot key
5080
- * (`"fdir@6.5.0(picomatch@4.0.4)"`). A string with no `(` — including
5081
- * `link:...` / `file:...` resolutions passes through untouched. So does a
5082
- * protocol-bearing string (a `:` ahead of the first `(`), where a parenthesis
5083
- * is path or URL text rather than a peer suffix: pnpm attaches suffixes to
5084
- * registry versions only. This is the single stripping implementation — do not
5085
- * hand-roll an `indexOf("(")` split elsewhere.
5086
- *
5087
- * @internal
5088
- */
5089
- const splitPeerSuffix = (raw) => {
5090
- const parenIndex = raw.indexOf("(");
5091
- if (parenIndex === -1) return { plain: raw };
5092
- if (raw.lastIndexOf(":", parenIndex) !== -1) return { plain: raw };
5093
- return {
5094
- plain: raw.slice(0, parenIndex),
5095
- peerSuffix: raw.slice(parenIndex)
5096
- };
5193
+ var Run = class {
5194
+ constructor() {}
5195
+ /**
5196
+ * Spawns `command`, collects stdout and stderr concurrently, and resolves
5197
+ * with the {@link CommandOutput} once the process exits.
5198
+ *
5199
+ * @remarks
5200
+ * A non-zero exit is a *result* here, not a failure — see {@link Run}'s
5201
+ * remarks for the split against {@link Run.text}, {@link Run.lines} and
5202
+ * {@link Run.json}.
5203
+ */
5204
+ static collect = collect;
5205
+ /**
5206
+ * Like {@link Run.collect}, but also tees each stream to the `Stdio` in `R`
5207
+ * as it arrives, for a caller that wants live output alongside the captured
5208
+ * {@link CommandOutput}.
5209
+ */
5210
+ static collectTee = collectTee;
5211
+ /**
5212
+ * Runs `command` and resolves with trimmed stdout on a zero exit.
5213
+ *
5214
+ * @remarks
5215
+ * A non-zero exit is a typed failure here — {@link CommandFailedError} —
5216
+ * unlike {@link Run.collect}, {@link Run.exitCode} and {@link Run.succeeds},
5217
+ * which treat it as a result.
5218
+ *
5219
+ * The trim strips **leading and trailing whitespace**, not just the trailing
5220
+ * newline. For parse-sensitive output where leading whitespace is data
5221
+ * (`git status --porcelain`, whose first entry's status column it would
5222
+ * silently eat), use {@link Run.collect} and read its {@link CommandOutput}'s
5223
+ * untrimmed `stdout` instead.
5224
+ */
5225
+ static text = text$4;
5226
+ /**
5227
+ * Runs `command` and resolves with stdout split into trimmed, non-empty
5228
+ * lines on a zero exit.
5229
+ *
5230
+ * @remarks
5231
+ * A non-zero exit is a typed failure here — {@link CommandFailedError} —
5232
+ * matching {@link Run.text} and {@link Run.json}.
5233
+ */
5234
+ static lines = lines;
5235
+ /**
5236
+ * Runs `command`, parses stdout as JSON and decodes it against `schema` on
5237
+ * a zero exit.
5238
+ *
5239
+ * @remarks
5240
+ * Fails with {@link CommandOutputError} when stdout is not JSON or does not
5241
+ * decode; a non-zero exit fails with {@link CommandFailedError}, matching
5242
+ * {@link Run.text} and {@link Run.lines}.
5243
+ *
5244
+ * This parses the **whole** of stdout and requires a zero exit. For a
5245
+ * protocol payload located by scanning stdout lines from the end — tolerant
5246
+ * of noise around it and of a non-zero exit — use {@link Run.jsonLine}
5247
+ * instead.
5248
+ */
5249
+ static json = json;
5250
+ /**
5251
+ * Runs `command` and, **scanning stdout lines from the end**, resolves with
5252
+ * the first line that both parses as JSON and decodes against `schema` —
5253
+ * the framing variant of {@link Run.json}, for a child that reports through
5254
+ * a single JSON protocol payload near the end of its output.
5255
+ *
5256
+ * @remarks
5257
+ * The framing tolerates noise on **both sides** of the payload: noise before
5258
+ * it (a subprocess-loaded hook's own `console.log`, a tool's warnings) and
5259
+ * noise after it (a hook logging from `process.on("exit", ...)` fires after
5260
+ * the payload has flushed — the trigger for widening the old "last non-empty
5261
+ * line must decode" contract, spencerbeggs/effected#292). Lines are split on
5262
+ * `\r?\n`, whitespace-only lines are dropped, and the scan runs from the last
5263
+ * line backwards until one decodes. The tolerance is positional, not
5264
+ * volumetric: the whole of stdout is still captured under
5265
+ * {@link RunOptions.maxOutputBytes} (default
5266
+ * {@link DEFAULT_MAX_OUTPUT_BYTES}, 16 MiB), so a child whose noise exceeds
5267
+ * the ceiling fails typed as `"tooLarge"` before any line is examined —
5268
+ * raise the ceiling for a child known to be loud in volume.
5269
+ *
5270
+ * The scan's consequence: when **multiple** lines decode under `schema`, the
5271
+ * **last** one wins. A child must therefore never emit two schema-valid
5272
+ * lines, and a consumer schema should be shaped so an accidental log line
5273
+ * cannot satisfy it — a discriminated envelope with a required literal field
5274
+ * (`ok: true | false`, the shape `@effected/workspaces`' `ReplayPayload`
5275
+ * uses) rather than a permissive record a stray `console.log(someObject)`
5276
+ * might match.
5277
+ *
5278
+ * Unlike {@link Run.json}, this parses **regardless of the exit code** — a
5279
+ * deliberate posture, not an oversight. A protocol payload discriminates
5280
+ * success in-band (its own `ok` field, its own error shape), so the payload
5281
+ * outranks the exit code: a child that crashes *after* flushing its payload
5282
+ * still reported, and a caller that wants exit-code semantics has
5283
+ * {@link Run.json}. When no line decodes anywhere, the typed
5284
+ * {@link CommandOutputError} carries the exit code and both captured streams
5285
+ * (redacted) as context, so the failure is diagnosable without re-running.
5286
+ * Its `kind` preserves the near-miss diagnostic: `"schema"` when at least
5287
+ * one line parsed as JSON but none decoded — with the **last parseable
5288
+ * line's** decode failure as `cause`, that line being the most probable
5289
+ * intended payload — and `"notJson"` only when no non-empty line was JSON at
5290
+ * all (carrying the last non-empty line's parse error). A spawn failure or
5291
+ * an opted-in timeout still fails with {@link CommandFailedError}.
5292
+ */
5293
+ static jsonLine = jsonLine;
5294
+ /**
5295
+ * Runs `command` and resolves with its exit code alone.
5296
+ *
5297
+ * @remarks
5298
+ * A non-zero exit is a *result* here, not a failure — see {@link Run}'s
5299
+ * remarks for the split against {@link Run.text}, {@link Run.lines} and
5300
+ * {@link Run.json}.
5301
+ */
5302
+ static exitCode = exitCode;
5303
+ /**
5304
+ * Runs `command` and resolves with whether it exited zero, collapsing a
5305
+ * spawn or other classified failure to `false` rather than propagating it.
5306
+ */
5307
+ static succeeds = succeeds;
5308
+ /** Decoded stdout lines as they arrive, for output too large or too long-lived to collect. */
5309
+ static stream = stream;
5310
+ /**
5311
+ * Spawns `command` and resolves with its pid without waiting for exit.
5312
+ *
5313
+ * @remarks
5314
+ * Unrefs the child **before** this scope closes, so it survives the
5315
+ * caller's scope closing — the Node backend's release skips the kill for an
5316
+ * unref'd child, and reversing that order kills it with the scope instead.
5317
+ * Fails with {@link CommandFailedError} if the process never starts.
5318
+ */
5319
+ static detach = detach;
5320
+ /**
5321
+ * Adds environment variables to a command WITHOUT losing the parent
5322
+ * environment: merges `env` over any existing command environment (new values
5323
+ * win, matching core's `ChildProcess.setEnv`) and sets `extendEnv: true`.
5324
+ *
5325
+ * @remarks
5326
+ * This combinator exists because of a core trap: `ChildProcess.setEnv` merges
5327
+ * into `options.env` but never sets `extendEnv`, and the Node spawner resolves
5328
+ * the child environment as `extendEnv ? { ...process.env, ...env } : env` — so
5329
+ * a command built with bare `setEnv({ SOME_VAR: x })` spawns a child whose
5330
+ * ENTIRE environment is that one variable: no `PATH`, no `HOME`. The failure is
5331
+ * silent at the type level and surfaces as "spawned tool cannot find its own
5332
+ * binary" at runtime.
5333
+ *
5334
+ * Deliberately forces `extendEnv: true` even where construction set it `false`
5335
+ * — inheriting the parent environment is this combinator's entire purpose. A
5336
+ * caller who wants a hermetic environment uses core's `setEnv` or construction
5337
+ * options (`ChildProcess.make(cmd, args, { env, extendEnv: false })`) directly.
5338
+ *
5339
+ * For a pipeline, applies to every command in the pipeline (mirroring core's
5340
+ * `setEnv`), preserving the pipe's own options. Composes core's public
5341
+ * vocabulary (`ChildProcess.make`, `ChildProcess.pipeTo`) — it re-declares
5342
+ * nothing.
5343
+ */
5344
+ static extendEnv = extendEnv;
5345
+ /** Default ceiling on captured bytes per stream. See {@link DEFAULT_MAX_OUTPUT_BYTES}. */
5346
+ static DEFAULT_MAX_OUTPUT_BYTES = DEFAULT_MAX_OUTPUT_BYTES;
5347
+ /** The placeholder written in place of a redacted secret. See {@link REDACTED}. */
5348
+ static REDACTED = "***";
5097
5349
  };
5350
+
5351
+ //#endregion
5352
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.3_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/ReleaseAgeGate.js
5353
+ const MS_PER_MINUTE = 6e4;
5098
5354
  /**
5099
- * Build one {@link ImporterDependency}, decoding the raw specifier string into
5100
- * the `@effected/npm` `ClassifiedSpecifier` tagged union. Returns `undefined`
5101
- * — a skip, never a throw when the name is empty or the specifier does not
5102
- * classify (e.g. an empty specifier), per the total-string-surgery discipline.
5103
- *
5104
- * A pnpm-recorded version is normalized through {@link splitPeerSuffix}: the
5105
- * `version` field carries the plain version and the split-off peer chain lands
5106
- * in `peerSuffix`. A version that is *only* a peer chain (empty plain part) is
5107
- * treated as no concrete version — a skip of both fields, never a throw.
5355
+ * A source's partial contribution to a {@link ReleaseAgeGate}: the effective
5356
+ * gate is assembled from more than one place (inline `pnpm-workspace.yaml`
5357
+ * keys, replayed `updateConfig` hooks, `pnpm config get` output), and each
5358
+ * source may set the age, the exclude list, both, or neither. Absent fields
5359
+ * contribute nothing to the combination.
5108
5360
  *
5109
- * @internal
5110
- */
5111
- const buildImporterDependency = (name, specifier, depType, version) => {
5112
- if (name === "") return void 0;
5113
- const exit = decodeSpecifier(specifier);
5114
- if (Exit.isFailure(exit)) return void 0;
5115
- const resolved = version !== void 0 && version !== "" ? splitPeerSuffix(version) : void 0;
5116
- return ImporterDependency.make({
5117
- name,
5118
- specifier: exit.value,
5119
- depType,
5120
- ...resolved !== void 0 && resolved.plain !== "" ? {
5121
- version: resolved.plain,
5122
- ...resolved.peerSuffix !== void 0 ? { peerSuffix: resolved.peerSuffix } : {}
5123
- } : {}
5124
- });
5125
- };
5126
- /**
5127
- * Collect an importer's declared dependencies off the shared dependency-sections
5128
- * table. Iterates {@link DEP_TYPES} in order, projecting each section value with
5129
- * `read`; malformed rows are skipped (never thrown). Key-bearing intermediates
5130
- * are the schema-decoded records, whose own-property `Object.entries` iteration
5131
- * neither pollutes nor drops a `__proto__` key.
5361
+ * Deliberately permissive: unlike {@link ReleaseAgeGate} it does not constrain
5362
+ * `ageMinutes` to be non-negative, because the raw values arrive from arbitrary
5363
+ * config sources and {@link ReleaseAgeGate.combine} is the single authority
5364
+ * that clamps them.
5132
5365
  *
5133
- * @internal
5366
+ * @public
5134
5367
  */
5135
- const importerDependencies = (entry, read) => {
5136
- const deps = [];
5137
- for (const field of DEP_TYPES) {
5138
- const section = entry[field];
5139
- if (!section) continue;
5140
- for (const [name, value] of Object.entries(section)) {
5141
- const { specifier, version } = read(value);
5142
- const dep = buildImporterDependency(name, specifier, field, version);
5143
- if (dep !== void 0) deps.push(dep);
5144
- }
5145
- }
5146
- return deps;
5147
- };
5148
- /** @internal */
5149
- const syntaxFailure = (cause) => ({
5150
- stage: "syntax",
5151
- cause
5152
- });
5153
- /** @internal */
5154
- const validationFailure = (cause) => ({
5155
- stage: "validation",
5156
- cause
5157
- });
5158
- /** @internal */
5159
- const framingFailure = (reason, documents) => ({
5160
- stage: "framing",
5161
- reason,
5162
- documents
5368
+ const PartialReleaseAgeGate = Schema.Struct({
5369
+ /** Minutes a release must age; absent means this source sets no age. */
5370
+ ageMinutes: Schema.optionalKey(Schema.Number),
5371
+ /** Exempt package-name patterns; absent means this source adds no exemptions. */
5372
+ exclude: Schema.optionalKey(Schema.Array(Schema.String))
5163
5373
  });
5164
- /**
5165
- * Whether the specifier is a workspace, link or file reference
5166
- * (`"workspace:*"`, `"link:../foo"`, `"file:../bar"`).
5167
- *
5168
- * @internal
5169
- */
5170
- const isWorkspaceSpecifier = (specifier) => specifier.startsWith("workspace:") || specifier.startsWith("link:") || specifier.startsWith("file:");
5171
- /**
5172
- * Extract inter-workspace dependency edges: for every workspace entry and
5173
- * dependency type, emit an edge for each dependency whose name is itself a
5174
- * workspace. Key-bearing intermediates are `Map`/`Set` — lockfile keys are
5175
- * attacker-adjacent strings (`__proto__`, `constructor`) and must never be
5176
- * assigned onto plain objects here.
5177
- *
5178
- * @internal
5179
- */
5180
- const extractWorkspaceDeps = (workspaces, workspaceNames) => {
5181
- const deps = [];
5182
- for (const [from, entry] of workspaces) for (const depType of DEP_TYPES) {
5183
- const depMap = entry[depType];
5184
- if (!depMap) continue;
5185
- for (const [name, constraint] of Object.entries(depMap)) if (workspaceNames.has(name)) deps.push(WorkspaceDependency.make({
5186
- from,
5187
- to: name,
5188
- depType,
5189
- constraint
5190
- }));
5191
- }
5192
- return deps;
5374
+ const AgeMinutes = Schema.Number.check(Schema.isGreaterThanOrEqualTo(0), Schema.isFinite());
5375
+ const matchesPattern = (name, pattern) => {
5376
+ if (pattern === name) return true;
5377
+ if (!pattern.includes("*")) return false;
5378
+ let nameIndex = 0;
5379
+ let patternIndex = 0;
5380
+ let starIndex = -1;
5381
+ let retryNameIndex = 0;
5382
+ while (nameIndex < name.length) if (pattern[patternIndex] === "*") {
5383
+ starIndex = patternIndex;
5384
+ patternIndex += 1;
5385
+ retryNameIndex = nameIndex;
5386
+ } else if (pattern[patternIndex] === name[nameIndex]) {
5387
+ patternIndex += 1;
5388
+ nameIndex += 1;
5389
+ } else if (starIndex !== -1) {
5390
+ patternIndex = starIndex + 1;
5391
+ retryNameIndex += 1;
5392
+ nameIndex = retryNameIndex;
5393
+ } else return false;
5394
+ while (pattern[patternIndex] === "*") patternIndex += 1;
5395
+ return patternIndex === pattern.length;
5193
5396
  };
5194
-
5195
- //#endregion
5196
- //#region ../../node_modules/.pnpm/@effected+jsonc@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/jsonc/JsoncNode.js
5397
+ const matchesExclude = (name, patterns) => patterns.some((pattern) => matchesPattern(name, pattern));
5197
5398
  /**
5198
- * Discriminator values for JSONC AST node types: the JSON value types
5199
- * (`string`/`number`/`boolean`/`null`), the structural types
5200
- * (`object`/`array`) and the `property` key-value pair type.
5399
+ * pnpm's publish-time release-age gate: the number of minutes a published
5400
+ * version must age before it is eligible, and the set of package-name patterns
5401
+ * exempt from the gate. Mirrors pnpm's `minimumReleaseAge` /
5402
+ * `minimumReleaseAgeExclude` config so a resolver can drop too-young candidate
5403
+ * versions before picking, avoiding `ERR_PNPM_NO_MATURE_MATCHING_VERSION`.
5201
5404
  *
5202
- * @public
5203
- */
5204
- const JsoncNodeType = Schema.Literals([
5205
- "object",
5206
- "array",
5207
- "property",
5208
- "string",
5209
- "number",
5210
- "boolean",
5211
- "null"
5212
- ]);
5213
- /**
5214
- * An immutable JSONC AST node produced by `Jsonc.parseTree`.
5405
+ * `ageMinutes` is constrained non-negative and finite; a `ReleaseAgeGate` with
5406
+ * `ageMinutes <= 0` is an inert gate that filters nothing. Assemble a gate from
5407
+ * multiple config sources with {@link ReleaseAgeGate.combine}, and apply it to
5408
+ * a package's candidate versions with {@link ReleaseAgeGate.filterVersions}.
5215
5409
  *
5216
- * The `parent` field present in Microsoft's `jsonc-parser` is intentionally
5217
- * omitted: circular references would break structural equality, serialization
5218
- * and Schema encode/decode. Child relationships are expressed via `children`,
5219
- * and the recursive type is handled with `Schema.suspend`.
5410
+ * @example
5411
+ * ```ts
5412
+ * import { ReleaseAgeGate } from "@effected/npm";
5220
5413
  *
5221
- * - `type` the `JsoncNodeType` discriminator.
5222
- * - `offset` / `length` — the node's span in the source (tight token-end
5223
- * discipline: spans never swallow trailing whitespace or comments).
5224
- * - `value` — the decoded JS value for leaf nodes; omitted for structural nodes.
5225
- * - `colonOffset` for `property` nodes, the offset of the `:` separator.
5226
- * - `children` — child nodes for `object`, `array` and `property` nodes.
5414
+ * const gate = ReleaseAgeGate.combine(
5415
+ * { ageMinutes: 1440 },
5416
+ * { exclude: ["@my-scope/*"] },
5417
+ * );
5418
+ * // gate.ageMinutes === 1440, gate.exclude === ["@my-scope/*"]
5227
5419
  *
5228
- * Construct via `JsoncNode.make(...)`, never `new JsoncNode(...)`.
5420
+ * const eligible = gate.filterVersions(
5421
+ * ["1.0.0", "1.0.1"],
5422
+ * { "1.0.0": "2020-01-01T00:00:00Z", "1.0.1": "2026-07-21T00:00:00Z" },
5423
+ * "prettier",
5424
+ * Date.now(),
5425
+ * );
5426
+ * ```
5229
5427
  *
5230
5428
  * @public
5231
5429
  */
5232
- var JsoncNode = class JsoncNode extends Schema.Class("JsoncNode")({
5233
- type: JsoncNodeType,
5234
- offset: Schema.Number,
5235
- length: Schema.Number,
5236
- value: Schema.optionalKey(Schema.Unknown),
5237
- colonOffset: Schema.optionalKey(Schema.Number),
5238
- children: Schema.optionalKey(Schema.Array(Schema.suspend(() => JsoncNode)))
5430
+ var ReleaseAgeGate = class ReleaseAgeGate extends Schema.Class("ReleaseAgeGate")({
5431
+ /** Minutes a published version must age before it is eligible (non-negative, finite). */
5432
+ ageMinutes: AgeMinutes,
5433
+ /** Package-name patterns exempt from the gate (exact names or `*`-globs). */
5434
+ exclude: Schema.Array(Schema.String)
5239
5435
  }) {
5240
5436
  /**
5241
- * Find a descendant node by path. String segments navigate object
5242
- * properties; number segments navigate array indices. Returns
5243
- * `Option.none()` when any segment cannot be resolved. Pure.
5437
+ * Combine partial contributions from multiple sources into one effective
5438
+ * gate: **strictest age wins** (the maximum of the contributed ages,
5439
+ * clamped to be non-negative) and the exclude sets **union** (deduplicated,
5440
+ * lexicographically sorted — a canonical wire form, so the combined gate is
5441
+ * deterministic regardless of the order contributions arrive in). A
5442
+ * contribution's absent field adds nothing; a
5443
+ * negative or non-finite contributed age is ignored by the clamp. With no
5444
+ * contributions (or only empty ones) the result is the inert zero gate
5445
+ * (`ageMinutes: 0`, `exclude: []`).
5244
5446
  *
5245
- * @param path - The path to resolve, relative to this node.
5246
- * @returns The descendant node, or `Option.none()` when `path` cannot be
5247
- * resolved.
5447
+ * `combine` is total it never throws on a fractional, negative, or
5448
+ * non-finite contribution which is why {@link (PartialReleaseAgeGate:variable)}
5449
+ * does not constrain its `ageMinutes` and this method owns the clamp.
5450
+ *
5451
+ * @param contributions - the partial gates to merge, one per source.
5248
5452
  */
5249
- find(path) {
5250
- let current = this;
5251
- for (const segment of path) {
5252
- if (current?.children === void 0) return Option.none();
5253
- if (typeof segment === "string") {
5254
- if (current.type !== "object") return Option.none();
5255
- current = current.children.find((child) => child.type === "property" && child.children !== void 0 && child.children[0]?.value === segment)?.children?.[1];
5256
- } else {
5257
- if (current.type !== "array") return Option.none();
5258
- current = current.children[segment];
5259
- }
5260
- }
5261
- return current !== void 0 ? Option.some(current) : Option.none();
5453
+ static combine(...contributions) {
5454
+ const ages = contributions.map((contribution) => contribution.ageMinutes).filter((age) => typeof age === "number" && Number.isFinite(age));
5455
+ const ageMinutes = ages.length > 0 ? Math.max(0, ...ages) : 0;
5456
+ const exclude = [...new Set(contributions.flatMap((contribution) => contribution.exclude ?? []))].sort();
5457
+ return ReleaseAgeGate.make({
5458
+ ageMinutes,
5459
+ exclude
5460
+ });
5262
5461
  }
5263
5462
  /**
5264
- * Find the innermost node whose span covers `offset`, or `Option.none()`
5265
- * if the offset is outside this subtree. Pure.
5463
+ * Whether a package name matches any of `patterns`, using pnpm's
5464
+ * `@pnpm/matcher` semantics: an exact-name match, or a `*`-glob where `*`
5465
+ * matches any run of characters **including `/`** — so a bare `*` matches a
5466
+ * scoped name like `@scope/pkg`, and `@scope/*` matches every package in a
5467
+ * scope.
5266
5468
  *
5267
- * @param offset - The zero-based character offset to locate.
5268
- * @returns The innermost covering node, or `Option.none()` when `offset`
5269
- * falls outside this subtree.
5469
+ * @remarks
5470
+ * This is deliberately **NOT** `@effected/glob`'s minimatch dialect, in
5471
+ * which `*` refuses to cross `/` (there `*` matches `pkg` but not
5472
+ * `@scope/pkg`, and you would need `**`). pnpm treats the package name as a
5473
+ * flat string, so this matcher does too. Do not "fix" this to route through
5474
+ * `@effected/glob`: it would silently change which packages a gate exempts
5475
+ * and diverge from pnpm's own behavior.
5476
+ *
5477
+ * @param name - the package name to test.
5478
+ * @param patterns - the exclude patterns (exact names or `*`-globs).
5270
5479
  */
5271
- findAtOffset(offset) {
5272
- return findAtOffsetImpl(this, offset, 0);
5480
+ static matchesExclude(name, patterns) {
5481
+ return matchesExclude(name, patterns);
5273
5482
  }
5274
5483
  /**
5275
- * Return the JSON path to the innermost node covering `offset`, or
5276
- * `Option.none()` if the offset is outside this subtree. The inverse of
5277
- * {@link JsoncNode.find}. Pure.
5484
+ * Whether this gate exempts the given package name from the release-age
5485
+ * check — `ReleaseAgeGate.matchesExclude(name, this.exclude)`.
5278
5486
  *
5279
- * @param offset - The zero-based character offset to locate.
5280
- * @returns The path to the innermost covering node, or `Option.none()`
5281
- * when `offset` falls outside this subtree.
5487
+ * @param name - the package name to test.
5282
5488
  */
5283
- pathAt(offset) {
5284
- return buildPath(this, offset, []);
5489
+ isExcluded(name) {
5490
+ return matchesExclude(name, this.exclude);
5285
5491
  }
5286
5492
  /**
5287
- * Reconstruct the plain JavaScript value represented by this subtree. Pure
5288
- * and total never fails, so no `Effect` wrapper.
5493
+ * Filter a package's candidate versions to those old enough to pass the
5494
+ * gate, given each version's publish timestamp and a caller-supplied `now`.
5289
5495
  *
5290
- * @returns The plain JavaScript value (object, array, string, number,
5291
- * boolean or `null`) this subtree represents.
5496
+ * A version is kept when it has a parseable publish timestamp at or before
5497
+ * the cutoff (`now - ageMinutes * 60000`). A version with a **missing or
5498
+ * unparseable** timestamp in `times` is **dropped** — matching pnpm's strict
5499
+ * posture: a version whose age cannot be established is treated as too young.
5500
+ * The clock is the caller's; this method reads no wall clock.
5501
+ *
5502
+ * Returns all versions unchanged (a no-op) when the gate is inert
5503
+ * (`ageMinutes <= 0`) or the package name is excluded.
5504
+ *
5505
+ * @param versions - the candidate version strings.
5506
+ * @param times - a map from version string to its ISO-8601 publish date.
5507
+ * @param name - the package name (checked against the gate's `exclude` list).
5508
+ * @param now - the current time in epoch milliseconds (the caller's clock).
5292
5509
  */
5293
- toValue() {
5294
- return evaluateNode(this, 0);
5510
+ filterVersions(versions, times, name, now) {
5511
+ if (this.ageMinutes <= 0 || this.isExcluded(name)) return versions;
5512
+ const cutoff = now - this.ageMinutes * MS_PER_MINUTE;
5513
+ return versions.filter((version) => {
5514
+ const time = times[version];
5515
+ if (time === void 0) return false;
5516
+ const published = Date.parse(time);
5517
+ return Number.isFinite(published) && published <= cutoff;
5518
+ });
5295
5519
  }
5296
5520
  };
5521
+
5522
+ //#endregion
5523
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/ImporterDependency.js
5297
5524
  /**
5298
- * Validation-free construction path for the trusted tree builder in
5299
- * `internal/parser.ts` — NOT part of the public surface (not re-exported from
5300
- * `index.ts`); external callers construct via the fully validating
5301
- * `JsoncNode.make`.
5302
- *
5303
- * Constructing a `JsoncNode` through `make`/`new` re-parses the recursive
5304
- * `children` field, and each element parse re-runs the class transformation,
5305
- * which re-parses ITS children — construction cost doubles per nesting level
5306
- * (issue #13; measured ~4s at depth 20, effectively hanging past 25). The
5307
- * parser guarantees validity by construction — every field comes straight off
5308
- * a scanner token — so it skips schema construction entirely.
5525
+ * One declared dependency of one workspace importer, as the lockfile records it.
5309
5526
  *
5310
- * A `Schema.Class` instance is its props assigned onto the class prototype:
5311
- * the base `Data.Class` constructor is exactly `Object.assign(this, props)`,
5312
- * and the prototype chain carries the methods, the class brand getter and
5313
- * structural equality (verified against effect@4.0.0-beta.97). Mirroring that
5314
- * with `Object.create` + `Object.assign` yields an instance identical to a
5315
- * `make`-built one, minus the validating parse.
5527
+ * @remarks
5528
+ * - `name` the dependency's package name.
5529
+ * - `specifier` the declared range, typed through `@effected/npm`'s
5530
+ * `DependencySpecifier.FromString` codec: the decoded value is a tag-matchable
5531
+ * `ClassifiedSpecifier` (`catalog:` / `workspace:` / range / dist-tag / raw),
5532
+ * while encoding round-trips the **exact original string byte-for-byte** — the
5533
+ * guarantee a before/after lockfile diff relies on.
5534
+ * - `version` — the concrete resolved version, **populated by pnpm only**:
5535
+ * comparable across refs and printable. pnpm records `{ specifier, version }`
5536
+ * per importer dependency, and the parser splits pnpm's peer-disambiguation
5537
+ * suffix off into `peerSuffix`, so `version` is always the plain version — or
5538
+ * a non-registry resolution (`link:../utils`, `file:...`), passed through
5539
+ * verbatim. bun and npm record resolved versions on their package entries
5540
+ * instead, so for those formats `version` is absent and a consumer joins by
5541
+ * `name` against `Lockfile.packages`.
5542
+ * - `peerSuffix` — pnpm's peer-disambiguation context: the raw parenthesized
5543
+ * chain the lockfile recorded after the version, e.g.
5544
+ * `(effect@4.0.0-beta.101)(ioredis@5.11.1(supports-color@8.1.1))`. Present
5545
+ * only when the lockfile recorded one — never for suffix-free pnpm entries,
5546
+ * and never for the other formats, which do not record peer context per
5547
+ * importer dependency.
5548
+ * - `depType` — which dependency map declared it, spelled with `@effected/npm`'s
5549
+ * kit-wide `DependencyField` vocabulary.
5316
5550
  *
5317
- * Contract: absent optional fields must be OMITTED, never passed as an
5318
- * explicit `undefined` (a present `undefined` would create an own property
5319
- * that `make` would have rejected).
5551
+ * @public
5320
5552
  */
5321
- const makeNodeUnsafe = (props) => Object.assign(Object.create(JsoncNode.prototype), props);
5322
- function findAtOffsetImpl(node, offset, depth) {
5323
- if (offset < node.offset || offset >= node.offset + node.length) return Option.none();
5324
- if (node.children === void 0 || depth >= 256) return Option.some(node);
5325
- for (const child of node.children) if (offset >= child.offset && offset < child.offset + child.length) return findAtOffsetImpl(child, offset, depth + 1);
5326
- return Option.some(node);
5327
- }
5328
- function buildPath(node, targetOffset, currentPath, depth = 0) {
5329
- if (targetOffset < node.offset || targetOffset >= node.offset + node.length) return Option.none();
5330
- if (node.children === void 0 || depth >= 256) return Option.some(currentPath);
5331
- if (node.type === "object") {
5332
- for (const prop of node.children) if (prop.type === "property" && prop.children !== void 0 && targetOffset >= prop.offset && targetOffset < prop.offset + prop.length) {
5333
- const key = prop.children[0]?.value;
5334
- const valuePath = [...currentPath, key];
5335
- const valueChild = prop.children[1];
5336
- if (valueChild !== void 0 && targetOffset >= valueChild.offset && targetOffset < valueChild.offset + valueChild.length) return buildPath(valueChild, targetOffset, valuePath, depth + 1);
5337
- return Option.some(valuePath);
5338
- }
5339
- } else if (node.type === "array") for (let i = 0; i < node.children.length; i++) {
5340
- const child = node.children[i];
5341
- if (targetOffset >= child.offset && targetOffset < child.offset + child.length) return buildPath(child, targetOffset, [...currentPath, i], depth + 1);
5342
- }
5343
- return Option.some(currentPath);
5344
- }
5345
- function evaluateNode(node, depth) {
5346
- if (depth >= 256) return node.type === "object" ? {} : node.type === "array" ? [] : null;
5347
- switch (node.type) {
5348
- case "object": {
5349
- const obj = {};
5350
- if (node.children !== void 0) {
5351
- for (const prop of node.children) if (prop.type === "property" && prop.children !== void 0 && prop.children.length === 2) {
5352
- const key = prop.children[0].value;
5353
- const value = evaluateNode(prop.children[1], depth + 1);
5354
- if (key === "__proto__") Object.defineProperty(obj, key, {
5355
- value,
5356
- writable: true,
5357
- enumerable: true,
5358
- configurable: true
5359
- });
5360
- else obj[key] = value;
5361
- }
5362
- }
5363
- return obj;
5364
- }
5365
- case "array": return (node.children ?? []).map((child) => evaluateNode(child, depth + 1));
5366
- case "property": return node.children?.[1] !== void 0 ? evaluateNode(node.children[1], depth + 1) : void 0;
5367
- default: return node.value;
5368
- }
5369
- }
5553
+ var ImporterDependency = class extends Schema.Class("ImporterDependency")({
5554
+ name: Schema.NonEmptyString,
5555
+ specifier: DependencySpecifier$1.FromString,
5556
+ version: Schema.optionalKey(Schema.String),
5557
+ peerSuffix: Schema.optionalKey(Schema.String),
5558
+ depType: DependencyField$1
5559
+ }) {};
5370
5560
 
5371
5561
  //#endregion
5372
- //#region ../../node_modules/.pnpm/@effected+jsonc@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/jsonc/internal/scanner.js
5373
- const isWhitespace = (ch) => ch === 32 || ch === 9 || ch === 11 || ch === 12 || ch === 160 || ch === 65279;
5374
- const isLineBreak$1 = (ch) => ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
5375
- const isDigit$1 = (ch) => ch >= 48 && ch <= 57;
5562
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/LockfileImporter.js
5376
5563
  /**
5377
- * Create a stateful {@link Scanner} for the given JSONC string.
5564
+ * One workspace importer's declared dependencies, as the lockfile records them.
5378
5565
  *
5379
- * @param text - JSONC string to tokenize.
5380
- * @param ignoreTrivia - When `true`, whitespace, line-break and comment tokens
5381
- * are skipped so only structural tokens are returned.
5566
+ * @remarks
5567
+ * - `path` the importer path relative to the workspace root, `"."` for the
5568
+ * root package (never empty a `NonEmptyString`) — the same keys as
5569
+ * `WorkspaceDiscovery.importerMap()` in
5570
+ * `@effected/workspaces`. This is the stable join key: `Lockfile#importer`
5571
+ * looks importers up by it, and `Lockfile#withImporterNames` deliberately
5572
+ * leaves importers untouched because the path — not a package name — keys
5573
+ * them.
5574
+ * - `dependencies` — each declared dependency as an {@link ImporterDependency}.
5575
+ *
5576
+ * Populated by the pnpm, bun and npm parsers. yarn does not record importers,
5577
+ * so a yarn lockfile always yields an empty `importers` array.
5578
+ *
5579
+ * @public
5382
5580
  */
5383
- const createScanner$2 = (text, ignoreTrivia = false) => {
5384
- const len = text.length;
5385
- let pos = 0;
5386
- let tokenOffset = 0;
5387
- let token = "Unknown";
5388
- let tokenValue = "";
5389
- let tokenError = "None";
5390
- const scanHexDigits = (count) => {
5391
- let value = 0;
5392
- for (let i = 0; i < count; i++) {
5393
- if (pos >= len) return -1;
5394
- const ch = text.charCodeAt(pos);
5581
+ var LockfileImporter = class extends Schema.Class("LockfileImporter")({
5582
+ path: Schema.NonEmptyString,
5583
+ dependencies: Schema.Array(ImporterDependency)
5584
+ }) {};
5585
+
5586
+ //#endregion
5587
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/ResolvedPackage.js
5588
+ const EMPTY_DEPENDENCIES = {};
5589
+ /**
5590
+ * A package resolved from a lockfile.
5591
+ *
5592
+ * @remarks
5593
+ * The common shape every format's entries normalize into:
5594
+ *
5595
+ * - `name` — the resolved package name. For pnpm *workspace* packages
5596
+ * straight out of `Lockfile.parse` this is the importer path until
5597
+ * `Lockfile#withImporterNames` rewrites it.
5598
+ * - `version` — the resolved version string (pnpm workspace packages carry
5599
+ * `"0.0.0"`; the lockfile does not record their real versions).
5600
+ * - `integrity` — optional `@effected/npm` `IntegrityHash`, covering npm/pnpm
5601
+ * `sha512-...` SRI and yarn Berry's `10c0/...` cache checksums (the yarn
5602
+ * textual form). An *absent* integrity is omitted, so a `ResolvedPackage` may
5603
+ * carry none; a *present but unparseable* integrity fails the parse typed at
5604
+ * validation rather than being silently dropped.
5605
+ * - `isWorkspace` — `true` for workspace-local packages.
5606
+ * - `relativePath` — the workspace-relative directory for workspace
5607
+ * packages, when the lockfile records one.
5608
+ * - `dependencies` — the package's own dependency map, defaulting to `{}`
5609
+ * both at construction and when decoding serialized data.
5610
+ *
5611
+ * @public
5612
+ */
5613
+ var ResolvedPackage = class extends Schema.Class("ResolvedPackage")({
5614
+ name: Schema.NonEmptyString,
5615
+ version: Schema.String,
5616
+ integrity: Schema.optionalKey(IntegrityHash$1),
5617
+ isWorkspace: Schema.Boolean,
5618
+ relativePath: Schema.optionalKey(Schema.String),
5619
+ dependencies: Schema.Record(Schema.String, Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed(EMPTY_DEPENDENCIES)), Schema.withConstructorDefault(Effect.succeed(EMPTY_DEPENDENCIES)))
5620
+ }) {};
5621
+
5622
+ //#endregion
5623
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/WorkspaceDependency.js
5624
+ /**
5625
+ * A directed dependency edge between two workspace packages as recorded in
5626
+ * the lockfile.
5627
+ *
5628
+ * @remarks
5629
+ * - `from` — the workspace package declaring the dependency. For pnpm this
5630
+ * is the importer path until `Lockfile#withImporterNames` rewrites it.
5631
+ * - `to` — the workspace package depended upon.
5632
+ * - `depType` — which dependency map holds the edge, spelled with
5633
+ * `@effected/npm`'s kit-wide `DependencyField` vocabulary.
5634
+ * - `constraint` — the declared specifier (e.g. `"workspace:*"`, `"^1.0.0"`).
5635
+ *
5636
+ * @public
5637
+ */
5638
+ var WorkspaceDependency = class extends Schema.Class("WorkspaceDependency")({
5639
+ from: Schema.NonEmptyString,
5640
+ to: Schema.NonEmptyString,
5641
+ depType: DependencyField$1,
5642
+ constraint: Schema.String
5643
+ }) {};
5644
+
5645
+ //#endregion
5646
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/PnpmExtension.js
5647
+ /**
5648
+ * Extension data specific to pnpm lockfiles, attached to `Lockfile.extension`
5649
+ * when the format is `"pnpm"`.
5650
+ *
5651
+ * @remarks
5652
+ * - `catalogs` — pnpm catalog definitions ({@link PnpmCatalogs}).
5653
+ * - `overrides` — the version override map recorded in the lockfile header.
5654
+ * - `settings` — pnpm settings recorded in the lockfile header.
5655
+ *
5656
+ * @public
5657
+ */
5658
+ var PnpmExtension = class extends Schema.Class("PnpmExtension")({
5659
+ _tag: Schema.tag("pnpm"),
5660
+ catalogs: Schema.optionalKey(Schema.Record(Schema.String, Schema.Record(Schema.String, Schema.Union([Schema.String, Schema.Struct({
5661
+ specifier: Schema.String,
5662
+ version: Schema.String
5663
+ })])))),
5664
+ overrides: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
5665
+ settings: Schema.optionalKey(Schema.Struct({
5666
+ autoInstallPeers: Schema.optionalKey(Schema.Boolean),
5667
+ excludeLinksFromLockfile: Schema.optionalKey(Schema.Boolean)
5668
+ }))
5669
+ }) {};
5670
+
5671
+ //#endregion
5672
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/LockfileFormat.js
5673
+ /**
5674
+ * The lockfile formats this package parses: bun's `bun.lock` (JSONC), npm's
5675
+ * `package-lock.json` (v2/v3 JSON), pnpm's `pnpm-lock.yaml` and yarn Berry's
5676
+ * `yarn.lock` (both YAML).
5677
+ *
5678
+ * @remarks
5679
+ * The literal names the *lockfile format*, not the package manager that
5680
+ * happens to write it — this package models lockfiles. Yarn support is
5681
+ * Berry only; classic (v1) `yarn.lock` is not YAML and fails
5682
+ * `Lockfile.parse` with a typed `LockfileParseError`.
5683
+ *
5684
+ * @public
5685
+ */
5686
+ const LockfileFormat = Schema.Literals([
5687
+ "bun",
5688
+ "npm",
5689
+ "pnpm",
5690
+ "yarn"
5691
+ ]);
5692
+ const FILENAMES = {
5693
+ bun: ["bun.lock", "bun.lockb"],
5694
+ npm: ["package-lock.json", "npm-shrinkwrap.json"],
5695
+ pnpm: ["pnpm-lock.yaml"],
5696
+ yarn: ["yarn.lock"]
5697
+ };
5698
+ /**
5699
+ * The conventional lockfile filename for a format: `"bun.lock"`,
5700
+ * `"package-lock.json"`, `"pnpm-lock.yaml"` or `"yarn.lock"`.
5701
+ *
5702
+ * @remarks
5703
+ * The primary name only — the first element of {@link filenamesFor}, which is
5704
+ * what detection that must also see the genuine alternates should use.
5705
+ *
5706
+ * @public
5707
+ */
5708
+ const filenameFor = (format) => FILENAMES[format][0];
5709
+
5710
+ //#endregion
5711
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/internal/shared.js
5712
+ /**
5713
+ * The four dependency sections of a manifest, in a stable order — the shared
5714
+ * dependency-sections table (v3's `DEP_SECTIONS`). Each entry is both the
5715
+ * manifest field name to read and the `@effected/npm` `DependencyField` it maps
5716
+ * to, since the two coincide. Consumed by `extractWorkspaceDeps` and by the
5717
+ * pnpm/bun/npm importer builders.
5718
+ *
5719
+ * @internal
5720
+ */
5721
+ const DEP_TYPES = [
5722
+ "dependencies",
5723
+ "devDependencies",
5724
+ "peerDependencies",
5725
+ "optionalDependencies"
5726
+ ];
5727
+ /**
5728
+ * Coerce a raw lockfile integrity string to the `@effected/npm` `IntegrityHash`
5729
+ * brand, which recognizes the SRI (`<algo>-<base64>`), corepack (`<algo>.<hex>`)
5730
+ * and yarn (`<cachekey>/<hex>`) textual forms.
5731
+ *
5732
+ * Absence and corruption are treated differently, and the distinction is the
5733
+ * point. An *absent* integrity (input `undefined`) succeeds with `undefined`,
5734
+ * so the caller omits the field — a lockfile that records no integrity is
5735
+ * legitimate. A *present but unparseable* integrity fails through the same
5736
+ * validation channel the shape checks use ({@link validationFailure}), so
5737
+ * `Lockfile.parse` surfaces it as a `LockfileParseError` with
5738
+ * `stage: "validation"` rather than silently dropping a corrupt value. Never a
5739
+ * defect. yarn's `10c0/<hex>` cache checksums are a recognized form, so real
5740
+ * yarn/npm/pnpm/bun integrity all still parses; only genuine corruption fails.
5741
+ *
5742
+ * @internal
5743
+ */
5744
+ const toIntegrityHash = (raw) => {
5745
+ if (raw === void 0) return Effect.succeed(void 0);
5746
+ return Schema.decodeUnknownEffect(IntegrityHash$1)(raw).pipe(Effect.mapError(validationFailure));
5747
+ };
5748
+ const decodeSpecifier = Schema.decodeUnknownExit(DependencySpecifier$1.FromString);
5749
+ /**
5750
+ * Split pnpm's peer-disambiguation suffix off a recorded string: everything
5751
+ * from the first `(` on is suffix, since package names and versions never
5752
+ * contain `(`. Handles both shapes pnpm records — a bare version
5753
+ * (`"1.0.0(effect@4.0.0)"`, importer entries) and a `name@version` snapshot key
5754
+ * (`"fdir@6.5.0(picomatch@4.0.4)"`). A string with no `(` — including
5755
+ * `link:...` / `file:...` resolutions — passes through untouched. So does a
5756
+ * protocol-bearing string (a `:` ahead of the first `(`), where a parenthesis
5757
+ * is path or URL text rather than a peer suffix: pnpm attaches suffixes to
5758
+ * registry versions only. This is the single stripping implementation — do not
5759
+ * hand-roll an `indexOf("(")` split elsewhere.
5760
+ *
5761
+ * @internal
5762
+ */
5763
+ const splitPeerSuffix = (raw) => {
5764
+ const parenIndex = raw.indexOf("(");
5765
+ if (parenIndex === -1) return { plain: raw };
5766
+ if (raw.lastIndexOf(":", parenIndex) !== -1) return { plain: raw };
5767
+ return {
5768
+ plain: raw.slice(0, parenIndex),
5769
+ peerSuffix: raw.slice(parenIndex)
5770
+ };
5771
+ };
5772
+ /**
5773
+ * Build one {@link ImporterDependency}, decoding the raw specifier string into
5774
+ * the `@effected/npm` `ClassifiedSpecifier` tagged union. Returns `undefined`
5775
+ * — a skip, never a throw — when the name is empty or the specifier does not
5776
+ * classify (e.g. an empty specifier), per the total-string-surgery discipline.
5777
+ *
5778
+ * A pnpm-recorded version is normalized through {@link splitPeerSuffix}: the
5779
+ * `version` field carries the plain version and the split-off peer chain lands
5780
+ * in `peerSuffix`. A version that is *only* a peer chain (empty plain part) is
5781
+ * treated as no concrete version — a skip of both fields, never a throw.
5782
+ *
5783
+ * @internal
5784
+ */
5785
+ const buildImporterDependency = (name, specifier, depType, version) => {
5786
+ if (name === "") return void 0;
5787
+ const exit = decodeSpecifier(specifier);
5788
+ if (Exit.isFailure(exit)) return void 0;
5789
+ const resolved = version !== void 0 && version !== "" ? splitPeerSuffix(version) : void 0;
5790
+ return ImporterDependency.make({
5791
+ name,
5792
+ specifier: exit.value,
5793
+ depType,
5794
+ ...resolved !== void 0 && resolved.plain !== "" ? {
5795
+ version: resolved.plain,
5796
+ ...resolved.peerSuffix !== void 0 ? { peerSuffix: resolved.peerSuffix } : {}
5797
+ } : {}
5798
+ });
5799
+ };
5800
+ /**
5801
+ * Collect an importer's declared dependencies off the shared dependency-sections
5802
+ * table. Iterates {@link DEP_TYPES} in order, projecting each section value with
5803
+ * `read`; malformed rows are skipped (never thrown). Key-bearing intermediates
5804
+ * are the schema-decoded records, whose own-property `Object.entries` iteration
5805
+ * neither pollutes nor drops a `__proto__` key.
5806
+ *
5807
+ * @internal
5808
+ */
5809
+ const importerDependencies = (entry, read) => {
5810
+ const deps = [];
5811
+ for (const field of DEP_TYPES) {
5812
+ const section = entry[field];
5813
+ if (!section) continue;
5814
+ for (const [name, value] of Object.entries(section)) {
5815
+ const { specifier, version } = read(value);
5816
+ const dep = buildImporterDependency(name, specifier, field, version);
5817
+ if (dep !== void 0) deps.push(dep);
5818
+ }
5819
+ }
5820
+ return deps;
5821
+ };
5822
+ /** @internal */
5823
+ const syntaxFailure = (cause) => ({
5824
+ stage: "syntax",
5825
+ cause
5826
+ });
5827
+ /** @internal */
5828
+ const validationFailure = (cause) => ({
5829
+ stage: "validation",
5830
+ cause
5831
+ });
5832
+ /** @internal */
5833
+ const framingFailure = (reason, documents) => ({
5834
+ stage: "framing",
5835
+ reason,
5836
+ documents
5837
+ });
5838
+ /**
5839
+ * Whether the specifier is a workspace, link or file reference
5840
+ * (`"workspace:*"`, `"link:../foo"`, `"file:../bar"`).
5841
+ *
5842
+ * @internal
5843
+ */
5844
+ const isWorkspaceSpecifier = (specifier) => specifier.startsWith("workspace:") || specifier.startsWith("link:") || specifier.startsWith("file:");
5845
+ /**
5846
+ * Extract inter-workspace dependency edges: for every workspace entry and
5847
+ * dependency type, emit an edge for each dependency whose name is itself a
5848
+ * workspace. Key-bearing intermediates are `Map`/`Set` — lockfile keys are
5849
+ * attacker-adjacent strings (`__proto__`, `constructor`) and must never be
5850
+ * assigned onto plain objects here.
5851
+ *
5852
+ * @internal
5853
+ */
5854
+ const extractWorkspaceDeps = (workspaces, workspaceNames) => {
5855
+ const deps = [];
5856
+ for (const [from, entry] of workspaces) for (const depType of DEP_TYPES) {
5857
+ const depMap = entry[depType];
5858
+ if (!depMap) continue;
5859
+ for (const [name, constraint] of Object.entries(depMap)) if (workspaceNames.has(name)) deps.push(WorkspaceDependency.make({
5860
+ from,
5861
+ to: name,
5862
+ depType,
5863
+ constraint
5864
+ }));
5865
+ }
5866
+ return deps;
5867
+ };
5868
+
5869
+ //#endregion
5870
+ //#region ../../node_modules/.pnpm/@effected+jsonc@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/jsonc/JsoncNode.js
5871
+ /**
5872
+ * Discriminator values for JSONC AST node types: the JSON value types
5873
+ * (`string`/`number`/`boolean`/`null`), the structural types
5874
+ * (`object`/`array`) and the `property` key-value pair type.
5875
+ *
5876
+ * @public
5877
+ */
5878
+ const JsoncNodeType = Schema.Literals([
5879
+ "object",
5880
+ "array",
5881
+ "property",
5882
+ "string",
5883
+ "number",
5884
+ "boolean",
5885
+ "null"
5886
+ ]);
5887
+ /**
5888
+ * An immutable JSONC AST node produced by `Jsonc.parseTree`.
5889
+ *
5890
+ * The `parent` field present in Microsoft's `jsonc-parser` is intentionally
5891
+ * omitted: circular references would break structural equality, serialization
5892
+ * and Schema encode/decode. Child relationships are expressed via `children`,
5893
+ * and the recursive type is handled with `Schema.suspend`.
5894
+ *
5895
+ * - `type` — the `JsoncNodeType` discriminator.
5896
+ * - `offset` / `length` — the node's span in the source (tight token-end
5897
+ * discipline: spans never swallow trailing whitespace or comments).
5898
+ * - `value` — the decoded JS value for leaf nodes; omitted for structural nodes.
5899
+ * - `colonOffset` — for `property` nodes, the offset of the `:` separator.
5900
+ * - `children` — child nodes for `object`, `array` and `property` nodes.
5901
+ *
5902
+ * Construct via `JsoncNode.make(...)`, never `new JsoncNode(...)`.
5903
+ *
5904
+ * @public
5905
+ */
5906
+ var JsoncNode = class JsoncNode extends Schema.Class("JsoncNode")({
5907
+ type: JsoncNodeType,
5908
+ offset: Schema.Number,
5909
+ length: Schema.Number,
5910
+ value: Schema.optionalKey(Schema.Unknown),
5911
+ colonOffset: Schema.optionalKey(Schema.Number),
5912
+ children: Schema.optionalKey(Schema.Array(Schema.suspend(() => JsoncNode)))
5913
+ }) {
5914
+ /**
5915
+ * Find a descendant node by path. String segments navigate object
5916
+ * properties; number segments navigate array indices. Returns
5917
+ * `Option.none()` when any segment cannot be resolved. Pure.
5918
+ *
5919
+ * @param path - The path to resolve, relative to this node.
5920
+ * @returns The descendant node, or `Option.none()` when `path` cannot be
5921
+ * resolved.
5922
+ */
5923
+ find(path) {
5924
+ let current = this;
5925
+ for (const segment of path) {
5926
+ if (current?.children === void 0) return Option.none();
5927
+ if (typeof segment === "string") {
5928
+ if (current.type !== "object") return Option.none();
5929
+ current = current.children.find((child) => child.type === "property" && child.children !== void 0 && child.children[0]?.value === segment)?.children?.[1];
5930
+ } else {
5931
+ if (current.type !== "array") return Option.none();
5932
+ current = current.children[segment];
5933
+ }
5934
+ }
5935
+ return current !== void 0 ? Option.some(current) : Option.none();
5936
+ }
5937
+ /**
5938
+ * Find the innermost node whose span covers `offset`, or `Option.none()`
5939
+ * if the offset is outside this subtree. Pure.
5940
+ *
5941
+ * @param offset - The zero-based character offset to locate.
5942
+ * @returns The innermost covering node, or `Option.none()` when `offset`
5943
+ * falls outside this subtree.
5944
+ */
5945
+ findAtOffset(offset) {
5946
+ return findAtOffsetImpl(this, offset, 0);
5947
+ }
5948
+ /**
5949
+ * Return the JSON path to the innermost node covering `offset`, or
5950
+ * `Option.none()` if the offset is outside this subtree. The inverse of
5951
+ * {@link JsoncNode.find}. Pure.
5952
+ *
5953
+ * @param offset - The zero-based character offset to locate.
5954
+ * @returns The path to the innermost covering node, or `Option.none()`
5955
+ * when `offset` falls outside this subtree.
5956
+ */
5957
+ pathAt(offset) {
5958
+ return buildPath(this, offset, []);
5959
+ }
5960
+ /**
5961
+ * Reconstruct the plain JavaScript value represented by this subtree. Pure
5962
+ * and total — never fails, so no `Effect` wrapper.
5963
+ *
5964
+ * @returns The plain JavaScript value (object, array, string, number,
5965
+ * boolean or `null`) this subtree represents.
5966
+ */
5967
+ toValue() {
5968
+ return evaluateNode(this, 0);
5969
+ }
5970
+ };
5971
+ /**
5972
+ * Validation-free construction path for the trusted tree builder in
5973
+ * `internal/parser.ts` — NOT part of the public surface (not re-exported from
5974
+ * `index.ts`); external callers construct via the fully validating
5975
+ * `JsoncNode.make`.
5976
+ *
5977
+ * Constructing a `JsoncNode` through `make`/`new` re-parses the recursive
5978
+ * `children` field, and each element parse re-runs the class transformation,
5979
+ * which re-parses ITS children — construction cost doubles per nesting level
5980
+ * (issue #13; measured ~4s at depth 20, effectively hanging past 25). The
5981
+ * parser guarantees validity by construction — every field comes straight off
5982
+ * a scanner token — so it skips schema construction entirely.
5983
+ *
5984
+ * A `Schema.Class` instance is its props assigned onto the class prototype:
5985
+ * the base `Data.Class` constructor is exactly `Object.assign(this, props)`,
5986
+ * and the prototype chain carries the methods, the class brand getter and
5987
+ * structural equality (verified against effect@4.0.0-beta.97). Mirroring that
5988
+ * with `Object.create` + `Object.assign` yields an instance identical to a
5989
+ * `make`-built one, minus the validating parse.
5990
+ *
5991
+ * Contract: absent optional fields must be OMITTED, never passed as an
5992
+ * explicit `undefined` (a present `undefined` would create an own property
5993
+ * that `make` would have rejected).
5994
+ */
5995
+ const makeNodeUnsafe = (props) => Object.assign(Object.create(JsoncNode.prototype), props);
5996
+ function findAtOffsetImpl(node, offset, depth) {
5997
+ if (offset < node.offset || offset >= node.offset + node.length) return Option.none();
5998
+ if (node.children === void 0 || depth >= 256) return Option.some(node);
5999
+ for (const child of node.children) if (offset >= child.offset && offset < child.offset + child.length) return findAtOffsetImpl(child, offset, depth + 1);
6000
+ return Option.some(node);
6001
+ }
6002
+ function buildPath(node, targetOffset, currentPath, depth = 0) {
6003
+ if (targetOffset < node.offset || targetOffset >= node.offset + node.length) return Option.none();
6004
+ if (node.children === void 0 || depth >= 256) return Option.some(currentPath);
6005
+ if (node.type === "object") {
6006
+ for (const prop of node.children) if (prop.type === "property" && prop.children !== void 0 && targetOffset >= prop.offset && targetOffset < prop.offset + prop.length) {
6007
+ const key = prop.children[0]?.value;
6008
+ const valuePath = [...currentPath, key];
6009
+ const valueChild = prop.children[1];
6010
+ if (valueChild !== void 0 && targetOffset >= valueChild.offset && targetOffset < valueChild.offset + valueChild.length) return buildPath(valueChild, targetOffset, valuePath, depth + 1);
6011
+ return Option.some(valuePath);
6012
+ }
6013
+ } else if (node.type === "array") for (let i = 0; i < node.children.length; i++) {
6014
+ const child = node.children[i];
6015
+ if (targetOffset >= child.offset && targetOffset < child.offset + child.length) return buildPath(child, targetOffset, [...currentPath, i], depth + 1);
6016
+ }
6017
+ return Option.some(currentPath);
6018
+ }
6019
+ function evaluateNode(node, depth) {
6020
+ if (depth >= 256) return node.type === "object" ? {} : node.type === "array" ? [] : null;
6021
+ switch (node.type) {
6022
+ case "object": {
6023
+ const obj = {};
6024
+ if (node.children !== void 0) {
6025
+ for (const prop of node.children) if (prop.type === "property" && prop.children !== void 0 && prop.children.length === 2) {
6026
+ const key = prop.children[0].value;
6027
+ const value = evaluateNode(prop.children[1], depth + 1);
6028
+ if (key === "__proto__") Object.defineProperty(obj, key, {
6029
+ value,
6030
+ writable: true,
6031
+ enumerable: true,
6032
+ configurable: true
6033
+ });
6034
+ else obj[key] = value;
6035
+ }
6036
+ }
6037
+ return obj;
6038
+ }
6039
+ case "array": return (node.children ?? []).map((child) => evaluateNode(child, depth + 1));
6040
+ case "property": return node.children?.[1] !== void 0 ? evaluateNode(node.children[1], depth + 1) : void 0;
6041
+ default: return node.value;
6042
+ }
6043
+ }
6044
+
6045
+ //#endregion
6046
+ //#region ../../node_modules/.pnpm/@effected+jsonc@0.5.2_effect@4.0.0-beta.101/node_modules/@effected/jsonc/internal/scanner.js
6047
+ const isWhitespace = (ch) => ch === 32 || ch === 9 || ch === 11 || ch === 12 || ch === 160 || ch === 65279;
6048
+ const isLineBreak$1 = (ch) => ch === 10 || ch === 13 || ch === 8232 || ch === 8233;
6049
+ const isDigit$1 = (ch) => ch >= 48 && ch <= 57;
6050
+ /**
6051
+ * Create a stateful {@link Scanner} for the given JSONC string.
6052
+ *
6053
+ * @param text - JSONC string to tokenize.
6054
+ * @param ignoreTrivia - When `true`, whitespace, line-break and comment tokens
6055
+ * are skipped so only structural tokens are returned.
6056
+ */
6057
+ const createScanner$2 = (text, ignoreTrivia = false) => {
6058
+ const len = text.length;
6059
+ let pos = 0;
6060
+ let tokenOffset = 0;
6061
+ let token = "Unknown";
6062
+ let tokenValue = "";
6063
+ let tokenError = "None";
6064
+ const scanHexDigits = (count) => {
6065
+ let value = 0;
6066
+ for (let i = 0; i < count; i++) {
6067
+ if (pos >= len) return -1;
6068
+ const ch = text.charCodeAt(pos);
5395
6069
  if (ch >= 48 && ch <= 57) value = value * 16 + (ch - 48);
5396
6070
  else if (ch >= 65 && ch <= 70) value = value * 16 + (ch - 65 + 10);
5397
6071
  else if (ch >= 97 && ch <= 102) value = value * 16 + (ch - 97 + 10);
@@ -7006,7 +7680,7 @@ var JsoncModifier = class {
7006
7680
  };
7007
7681
 
7008
7682
  //#endregion
7009
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/bun.js
7683
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/internal/bun.js
7010
7684
  const DepRecord$2 = Schema.optionalKey(Schema.Record(Schema.String, Schema.String));
7011
7685
  const BunWorkspaceEntry = Schema.Struct({
7012
7686
  name: Schema.optionalKey(Schema.String),
@@ -7100,7 +7774,7 @@ const toFields$3 = (raw) => Effect.gen(function* () {
7100
7774
  });
7101
7775
 
7102
7776
  //#endregion
7103
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/npm.js
7777
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/internal/npm.js
7104
7778
  const DepRecord$1 = Schema.optionalKey(Schema.Record(Schema.String, Schema.String));
7105
7779
  const NpmPackageEntry = Schema.Struct({
7106
7780
  name: Schema.optionalKey(Schema.String),
@@ -14128,7 +14802,7 @@ function deepEqualValues(a, b) {
14128
14802
  }
14129
14803
 
14130
14804
  //#endregion
14131
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/documents.js
14805
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/internal/documents.js
14132
14806
  /**
14133
14807
  * An empty YAML document composes to `null` (`Yaml.parseAll("")` is `[null]`,
14134
14808
  * and the trailing document of an env-only `pnpm-lock.yaml` is `null` too).
@@ -14199,7 +14873,7 @@ const selectSoleDocument = (content) => Effect.gen(function* () {
14199
14873
  });
14200
14874
 
14201
14875
  //#endregion
14202
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/pnpm.js
14876
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/internal/pnpm.js
14203
14877
  const PnpmImporterDeps = Schema.optionalKey(Schema.Record(Schema.String, Schema.Struct({
14204
14878
  specifier: Schema.String,
14205
14879
  version: Schema.String
@@ -14225,590 +14899,1047 @@ const PnpmLockfileRaw = Schema.Struct({
14225
14899
  packages: Schema.optionalKey(Schema.Record(Schema.String, Schema.Struct({ resolution: Schema.optionalKey(Schema.Struct({ integrity: Schema.optionalKey(Schema.String) })) })))
14226
14900
  });
14227
14901
  /**
14228
- * Parse pnpm `pnpm-lock.yaml` content into the unified field bundle.
14902
+ * Parse pnpm `pnpm-lock.yaml` content into the unified field bundle.
14903
+ *
14904
+ * `pnpm-lock.yaml` is a YAML *stream*, not a single document: a workspace
14905
+ * using `configDependencies` gets a config-dependencies preamble document
14906
+ * ahead of the lockfile. {@link selectPnpmDocument} locates the lockfile
14907
+ * deterministically (it is the last document); a stream carrying no lockfile
14908
+ * document fails through the typed framing channel rather than silently
14909
+ * reporting the preamble as an empty workspace.
14910
+ *
14911
+ * Workspace packages are keyed by importer *path* with version `"0.0.0"`;
14912
+ * `Lockfile#withImporterNames` is the explicit second stage that rewrites
14913
+ * them to real names.
14914
+ *
14915
+ * @internal
14916
+ */
14917
+ const parsePnpm = (content) => Effect.gen(function* () {
14918
+ const { document, documents } = yield* selectPnpmDocument(content);
14919
+ const validated = yield* Schema.decodeUnknownEffect(PnpmLockfileRaw)(document).pipe(Effect.mapError(validationFailure));
14920
+ if (Object.keys(validated.importers).length === 0) return yield* Effect.fail(framingFailure("noImporters", documents));
14921
+ return yield* toFields$1(validated);
14922
+ });
14923
+ const toVersionMap = (deps) => {
14924
+ if (!deps) return void 0;
14925
+ return Object.fromEntries(Object.entries(deps).map(([name, info]) => [name, info.specifier]));
14926
+ };
14927
+ const importerDepGroups = (importer) => [
14928
+ importer.dependencies,
14929
+ importer.devDependencies,
14930
+ importer.peerDependencies,
14931
+ importer.optionalDependencies
14932
+ ];
14933
+ const toFields$1 = (raw) => Effect.gen(function* () {
14934
+ const workspaceEntries = /* @__PURE__ */ new Map();
14935
+ const workspaceNames = /* @__PURE__ */ new Set();
14936
+ const importers = [];
14937
+ for (const [importerPath, importer] of Object.entries(raw.importers)) {
14938
+ if (importerPath === "") continue;
14939
+ importers.push(LockfileImporter.make({
14940
+ path: importerPath,
14941
+ dependencies: importerDependencies(importer, (info) => ({
14942
+ specifier: info.specifier,
14943
+ version: info.version
14944
+ }))
14945
+ }));
14946
+ const deps = toVersionMap(importer.dependencies);
14947
+ const devDeps = toVersionMap(importer.devDependencies);
14948
+ const peerDeps = toVersionMap(importer.peerDependencies);
14949
+ const optDeps = toVersionMap(importer.optionalDependencies);
14950
+ workspaceEntries.set(importerPath, {
14951
+ ...deps ? { dependencies: deps } : {},
14952
+ ...devDeps ? { devDependencies: devDeps } : {},
14953
+ ...peerDeps ? { peerDependencies: peerDeps } : {},
14954
+ ...optDeps ? { optionalDependencies: optDeps } : {}
14955
+ });
14956
+ for (const group of importerDepGroups(importer)) {
14957
+ if (!group) continue;
14958
+ for (const [name, info] of Object.entries(group)) if (name !== "" && info.version.startsWith("link:")) workspaceNames.add(name);
14959
+ }
14960
+ }
14961
+ for (const path of Object.keys(raw.importers)) if (path !== "." && path !== "") workspaceNames.add(path);
14962
+ const packages = [];
14963
+ for (const importerPath of Object.keys(raw.importers)) {
14964
+ if (importerPath === "." || importerPath === "") continue;
14965
+ packages.push(ResolvedPackage.make({
14966
+ name: importerPath,
14967
+ version: "0.0.0",
14968
+ isWorkspace: true,
14969
+ relativePath: importerPath
14970
+ }));
14971
+ }
14972
+ if (raw.packages) for (const [key, pkg] of Object.entries(raw.packages)) {
14973
+ const { plain: bare } = splitPeerSuffix(key);
14974
+ const atIndex = bare.lastIndexOf("@");
14975
+ if (atIndex <= 0) continue;
14976
+ const name = bare.slice(0, atIndex);
14977
+ const version = bare.slice(atIndex + 1);
14978
+ const integrity = yield* toIntegrityHash(pkg.resolution?.integrity);
14979
+ packages.push(ResolvedPackage.make({
14980
+ name,
14981
+ version,
14982
+ ...integrity !== void 0 ? { integrity } : {},
14983
+ isWorkspace: false
14984
+ }));
14985
+ }
14986
+ const workspaceDependencies = extractWorkspaceDeps(workspaceEntries, workspaceNames);
14987
+ const extension = PnpmExtension.make({
14988
+ ...raw.catalogs !== void 0 ? { catalogs: raw.catalogs } : {},
14989
+ ...raw.overrides !== void 0 ? { overrides: raw.overrides } : {},
14990
+ ...raw.settings !== void 0 ? { settings: raw.settings } : {}
14991
+ });
14992
+ return {
14993
+ lockfileVersion: String(raw.lockfileVersion),
14994
+ packages,
14995
+ workspaceDependencies,
14996
+ importers,
14997
+ extension
14998
+ };
14999
+ });
15000
+
15001
+ //#endregion
15002
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/internal/yarn.js
15003
+ const YarnLockfileRaw = Schema.Record(Schema.String, Schema.Unknown);
15004
+ const DepRecord = Schema.optionalKey(Schema.Record(Schema.String, Schema.String));
15005
+ const YarnEntry = Schema.Struct({
15006
+ version: Schema.optionalKey(Schema.String),
15007
+ resolution: Schema.optionalKey(Schema.String),
15008
+ dependencies: DepRecord,
15009
+ devDependencies: DepRecord,
15010
+ peerDependencies: DepRecord,
15011
+ optionalDependencies: DepRecord,
15012
+ checksum: Schema.optionalKey(Schema.String),
15013
+ languageName: Schema.optionalKey(Schema.String),
15014
+ linkType: Schema.optionalKey(Schema.String),
15015
+ bin: Schema.optionalKey(Schema.Unknown)
15016
+ });
15017
+ const YarnMetadata = Schema.Struct({ version: Schema.optionalKey(Schema.Union([Schema.String, Schema.Number])) });
15018
+ /**
15019
+ * Parse yarn Berry `yarn.lock` content into the unified field bundle.
15020
+ *
15021
+ * Yarn Berry lockfiles are YAML with a flat key structure where each key
15022
+ * encodes package name + resolution descriptor(s) (e.g.
15023
+ * `"@scope/name@npm:^1.0.0"`); workspace entries carry `linkType: "soft"`.
15024
+ *
15025
+ * @internal
15026
+ */
15027
+ const parseYarn = (content) => Effect.gen(function* () {
15028
+ const { document } = yield* selectSoleDocument(content);
15029
+ const raw = yield* Schema.decodeUnknownEffect(YarnLockfileRaw)(document).pipe(Effect.mapError(validationFailure));
15030
+ const metadata = raw.__metadata === void 0 ? void 0 : yield* Schema.decodeUnknownEffect(YarnMetadata)(raw.__metadata).pipe(Effect.mapError(validationFailure));
15031
+ const lockfileVersion = metadata?.version === void 0 ? "unknown" : String(metadata.version);
15032
+ const decoded = /* @__PURE__ */ new Map();
15033
+ for (const [key, value] of Object.entries(raw)) {
15034
+ if (key === "__metadata") continue;
15035
+ const entry = yield* Schema.decodeUnknownEffect(YarnEntry)(value).pipe(Effect.mapError(validationFailure));
15036
+ decoded.set(key, entry);
15037
+ }
15038
+ return yield* toFields(lockfileVersion, decoded);
15039
+ });
15040
+ const toFields = (lockfileVersion, decoded) => Effect.gen(function* () {
15041
+ const packages = [];
15042
+ const workspaceNames = /* @__PURE__ */ new Set();
15043
+ const workspaceEntries = /* @__PURE__ */ new Map();
15044
+ for (const [key, entry] of decoded) if (entry.linkType === "soft") {
15045
+ const name = extractYarnPackageName(key);
15046
+ if (name !== void 0) workspaceNames.add(name);
15047
+ }
15048
+ for (const [key, entry] of decoded) {
15049
+ const name = extractYarnPackageName(key);
15050
+ if (name === void 0) continue;
15051
+ const isWorkspace = entry.linkType === "soft";
15052
+ const relativePath = isWorkspace ? extractYarnWorkspacePath(key) : void 0;
15053
+ const integrity = yield* toIntegrityHash(entry.checksum);
15054
+ packages.push(ResolvedPackage.make({
15055
+ name,
15056
+ version: entry.version ?? "0.0.0",
15057
+ ...integrity !== void 0 ? { integrity } : {},
15058
+ isWorkspace,
15059
+ ...relativePath !== void 0 ? { relativePath } : {}
15060
+ }));
15061
+ if (isWorkspace) {
15062
+ const deps = cleanYarnDeps(entry.dependencies);
15063
+ const devDeps = cleanYarnDeps(entry.devDependencies);
15064
+ const peerDeps = cleanYarnDeps(entry.peerDependencies);
15065
+ const optDeps = cleanYarnDeps(entry.optionalDependencies);
15066
+ workspaceEntries.set(name, {
15067
+ ...deps ? { dependencies: deps } : {},
15068
+ ...devDeps ? { devDependencies: devDeps } : {},
15069
+ ...peerDeps ? { peerDependencies: peerDeps } : {},
15070
+ ...optDeps ? { optionalDependencies: optDeps } : {}
15071
+ });
15072
+ }
15073
+ }
15074
+ return {
15075
+ lockfileVersion,
15076
+ packages,
15077
+ workspaceDependencies: extractWorkspaceDeps(workspaceEntries, workspaceNames),
15078
+ importers: []
15079
+ };
15080
+ });
15081
+ /**
15082
+ * Extract the package name from a yarn lockfile key. Handles compound keys
15083
+ * (`"a@workspace:*, a@workspace:packages/a"`) via the first descriptor and
15084
+ * `@patch:` descriptors (which embed `@npm:` inside). Total: malformed keys
15085
+ * yield `undefined`.
15086
+ *
15087
+ * @internal
15088
+ */
15089
+ const extractYarnPackageName = (key) => {
15090
+ const commaIdx = key.indexOf(", ");
15091
+ const descriptor = commaIdx === -1 ? key : key.slice(0, commaIdx);
15092
+ const patchIdx = descriptor.indexOf("@patch:");
15093
+ if (patchIdx > 0) return descriptor.slice(0, patchIdx);
15094
+ const npmIdx = descriptor.lastIndexOf("@npm:");
15095
+ const wsIdx = descriptor.lastIndexOf("@workspace:");
15096
+ const idx = Math.max(npmIdx, wsIdx);
15097
+ if (idx <= 0) return void 0;
15098
+ return descriptor.slice(0, idx);
15099
+ };
15100
+ /**
15101
+ * Extract the workspace-relative path from a yarn lockfile key: the segment
15102
+ * after `@workspace:` in the first descriptor carrying a non-`*` path.
15103
+ *
15104
+ * @internal
15105
+ */
15106
+ const extractYarnWorkspacePath = (key) => {
15107
+ for (const desc of key.split(", ")) {
15108
+ const wsIdx = desc.lastIndexOf("@workspace:");
15109
+ if (wsIdx >= 0) {
15110
+ const path = desc.slice(wsIdx + 11);
15111
+ if (path !== "" && path !== "*") return path;
15112
+ }
15113
+ }
15114
+ };
15115
+ /**
15116
+ * Strip the `"npm:"` prefix from yarn dependency specifiers.
15117
+ *
15118
+ * @internal
15119
+ */
15120
+ const cleanYarnDeps = (deps) => {
15121
+ if (!deps) return void 0;
15122
+ return Object.fromEntries(Object.entries(deps).map(([name, value]) => [name, value.startsWith("npm:") ? value.slice(4) : value]));
15123
+ };
15124
+
15125
+ //#endregion
15126
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/Lockfile.js
15127
+ const EMPTY_IMPORTERS = [];
15128
+ /**
15129
+ * Failure of `Lockfile.parse`: the given content is not a valid lockfile of
15130
+ * the requested format.
15131
+ *
15132
+ * @remarks
15133
+ * - `format` — which format was being parsed.
15134
+ * - `stage` — `"syntax"` when the text itself failed to parse (YAML, JSON,
15135
+ * JSONC), `"validation"` when the text parsed but did not have the
15136
+ * format's expected shape.
15137
+ * - `cause` — the underlying jsonc/yaml/JSON/Schema error, preserved
15138
+ * structurally.
15139
+ *
15140
+ * Malformed input always exits through this typed failure, never as a
15141
+ * defect. Parse takes content, not a path — the caller that did the IO owns
15142
+ * any path context.
15143
+ *
15144
+ * @public
15145
+ */
15146
+ var LockfileParseError = class extends Schema.TaggedErrorClass()("LockfileParseError", {
15147
+ format: LockfileFormat,
15148
+ stage: Schema.Literals(["syntax", "validation"]),
15149
+ cause: Schema.Defect()
15150
+ }) {
15151
+ get message() {
15152
+ return this.stage === "syntax" ? `Failed to parse ${this.format} lockfile: the content is not well-formed` : `Failed to parse ${this.format} lockfile: the content does not have the expected ${this.format} shape`;
15153
+ }
15154
+ };
15155
+ /**
15156
+ * Failure of `Lockfile.parse`: the content parsed as text, but no single
15157
+ * lockfile document could be located in it.
14229
15158
  *
14230
- * `pnpm-lock.yaml` is a YAML *stream*, not a single document: a workspace
14231
- * using `configDependencies` gets a config-dependencies preamble document
14232
- * ahead of the lockfile. {@link selectPnpmDocument} locates the lockfile
14233
- * deterministically (it is the last document); a stream carrying no lockfile
14234
- * document fails through the typed framing channel rather than silently
14235
- * reporting the preamble as an empty workspace.
15159
+ * @remarks
15160
+ * `pnpm-lock.yaml` is a YAML **stream**. pnpm 11 writes a
15161
+ * config-dependencies preamble document ahead of the lockfile whenever the
15162
+ * workspace uses `configDependencies`, so the file holds two documents. The
15163
+ * lockfile is the last one — pnpm composes the preamble as a prefix and a
15164
+ * parser that reads only the first document gets the preamble: a document
15165
+ * that *validates*, and yields a lockfile with an empty workspace. This error
15166
+ * exists so that case can never again succeed quietly.
14236
15167
  *
14237
- * Workspace packages are keyed by importer *path* with version `"0.0.0"`;
14238
- * `Lockfile#withImporterNames` is the explicit second stage that rewrites
14239
- * them to real names.
15168
+ * - `format` which format was being parsed.
15169
+ * - `documents` how many YAML documents the stream carried.
15170
+ * - `reason`:
15171
+ * - `"noLockfileDocument"` — the stream carries no lockfile document. An
15172
+ * env-only `pnpm-lock.yaml` (a config-dependencies preamble and nothing
15173
+ * after it) reads this way, as does empty content. pnpm itself treats
15174
+ * such a file as having no lockfile.
15175
+ * - `"noImporters"` — the located document declares no importers, so it
15176
+ * describes no workspace. pnpm always records at least the root importer.
15177
+ * - `"unexpectedDocuments"` — the stream carries several documents in a
15178
+ * format that defines no document framing (yarn). Rather than silently
15179
+ * taking the first, parsing refuses to guess.
14240
15180
  *
14241
- * @internal
15181
+ * It carries typed fields rather than a `cause`: unlike
15182
+ * {@link LockfileParseError}, there is no underlying engine failure to wrap —
15183
+ * the text parsed fine.
15184
+ *
15185
+ * @public
14242
15186
  */
14243
- const parsePnpm = (content) => Effect.gen(function* () {
14244
- const { document, documents } = yield* selectPnpmDocument(content);
14245
- const validated = yield* Schema.decodeUnknownEffect(PnpmLockfileRaw)(document).pipe(Effect.mapError(validationFailure));
14246
- if (Object.keys(validated.importers).length === 0) return yield* Effect.fail(framingFailure("noImporters", documents));
14247
- return yield* toFields$1(validated);
14248
- });
14249
- const toVersionMap = (deps) => {
14250
- if (!deps) return void 0;
14251
- return Object.fromEntries(Object.entries(deps).map(([name, info]) => [name, info.specifier]));
15187
+ var LockfileFramingError = class extends Schema.TaggedErrorClass()("LockfileFramingError", {
15188
+ format: LockfileFormat,
15189
+ reason: Schema.Literals([
15190
+ "noLockfileDocument",
15191
+ "noImporters",
15192
+ "unexpectedDocuments"
15193
+ ]),
15194
+ documents: Schema.Int
15195
+ }) {
15196
+ get message() {
15197
+ const detail = this.reason === "noImporters" ? "the lockfile document declares no importers, so it describes no workspace" : this.reason === "unexpectedDocuments" ? `expected a single YAML document but the content carries ${this.documents}` : `the content carries no lockfile document (${this.documents} YAML document(s) found)`;
15198
+ return `Failed to parse ${this.format} lockfile: ${detail}`;
15199
+ }
14252
15200
  };
14253
- const importerDepGroups = (importer) => [
14254
- importer.dependencies,
14255
- importer.devDependencies,
14256
- importer.peerDependencies,
14257
- importer.optionalDependencies
14258
- ];
14259
- const toFields$1 = (raw) => Effect.gen(function* () {
14260
- const workspaceEntries = /* @__PURE__ */ new Map();
14261
- const workspaceNames = /* @__PURE__ */ new Set();
14262
- const importers = [];
14263
- for (const [importerPath, importer] of Object.entries(raw.importers)) {
14264
- if (importerPath === "") continue;
14265
- importers.push(LockfileImporter.make({
14266
- path: importerPath,
14267
- dependencies: importerDependencies(importer, (info) => ({
14268
- specifier: info.specifier,
14269
- version: info.version
14270
- }))
14271
- }));
14272
- const deps = toVersionMap(importer.dependencies);
14273
- const devDeps = toVersionMap(importer.devDependencies);
14274
- const peerDeps = toVersionMap(importer.peerDependencies);
14275
- const optDeps = toVersionMap(importer.optionalDependencies);
14276
- workspaceEntries.set(importerPath, {
14277
- ...deps ? { dependencies: deps } : {},
14278
- ...devDeps ? { devDependencies: devDeps } : {},
14279
- ...peerDeps ? { peerDependencies: peerDeps } : {},
14280
- ...optDeps ? { optionalDependencies: optDeps } : {}
15201
+ const dispatch = (format, content) => {
15202
+ switch (format) {
15203
+ case "bun": return parseBun(content);
15204
+ case "npm": return parseNpm(content);
15205
+ case "pnpm": return parsePnpm(content);
15206
+ case "yarn": return parseYarn(content);
15207
+ }
15208
+ };
15209
+ /**
15210
+ * The unified lockfile model all four formats normalize into.
15211
+ *
15212
+ * @remarks
15213
+ * - `format` — which lockfile format produced the data.
15214
+ * - `lockfileVersion` — the lockfile format version string.
15215
+ * - `packages` every resolved package.
15216
+ * - `workspaceDependencies` — inter-workspace dependency edges.
15217
+ * - `importers` — each workspace importer's declared dependencies
15218
+ * ({@link LockfileImporter}), keyed by importer path. Populated by the pnpm,
15219
+ * bun and npm parsers; always empty for yarn, which records no importers.
15220
+ * - `extension` — format-specific residue (`PnpmExtension` or
15221
+ * `BunExtension`) when the format records any.
15222
+ *
15223
+ * For pnpm, `Lockfile.parse` emits the honest importer-path-keyed model
15224
+ * (workspace packages named by importer path, version `"0.0.0"`);
15225
+ * {@link Lockfile.withImporterNames} is the explicit, pure second stage
15226
+ * that rewrites those names once the caller has read the workspace
15227
+ * manifests. npm, yarn and bun lockfiles carry real names and need no
15228
+ * second stage.
15229
+ *
15230
+ * @public
15231
+ */
15232
+ var Lockfile = class Lockfile extends Schema.Class("Lockfile")({
15233
+ format: LockfileFormat,
15234
+ lockfileVersion: Schema.String,
15235
+ packages: Schema.Array(ResolvedPackage),
15236
+ workspaceDependencies: Schema.Array(WorkspaceDependency),
15237
+ importers: Schema.Array(LockfileImporter).pipe(Schema.withDecodingDefaultKey(Effect.succeed([])), Schema.withConstructorDefault(Effect.succeed(EMPTY_IMPORTERS))),
15238
+ extension: Schema.optionalKey(Schema.Union([PnpmExtension, BunExtension]))
15239
+ }) {
15240
+ /** Lazily built name → packages index; deliberately outside the schema, never encodes. */
15241
+ #nameIndex;
15242
+ /** Lazily built importer-path → importer index; deliberately outside the schema, never encodes. */
15243
+ #importerIndex;
15244
+ /**
15245
+ * Parse lockfile content of a known format into the unified model — the
15246
+ * package's only fallible boundary.
15247
+ *
15248
+ * @param content - The lockfile text (this package does no IO; the caller
15249
+ * reads the file).
15250
+ * @param options - The lockfile format to parse as.
15251
+ * @returns An `Effect` succeeding with the {@link Lockfile}, or failing
15252
+ * with {@link LockfileParseError} (malformed text or the wrong shape) or
15253
+ * {@link LockfileFramingError} (the text parsed, but no lockfile document
15254
+ * could be located in the stream — see that error for why a
15255
+ * multi-document `pnpm-lock.yaml` needs it).
15256
+ */
15257
+ static parse = Effect.fn("Lockfile.parse")(function* (content, options) {
15258
+ const fields = yield* dispatch(options.format, content).pipe(Effect.mapError((failure) => failure.stage === "framing" ? new LockfileFramingError({
15259
+ format: options.format,
15260
+ reason: failure.reason,
15261
+ documents: failure.documents
15262
+ }) : new LockfileParseError({
15263
+ format: options.format,
15264
+ stage: failure.stage,
15265
+ cause: failure.cause
15266
+ })));
15267
+ return Lockfile.make({
15268
+ format: options.format,
15269
+ lockfileVersion: fields.lockfileVersion,
15270
+ packages: fields.packages,
15271
+ workspaceDependencies: fields.workspaceDependencies,
15272
+ importers: fields.importers,
15273
+ ...fields.extension !== void 0 ? { extension: fields.extension } : {}
14281
15274
  });
14282
- for (const group of importerDepGroups(importer)) {
14283
- if (!group) continue;
14284
- for (const [name, info] of Object.entries(group)) if (name !== "" && info.version.startsWith("link:")) workspaceNames.add(name);
15275
+ });
15276
+ /**
15277
+ * Rewrite pnpm importer-path names to real package names the explicit
15278
+ * second stage of pnpm parsing. Total and pure.
15279
+ *
15280
+ * @remarks
15281
+ * Workspace packages whose `relativePath` appears in `names` are renamed;
15282
+ * dependency edge ends are rewritten through the same map. Entries not in
15283
+ * the map keep their path name, and non-pnpm lockfiles are unaffected (no
15284
+ * key matches). Versions are not touched — pnpm workspace packages keep
15285
+ * `"0.0.0"` (the lockfile does not record their real versions).
15286
+ *
15287
+ * @param names - Importer path → real package name.
15288
+ * @returns A new {@link Lockfile} with names rewritten.
15289
+ */
15290
+ withImporterNames(names) {
15291
+ const packages = this.packages.map((pkg) => {
15292
+ if (!pkg.isWorkspace || pkg.relativePath === void 0) return pkg;
15293
+ const realName = names.get(pkg.relativePath);
15294
+ if (realName === void 0 || realName === "" || realName === pkg.name) return pkg;
15295
+ return ResolvedPackage.make({
15296
+ name: realName,
15297
+ version: pkg.version,
15298
+ ...pkg.integrity !== void 0 ? { integrity: pkg.integrity } : {},
15299
+ isWorkspace: pkg.isWorkspace,
15300
+ relativePath: pkg.relativePath,
15301
+ dependencies: pkg.dependencies
15302
+ });
15303
+ });
15304
+ const workspaceDependencies = this.workspaceDependencies.map((dep) => {
15305
+ const mappedFrom = names.get(dep.from);
15306
+ const mappedTo = names.get(dep.to);
15307
+ const from = mappedFrom === void 0 || mappedFrom === "" ? dep.from : mappedFrom;
15308
+ const to = mappedTo === void 0 || mappedTo === "" ? dep.to : mappedTo;
15309
+ if (from === dep.from && to === dep.to) return dep;
15310
+ return WorkspaceDependency.make({
15311
+ from,
15312
+ to,
15313
+ depType: dep.depType,
15314
+ constraint: dep.constraint
15315
+ });
15316
+ });
15317
+ return Lockfile.make({
15318
+ format: this.format,
15319
+ lockfileVersion: this.lockfileVersion,
15320
+ packages,
15321
+ workspaceDependencies,
15322
+ importers: this.importers,
15323
+ ...this.extension !== void 0 ? { extension: this.extension } : {}
15324
+ });
15325
+ }
15326
+ /**
15327
+ * Every resolved package with the given name — one entry per resolved
15328
+ * version. Backed by a lazily built index, so repeated lookups are O(1).
15329
+ *
15330
+ * @param name - The package name to look up.
15331
+ * @returns The matching packages, empty when the name is not in the
15332
+ * lockfile.
15333
+ */
15334
+ packagesNamed(name) {
15335
+ if (this.#nameIndex === void 0) {
15336
+ const index = /* @__PURE__ */ new Map();
15337
+ for (const pkg of this.packages) {
15338
+ const bucket = index.get(pkg.name);
15339
+ if (bucket === void 0) index.set(pkg.name, [pkg]);
15340
+ else bucket.push(pkg);
15341
+ }
15342
+ this.#nameIndex = index;
14285
15343
  }
15344
+ return this.#nameIndex.get(name) ?? [];
14286
15345
  }
14287
- for (const path of Object.keys(raw.importers)) if (path !== "." && path !== "") workspaceNames.add(path);
14288
- const packages = [];
14289
- for (const importerPath of Object.keys(raw.importers)) {
14290
- if (importerPath === "." || importerPath === "") continue;
14291
- packages.push(ResolvedPackage.make({
14292
- name: importerPath,
14293
- version: "0.0.0",
14294
- isWorkspace: true,
14295
- relativePath: importerPath
14296
- }));
15346
+ /**
15347
+ * The importer at the given path — `"."` for the workspace root — or
15348
+ * `Option.none()` when the lockfile records no importer there. Backed by a
15349
+ * lazily built index, so repeated lookups are O(1). The index is a `Map`,
15350
+ * so an attacker-adjacent path (`__proto__`, `constructor`) neither pollutes
15351
+ * nor collides.
15352
+ *
15353
+ * @param path - The importer path to look up.
15354
+ * @returns The matching {@link LockfileImporter}, or `Option.none()`.
15355
+ */
15356
+ importer(path) {
15357
+ if (this.#importerIndex === void 0) {
15358
+ const index = /* @__PURE__ */ new Map();
15359
+ for (const imp of this.importers) index.set(imp.path, imp);
15360
+ this.#importerIndex = index;
15361
+ }
15362
+ return Option.fromUndefinedOr(this.#importerIndex.get(path));
14297
15363
  }
14298
- if (raw.packages) for (const [key, pkg] of Object.entries(raw.packages)) {
14299
- const { plain: bare } = splitPeerSuffix(key);
14300
- const atIndex = bare.lastIndexOf("@");
14301
- if (atIndex <= 0) continue;
14302
- const name = bare.slice(0, atIndex);
14303
- const version = bare.slice(atIndex + 1);
14304
- const integrity = yield* toIntegrityHash(pkg.resolution?.integrity);
14305
- packages.push(ResolvedPackage.make({
14306
- name,
14307
- version,
14308
- ...integrity !== void 0 ? { integrity } : {},
14309
- isWorkspace: false
14310
- }));
15364
+ /** The workspace-local packages. */
15365
+ get workspacePackages() {
15366
+ return this.packages.filter((pkg) => pkg.isWorkspace);
14311
15367
  }
14312
- const workspaceDependencies = extractWorkspaceDeps(workspaceEntries, workspaceNames);
14313
- const extension = PnpmExtension.make({
14314
- ...raw.catalogs !== void 0 ? { catalogs: raw.catalogs } : {},
14315
- ...raw.overrides !== void 0 ? { overrides: raw.overrides } : {},
14316
- ...raw.settings !== void 0 ? { settings: raw.settings } : {}
14317
- });
14318
- return {
14319
- lockfileVersion: String(raw.lockfileVersion),
14320
- packages,
14321
- workspaceDependencies,
14322
- importers,
14323
- extension
14324
- };
14325
- });
15368
+ };
14326
15369
 
14327
15370
  //#endregion
14328
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/internal/yarn.js
14329
- const YarnLockfileRaw = Schema.Record(Schema.String, Schema.Unknown);
14330
- const DepRecord = Schema.optionalKey(Schema.Record(Schema.String, Schema.String));
14331
- const YarnEntry = Schema.Struct({
14332
- version: Schema.optionalKey(Schema.String),
14333
- resolution: Schema.optionalKey(Schema.String),
14334
- dependencies: DepRecord,
14335
- devDependencies: DepRecord,
14336
- peerDependencies: DepRecord,
14337
- optionalDependencies: DepRecord,
14338
- checksum: Schema.optionalKey(Schema.String),
14339
- languageName: Schema.optionalKey(Schema.String),
14340
- linkType: Schema.optionalKey(Schema.String),
14341
- bin: Schema.optionalKey(Schema.Unknown)
14342
- });
14343
- const YarnMetadata = Schema.Struct({ version: Schema.optionalKey(Schema.Union([Schema.String, Schema.Number])) });
15371
+ //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._3c1784fba62fde9a5bac4cf15387fd04/node_modules/@effected/lockfiles/LockfileIntegrity.js
14344
15372
  /**
14345
- * Parse yarn Berry `yarn.lock` content into the unified field bundle.
15373
+ * The minimal manifest shape {@link LockfileIntegrity.compare} checks a
15374
+ * lockfile against: a package name plus the four optional dependency maps.
14346
15375
  *
14347
- * Yarn Berry lockfiles are YAML with a flat key structure where each key
14348
- * encodes package name + resolution descriptor(s) (e.g.
14349
- * `"@scope/name@npm:^1.0.0"`); workspace entries carry `linkType: "soft"`.
15376
+ * @remarks
15377
+ * Deliberately *not* a `@effected/package-json` type this package takes
15378
+ * manifests as plain values so its consumers own the manifest IO (and may
15379
+ * derive these from any richer model).
14350
15380
  *
14351
- * @internal
15381
+ * @public
14352
15382
  */
14353
- const parseYarn = (content) => Effect.gen(function* () {
14354
- const { document } = yield* selectSoleDocument(content);
14355
- const raw = yield* Schema.decodeUnknownEffect(YarnLockfileRaw)(document).pipe(Effect.mapError(validationFailure));
14356
- const metadata = raw.__metadata === void 0 ? void 0 : yield* Schema.decodeUnknownEffect(YarnMetadata)(raw.__metadata).pipe(Effect.mapError(validationFailure));
14357
- const lockfileVersion = metadata?.version === void 0 ? "unknown" : String(metadata.version);
14358
- const decoded = /* @__PURE__ */ new Map();
14359
- for (const [key, value] of Object.entries(raw)) {
14360
- if (key === "__metadata") continue;
14361
- const entry = yield* Schema.decodeUnknownEffect(YarnEntry)(value).pipe(Effect.mapError(validationFailure));
14362
- decoded.set(key, entry);
14363
- }
14364
- return yield* toFields(lockfileVersion, decoded);
14365
- });
14366
- const toFields = (lockfileVersion, decoded) => Effect.gen(function* () {
14367
- const packages = [];
14368
- const workspaceNames = /* @__PURE__ */ new Set();
14369
- const workspaceEntries = /* @__PURE__ */ new Map();
14370
- for (const [key, entry] of decoded) if (entry.linkType === "soft") {
14371
- const name = extractYarnPackageName(key);
14372
- if (name !== void 0) workspaceNames.add(name);
14373
- }
14374
- for (const [key, entry] of decoded) {
14375
- const name = extractYarnPackageName(key);
14376
- if (name === void 0) continue;
14377
- const isWorkspace = entry.linkType === "soft";
14378
- const relativePath = isWorkspace ? extractYarnWorkspacePath(key) : void 0;
14379
- const integrity = yield* toIntegrityHash(entry.checksum);
14380
- packages.push(ResolvedPackage.make({
14381
- name,
14382
- version: entry.version ?? "0.0.0",
14383
- ...integrity !== void 0 ? { integrity } : {},
14384
- isWorkspace,
14385
- ...relativePath !== void 0 ? { relativePath } : {}
14386
- }));
14387
- if (isWorkspace) {
14388
- const deps = cleanYarnDeps(entry.dependencies);
14389
- const devDeps = cleanYarnDeps(entry.devDependencies);
14390
- const peerDeps = cleanYarnDeps(entry.peerDependencies);
14391
- const optDeps = cleanYarnDeps(entry.optionalDependencies);
14392
- workspaceEntries.set(name, {
14393
- ...deps ? { dependencies: deps } : {},
14394
- ...devDeps ? { devDependencies: devDeps } : {},
14395
- ...peerDeps ? { peerDependencies: peerDeps } : {},
14396
- ...optDeps ? { optionalDependencies: optDeps } : {}
14397
- });
15383
+ var WorkspaceManifest = class extends Schema.Class("WorkspaceManifest")({
15384
+ name: Schema.NonEmptyString,
15385
+ dependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
15386
+ devDependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
15387
+ peerDependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
15388
+ optionalDependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.String))
15389
+ }) {};
15390
+ const decodeRange = Schema.decodeUnknownExit(Range$1.FromString);
15391
+ const decodeSemVer = Schema.decodeUnknownExit(SemVer.FromString);
15392
+ /**
15393
+ * Result of checking a parsed lockfile against the workspace's declared
15394
+ * manifests.
15395
+ *
15396
+ * @remarks
15397
+ * A data type, not an error: it reports *what* mismatches exist without
15398
+ * failing anything.
15399
+ *
15400
+ * - `valid` `true` when the lockfile is fully consistent.
15401
+ * - `missingWorkspaces` — workspace names present in the manifests but
15402
+ * absent from the lockfile.
15403
+ * - `extraWorkspaces` — workspace names in the lockfile with no matching
15404
+ * manifest.
15405
+ * - `unsatisfiedConstraints` — declared constraints the lockfile's resolved
15406
+ * versions do not satisfy.
15407
+ *
15408
+ * @public
15409
+ */
15410
+ var LockfileIntegrity = class LockfileIntegrity extends Schema.Class("LockfileIntegrity")({
15411
+ valid: Schema.Boolean,
15412
+ missingWorkspaces: Schema.Array(Schema.String),
15413
+ extraWorkspaces: Schema.Array(Schema.String),
15414
+ unsatisfiedConstraints: Schema.Array(Schema.Struct({
15415
+ workspace: Schema.String,
15416
+ dependency: Schema.String,
15417
+ constraint: Schema.String,
15418
+ resolved: Schema.String,
15419
+ depType: DependencyField$1
15420
+ }))
15421
+ }) {
15422
+ /**
15423
+ * Check a lockfile's consistency against workspace manifests — a total,
15424
+ * pure function: no Effect, no error channel, no IO.
15425
+ *
15426
+ * @remarks
15427
+ * Constraint checking is best-effort by design: `workspace:` / `link:` /
15428
+ * `file:` specifiers and rows whose range (or every resolved version) does
15429
+ * not parse as SemVer are skipped, exactly as in the v3 implementation.
15430
+ * A lockfile may resolve the same package at several versions; a
15431
+ * constraint is satisfied when *any* resolved version matches, and an
15432
+ * unsatisfied row reports every candidate in `resolved`. The
15433
+ * caller reads the manifests (this package does no IO). For pnpm, apply
15434
+ * `Lockfile#withImporterNames` first so workspace names align with
15435
+ * manifest names.
15436
+ *
15437
+ * (Named `compare`, not `check`: every v4 `Schema.Class` already carries
15438
+ * a `static check(...checks)` for attaching schema checks, and statics
15439
+ * cannot be shadowed with an incompatible signature.)
15440
+ *
15441
+ * @param lockfile - The parsed lockfile.
15442
+ * @param manifests - The workspace manifests to compare against.
15443
+ * @returns The integrity report.
15444
+ */
15445
+ static compare(lockfile, manifests) {
15446
+ const workspacePackages = lockfile.packages.filter((p) => p.isWorkspace && p.relativePath !== void 0);
15447
+ const lockfileWsNames = new Set(workspacePackages.map((p) => p.name));
15448
+ const manifestNames = new Set(manifests.map((m) => m.name));
15449
+ const missingWorkspaces = [...manifestNames].filter((n) => !lockfileWsNames.has(n));
15450
+ const extraWorkspaces = [...lockfileWsNames].filter((n) => !manifestNames.has(n));
15451
+ const resolvedIndex = /* @__PURE__ */ new Map();
15452
+ for (const p of lockfile.packages) {
15453
+ const versions = resolvedIndex.get(p.name);
15454
+ if (versions === void 0) resolvedIndex.set(p.name, [p.version]);
15455
+ else versions.push(p.version);
15456
+ }
15457
+ const unsatisfiedConstraints = [];
15458
+ for (const manifest of manifests) for (const depType of DEP_TYPES) {
15459
+ const depMap = manifest[depType];
15460
+ if (!depMap) continue;
15461
+ for (const [dependency, constraint] of Object.entries(depMap)) {
15462
+ if (isWorkspaceSpecifier(constraint)) continue;
15463
+ const candidates = resolvedIndex.get(dependency);
15464
+ if (candidates === void 0) continue;
15465
+ const rangeExit = decodeRange(constraint);
15466
+ if (Exit.isFailure(rangeExit)) continue;
15467
+ const versions = candidates.map((candidate) => decodeSemVer(candidate)).filter(Exit.isSuccess);
15468
+ if (versions.length === 0) continue;
15469
+ if (!versions.some((v) => rangeExit.value.test(v.value))) unsatisfiedConstraints.push({
15470
+ workspace: manifest.name,
15471
+ dependency,
15472
+ constraint,
15473
+ resolved: candidates.join(", "),
15474
+ depType
15475
+ });
15476
+ }
14398
15477
  }
15478
+ return LockfileIntegrity.make({
15479
+ valid: missingWorkspaces.length === 0 && extraWorkspaces.length === 0 && unsatisfiedConstraints.length === 0,
15480
+ missingWorkspaces,
15481
+ extraWorkspaces,
15482
+ unsatisfiedConstraints
15483
+ });
14399
15484
  }
14400
- return {
14401
- lockfileVersion,
14402
- packages,
14403
- workspaceDependencies: extractWorkspaceDeps(workspaceEntries, workspaceNames),
14404
- importers: []
14405
- };
14406
- });
15485
+ };
15486
+
15487
+ //#endregion
15488
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/CatalogResolver.js
14407
15489
  /**
14408
- * Extract the package name from a yarn lockfile key. Handles compound keys
14409
- * (`"a@workspace:*, a@workspace:packages/a"`) via the first descriptor and
14410
- * `@patch:` descriptors (which embed `@npm:` inside). Total: malformed keys
14411
- * yield `undefined`.
15490
+ * Contract for resolving pnpm `catalog:` dependency specifiers to concrete
15491
+ * version ranges.
15492
+ *
15493
+ * `rangeOf` takes a package name and an optional catalog name
15494
+ * (`Option.none()` selects the default catalog) and returns the configured
15495
+ * range as `Option.some`, or `Option.none()` when the specifier is absent
15496
+ * from the catalog. By convention the error channel is reserved for a
15497
+ * failure in the resolution mechanism itself — an unmatched package or
15498
+ * catalog name is an `Option.none()` success, never an error. A failure to
15499
+ * *assemble* the catalogs (an unreadable or malformed catalog source)
15500
+ * surfaces typed as a {@link CatalogAssemblyError}; any other mechanism
15501
+ * failure is a {@link DependencyResolutionError}.
15502
+ *
15503
+ * This is a contract-only service: {@link CatalogResolver.noop} is the sole
15504
+ * implementation this package ships, and it resolves nothing. Real consumers
15505
+ * (e.g. `@effected/workspaces`) provide a working implementation at the
15506
+ * application boundary.
15507
+ *
15508
+ * @example
15509
+ * ```ts
15510
+ * import { Effect, Option } from "effect";
15511
+ * import { CatalogResolver } from "@effected/npm";
15512
+ *
15513
+ * const program = Effect.gen(function* () {
15514
+ * const resolver = yield* CatalogResolver;
15515
+ * return yield* resolver.rangeOf("effect", Option.none());
15516
+ * });
15517
+ *
15518
+ * Effect.runPromise(Effect.provide(program, CatalogResolver.noop));
15519
+ * // => Option.none()
15520
+ * ```
14412
15521
  *
14413
- * @internal
15522
+ * @public
14414
15523
  */
14415
- const extractYarnPackageName = (key) => {
14416
- const commaIdx = key.indexOf(", ");
14417
- const descriptor = commaIdx === -1 ? key : key.slice(0, commaIdx);
14418
- const patchIdx = descriptor.indexOf("@patch:");
14419
- if (patchIdx > 0) return descriptor.slice(0, patchIdx);
14420
- const npmIdx = descriptor.lastIndexOf("@npm:");
14421
- const wsIdx = descriptor.lastIndexOf("@workspace:");
14422
- const idx = Math.max(npmIdx, wsIdx);
14423
- if (idx <= 0) return void 0;
14424
- return descriptor.slice(0, idx);
15524
+ var CatalogResolver = class CatalogResolver extends Context.Service()("@effected/npm/CatalogResolver") {
15525
+ /**
15526
+ * No-op default: `rangeOf` always succeeds with `Option.none()`, never
15527
+ * consulting an actual catalog. A pure `Layer.succeed`, bound to a const
15528
+ * so it memoizes by reference — the layer is built once, not once per
15529
+ * reference to `CatalogResolver.noop`.
15530
+ */
15531
+ static noop = Layer.succeed(CatalogResolver, { rangeOf: () => Effect.succeed(Option.none()) });
14425
15532
  };
15533
+
15534
+ //#endregion
15535
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/WorkspaceResolver.js
14426
15536
  /**
14427
- * Extract the workspace-relative path from a yarn lockfile key: the segment
14428
- * after `@workspace:` in the first descriptor carrying a non-`*` path.
15537
+ * Raised when a `catalog:` or `workspace:` specifier cannot be resolved
15538
+ * because the resolution mechanism itself failed not for an ordinary
15539
+ * unmatched specifier, which resolves to `Option.none()` instead. Both
15540
+ * {@link CatalogResolver} and {@link WorkspaceResolver} fail with it.
14429
15541
  *
14430
- * @internal
15542
+ * `cause` preserves the originating failure on a structured `Schema.Defect`
15543
+ * field rather than folding it into a string, so callers can branch on the
15544
+ * original value (an `Error`, a parsed diagnostic, anything); `specifier`
15545
+ * records the specifier string that failed to resolve.
15546
+ *
15547
+ * @public
14431
15548
  */
14432
- const extractYarnWorkspacePath = (key) => {
14433
- for (const desc of key.split(", ")) {
14434
- const wsIdx = desc.lastIndexOf("@workspace:");
14435
- if (wsIdx >= 0) {
14436
- const path = desc.slice(wsIdx + 11);
14437
- if (path !== "" && path !== "*") return path;
14438
- }
15549
+ var DependencyResolutionError = class extends Schema.TaggedErrorClass()("DependencyResolutionError", {
15550
+ specifier: Schema.String,
15551
+ cause: Schema.Defect()
15552
+ }) {
15553
+ /** Renders `specifier` into a one-line failure message. */
15554
+ get message() {
15555
+ return `Failed to resolve dependency specifier "${this.specifier}"`;
14439
15556
  }
14440
15557
  };
14441
15558
  /**
14442
- * Strip the `"npm:"` prefix from yarn dependency specifiers.
15559
+ * Contract for resolving pnpm `workspace:` dependency specifiers to concrete
15560
+ * versions.
14443
15561
  *
14444
- * @internal
15562
+ * `versionOf` takes a workspace package name and returns its concrete
15563
+ * version (the range modifier stripped) as `Option.some`, or
15564
+ * `Option.none()` when the name is not a known workspace member.
15565
+ *
15566
+ * This is a contract-only service: {@link WorkspaceResolver.noop} is the
15567
+ * sole implementation this package ships, and it resolves nothing. Real
15568
+ * consumers (e.g. `@effected/workspaces`) provide a working implementation
15569
+ * at the application boundary.
15570
+ *
15571
+ * @example
15572
+ * ```ts
15573
+ * import { Effect } from "effect";
15574
+ * import { WorkspaceResolver } from "@effected/npm";
15575
+ *
15576
+ * const program = Effect.gen(function* () {
15577
+ * const resolver = yield* WorkspaceResolver;
15578
+ * return yield* resolver.versionOf("@effected/semver");
15579
+ * });
15580
+ *
15581
+ * Effect.runPromise(Effect.provide(program, WorkspaceResolver.noop));
15582
+ * // => Option.none()
15583
+ * ```
15584
+ *
15585
+ * @public
14445
15586
  */
14446
- const cleanYarnDeps = (deps) => {
14447
- if (!deps) return void 0;
14448
- return Object.fromEntries(Object.entries(deps).map(([name, value]) => [name, value.startsWith("npm:") ? value.slice(4) : value]));
15587
+ var WorkspaceResolver = class WorkspaceResolver extends Context.Service()("@effected/npm/WorkspaceResolver") {
15588
+ /**
15589
+ * No-op default: `versionOf` always succeeds with `Option.none()`, never
15590
+ * consulting an actual workspace. A pure `Layer.succeed`, bound to a
15591
+ * const so it memoizes by reference.
15592
+ */
15593
+ static noop = Layer.succeed(WorkspaceResolver, { versionOf: () => Effect.succeed(Option.none()) });
14449
15594
  };
14450
15595
 
14451
15596
  //#endregion
14452
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/Lockfile.js
14453
- const EMPTY_IMPORTERS = [];
15597
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySection.js
14454
15598
  /**
14455
- * Failure of `Lockfile.parse`: the given content is not a valid lockfile of
14456
- * the requested format.
14457
- *
14458
- * @remarks
14459
- * - `format` — which format was being parsed.
14460
- * - `stage` — `"syntax"` when the text itself failed to parse (YAML, JSON,
14461
- * JSONC), `"validation"` when the text parsed but did not have the
14462
- * format's expected shape.
14463
- * - `cause` — the underlying jsonc/yaml/JSON/Schema error, preserved
14464
- * structurally.
15599
+ * The short dependency kind: which dependency map an entry came from, named the
15600
+ * way consumers branch on it.
14465
15601
  *
14466
- * Malformed input always exits through this typed failure, never as a
14467
- * defect. Parse takes content, not a path — the caller that did the IO owns
14468
- * any path context.
15602
+ * @public
15603
+ */
15604
+ const DependencyKind = Schema.Literals([
15605
+ "prod",
15606
+ "dev",
15607
+ "peer",
15608
+ "optional"
15609
+ ]);
15610
+ /**
15611
+ * The manifest field name a dependency is declared under, matching the
15612
+ * `package.json` / `package-lock.json` key exactly.
14469
15613
  *
14470
15614
  * @public
14471
15615
  */
14472
- var LockfileParseError = class extends Schema.TaggedErrorClass()("LockfileParseError", {
14473
- format: LockfileFormat,
14474
- stage: Schema.Literals(["syntax", "validation"]),
14475
- cause: Schema.Defect()
14476
- }) {
14477
- get message() {
14478
- return this.stage === "syntax" ? `Failed to parse ${this.format} lockfile: the content is not well-formed` : `Failed to parse ${this.format} lockfile: the content does not have the expected ${this.format} shape`;
14479
- }
15616
+ const DependencyField = Schema.Literals([
15617
+ "dependencies",
15618
+ "devDependencies",
15619
+ "peerDependencies",
15620
+ "optionalDependencies"
15621
+ ]);
15622
+ const KIND_TO_FIELD = {
15623
+ prod: "dependencies",
15624
+ dev: "devDependencies",
15625
+ peer: "peerDependencies",
15626
+ optional: "optionalDependencies"
14480
15627
  };
15628
+ const FIELD_TO_KIND = Object.fromEntries(Object.entries(KIND_TO_FIELD).map(([kind, field]) => [field, kind]));
15629
+
15630
+ //#endregion
15631
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/DependencySpecifier.js
14481
15632
  /**
14482
- * Failure of `Lockfile.parse`: the content parsed as text, but no single
14483
- * lockfile document could be located in it.
14484
- *
14485
- * @remarks
14486
- * `pnpm-lock.yaml` is a YAML **stream**. pnpm 11 writes a
14487
- * config-dependencies preamble document ahead of the lockfile whenever the
14488
- * workspace uses `configDependencies`, so the file holds two documents. The
14489
- * lockfile is the last one — pnpm composes the preamble as a prefix — and a
14490
- * parser that reads only the first document gets the preamble: a document
14491
- * that *validates*, and yields a lockfile with an empty workspace. This error
14492
- * exists so that case can never again succeed quietly.
14493
- *
14494
- * - `format` — which format was being parsed.
14495
- * - `documents` — how many YAML documents the stream carried.
14496
- * - `reason`:
14497
- * - `"noLockfileDocument"` — the stream carries no lockfile document. An
14498
- * env-only `pnpm-lock.yaml` (a config-dependencies preamble and nothing
14499
- * after it) reads this way, as does empty content. pnpm itself treats
14500
- * such a file as having no lockfile.
14501
- * - `"noImporters"` — the located document declares no importers, so it
14502
- * describes no workspace. pnpm always records at least the root importer.
14503
- * - `"unexpectedDocuments"` — the stream carries several documents in a
14504
- * format that defines no document framing (yarn). Rather than silently
14505
- * taking the first, parsing refuses to guess.
15633
+ * Indicates that a string could not be parsed as a valid dependency specifier.
14506
15634
  *
14507
- * It carries typed fields rather than a `cause`: unlike
14508
- * {@link LockfileParseError}, there is no underlying engine failure to wrap —
14509
- * the text parsed fine.
15635
+ * Raised by {@link DependencySpecifier.decode}. The offending string is
15636
+ * preserved on `input`.
14510
15637
  *
14511
15638
  * @public
14512
15639
  */
14513
- var LockfileFramingError = class extends Schema.TaggedErrorClass()("LockfileFramingError", {
14514
- format: LockfileFormat,
14515
- reason: Schema.Literals([
14516
- "noLockfileDocument",
14517
- "noImporters",
14518
- "unexpectedDocuments"
14519
- ]),
14520
- documents: Schema.Int
14521
- }) {
15640
+ var InvalidDependencySpecifierError = class extends Schema.TaggedErrorClass()("InvalidDependencySpecifierError", {
15641
+ /** The raw input string that failed validation. */
15642
+ input: Schema.String }) {
14522
15643
  get message() {
14523
- const detail = this.reason === "noImporters" ? "the lockfile document declares no importers, so it describes no workspace" : this.reason === "unexpectedDocuments" ? `expected a single YAML document but the content carries ${this.documents}` : `the content carries no lockfile document (${this.documents} YAML document(s) found)`;
14524
- return `Failed to parse ${this.format} lockfile: ${detail}`;
15644
+ return `Invalid dependency specifier "${this.input}": not a recognized specifier`;
14525
15645
  }
14526
15646
  };
14527
- const dispatch = (format, content) => {
14528
- switch (format) {
14529
- case "bun": return parseBun(content);
14530
- case "npm": return parseNpm(content);
14531
- case "pnpm": return parsePnpm(content);
14532
- case "yarn": return parseYarn(content);
14533
- }
15647
+ const CATALOG_PREFIX = "catalog:";
15648
+ const WORKSPACE_PREFIX = "workspace:";
15649
+ const isBarePath = (value) => value.startsWith("./") || value.startsWith("../") || value.startsWith("~/") || value.startsWith("/");
15650
+ const isGitHubShorthand = (value) => !value.startsWith(".") && !value.startsWith("~") && !value.startsWith("/") && /^[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+(#.*)?$/.test(value);
15651
+ const isGit = (value) => value.startsWith("git+") || value.startsWith("git://") || value.startsWith("github:") || value.startsWith("gist:") || value.startsWith("bitbucket:") || value.startsWith("gitlab:") || isGitHubShorthand(value);
15652
+ const isLocal = (value) => value.startsWith("file:") || value.startsWith("link:") || value.startsWith("portal:") || isBarePath(value);
15653
+ const isLink = (value) => value.startsWith("link:");
15654
+ const isPortal = (value) => value.startsWith("portal:");
15655
+ const isCatalog = (value) => value.startsWith(CATALOG_PREFIX);
15656
+ const isWorkspace = (value) => value.startsWith(WORKSPACE_PREFIX);
15657
+ const isUrl$1 = (value) => value.startsWith("http://") || value.startsWith("https://");
15658
+ const parseRange = (value) => {
15659
+ const exit = Schema.decodeUnknownExit(Range$1.FromString)(value);
15660
+ return Exit.isSuccess(exit) ? Option.some(exit.value) : Option.none();
15661
+ };
15662
+ const isRange = (value) => Option.isSome(parseRange(value));
15663
+ const protocolOf = (value) => {
15664
+ if (value.startsWith(CATALOG_PREFIX)) return "catalog";
15665
+ if (value.startsWith(WORKSPACE_PREFIX)) return "workspace";
15666
+ if (value.startsWith("link:")) return "link";
15667
+ if (value.startsWith("portal:")) return "portal";
15668
+ if (value.startsWith("file:") || isBarePath(value)) return "file";
15669
+ if (value.startsWith("npm:")) return "npm";
15670
+ if (isGit(value)) return "git";
15671
+ if (isUrl$1(value)) return "url";
15672
+ if (isRange(value)) return "range";
15673
+ if (/^[a-zA-Z][a-zA-Z0-9._-]*$/.test(value)) return "tag";
15674
+ return "unknown";
15675
+ };
15676
+ const isTag = (value) => protocolOf(value) === "tag";
15677
+ const catalogNameOf$1 = (specifier) => {
15678
+ if (!isCatalog(specifier)) return Option.none();
15679
+ const rest = specifier.slice(8).trim();
15680
+ return rest.length === 0 ? Option.none() : Option.some(rest);
15681
+ };
15682
+ const projectRangeModifier = (range, version) => range === "*" || range === "" ? version : range === "~" ? `~${version}` : range === "^" ? `^${version}` : range;
15683
+ const splitWorkspaceRest = (rest) => {
15684
+ const at = rest.lastIndexOf("@");
15685
+ return at > 0 ? {
15686
+ target: rest.slice(0, at),
15687
+ range: rest.slice(at + 1)
15688
+ } : {
15689
+ target: void 0,
15690
+ range: rest
15691
+ };
15692
+ };
15693
+ const projectWorkspaceRange = (rest, version) => {
15694
+ const { target, range } = splitWorkspaceRest(rest);
15695
+ const projected = projectRangeModifier(range, version);
15696
+ return target === void 0 ? projected : `npm:${target}@${projected}`;
15697
+ };
15698
+ const resolveWorkspace = (specifier, version) => isWorkspace(specifier) ? projectWorkspaceRange(specifier.slice(10), version) : specifier;
15699
+ const workspaceTargetOf = (specifier) => {
15700
+ if (!isWorkspace(specifier)) return Option.none();
15701
+ const { target } = splitWorkspaceRest(specifier.slice(10));
15702
+ return target === void 0 ? Option.none() : Option.some(target);
14534
15703
  };
14535
15704
  /**
14536
- * The unified lockfile model all four formats normalize into.
14537
- *
14538
- * @remarks
14539
- * - `format` — which lockfile format produced the data.
14540
- * - `lockfileVersion` — the lockfile format version string.
14541
- * - `packages` — every resolved package.
14542
- * - `workspaceDependencies` inter-workspace dependency edges.
14543
- * - `importers` — each workspace importer's declared dependencies
14544
- * ({@link LockfileImporter}), keyed by importer path. Populated by the pnpm,
14545
- * bun and npm parsers; always empty for yarn, which records no importers.
14546
- * - `extension` — format-specific residue (`PnpmExtension` or
14547
- * `BunExtension`) when the format records any.
15705
+ * Whether a string is a recognized dependency specifier: a semver range, exact
15706
+ * version, dist-tag, URL, git ref, GitHub shorthand, file path, or an
15707
+ * `npm:` / `catalog:` / `workspace:` protocol.
15708
+ *
15709
+ * @public
15710
+ */
15711
+ const isValidDependencySpecifier = (value) => value.length > 0 && protocolOf(value) !== "unknown";
15712
+ /**
15713
+ * A `catalog:` reference. `name` carries the catalog name, or `Option.none()`
15714
+ * for the default catalog (`catalog:`).
14548
15715
  *
14549
- * For pnpm, `Lockfile.parse` emits the honest importer-path-keyed model
14550
- * (workspace packages named by importer path, version `"0.0.0"`);
14551
- * {@link Lockfile.withImporterNames} is the explicit, pure second stage
14552
- * that rewrites those names once the caller has read the workspace
14553
- * manifests. npm, yarn and bun lockfiles carry real names and need no
14554
- * second stage.
15716
+ * @public
15717
+ */
15718
+ var CatalogSpecifier = class extends Schema.TaggedClass()("catalog", {
15719
+ /** The original specifier string. */
15720
+ raw: Schema.String,
15721
+ /** The catalog name, or `Option.none()` for the default catalog. */
15722
+ name: Schema.Option(Schema.String)
15723
+ }) {};
15724
+ /**
15725
+ * A `workspace:` reference. `range` carries the part after `workspace:` — a
15726
+ * range modifier (`*`, `^`, `~`), a concrete range, or an alias form.
14555
15727
  *
14556
15728
  * @public
14557
15729
  */
14558
- var Lockfile = class Lockfile extends Schema.Class("Lockfile")({
14559
- format: LockfileFormat,
14560
- lockfileVersion: Schema.String,
14561
- packages: Schema.Array(ResolvedPackage),
14562
- workspaceDependencies: Schema.Array(WorkspaceDependency),
14563
- importers: Schema.Array(LockfileImporter).pipe(Schema.withDecodingDefaultKey(Effect.succeed([])), Schema.withConstructorDefault(Effect.succeed(EMPTY_IMPORTERS))),
14564
- extension: Schema.optionalKey(Schema.Union([PnpmExtension, BunExtension]))
15730
+ var WorkspaceSpecifier = class extends Schema.TaggedClass()("workspace", {
15731
+ /** The original specifier string. */
15732
+ raw: Schema.String,
15733
+ /** The part after `workspace:` (e.g. `*`, `^1.2.3`, or an alias form). */
15734
+ range: Schema.String
14565
15735
  }) {
14566
- /** Lazily built name → packages index; deliberately outside the schema, never encodes. */
14567
- #nameIndex;
14568
- /** Lazily built importer-path → importer index; deliberately outside the schema, never encodes. */
14569
- #importerIndex;
14570
- /**
14571
- * Parse lockfile content of a known format into the unified model — the
14572
- * package's only fallible boundary.
14573
- *
14574
- * @param content - The lockfile text (this package does no IO; the caller
14575
- * reads the file).
14576
- * @param options - The lockfile format to parse as.
14577
- * @returns An `Effect` succeeding with the {@link Lockfile}, or failing
14578
- * with {@link LockfileParseError} (malformed text or the wrong shape) or
14579
- * {@link LockfileFramingError} (the text parsed, but no lockfile document
14580
- * could be located in the stream — see that error for why a
14581
- * multi-document `pnpm-lock.yaml` needs it).
14582
- */
14583
- static parse = Effect.fn("Lockfile.parse")(function* (content, options) {
14584
- const fields = yield* dispatch(options.format, content).pipe(Effect.mapError((failure) => failure.stage === "framing" ? new LockfileFramingError({
14585
- format: options.format,
14586
- reason: failure.reason,
14587
- documents: failure.documents
14588
- }) : new LockfileParseError({
14589
- format: options.format,
14590
- stage: failure.stage,
14591
- cause: failure.cause
14592
- })));
14593
- return Lockfile.make({
14594
- format: options.format,
14595
- lockfileVersion: fields.lockfileVersion,
14596
- packages: fields.packages,
14597
- workspaceDependencies: fields.workspaceDependencies,
14598
- importers: fields.importers,
14599
- ...fields.extension !== void 0 ? { extension: fields.extension } : {}
14600
- });
14601
- });
14602
15736
  /**
14603
- * Rewrite pnpm importer-path names to real package names the explicit
14604
- * second stage of pnpm parsing. Total and pure.
15737
+ * The pnpm publish-time projection of this specifier against a concrete
15738
+ * workspace version: `*` (or an empty range) becomes `version`, `~` becomes
15739
+ * `~version`, `^` becomes `^version`, and a pinned range passes through
15740
+ * unchanged. The alias form (`workspace:<name>@<range>`) becomes pnpm's
15741
+ * publish-time aliased dependency `npm:<name>@<projected>`, with the range
15742
+ * modifier projected the same way — `version` must then be the TARGET
15743
+ * package's version (see `DependencySpecifier.workspaceTargetOf`).
14605
15744
  *
14606
15745
  * @remarks
14607
- * Workspace packages whose `relativePath` appears in `names` are renamed;
14608
- * dependency edge ends are rewritten through the same map. Entries not in
14609
- * the map keep their path name, and non-pnpm lockfiles are unaffected (no
14610
- * key matches). Versions are not touched — pnpm workspace packages keep
14611
- * `"0.0.0"` (the lockfile does not record their real versions).
14612
- *
14613
- * @param names - Importer path → real package name.
14614
- * @returns A new {@link Lockfile} with names rewritten.
14615
- */
14616
- withImporterNames(names) {
14617
- const packages = this.packages.map((pkg) => {
14618
- if (!pkg.isWorkspace || pkg.relativePath === void 0) return pkg;
14619
- const realName = names.get(pkg.relativePath);
14620
- if (realName === void 0 || realName === "" || realName === pkg.name) return pkg;
14621
- return ResolvedPackage.make({
14622
- name: realName,
14623
- version: pkg.version,
14624
- ...pkg.integrity !== void 0 ? { integrity: pkg.integrity } : {},
14625
- isWorkspace: pkg.isWorkspace,
14626
- relativePath: pkg.relativePath,
14627
- dependencies: pkg.dependencies
14628
- });
14629
- });
14630
- const workspaceDependencies = this.workspaceDependencies.map((dep) => {
14631
- const mappedFrom = names.get(dep.from);
14632
- const mappedTo = names.get(dep.to);
14633
- const from = mappedFrom === void 0 || mappedFrom === "" ? dep.from : mappedFrom;
14634
- const to = mappedTo === void 0 || mappedTo === "" ? dep.to : mappedTo;
14635
- if (from === dep.from && to === dep.to) return dep;
14636
- return WorkspaceDependency.make({
14637
- from,
14638
- to,
14639
- depType: dep.depType,
14640
- constraint: dep.constraint
14641
- });
14642
- });
14643
- return Lockfile.make({
14644
- format: this.format,
14645
- lockfileVersion: this.lockfileVersion,
14646
- packages,
14647
- workspaceDependencies,
14648
- importers: this.importers,
14649
- ...this.extension !== void 0 ? { extension: this.extension } : {}
14650
- });
14651
- }
14652
- /**
14653
- * Every resolved package with the given name — one entry per resolved
14654
- * version. Backed by a lazily built index, so repeated lookups are O(1).
14655
- *
14656
- * @param name - The package name to look up.
14657
- * @returns The matching packages, empty when the name is not in the
14658
- * lockfile.
14659
- */
14660
- packagesNamed(name) {
14661
- if (this.#nameIndex === void 0) {
14662
- const index = /* @__PURE__ */ new Map();
14663
- for (const pkg of this.packages) {
14664
- const bucket = index.get(pkg.name);
14665
- if (bucket === void 0) index.set(pkg.name, [pkg]);
14666
- else bucket.push(pkg);
14667
- }
14668
- this.#nameIndex = index;
14669
- }
14670
- return this.#nameIndex.get(name) ?? [];
14671
- }
14672
- /**
14673
- * The importer at the given path — `"."` for the workspace root — or
14674
- * `Option.none()` when the lockfile records no importer there. Backed by a
14675
- * lazily built index, so repeated lookups are O(1). The index is a `Map`,
14676
- * so an attacker-adjacent path (`__proto__`, `constructor`) neither pollutes
14677
- * nor collides.
15746
+ * The same projection as `DependencySpecifier.resolveWorkspace`, applied to
15747
+ * this instance's already-extracted `range`; the two share one internal
15748
+ * implementation.
14678
15749
  *
14679
- * @param path - The importer path to look up.
14680
- * @returns The matching {@link LockfileImporter}, or `Option.none()`.
15750
+ * @param version - The concrete version of the workspace package the
15751
+ * specifier points at (the alias target's version for the alias form).
14681
15752
  */
14682
- importer(path) {
14683
- if (this.#importerIndex === void 0) {
14684
- const index = /* @__PURE__ */ new Map();
14685
- for (const imp of this.importers) index.set(imp.path, imp);
14686
- this.#importerIndex = index;
14687
- }
14688
- return Option.fromUndefinedOr(this.#importerIndex.get(path));
14689
- }
14690
- /** The workspace-local packages. */
14691
- get workspacePackages() {
14692
- return this.packages.filter((pkg) => pkg.isWorkspace);
15753
+ resolve(version) {
15754
+ return projectWorkspaceRange(this.range, version);
14693
15755
  }
14694
15756
  };
15757
+ /**
15758
+ * A plain semver range or exact version (e.g. `^1.2.3`, `1.x`, `>=1 <2`).
15759
+ *
15760
+ * @public
15761
+ */
15762
+ var RangeSpecifier = class extends Schema.TaggedClass()("range", {
15763
+ /** The original specifier string. */
15764
+ raw: Schema.String }) {};
15765
+ /**
15766
+ * A bare dist-tag (e.g. `latest`, `next`).
15767
+ *
15768
+ * @public
15769
+ */
15770
+ var DistTagSpecifier = class extends Schema.TaggedClass()("dist-tag", {
15771
+ /** The original specifier string (also the tag name). */
15772
+ raw: Schema.String }) {};
15773
+ /**
15774
+ * The honest fallback for `file:` / `link:` / `portal:` / git / URL / `npm:`
15775
+ * forms this concept does not further interpret.
15776
+ *
15777
+ * @public
15778
+ */
15779
+ var RawSpecifier = class extends Schema.TaggedClass()("raw", {
15780
+ /** The original specifier string. */
15781
+ raw: Schema.String }) {};
15782
+ const Classified = Schema.Union([
15783
+ CatalogSpecifier,
15784
+ WorkspaceSpecifier,
15785
+ RangeSpecifier,
15786
+ DistTagSpecifier,
15787
+ RawSpecifier
15788
+ ]);
15789
+ const classify$1 = (value) => {
15790
+ if (isCatalog(value)) return CatalogSpecifier.make({
15791
+ raw: value,
15792
+ name: catalogNameOf$1(value)
15793
+ });
15794
+ if (isWorkspace(value)) return WorkspaceSpecifier.make({
15795
+ raw: value,
15796
+ range: value.slice(10)
15797
+ });
15798
+ if (isRange(value)) return RangeSpecifier.make({ raw: value });
15799
+ if (isTag(value)) return DistTagSpecifier.make({ raw: value });
15800
+ return RawSpecifier.make({ raw: value });
15801
+ };
15802
+ const fromString = Schema.String.pipe(Schema.decodeTo(Classified, SchemaTransformation.transformOrFail({
15803
+ decode: (input) => isValidDependencySpecifier(input) ? Effect.succeed(classify$1(input)) : Effect.fail(new SchemaIssue.InvalidValue(Option.some(input), { message: `Invalid dependency specifier: "${input}"` })),
15804
+ encode: (classified) => Effect.succeed(classified.raw)
15805
+ })));
15806
+ const brandedSpecifier = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => isValidDependencySpecifier(value) ? void 0 : "Expected a valid dependency specifier")), Schema.brand("DependencySpecifier"));
15807
+ const decode$3 = (input) => Schema.decodeUnknownEffect(brandedSpecifier)(input).pipe(Effect.mapError(() => new InvalidDependencySpecifierError({ input })));
15808
+ /**
15809
+ * A valid dependency version specifier, carrying the protocol taxonomy statics
15810
+ * (`DependencySpecifier.protocolOf` and friends) that classify any specifier
15811
+ * string, plus the {@link (DependencySpecifier:variable).FromString} codec that
15812
+ * decodes a string into a {@link ClassifiedSpecifier} tagged union. Use it as a
15813
+ * schema for a specifier field and reach for the statics to inspect a raw
15814
+ * string.
15815
+ *
15816
+ * @public
15817
+ */
15818
+ const DependencySpecifier = Object.assign(brandedSpecifier, {
15819
+ protocolOf,
15820
+ parseRange,
15821
+ isRange,
15822
+ isTag,
15823
+ isGit,
15824
+ isUrl: isUrl$1,
15825
+ isLocal,
15826
+ isLink,
15827
+ isPortal,
15828
+ isCatalog,
15829
+ isWorkspace,
15830
+ catalogNameOf: catalogNameOf$1,
15831
+ resolveWorkspace,
15832
+ workspaceTargetOf,
15833
+ isValid: isValidDependencySpecifier,
15834
+ decode: decode$3,
15835
+ FromString: fromString
15836
+ });
14695
15837
 
14696
15838
  //#endregion
14697
- //#region ../../node_modules/.pnpm/@effected+lockfiles@0.3.2_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__@effected+npm@0._ff048038a9678f5144f817ad24d8f96e/node_modules/@effected/lockfiles/LockfileIntegrity.js
15839
+ //#region ../../node_modules/.pnpm/@effected+npm@0.8.2_@effected+semver@0.3.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/npm/IntegrityHash.js
15840
+ const SRI_RE = /^(sha1|sha256|sha384|sha512)-[A-Za-z0-9+/]+={0,2}$/;
15841
+ const COREPACK_RE = /^(sha1|sha224|sha256|sha384|sha512)\.[0-9a-f]+$/;
15842
+ const YARN_RE = /^[0-9]+(c[0-9]+)?\/[0-9a-f]+$/;
15843
+ const isSri = (value) => SRI_RE.test(value);
15844
+ const isCorepack = (value) => COREPACK_RE.test(value);
15845
+ const isYarnChecksum = (value) => YARN_RE.test(value);
14698
15846
  /**
14699
- * The minimal manifest shape {@link LockfileIntegrity.compare} checks a
14700
- * lockfile against: a package name plus the four optional dependency maps.
15847
+ * Whether a string is a valid integrity hash in the SRI (`<algo>-<base64>`),
15848
+ * corepack (`<algo>.<hex>`) or yarn (`<cachekey>/<hex>`) form.
14701
15849
  *
14702
- * @remarks
14703
- * Deliberately *not* a `@effected/package-json` type — this package takes
14704
- * manifests as plain values so its consumers own the manifest IO (and may
14705
- * derive these from any richer model).
15850
+ * @public
15851
+ */
15852
+ const isValidIntegrityHash = (value) => isSri(value) || isCorepack(value) || isYarnChecksum(value);
15853
+ const algorithmOf = (value) => {
15854
+ if (isSri(value)) return Option.some(value.slice(0, value.indexOf("-")));
15855
+ if (isCorepack(value)) return Option.some(value.slice(0, value.indexOf(".")));
15856
+ return Option.none();
15857
+ };
15858
+ /**
15859
+ * Indicates that a string could not be parsed as a valid integrity hash.
15860
+ *
15861
+ * Raised by {@link IntegrityHash.decode}. The offending string is preserved on
15862
+ * `input`.
14706
15863
  *
14707
15864
  * @public
14708
15865
  */
14709
- var WorkspaceManifest = class extends Schema.Class("WorkspaceManifest")({
14710
- name: Schema.NonEmptyString,
14711
- dependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
14712
- devDependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
14713
- peerDependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.String)),
14714
- optionalDependencies: Schema.optionalKey(Schema.Record(Schema.String, Schema.String))
14715
- }) {};
14716
- const decodeRange = Schema.decodeUnknownExit(Range$1.FromString);
14717
- const decodeSemVer = Schema.decodeUnknownExit(SemVer.FromString);
15866
+ var InvalidIntegrityHashError = class extends Schema.TaggedErrorClass()("InvalidIntegrityHashError", {
15867
+ /** The raw input string that failed validation. */
15868
+ input: Schema.String }) {
15869
+ get message() {
15870
+ return `Invalid integrity hash "${this.input}": expected an SRI (<algo>-<base64>), corepack (<algo>.<hex>) or yarn (<cachekey>/<hex>) form`;
15871
+ }
15872
+ };
15873
+ const brandedIntegrity = Schema.String.pipe(Schema.check(Schema.makeFilter((value) => isValidIntegrityHash(value) ? void 0 : "Expected an SRI, corepack or yarn integrity hash")), Schema.brand("IntegrityHash"));
15874
+ const decode$2 = (input) => Schema.decodeUnknownEffect(brandedIntegrity)(input).pipe(Effect.mapError(() => new InvalidIntegrityHashError({ input })));
14718
15875
  /**
14719
- * Result of checking a parsed lockfile against the workspace's declared
14720
- * manifests.
15876
+ * A subresource-integrity hash, covering the SRI (`sha512-<base64>`), corepack
15877
+ * (`sha512.<hex>`) and yarn (`10c0/<hex>`) textual forms, carrying taxonomy
15878
+ * statics (`IntegrityHash.algorithmOf` and friends). Use it as a schema for an
15879
+ * integrity field and reach for the statics to inspect a raw string.
15880
+ *
15881
+ * @public
15882
+ */
15883
+ const IntegrityHash = Object.assign(brandedIntegrity, {
15884
+ isSri,
15885
+ isCorepack,
15886
+ isYarnChecksum,
15887
+ isValid: isValidIntegrityHash,
15888
+ algorithmOf,
15889
+ decode: decode$2
15890
+ });
15891
+ /**
15892
+ * {@link (IntegrityHash:variable)} narrowed to the corepack `<algo>.<hex>` form
15893
+ * — `sha512.deadbeef`, and corepack's own sha224 default pins
15894
+ * (`sha224.877304e3…`). An SRI (`sha512-<base64>`) or yarn (`10c0/<hex>`)
15895
+ * hash, both valid `IntegrityHash` values, fails this schema.
14721
15896
  *
14722
15897
  * @remarks
14723
- * A data type, not an error: it reports *what* mismatches exist without
14724
- * failing anything.
15898
+ * The corepack pin tail (`<name>@<version>+<integrity>`) is the one place the
15899
+ * kit meets this form, and two schemas name it: `PackageManagerPin.integrity`
15900
+ * here and `@effected/package-json`'s `PackageManager.integrity`. Both consume
15901
+ * **this** schema — the restriction existed privately in each module until they
15902
+ * were consolidated, and a private copy is exactly how the two drift (the
15903
+ * widening that admitted sha224 had to be made twice).
14725
15904
  *
14726
- * - `valid` `true` when the lockfile is fully consistent.
14727
- * - `missingWorkspaces` workspace names present in the manifests but
14728
- * absent from the lockfile.
14729
- * - `extraWorkspaces` workspace names in the lockfile with no matching
14730
- * manifest.
14731
- * - `unsatisfiedConstraints` — declared constraints the lockfile's resolved
14732
- * versions do not satisfy.
15905
+ * It decodes to the same {@link IntegrityHashBrand} the unrestricted schema
15906
+ * does, so a corepack-validated value assigns anywhere an `IntegrityHash` is
15907
+ * expected; there is no second brand. Reach for
15908
+ * `IntegrityHash.isCorepack(value)` to ask the same question about a raw
15909
+ * string without decoding.
15910
+ *
15911
+ * That single brand is also why sharing this schema is not type-enforced, and
15912
+ * the consequence is sharper than it looks: a `Schema.check` is **erased from
15913
+ * the built type**, so this schema and the unrestricted one are the same
15914
+ * declared type. A consumer that quietly reverts to a private copy compiles
15915
+ * clean, and — if the copy is faithful — passes every rejection test too.
15916
+ * Neither `tsc` nor behaviour can see the re-fork.
15917
+ *
15918
+ * What does see it is **object identity**, so each consumer's suite asserts
15919
+ * that its field schema IS this export:
15920
+ * `PackageManagerPin.fields.integrity.schema === CorepackIntegrityHash` (an
15921
+ * `optionalKey` field keeps the inner schema on `.schema`), and
15922
+ * `PackageManager.fields.integrity.value === CorepackIntegrityHash` on the
15923
+ * `@effected/package-json` side (a `Schema.Option` keeps it on `.value`). Both
15924
+ * assertions carry a control against the unrestricted brand, so they discriminate
15925
+ * rather than passing on any schema at all. That identity assertion is the only
15926
+ * thing standing between the two surfaces and a silent re-fork; do not replace
15927
+ * it with a behavioural test, which cannot fail.
15928
+ *
15929
+ * @example
15930
+ * ```ts
15931
+ * import { CorepackIntegrityHash } from "@effected/npm";
15932
+ * import { Schema } from "effect";
15933
+ *
15934
+ * const decode = Schema.decodeUnknownExit(CorepackIntegrityHash);
15935
+ *
15936
+ * decode("sha512.deadbeef"); // success
15937
+ * decode("sha512-3q2+7w=="); // failure — SRI form
15938
+ * ```
14733
15939
  *
14734
15940
  * @public
14735
15941
  */
14736
- var LockfileIntegrity = class LockfileIntegrity extends Schema.Class("LockfileIntegrity")({
14737
- valid: Schema.Boolean,
14738
- missingWorkspaces: Schema.Array(Schema.String),
14739
- extraWorkspaces: Schema.Array(Schema.String),
14740
- unsatisfiedConstraints: Schema.Array(Schema.Struct({
14741
- workspace: Schema.String,
14742
- dependency: Schema.String,
14743
- constraint: Schema.String,
14744
- resolved: Schema.String,
14745
- depType: DependencyField
14746
- }))
14747
- }) {
14748
- /**
14749
- * Check a lockfile's consistency against workspace manifests — a total,
14750
- * pure function: no Effect, no error channel, no IO.
14751
- *
14752
- * @remarks
14753
- * Constraint checking is best-effort by design: `workspace:` / `link:` /
14754
- * `file:` specifiers and rows whose range (or every resolved version) does
14755
- * not parse as SemVer are skipped, exactly as in the v3 implementation.
14756
- * A lockfile may resolve the same package at several versions; a
14757
- * constraint is satisfied when *any* resolved version matches, and an
14758
- * unsatisfied row reports every candidate in `resolved`. The
14759
- * caller reads the manifests (this package does no IO). For pnpm, apply
14760
- * `Lockfile#withImporterNames` first so workspace names align with
14761
- * manifest names.
14762
- *
14763
- * (Named `compare`, not `check`: every v4 `Schema.Class` already carries
14764
- * a `static check(...checks)` for attaching schema checks, and statics
14765
- * cannot be shadowed with an incompatible signature.)
14766
- *
14767
- * @param lockfile - The parsed lockfile.
14768
- * @param manifests - The workspace manifests to compare against.
14769
- * @returns The integrity report.
14770
- */
14771
- static compare(lockfile, manifests) {
14772
- const workspacePackages = lockfile.packages.filter((p) => p.isWorkspace && p.relativePath !== void 0);
14773
- const lockfileWsNames = new Set(workspacePackages.map((p) => p.name));
14774
- const manifestNames = new Set(manifests.map((m) => m.name));
14775
- const missingWorkspaces = [...manifestNames].filter((n) => !lockfileWsNames.has(n));
14776
- const extraWorkspaces = [...lockfileWsNames].filter((n) => !manifestNames.has(n));
14777
- const resolvedIndex = /* @__PURE__ */ new Map();
14778
- for (const p of lockfile.packages) {
14779
- const versions = resolvedIndex.get(p.name);
14780
- if (versions === void 0) resolvedIndex.set(p.name, [p.version]);
14781
- else versions.push(p.version);
14782
- }
14783
- const unsatisfiedConstraints = [];
14784
- for (const manifest of manifests) for (const depType of DEP_TYPES) {
14785
- const depMap = manifest[depType];
14786
- if (!depMap) continue;
14787
- for (const [dependency, constraint] of Object.entries(depMap)) {
14788
- if (isWorkspaceSpecifier(constraint)) continue;
14789
- const candidates = resolvedIndex.get(dependency);
14790
- if (candidates === void 0) continue;
14791
- const rangeExit = decodeRange(constraint);
14792
- if (Exit.isFailure(rangeExit)) continue;
14793
- const versions = candidates.map((candidate) => decodeSemVer(candidate)).filter(Exit.isSuccess);
14794
- if (versions.length === 0) continue;
14795
- if (!versions.some((v) => rangeExit.value.test(v.value))) unsatisfiedConstraints.push({
14796
- workspace: manifest.name,
14797
- dependency,
14798
- constraint,
14799
- resolved: candidates.join(", "),
14800
- depType
14801
- });
14802
- }
14803
- }
14804
- return LockfileIntegrity.make({
14805
- valid: missingWorkspaces.length === 0 && extraWorkspaces.length === 0 && unsatisfiedConstraints.length === 0,
14806
- missingWorkspaces,
14807
- extraWorkspaces,
14808
- unsatisfiedConstraints
14809
- });
14810
- }
14811
- };
15942
+ const CorepackIntegrityHash = brandedIntegrity.pipe(Schema.check(Schema.makeFilter((value) => isCorepack(value) ? void 0 : "Expected a corepack (<algo>.<hex>) integrity hash")));
14812
15943
 
14813
15944
  //#endregion
14814
15945
  //#region ../../node_modules/.pnpm/@effected+package-json@0.7.3_effect@4.0.0-beta.101/node_modules/@effected/package-json/Dependency.js
@@ -17555,7 +18686,7 @@ var Package = class Package extends Schema.Class("Package")({
17555
18686
  };
17556
18687
 
17557
18688
  //#endregion
17558
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspacePackage.js
18689
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspacePackage.js
17559
18690
  const EMPTY$1 = Object.freeze(Object.create(null));
17560
18691
  const EMPTY_MANIFEST = Object.freeze(Object.create(null));
17561
18692
  /**
@@ -18157,7 +19288,7 @@ var Walker$1 = class {
18157
19288
  };
18158
19289
 
18159
19290
  //#endregion
18160
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceRoot.js
19291
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceRoot.js
18161
19292
  /**
18162
19293
  * The marker filenames {@link WorkspaceRoot} probes for, in priority order.
18163
19294
  *
@@ -18345,7 +19476,7 @@ var WorkspaceRoot = class WorkspaceRoot extends Context.Service()("@effected/wor
18345
19476
  };
18346
19477
 
18347
19478
  //#endregion
18348
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/limits.js
19479
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/limits.js
18349
19480
  /**
18350
19481
  * Hard ceiling on directories the enumerator will visit for one pattern set.
18351
19482
  * Guards the pathological case a depth cap alone does not: a wide, shallow
@@ -18364,7 +19495,7 @@ const MAX_ENUMERATION_ENTRIES = 1e5;
18364
19495
  const PRUNED_DIRECTORIES = /* @__PURE__ */ new Set([".git", "node_modules"]);
18365
19496
 
18366
19497
  //#endregion
18367
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/traverse.js
19498
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/traverse.js
18368
19499
  /** Directory names never descended into. */
18369
19500
  const isPruned = (entry) => PRUNED_DIRECTORIES.has(entry);
18370
19501
  /** Join root-relative POSIX segments; `""` is the root itself. */
@@ -18455,7 +19586,7 @@ var Traversal = class {
18455
19586
  };
18456
19587
 
18457
19588
  //#endregion
18458
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/enumerate.js
19589
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/enumerate.js
18459
19590
  /** Strip a trailing slash from `GlobPattern.enumerationPrefix` to get a relative directory. */
18460
19591
  const baseOf = (pattern) => pattern.enumerationPrefix.replace(/\/$/, "");
18461
19592
  /**
@@ -18526,7 +19657,7 @@ const enumerate = (root, globs, options) => Effect.gen(function* () {
18526
19657
  });
18527
19658
 
18528
19659
  //#endregion
18529
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/patterns.js
19660
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/patterns.js
18530
19661
  const stringsOf = (value) => Array.isArray(value) ? value.filter((entry) => typeof entry === "string") : void 0;
18531
19662
  /** The `packages:` list of a `pnpm-workspace.yaml` document. Total on a parsed document. */
18532
19663
  const pnpmPatternsOf = (document) => {
@@ -18584,7 +19715,7 @@ const readPatterns = (root) => Effect.gen(function* () {
18584
19715
  });
18585
19716
 
18586
19717
  //#endregion
18587
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceDiscovery.js
19718
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceDiscovery.js
18588
19719
  /**
18589
19720
  * Raised when a workspace member's `package.json` cannot be read, parsed, or
18590
19721
  * used — it is missing, malformed, or lacks a `name` or `version`.
@@ -18837,6 +19968,15 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends Context.Service()("@ef
18837
19968
  for (const entry of index) if (filePath.startsWith(entry.prefix)) return Option.some(entry.package);
18838
19969
  return Option.none();
18839
19970
  };
19971
+ const packageIndexes = /* @__PURE__ */ new WeakMap();
19972
+ const packagesByName = (all) => {
19973
+ const cached = packageIndexes.get(all);
19974
+ if (cached !== void 0) return cached;
19975
+ const index = /* @__PURE__ */ new Map();
19976
+ for (const pkg of all) if (!index.has(pkg.name)) index.set(pkg.name, pkg);
19977
+ packageIndexes.set(all, index);
19978
+ return index;
19979
+ };
18840
19980
  return {
18841
19981
  info: Effect.fn("WorkspaceDiscovery.info")(function* () {
18842
19982
  return (yield* memo).info;
@@ -18850,7 +19990,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends Context.Service()("@ef
18850
19990
  }),
18851
19991
  getPackage: Effect.fn("WorkspaceDiscovery.getPackage")(function* (name) {
18852
19992
  const all = yield* packages;
18853
- const found = all.find((pkg) => pkg.name === name);
19993
+ const found = packagesByName(all).get(name);
18854
19994
  if (found !== void 0) return found;
18855
19995
  return yield* Effect.fail(new PackageNotFoundError({
18856
19996
  name,
@@ -19012,9 +20152,18 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends Context.Service()("@ef
19012
20152
  * // `Package.resolve` now resolves `workspace:*` for real.
19013
20153
  * ```
19014
20154
  */
19015
- static workspaceResolver = Layer.effect(WorkspaceResolver, Effect.gen(function* () {
20155
+ static workspaceResolver = Layer.effect(WorkspaceResolver$1, Effect.gen(function* () {
19016
20156
  const discovery = yield* WorkspaceDiscovery;
19017
- return { versionOf: (packageName) => discovery.listPackages().pipe(Effect.map((all) => Option.fromUndefinedOr(all.find((pkg) => pkg.name === packageName)?.version)), Effect.mapError((cause) => new DependencyResolutionError({
20157
+ const versionIndexes = /* @__PURE__ */ new WeakMap();
20158
+ const versionsByName = (all) => {
20159
+ const cached = versionIndexes.get(all);
20160
+ if (cached !== void 0) return cached;
20161
+ const index = /* @__PURE__ */ new Map();
20162
+ for (const pkg of all) if (!index.has(pkg.name)) index.set(pkg.name, pkg.version);
20163
+ versionIndexes.set(all, index);
20164
+ return index;
20165
+ };
20166
+ return { versionOf: (packageName) => discovery.listPackages().pipe(Effect.map((all) => Option.fromUndefinedOr(versionsByName(all).get(packageName))), Effect.mapError((cause) => new DependencyResolutionError$1({
19018
20167
  specifier: `workspace:${packageName}`,
19019
20168
  cause
19020
20169
  }))) };
@@ -19023,7 +20172,7 @@ var WorkspaceDiscovery = class WorkspaceDiscovery extends Context.Service()("@ef
19023
20172
  const isStringRecord$2 = (value) => value !== null && typeof value === "object" && !Array.isArray(value) && Object.values(value).every((entry) => typeof entry === "string");
19024
20173
 
19025
20174
  //#endregion
19026
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/DependencyGraph.js
20175
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/DependencyGraph.js
19027
20176
  /**
19028
20177
  * Raised when the workspace dependency graph cannot be topologically ordered
19029
20178
  * because it contains a cycle.
@@ -20669,7 +21818,7 @@ var Git = class Git extends Context.Service()("@effected/git/Git") {
20669
21818
  };
20670
21819
 
20671
21820
  //#endregion
20672
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ChangeDetector.js
21821
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ChangeDetector.js
20673
21822
  /**
20674
21823
  * Which git refs to compare, and whether to fold in the working tree.
20675
21824
  *
@@ -20969,7 +22118,7 @@ function resolveFromCatalog(catalogs, wantedDependency) {
20969
22118
  }
20970
22119
 
20971
22120
  //#endregion
20972
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/catalogs.js
22121
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/catalogs.js
20973
22122
  /** Project a pnpm-workspace manifest's `catalog` / `catalogs` fields into a `Catalogs` map. */
20974
22123
  const inlineCatalogs = (manifest) => {
20975
22124
  if (manifest.catalog === void 0 && manifest.catalogs === void 0) return {};
@@ -21035,7 +22184,7 @@ const rangeOf = (catalogs, dependency, specifier) => {
21035
22184
  };
21036
22185
 
21037
22186
  //#endregion
21038
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ConfigDependencyHooks.js
22187
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/ConfigDependencyHooks.js
21039
22188
  /** Whether `value` is a non-null, non-array object. */
21040
22189
  const isObject$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
21041
22190
  /**
@@ -21128,6 +22277,137 @@ const updateConfigOf = (mod) => {
21128
22277
  }
21129
22278
  };
21130
22279
  /**
22280
+ * The subprocess replay program {@link ConfigDependencyHooks.layerSubprocess}
22281
+ * hands to `node --input-type=module -e`.
22282
+ *
22283
+ * @remarks
22284
+ * A **static** string constant, deliberately: a bundler compiles a *computed*
22285
+ * dynamic `import()` into a context module that cannot resolve a runtime path
22286
+ * (`Cannot find module 'file:///…'`), so the computed import has to run in a
22287
+ * child process whose program text carries **no interpolated runtime value** —
22288
+ * the workspace root, the seed and the dependency names all arrive via argv
22289
+ * (`process.argv.slice(1)` under `-e`), never spliced into the script.
22290
+ *
22291
+ * The script mirrors this module's in-process semantics exactly so the two
22292
+ * layers are drop-in interchangeable: `pnpmfile.mjs` before `pnpmfile.cjs`
22293
+ * (pnpm 11's loader order), the `ERR_MODULE_NOT_FOUND`-for-the-candidate-itself
22294
+ * skip discrimination (`err.url` equality), the same hook-locator shapes, the
22295
+ * same tolerant threading of returned data (`configOf` / `finiteNumberOr` /
22296
+ * `stringArrayOr` clones below), and the same synchronous hook call. Only the
22297
+ * *mechanism* failures are reported: the script prints one final line of JSON —
22298
+ * `{ ok: true, config }` on success, `{ ok: false, name, message, stack? }`
22299
+ * naming the offending dependency on a load/replay failure — and exits through
22300
+ * the write callback so the payload is flushed even if a hook left the event
22301
+ * loop occupied. The final-line framing tolerates a hook's own `console.log`
22302
+ * noise on stdout.
22303
+ */
22304
+ const REPLAY_SCRIPT = `
22305
+ const [root, seedJson, ...names] = process.argv.slice(1);
22306
+ const { pathToFileURL } = await import("node:url");
22307
+ const { join } = await import("node:path");
22308
+ const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
22309
+ const finiteNumberOr = (value, fallback) => (typeof value === "number" && Number.isFinite(value) ? value : fallback);
22310
+ const stringArrayOr = (value, fallback) =>
22311
+ Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : fallback;
22312
+ const configOf = (value, fallback) =>
22313
+ isObject(value)
22314
+ ? {
22315
+ catalog: isObject(value.catalog) ? value.catalog : fallback.catalog,
22316
+ catalogs: isObject(value.catalogs) ? value.catalogs : fallback.catalogs,
22317
+ minimumReleaseAge: finiteNumberOr(value.minimumReleaseAge, fallback.minimumReleaseAge),
22318
+ minimumReleaseAgeExclude: stringArrayOr(value.minimumReleaseAgeExclude, fallback.minimumReleaseAgeExclude),
22319
+ }
22320
+ : fallback;
22321
+ const failure = (name, cause) => ({
22322
+ ok: false,
22323
+ name,
22324
+ message: cause instanceof Error ? cause.message : String(cause),
22325
+ ...(cause instanceof Error && typeof cause.stack === "string" ? { stack: cause.stack } : {}),
22326
+ });
22327
+ const replay = async () => {
22328
+ let catalog = {};
22329
+ const catalogs = {};
22330
+ for (const [name, entries] of Object.entries(JSON.parse(seedJson))) {
22331
+ if (name === "default") catalog = { ...entries };
22332
+ else catalogs[name] = { ...entries };
22333
+ }
22334
+ let config = { catalog, catalogs, minimumReleaseAge: undefined, minimumReleaseAgeExclude: undefined };
22335
+ for (const name of names) {
22336
+ let loaded;
22337
+ let found = false;
22338
+ for (const filename of ["pnpmfile.mjs", "pnpmfile.cjs"]) {
22339
+ const candidate = pathToFileURL(join(root, "node_modules", ".pnpm-config", name, filename)).href;
22340
+ try {
22341
+ loaded = await import(candidate);
22342
+ found = true;
22343
+ break;
22344
+ } catch (cause) {
22345
+ const url =
22346
+ isObject(cause) && cause.code === "ERR_MODULE_NOT_FOUND" && typeof cause.url === "string"
22347
+ ? cause.url
22348
+ : undefined;
22349
+ if (url === candidate) continue;
22350
+ return failure(name, cause);
22351
+ }
22352
+ }
22353
+ if (!found) continue;
22354
+ let hook;
22355
+ for (const candidate of [loaded, isObject(loaded) ? loaded.default : undefined]) {
22356
+ if (!isObject(candidate)) continue;
22357
+ if (isObject(candidate.hooks) && typeof candidate.hooks.updateConfig === "function") {
22358
+ hook = candidate.hooks.updateConfig;
22359
+ break;
22360
+ }
22361
+ if (typeof candidate.updateConfig === "function") {
22362
+ hook = candidate.updateConfig;
22363
+ break;
22364
+ }
22365
+ }
22366
+ if (hook === undefined) continue;
22367
+ try {
22368
+ config = configOf(hook(config), config);
22369
+ } catch (cause) {
22370
+ return failure(name, cause);
22371
+ }
22372
+ }
22373
+ return { ok: true, config };
22374
+ };
22375
+ const payload = await replay();
22376
+ process.stdout.write("\\n" + JSON.stringify(payload) + "\\n", () => process.exit(0));
22377
+ `;
22378
+ /**
22379
+ * The ceiling on one subprocess replay. A config dependency's `updateConfig`
22380
+ * reads and rewrites a config object — no install work, no network — so thirty
22381
+ * seconds is generous. Without a ceiling a pnpmfile that loops or awaits a
22382
+ * promise that never settles hangs `inject`, and through it the one memoized
22383
+ * {@link WorkspaceCatalogs} assemble pass every catalog read blocks on. Expiry
22384
+ * kills the child (`Run` scopes it) and surfaces as a `CommandFailedError`
22385
+ * through the same typed transport-failure path as any other mechanism failure.
22386
+ */
22387
+ const REPLAY_TIMEOUT = Duration.seconds(30);
22388
+ /**
22389
+ * The subprocess protocol payload — the child's final stdout line, framed and
22390
+ * parsed by `Run.jsonLine`. The envelope is strict (a payload without a usable
22391
+ * `ok` discriminant is a mechanism failure, typed); the `config` slice inside a
22392
+ * success stays `Unknown` because a hook's returned *data* is tolerantly
22393
+ * threaded (`configOf`), never fatal.
22394
+ */
22395
+ const ReplayPayload = Schema.Union([Schema.Struct({
22396
+ ok: Schema.Literal(true),
22397
+ config: Schema.Unknown
22398
+ }), Schema.Struct({
22399
+ ok: Schema.Literal(false),
22400
+ name: Schema.optionalKey(Schema.String),
22401
+ message: Schema.optionalKey(Schema.String),
22402
+ stack: Schema.optionalKey(Schema.String)
22403
+ })]);
22404
+ /** Rebuild the subprocess's serialized failure as an `Error`, preserving the child-side stack when it carried one. */
22405
+ const replayFailureCause = (payload) => {
22406
+ const error = new Error(payload.message ?? "config dependency hook replay failed");
22407
+ if (payload.stack !== void 0) error.stack = payload.stack;
22408
+ return error;
22409
+ };
22410
+ /**
21131
22411
  * Replays a workspace's `configDependencies` `updateConfig` hooks over the inline
21132
22412
  * catalogs — the opt-in seam that lets hook-injected catalogs participate in
21133
22413
  * assembly.
@@ -21220,10 +22500,99 @@ var ConfigDependencyHooks = class ConfigDependencyHooks extends Context.Service(
21220
22500
  releaseAge: releaseAgeOf(config)
21221
22501
  };
21222
22502
  }) });
22503
+ /**
22504
+ * The subprocess layer: replays each config dependency's pnpmfile in a `node`
22505
+ * child process instead of an in-process dynamic `import()`, with identical
22506
+ * typed semantics to {@link ConfigDependencyHooks.layerLive} — the two are
22507
+ * drop-in interchangeable.
22508
+ *
22509
+ * @remarks
22510
+ * `layerLive` computes the `import()` path at runtime, and a bundler (rspack,
22511
+ * for one) compiles a *computed* dynamic import into a context module that
22512
+ * throws `Cannot find module 'file:///…'` at runtime — so in any bundled
22513
+ * consumer, a GitHub Action above all, the in-process replay is unreachable.
22514
+ * This layer keeps every computed load out of the bundle graph: the replay
22515
+ * program is a **static** string constant passed via argv
22516
+ * (`node --input-type=module -e <script> <root> <seed> <...names>`), and the
22517
+ * child process performs the computed imports where no bundler rewrote them.
22518
+ * A subprocess also keeps config-dependency code out of the consumer's own
22519
+ * process.
22520
+ *
22521
+ * The contract's semantics are unchanged, not the downstream fail-open shape:
22522
+ * an empty `configDependencies` returns the seed without spawning anything; a
22523
+ * `..` path segment in a dependency name fails typed **before** any spawn; a
22524
+ * missing pnpmfile (neither `.mjs` nor `.cjs`) is the one legitimate skip,
22525
+ * discriminated inside the child by `err.url` equality exactly as
22526
+ * `layerLive` discriminates in process; any other load failure — a syntax
22527
+ * error, a throwing top level, an `ERR_MODULE_NOT_FOUND` for a module the
22528
+ * pnpmfile itself imports — and a hook that throws when called are serialized
22529
+ * back per-name and surface typed as a `hooks`-source `CatalogAssemblyError`
22530
+ * naming that dependency. A hook's returned *data* stays tolerantly threaded
22531
+ * (last well-formed write wins), never fatal. Spawn and transport failures —
22532
+ * `node` absent, a non-zero exit without a result payload, unparseable
22533
+ * output — fail typed too, never a defect and never a silent skip.
22534
+ *
22535
+ * Two bounds this layer imposes that `layerLive` cannot: the replay is
22536
+ * given thirty seconds (a pnpmfile that loops or awaits forever fails typed
22537
+ * instead of hanging the memoized assemble pass — a subprocess is killable,
22538
+ * while `layerLive`'s in-process synchronous hook call is not interruptible
22539
+ * by any means, so the asymmetry is inherent, not a parity violation), and
22540
+ * the child's stdout is captured under `Run.jsonLine`'s 16 MiB default
22541
+ * ceiling (a hook that logs more than that fails typed as `tooLarge`, where
22542
+ * `layerLive` — which captures nothing — would succeed).
22543
+ *
22544
+ * Catalog folding and normalization stay in the **parent** (the same
22545
+ * `@pnpm/catalogs`-derived path `layerLive` uses); the child returns only the
22546
+ * raw threaded config slice, since the script cannot import kit code.
22547
+ *
22548
+ * Requires core's `ChildProcessSpawner`, resolved when the layer is built —
22549
+ * the consumer provides it once at the edge (`@effect/platform-node`'s
22550
+ * `NodeServices.layer`), the same discharge `@effected/git` uses. Wired by
22551
+ * `WorkspaceCatalogs.layerWithConfigDependenciesSubprocess` /
22552
+ * `Workspaces.layerWithConfigDependenciesSubprocess`.
22553
+ */
22554
+ static layerSubprocess = Layer.effect(ConfigDependencyHooks, Effect.gen(function* () {
22555
+ const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
22556
+ return { inject: (root, configDependencies, seed) => Effect.gen(function* () {
22557
+ const names = Object.keys(configDependencies);
22558
+ if (names.length === 0) return {
22559
+ catalogs: seed,
22560
+ releaseAge: {}
22561
+ };
22562
+ for (const name of names) if (hasTraversalSegment(name)) return yield* Effect.fail(new CatalogAssemblyError({
22563
+ source: "hooks",
22564
+ path: name,
22565
+ cause: /* @__PURE__ */ new Error(`config dependency name has a '..' path segment: ${name}`)
22566
+ }));
22567
+ const command = ChildProcess.make("node", [
22568
+ "--input-type=module",
22569
+ "-e",
22570
+ REPLAY_SCRIPT,
22571
+ root,
22572
+ JSON.stringify(seed),
22573
+ ...names
22574
+ ]);
22575
+ const payload = yield* Run.jsonLine(command, ReplayPayload, { timeout: REPLAY_TIMEOUT }).pipe(Effect.provideService(ChildProcessSpawner.ChildProcessSpawner, spawner), Effect.catch((cause) => Effect.fail(new CatalogAssemblyError({
22576
+ source: "hooks",
22577
+ path: root,
22578
+ cause
22579
+ }))));
22580
+ if (payload.ok === false) return yield* Effect.fail(new CatalogAssemblyError({
22581
+ source: "hooks",
22582
+ path: payload.name ?? root,
22583
+ cause: replayFailureCause(payload)
22584
+ }));
22585
+ const config = configOf(payload.config, seedToConfig(seed));
22586
+ return {
22587
+ catalogs: configToEntries(config),
22588
+ releaseAge: releaseAgeOf(config)
22589
+ };
22590
+ }) };
22591
+ }));
21223
22592
  };
21224
22593
 
21225
22594
  //#endregion
21226
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/PackageManagerName.js
22595
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/PackageManagerName.js
21227
22596
  /**
21228
22597
  * The four package managers this package understands.
21229
22598
  *
@@ -21552,7 +22921,7 @@ var PackageManagerDetector = class PackageManagerDetector extends Context.Servic
21552
22921
  };
21553
22922
 
21554
22923
  //#endregion
21555
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/LockfileReader.js
22924
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/LockfileReader.js
21556
22925
  /**
21557
22926
  * Raised when the workspace's lockfile cannot be read off disk.
21558
22927
  *
@@ -21733,7 +23102,7 @@ var LockfileReader = class LockfileReader extends Context.Service()("@effected/w
21733
23102
  };
21734
23103
 
21735
23104
  //#endregion
21736
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Publishability.js
23105
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Publishability.js
21737
23106
  /** The public npm registry, used when `publishConfig.registry` says nothing. */
21738
23107
  const DEFAULT_REGISTRY = "https://registry.npmjs.org/";
21739
23108
  /**
@@ -21893,7 +23262,7 @@ var PublishabilityDetector = class extends Context.Service()("@effected/workspac
21893
23262
  };
21894
23263
 
21895
23264
  //#endregion
21896
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/importerVersions.js
23265
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/internal/importerVersions.js
21897
23266
  /**
21898
23267
  * Strip pnpm's peer-disambiguation suffix from a recorded importer version.
21899
23268
  *
@@ -21980,7 +23349,7 @@ const unanimousVersionOf = (index, dependency) => {
21980
23349
  };
21981
23350
 
21982
23351
  //#endregion
21983
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceCatalogs.js
23352
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceCatalogs.js
21984
23353
  /**
21985
23354
  * An immutable, fully-normalized catalog collection — the one catalog
21986
23355
  * resolution semantic in the package.
@@ -22401,6 +23770,24 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends Context.Service()("@effe
22401
23770
  */
22402
23771
  static layerWithConfigDependencies = (options) => Layer.effect(WorkspaceCatalogs, WorkspaceCatalogs.make(options)).pipe(Layer.provide(ConfigDependencyHooks.layerLive));
22403
23772
  /**
23773
+ * The opt-in layer that replays config-dependency `pnpmfile` hooks in a
23774
+ * `node` **child process**: it wires
23775
+ * {@link ConfigDependencyHooks.layerSubprocess} in place of the in-process
23776
+ * `layerLive`.
23777
+ *
23778
+ * @remarks
23779
+ * Same typed semantics as {@link WorkspaceCatalogs.layerWithConfigDependencies}
23780
+ * — the two hook layers are drop-in interchangeable — but the replay's
23781
+ * computed dynamic `import()` runs in the subprocess, so it survives bundling
23782
+ * (a bundler compiles a computed in-process `import()` into a context module
23783
+ * that cannot resolve at runtime — every bundled GitHub Action hits this).
23784
+ * The cost is one extra requirement: core's `ChildProcessSpawner`, provided
23785
+ * once at the edge (`@effect/platform-node`'s `NodeServices.layer`) — the
23786
+ * same sanctioned R-widening as `Workspaces.layerWithGit`. Parameterized, so
23787
+ * bind it to a `const` and reuse it.
23788
+ */
23789
+ static layerWithConfigDependenciesSubprocess = (options) => Layer.effect(WorkspaceCatalogs, WorkspaceCatalogs.make(options)).pipe(Layer.provide(ConfigDependencyHooks.layerSubprocess));
23790
+ /**
22404
23791
  * A test double satisfying the full {@link WorkspaceCatalogsShape} with no
22405
23792
  * filesystem, lockfile read, or hook replay.
22406
23793
  *
@@ -22477,9 +23864,9 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends Context.Service()("@effe
22477
23864
  * consumers to `_tag`-sniff `unknown`); only the remaining mechanism failure,
22478
23865
  * an unfindable workspace root, is wrapped as `DependencyResolutionError`.
22479
23866
  */
22480
- static catalogResolver = Layer.effect(CatalogResolver, Effect.gen(function* () {
23867
+ static catalogResolver = Layer.effect(CatalogResolver$1, Effect.gen(function* () {
22481
23868
  const catalogs = yield* WorkspaceCatalogs;
22482
- return { rangeOf: (packageName, catalog) => catalogs.set().pipe(Effect.map((set) => set.rangeOf(packageName, catalog)), Effect.catchTag("WorkspaceRootNotFoundError", (cause) => Effect.fail(new DependencyResolutionError({
23869
+ return { rangeOf: (packageName, catalog) => catalogs.set().pipe(Effect.map((set) => set.rangeOf(packageName, catalog)), Effect.catchTag("WorkspaceRootNotFoundError", (cause) => Effect.fail(new DependencyResolutionError$1({
22483
23870
  specifier: Option.match(catalog, {
22484
23871
  onNone: () => "catalog:",
22485
23872
  onSome: (name) => `catalog:${name}`
@@ -22490,7 +23877,7 @@ var WorkspaceCatalogs = class WorkspaceCatalogs extends Context.Service()("@effe
22490
23877
  };
22491
23878
 
22492
23879
  //#endregion
22493
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
23880
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceStateSnapshot.js
22494
23881
  const EMPTY = Object.freeze(Object.create(null));
22495
23882
  const DependencyMap = Schema.Record(Schema.String, Schema.String).pipe(Schema.withDecodingDefaultKey(Effect.succeed(EMPTY)), Schema.withConstructorDefault(Effect.succeed(EMPTY)));
22496
23883
  /**
@@ -22669,7 +24056,7 @@ var WorkspaceStateSnapshot = class extends Schema.Class("WorkspaceStateSnapshot"
22669
24056
  * resolving to `Option.none()` so the caller falls back to the raw string.
22670
24057
  */
22671
24058
  #resolveWith(dependency, specifier, onUnresolvedCatalog) {
22672
- const exit = Schema.decodeUnknownExit(DependencySpecifier.FromString)(specifier);
24059
+ const exit = Schema.decodeUnknownExit(DependencySpecifier$1.FromString)(specifier);
22673
24060
  if (!Exit.isSuccess(exit)) return Option.none();
22674
24061
  const classified = exit.value;
22675
24062
  switch (classified._tag) {
@@ -22694,7 +24081,7 @@ var WorkspaceStateSnapshot = class extends Schema.Class("WorkspaceStateSnapshot"
22694
24081
  * `rangeOf` never fails.
22695
24082
  */
22696
24083
  get catalogResolver() {
22697
- if (this.#catalogResolver === void 0) this.#catalogResolver = Layer.succeed(CatalogResolver, { rangeOf: (packageName, catalog) => Effect.succeed(this.catalogs.rangeOf(packageName, catalog)) });
24084
+ if (this.#catalogResolver === void 0) this.#catalogResolver = Layer.succeed(CatalogResolver$1, { rangeOf: (packageName, catalog) => Effect.succeed(this.catalogs.rangeOf(packageName, catalog)) });
22698
24085
  return this.#catalogResolver;
22699
24086
  }
22700
24087
  /**
@@ -22703,7 +24090,7 @@ var WorkspaceStateSnapshot = class extends Schema.Class("WorkspaceStateSnapshot"
22703
24090
  * `workspace:` specifiers as of this ref. Built once per instance and cached.
22704
24091
  */
22705
24092
  get workspaceResolver() {
22706
- if (this.#workspaceResolver === void 0) this.#workspaceResolver = Layer.succeed(WorkspaceResolver, { versionOf: (packageName) => Effect.succeed(Option.fromUndefinedOr(this.#versions().get(packageName))) });
24093
+ if (this.#workspaceResolver === void 0) this.#workspaceResolver = Layer.succeed(WorkspaceResolver$1, { versionOf: (packageName) => Effect.succeed(Option.fromUndefinedOr(this.#versions().get(packageName))) });
22707
24094
  return this.#workspaceResolver;
22708
24095
  }
22709
24096
  /** Both snapshot-scoped resolver layers merged. Built once per instance and cached. */
@@ -22714,7 +24101,7 @@ var WorkspaceStateSnapshot = class extends Schema.Class("WorkspaceStateSnapshot"
22714
24101
  };
22715
24102
 
22716
24103
  //#endregion
22717
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceSnapshots.js
24104
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/WorkspaceSnapshots.js
22718
24105
  /** Whether `value` is a non-null, non-array object. */
22719
24106
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
22720
24107
  /** Whether every value in a record is a string — a usable dependency map. */
@@ -22992,7 +24379,7 @@ var WorkspaceSnapshots = class WorkspaceSnapshots extends Context.Service()("@ef
22992
24379
  };
22993
24380
 
22994
24381
  //#endregion
22995
- //#region ../../node_modules/.pnpm/@effected+workspaces@0.9.5_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Workspaces.js
24382
+ //#region ../../node_modules/.pnpm/@effected+workspaces@0.10.0_@effected+jsonc@0.5.2_effect@4.0.0-beta.101__effect@4.0.0-beta.101/node_modules/@effected/workspaces/Workspaces.js
22996
24383
  const compose = (options, catalogsFactory) => {
22997
24384
  const roots = WorkspaceRoot.layer;
22998
24385
  const detector = PackageManagerDetector.layer;
@@ -23009,6 +24396,7 @@ const layerWithGit = (options) => {
23009
24396
  };
23010
24397
  const resolvers = Layer.mergeAll(WorkspaceCatalogs.catalogResolver, WorkspaceDiscovery.workspaceResolver);
23011
24398
  const layerWithConfigDependencies = (options) => compose(options, WorkspaceCatalogs.layerWithConfigDependencies);
24399
+ const layerWithConfigDependenciesSubprocess = (options) => compose(options, WorkspaceCatalogs.layerWithConfigDependenciesSubprocess);
23012
24400
  const resolverLayer = (options) => resolvers.pipe(Layer.provide(layerWithConfigDependencies(options)));
23013
24401
  const resolveManifest = Effect.fn("Workspaces.resolveManifest")(function* (manifest, options) {
23014
24402
  return yield* manifest.resolve().pipe(Effect.provide(resolverLayer(options)));
@@ -23090,6 +24478,32 @@ var Workspaces = class {
23090
24478
  */
23091
24479
  static layerWithConfigDependencies = layerWithConfigDependencies;
23092
24480
  /**
24481
+ * The git-free composite with config-dependency hook replay in a `node`
24482
+ * **child process** —
24483
+ * {@link WorkspaceCatalogs.layerWithConfigDependenciesSubprocess} in place of
24484
+ * the in-process replay.
24485
+ *
24486
+ * @remarks
24487
+ * Same typed semantics as {@link Workspaces.layerWithConfigDependencies}; the
24488
+ * difference is mechanism, and it matters in exactly one environment class: a
24489
+ * **bundled** consumer. The in-process replay's computed dynamic `import()`
24490
+ * is compiled by bundlers (rspack among them) into a context module that
24491
+ * throws `Cannot find module 'file:///…'` at runtime, which makes
24492
+ * `WorkspaceCatalogs.releaseAgeGate()` unreachable from any bundled GitHub
24493
+ * Action. Here the computed import runs inside a `node` child process whose
24494
+ * program text is a static string handed over argv, so nothing computed
24495
+ * enters the bundle graph.
24496
+ *
24497
+ * The extra requirement is core's `ChildProcessSpawner`, provided once at
24498
+ * the edge (`@effect/platform-node`'s `NodeServices.layer`) — the same
24499
+ * sanctioned R-widening as {@link Workspaces.layerWithGit}, and the reason
24500
+ * this is a separate composite rather than a flag: a consumer that keeps the
24501
+ * in-process replay should not have to be able to spawn a subprocess.
24502
+ *
24503
+ * **Bind the result to a `const`.**
24504
+ */
24505
+ static layerWithConfigDependenciesSubprocess = layerWithConfigDependenciesSubprocess;
24506
+ /**
23093
24507
  * The git-free composite plus {@link ChangeDetector} and
23094
24508
  * {@link WorkspaceSnapshots}, over `@effected/git`'s `Git` service.
23095
24509
  *