@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.
- package/changesets-changelog.cjs +1708 -396
- package/changesets-changelog.d.cts +254 -32
- package/changesets-changelog.d.ts +254 -32
- package/changesets-changelog.js +2682 -1268
- package/changesets-markdownlint.cjs +1708 -396
- package/changesets-markdownlint.d.cts +254 -32
- package/changesets-markdownlint.d.ts +254 -32
- package/changesets-markdownlint.js +2682 -1268
- package/package.json +4 -4
- package/tsconfig/node/dist/tsconfig.tsbuildinfo +1 -1
package/changesets-changelog.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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$
|
|
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$
|
|
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$
|
|
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.
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
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$
|
|
4349
|
-
isLocal,
|
|
4350
|
-
isLink,
|
|
4351
|
-
isPortal,
|
|
4352
|
-
isCatalog,
|
|
4353
|
-
isWorkspace,
|
|
4354
|
-
catalogNameOf: catalogNameOf$
|
|
4355
|
-
resolveWorkspace,
|
|
4356
|
-
workspaceTargetOf,
|
|
4357
|
-
isValid: isValidDependencySpecifier,
|
|
4358
|
-
decode: decode$
|
|
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.
|
|
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$
|
|
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$
|
|
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.
|
|
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+
|
|
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
|
-
*
|
|
4682
|
-
*
|
|
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
|
-
*
|
|
4688
|
-
*
|
|
4689
|
-
*
|
|
4690
|
-
*
|
|
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
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
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
|
-
*
|
|
4726
|
-
*
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
|
|
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
|
-
*
|
|
4741
|
-
*
|
|
4742
|
-
*
|
|
4743
|
-
* )
|
|
4744
|
-
*
|
|
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
|
-
*
|
|
4747
|
-
*
|
|
4748
|
-
*
|
|
4749
|
-
*
|
|
4750
|
-
*
|
|
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
|
|
4757
|
-
|
|
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
|
-
*
|
|
4790
|
-
*
|
|
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
|
-
*
|
|
4797
|
-
*
|
|
4798
|
-
*
|
|
4799
|
-
*
|
|
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
|
-
*
|
|
4804
|
-
*
|
|
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
|
|
4807
|
-
return matchesExclude(name, patterns);
|
|
4808
|
-
}
|
|
4779
|
+
static apply = apply;
|
|
4809
4780
|
/**
|
|
4810
|
-
*
|
|
4811
|
-
*
|
|
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
|
-
|
|
4816
|
-
return matchesExclude(name, this.exclude);
|
|
4817
|
-
}
|
|
4785
|
+
static applyArgs = applyArgs;
|
|
4818
4786
|
/**
|
|
4819
|
-
*
|
|
4820
|
-
*
|
|
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
|
-
*
|
|
4829
|
-
*
|
|
4830
|
-
*
|
|
4831
|
-
*
|
|
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
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
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+
|
|
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
|
-
*
|
|
4804
|
+
* Raised when a captured stream exceeds its byte budget.
|
|
4852
4805
|
*
|
|
4853
4806
|
* @remarks
|
|
4854
|
-
*
|
|
4855
|
-
*
|
|
4856
|
-
*
|
|
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
|
|
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
|
-
*
|
|
4813
|
+
* Collects a byte stream into a string, failing once more than `limit` bytes
|
|
4814
|
+
* have arrived.
|
|
4891
4815
|
*
|
|
4892
4816
|
* @remarks
|
|
4893
|
-
*
|
|
4894
|
-
*
|
|
4895
|
-
*
|
|
4896
|
-
*
|
|
4897
|
-
*
|
|
4898
|
-
|
|
4899
|
-
*
|
|
4900
|
-
|
|
4901
|
-
|
|
4902
|
-
*
|
|
4903
|
-
|
|
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+
|
|
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
|
-
*
|
|
4832
|
+
* Default ceiling on captured bytes per stream (16 MiB).
|
|
4917
4833
|
*
|
|
4918
4834
|
* @remarks
|
|
4919
|
-
*
|
|
4920
|
-
*
|
|
4921
|
-
*
|
|
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
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
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
|
-
*
|
|
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
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
4979
|
-
* - `
|
|
4980
|
-
*
|
|
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
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
4991
|
-
|
|
4992
|
-
|
|
4993
|
-
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
5006
|
-
*
|
|
5007
|
-
*
|
|
5008
|
-
*
|
|
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
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
5017
|
-
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
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
|
-
*
|
|
5026
|
-
* `"package-lock.json"`, `"pnpm-lock.yaml"` or `"yarn.lock"`.
|
|
5168
|
+
* Structured running of core `ChildProcess.Command` values.
|
|
5027
5169
|
*
|
|
5028
5170
|
* @remarks
|
|
5029
|
-
*
|
|
5030
|
-
*
|
|
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
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
*
|
|
5040
|
-
*
|
|
5041
|
-
*
|
|
5042
|
-
*
|
|
5043
|
-
*
|
|
5044
|
-
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
|
|
5051
|
-
|
|
5052
|
-
|
|
5053
|
-
|
|
5054
|
-
*
|
|
5055
|
-
*
|
|
5056
|
-
*
|
|
5057
|
-
*
|
|
5058
|
-
*
|
|
5059
|
-
*
|
|
5060
|
-
*
|
|
5061
|
-
*
|
|
5062
|
-
*
|
|
5063
|
-
*
|
|
5064
|
-
*
|
|
5065
|
-
|
|
5066
|
-
|
|
5067
|
-
|
|
5068
|
-
*
|
|
5069
|
-
|
|
5070
|
-
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
}
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
*
|
|
5078
|
-
*
|
|
5079
|
-
*
|
|
5080
|
-
*
|
|
5081
|
-
*
|
|
5082
|
-
*
|
|
5083
|
-
*
|
|
5084
|
-
*
|
|
5085
|
-
*
|
|
5086
|
-
*
|
|
5087
|
-
* @
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
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
|
-
*
|
|
5100
|
-
*
|
|
5101
|
-
*
|
|
5102
|
-
*
|
|
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
|
-
* @
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
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
|
-
* @
|
|
5366
|
+
* @public
|
|
5134
5367
|
*/
|
|
5135
|
-
const
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
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
|
-
|
|
5166
|
-
|
|
5167
|
-
*
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
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
|
-
*
|
|
5199
|
-
*
|
|
5200
|
-
*
|
|
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
|
-
*
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
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
|
-
*
|
|
5217
|
-
*
|
|
5218
|
-
*
|
|
5219
|
-
* and the recursive type is handled with `Schema.suspend`.
|
|
5410
|
+
* @example
|
|
5411
|
+
* ```ts
|
|
5412
|
+
* import { ReleaseAgeGate } from "@effected/npm";
|
|
5220
5413
|
*
|
|
5221
|
-
*
|
|
5222
|
-
*
|
|
5223
|
-
*
|
|
5224
|
-
*
|
|
5225
|
-
*
|
|
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
|
-
*
|
|
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
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
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
|
-
*
|
|
5242
|
-
*
|
|
5243
|
-
*
|
|
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
|
-
*
|
|
5246
|
-
*
|
|
5247
|
-
*
|
|
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
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
|
|
5255
|
-
|
|
5256
|
-
|
|
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
|
-
*
|
|
5265
|
-
*
|
|
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
|
-
* @
|
|
5268
|
-
*
|
|
5269
|
-
*
|
|
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
|
-
|
|
5272
|
-
return
|
|
5480
|
+
static matchesExclude(name, patterns) {
|
|
5481
|
+
return matchesExclude(name, patterns);
|
|
5273
5482
|
}
|
|
5274
5483
|
/**
|
|
5275
|
-
*
|
|
5276
|
-
* `
|
|
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
|
|
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
|
-
|
|
5284
|
-
return
|
|
5489
|
+
isExcluded(name) {
|
|
5490
|
+
return matchesExclude(name, this.exclude);
|
|
5285
5491
|
}
|
|
5286
5492
|
/**
|
|
5287
|
-
*
|
|
5288
|
-
*
|
|
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
|
-
*
|
|
5291
|
-
*
|
|
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
|
-
|
|
5294
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
5311
|
-
*
|
|
5312
|
-
*
|
|
5313
|
-
*
|
|
5314
|
-
*
|
|
5315
|
-
*
|
|
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
|
-
*
|
|
5318
|
-
* explicit `undefined` (a present `undefined` would create an own property
|
|
5319
|
-
* that `make` would have rejected).
|
|
5551
|
+
* @public
|
|
5320
5552
|
*/
|
|
5321
|
-
|
|
5322
|
-
|
|
5323
|
-
|
|
5324
|
-
|
|
5325
|
-
|
|
5326
|
-
|
|
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.
|
|
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
|
-
*
|
|
5564
|
+
* One workspace importer's declared dependencies, as the lockfile records them.
|
|
5378
5565
|
*
|
|
5379
|
-
* @
|
|
5380
|
-
*
|
|
5381
|
-
*
|
|
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
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5393
|
-
|
|
5394
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
*
|
|
14231
|
-
*
|
|
14232
|
-
* ahead of the lockfile
|
|
14233
|
-
*
|
|
14234
|
-
*
|
|
14235
|
-
*
|
|
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
|
-
*
|
|
14238
|
-
* `
|
|
14239
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
14244
|
-
|
|
14245
|
-
|
|
14246
|
-
|
|
14247
|
-
|
|
14248
|
-
|
|
14249
|
-
|
|
14250
|
-
|
|
14251
|
-
|
|
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
|
|
14254
|
-
|
|
14255
|
-
|
|
14256
|
-
|
|
14257
|
-
|
|
14258
|
-
|
|
14259
|
-
|
|
14260
|
-
|
|
14261
|
-
|
|
14262
|
-
|
|
14263
|
-
|
|
14264
|
-
|
|
14265
|
-
|
|
14266
|
-
|
|
14267
|
-
|
|
14268
|
-
|
|
14269
|
-
|
|
14270
|
-
|
|
14271
|
-
|
|
14272
|
-
|
|
14273
|
-
|
|
14274
|
-
|
|
14275
|
-
|
|
14276
|
-
|
|
14277
|
-
|
|
14278
|
-
|
|
14279
|
-
|
|
14280
|
-
|
|
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
|
-
|
|
14283
|
-
|
|
14284
|
-
|
|
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
|
-
|
|
14288
|
-
|
|
14289
|
-
|
|
14290
|
-
|
|
14291
|
-
|
|
14292
|
-
|
|
14293
|
-
|
|
14294
|
-
|
|
14295
|
-
|
|
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
|
-
|
|
14299
|
-
|
|
14300
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
*
|
|
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
|
-
*
|
|
14348
|
-
*
|
|
14349
|
-
*
|
|
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
|
-
* @
|
|
15381
|
+
* @public
|
|
14352
15382
|
*/
|
|
14353
|
-
|
|
14354
|
-
|
|
14355
|
-
|
|
14356
|
-
|
|
14357
|
-
|
|
14358
|
-
|
|
14359
|
-
|
|
14360
|
-
|
|
14361
|
-
|
|
14362
|
-
|
|
14363
|
-
|
|
14364
|
-
|
|
14365
|
-
|
|
14366
|
-
|
|
14367
|
-
|
|
14368
|
-
|
|
14369
|
-
|
|
14370
|
-
|
|
14371
|
-
|
|
14372
|
-
|
|
14373
|
-
|
|
14374
|
-
|
|
14375
|
-
|
|
14376
|
-
|
|
14377
|
-
|
|
14378
|
-
|
|
14379
|
-
|
|
14380
|
-
|
|
14381
|
-
|
|
14382
|
-
|
|
14383
|
-
|
|
14384
|
-
|
|
14385
|
-
|
|
14386
|
-
|
|
14387
|
-
|
|
14388
|
-
|
|
14389
|
-
|
|
14390
|
-
|
|
14391
|
-
|
|
14392
|
-
|
|
14393
|
-
|
|
14394
|
-
|
|
14395
|
-
|
|
14396
|
-
|
|
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
|
-
|
|
14401
|
-
|
|
14402
|
-
|
|
14403
|
-
|
|
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
|
-
*
|
|
14409
|
-
*
|
|
14410
|
-
*
|
|
14411
|
-
*
|
|
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
|
-
* @
|
|
15522
|
+
* @public
|
|
14414
15523
|
*/
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
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
|
-
*
|
|
14428
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
14433
|
-
|
|
14434
|
-
|
|
14435
|
-
|
|
14436
|
-
|
|
14437
|
-
|
|
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
|
-
*
|
|
15559
|
+
* Contract for resolving pnpm `workspace:` dependency specifiers to concrete
|
|
15560
|
+
* versions.
|
|
14443
15561
|
*
|
|
14444
|
-
*
|
|
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
|
-
|
|
14447
|
-
|
|
14448
|
-
|
|
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+
|
|
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
|
-
*
|
|
14456
|
-
*
|
|
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
|
-
*
|
|
14467
|
-
|
|
14468
|
-
|
|
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
|
-
|
|
14473
|
-
|
|
14474
|
-
|
|
14475
|
-
|
|
14476
|
-
|
|
14477
|
-
|
|
14478
|
-
|
|
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
|
-
*
|
|
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
|
-
*
|
|
14508
|
-
*
|
|
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
|
|
14514
|
-
|
|
14515
|
-
|
|
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
|
-
|
|
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
|
|
14528
|
-
|
|
14529
|
-
|
|
14530
|
-
|
|
14531
|
-
|
|
14532
|
-
|
|
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
|
-
*
|
|
14537
|
-
*
|
|
14538
|
-
*
|
|
14539
|
-
*
|
|
14540
|
-
*
|
|
14541
|
-
|
|
14542
|
-
|
|
14543
|
-
|
|
14544
|
-
*
|
|
14545
|
-
*
|
|
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
|
-
*
|
|
14550
|
-
|
|
14551
|
-
|
|
14552
|
-
|
|
14553
|
-
|
|
14554
|
-
|
|
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
|
|
14559
|
-
|
|
14560
|
-
|
|
14561
|
-
|
|
14562
|
-
|
|
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
|
-
*
|
|
14604
|
-
*
|
|
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
|
-
*
|
|
14608
|
-
*
|
|
14609
|
-
*
|
|
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
|
|
14680
|
-
*
|
|
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
|
-
|
|
14683
|
-
|
|
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+
|
|
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
|
-
*
|
|
14700
|
-
*
|
|
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
|
-
* @
|
|
14703
|
-
|
|
14704
|
-
|
|
14705
|
-
|
|
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
|
|
14710
|
-
|
|
14711
|
-
|
|
14712
|
-
|
|
14713
|
-
|
|
14714
|
-
|
|
14715
|
-
}
|
|
14716
|
-
const
|
|
14717
|
-
const
|
|
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
|
-
*
|
|
14720
|
-
*
|
|
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
|
-
*
|
|
14724
|
-
*
|
|
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
|
-
*
|
|
14727
|
-
*
|
|
14728
|
-
*
|
|
14729
|
-
*
|
|
14730
|
-
*
|
|
14731
|
-
*
|
|
14732
|
-
*
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
*
|