@clossys/launcher 0.3.1 → 0.4.0
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/README.md +1324 -60
- package/contracts/conversation-contract.md +2 -2
- package/contracts/product-ci-workflow.yml +74 -0
- package/contracts/repository-inventory.json +53 -0
- package/dist/admission-fixture.d.ts +168 -0
- package/dist/admission-fixture.d.ts.map +1 -0
- package/dist/admission-fixture.js +453 -0
- package/dist/admission-fixture.js.map +1 -0
- package/dist/admission.d.ts +124 -0
- package/dist/admission.d.ts.map +1 -0
- package/dist/admission.js +799 -0
- package/dist/admission.js.map +1 -0
- package/dist/agents-guide.d.ts +9 -0
- package/dist/agents-guide.d.ts.map +1 -0
- package/dist/agents-guide.js +26 -0
- package/dist/agents-guide.js.map +1 -0
- package/dist/apply-command-options.check.d.ts +12 -0
- package/dist/apply-command-options.check.d.ts.map +1 -0
- package/dist/apply-command-options.check.js +20 -0
- package/dist/apply-command-options.check.js.map +1 -0
- package/dist/apply-plan-cli.d.ts +39 -1
- package/dist/apply-plan-cli.d.ts.map +1 -1
- package/dist/apply-plan-cli.js +432 -15
- package/dist/apply-plan-cli.js.map +1 -1
- package/dist/apply-plan.d.ts +46 -59
- package/dist/apply-plan.d.ts.map +1 -1
- package/dist/apply-plan.js +112 -97
- package/dist/apply-plan.js.map +1 -1
- package/dist/apply-step-fixture.d.ts +87 -0
- package/dist/apply-step-fixture.d.ts.map +1 -0
- package/dist/apply-step-fixture.js +199 -0
- package/dist/apply-step-fixture.js.map +1 -0
- package/dist/apply-store.d.ts +93 -0
- package/dist/apply-store.d.ts.map +1 -0
- package/dist/apply-store.js +625 -0
- package/dist/apply-store.js.map +1 -0
- package/dist/approval-sheet.d.ts +21 -0
- package/dist/approval-sheet.d.ts.map +1 -0
- package/dist/approval-sheet.js +157 -0
- package/dist/approval-sheet.js.map +1 -0
- package/dist/body-command.d.ts +42 -0
- package/dist/body-command.d.ts.map +1 -0
- package/dist/body-command.js +143 -0
- package/dist/body-command.js.map +1 -0
- package/dist/change-set-contract.d.ts +381 -0
- package/dist/change-set-contract.d.ts.map +1 -0
- package/dist/change-set-contract.js +738 -0
- package/dist/change-set-contract.js.map +1 -0
- package/dist/change-set-digest.d.ts +28 -0
- package/dist/change-set-digest.d.ts.map +1 -0
- package/dist/change-set-digest.js +65 -0
- package/dist/change-set-digest.js.map +1 -0
- package/dist/check-cli.d.ts.map +1 -1
- package/dist/check-cli.js +14 -3
- package/dist/check-cli.js.map +1 -1
- package/dist/cli.d.ts +17 -6
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +84 -23
- package/dist/cli.js.map +1 -1
- package/dist/core.d.ts +79 -22
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +843 -268
- package/dist/core.js.map +1 -1
- package/dist/dry-materialize.d.ts +63 -0
- package/dist/dry-materialize.d.ts.map +1 -0
- package/dist/dry-materialize.js +330 -0
- package/dist/dry-materialize.js.map +1 -0
- package/dist/generated/contract-schema.generated.d.ts +97 -0
- package/dist/generated/contract-schema.generated.d.ts.map +1 -0
- package/dist/generated/contract-schema.generated.js +496 -0
- package/dist/generated/contract-schema.generated.js.map +1 -0
- package/dist/generated/package-scope.generated.d.ts +6 -0
- package/dist/generated/package-scope.generated.d.ts.map +1 -0
- package/dist/generated/package-scope.generated.js +10 -0
- package/dist/generated/package-scope.generated.js.map +1 -0
- package/dist/generated/plan-contracts.generated.d.ts +3 -0
- package/dist/generated/plan-contracts.generated.d.ts.map +1 -0
- package/dist/generated/plan-contracts.generated.js +2840 -0
- package/dist/generated/plan-contracts.generated.js.map +1 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +11 -0
- package/dist/host.js.map +1 -1
- package/dist/identity.d.ts +15 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +48 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +34 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -2
- package/dist/index.js.map +1 -1
- package/dist/inventory-adoption.d.ts +24 -5
- package/dist/inventory-adoption.d.ts.map +1 -1
- package/dist/inventory-adoption.js +70 -25
- package/dist/inventory-adoption.js.map +1 -1
- package/dist/inventory-choice.d.ts +40 -0
- package/dist/inventory-choice.d.ts.map +1 -0
- package/dist/inventory-choice.js +156 -0
- package/dist/inventory-choice.js.map +1 -0
- package/dist/inventory-contract.d.ts +89 -0
- package/dist/inventory-contract.d.ts.map +1 -0
- package/dist/inventory-contract.js +121 -0
- package/dist/inventory-contract.js.map +1 -0
- package/dist/key-editor.d.ts +30 -0
- package/dist/key-editor.d.ts.map +1 -0
- package/dist/key-editor.js +445 -0
- package/dist/key-editor.js.map +1 -0
- package/dist/ledger-contract.d.ts +187 -0
- package/dist/ledger-contract.d.ts.map +1 -0
- package/dist/ledger-contract.js +532 -0
- package/dist/ledger-contract.js.map +1 -0
- package/dist/ledger-trust.d.ts +90 -0
- package/dist/ledger-trust.d.ts.map +1 -0
- package/dist/ledger-trust.js +198 -0
- package/dist/ledger-trust.js.map +1 -0
- package/dist/lockfile-invariants.d.ts +48 -0
- package/dist/lockfile-invariants.d.ts.map +1 -0
- package/dist/lockfile-invariants.js +375 -0
- package/dist/lockfile-invariants.js.map +1 -0
- package/dist/lockfile-readers.d.ts +72 -0
- package/dist/lockfile-readers.d.ts.map +1 -0
- package/dist/lockfile-readers.js +713 -0
- package/dist/lockfile-readers.js.map +1 -0
- package/dist/lockfile-regen.d.ts +106 -0
- package/dist/lockfile-regen.d.ts.map +1 -0
- package/dist/lockfile-regen.js +760 -0
- package/dist/lockfile-regen.js.map +1 -0
- package/dist/lockfile-tool-env.d.ts +29 -0
- package/dist/lockfile-tool-env.d.ts.map +1 -0
- package/dist/lockfile-tool-env.js +111 -0
- package/dist/lockfile-tool-env.js.map +1 -0
- package/dist/materialize.d.ts +113 -0
- package/dist/materialize.d.ts.map +1 -0
- package/dist/materialize.js +840 -0
- package/dist/materialize.js.map +1 -0
- package/dist/observe-repository.d.ts +90 -0
- package/dist/observe-repository.d.ts.map +1 -0
- package/dist/observe-repository.js +1367 -0
- package/dist/observe-repository.js.map +1 -0
- package/dist/plan-bundle-setup-fixture.d.ts +68 -0
- package/dist/plan-bundle-setup-fixture.d.ts.map +1 -0
- package/dist/plan-bundle-setup-fixture.js +167 -0
- package/dist/plan-bundle-setup-fixture.js.map +1 -0
- package/dist/plan-bundle.d.ts +250 -0
- package/dist/plan-bundle.d.ts.map +1 -0
- package/dist/plan-bundle.js +827 -0
- package/dist/plan-bundle.js.map +1 -0
- package/dist/plan-command.d.ts +29 -0
- package/dist/plan-command.d.ts.map +1 -0
- package/dist/plan-command.js +493 -0
- package/dist/plan-command.js.map +1 -0
- package/dist/plan-contract.d.ts +153 -0
- package/dist/plan-contract.d.ts.map +1 -0
- package/dist/plan-contract.js +61 -0
- package/dist/plan-contract.js.map +1 -0
- package/dist/plan-digest.d.ts +25 -0
- package/dist/plan-digest.d.ts.map +1 -0
- package/dist/plan-digest.js +106 -0
- package/dist/plan-digest.js.map +1 -0
- package/dist/plan-rules.d.ts +23 -0
- package/dist/plan-rules.d.ts.map +1 -0
- package/dist/plan-rules.js +177 -0
- package/dist/plan-rules.js.map +1 -0
- package/dist/planned-bundle.d.ts +20 -0
- package/dist/planned-bundle.d.ts.map +1 -0
- package/dist/planned-bundle.js +191 -0
- package/dist/planned-bundle.js.map +1 -0
- package/dist/product-repository.d.ts +4 -0
- package/dist/product-repository.d.ts.map +1 -1
- package/dist/product-repository.js +9 -1
- package/dist/product-repository.js.map +1 -1
- package/dist/provenance-gate.d.ts +48 -0
- package/dist/provenance-gate.d.ts.map +1 -0
- package/dist/provenance-gate.js +324 -0
- package/dist/provenance-gate.js.map +1 -0
- package/dist/pull-request-body.d.ts +45 -0
- package/dist/pull-request-body.d.ts.map +1 -0
- package/dist/pull-request-body.js +232 -0
- package/dist/pull-request-body.js.map +1 -0
- package/dist/registry-snapshot.d.ts +141 -0
- package/dist/registry-snapshot.d.ts.map +1 -0
- package/dist/registry-snapshot.js +483 -0
- package/dist/registry-snapshot.js.map +1 -0
- package/dist/release-age-edit.d.ts +52 -0
- package/dist/release-age-edit.d.ts.map +1 -0
- package/dist/release-age-edit.js +413 -0
- package/dist/release-age-edit.js.map +1 -0
- package/dist/root-entries.d.ts +36 -0
- package/dist/root-entries.d.ts.map +1 -0
- package/dist/root-entries.js +80 -0
- package/dist/root-entries.js.map +1 -0
- package/dist/setup-template-scripts.d.ts +34 -0
- package/dist/setup-template-scripts.d.ts.map +1 -0
- package/dist/setup-template-scripts.js +557 -0
- package/dist/setup-template-scripts.js.map +1 -0
- package/dist/setup-templates.d.ts +54 -0
- package/dist/setup-templates.d.ts.map +1 -0
- package/dist/setup-templates.js +427 -0
- package/dist/setup-templates.js.map +1 -0
- package/dist/skills.d.ts +34 -1
- package/dist/skills.d.ts.map +1 -1
- package/dist/skills.js +129 -17
- package/dist/skills.js.map +1 -1
- package/dist/status.d.ts +63 -0
- package/dist/status.d.ts.map +1 -0
- package/dist/status.js +539 -0
- package/dist/status.js.map +1 -0
- package/dist/types.d.ts +151 -13
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
- package/skeleton/README.md +14 -9
- package/skeleton/package.json +2 -1
- package/skill/SKILL.md +23 -7
- package/skill-catalogue/advisor/SKILL.md +59 -6
- package/skill-catalogue/architect/SKILL.md +2 -2
- package/skill-catalogue/bouncer/SKILL.md +2 -2
- package/skill-catalogue/builder/SKILL.md +2 -2
- package/skill-catalogue/butler/SKILL.md +2 -2
- package/skill-catalogue/controller/SKILL.md +2 -2
- package/skill-catalogue/customer/SKILL.md +2 -2
- package/skill-catalogue/designer/SKILL.md +4 -2
- package/skill-catalogue/giver/SKILL.md +2 -2
- package/skill-catalogue/influencer/SKILL.md +2 -2
- package/skill-catalogue/inspector/SKILL.md +2 -2
- package/skill-catalogue/integrator/SKILL.md +2 -2
- package/skill-catalogue/keeper/SKILL.md +2 -2
- package/skill-catalogue/launcher/SKILL.md +23 -7
- package/skill-catalogue/locksmith/SKILL.md +2 -2
- package/skill-catalogue/messenger/SKILL.md +2 -2
- package/skill-catalogue/observer/SKILL.md +2 -2
- package/skill-catalogue/publisher/SKILL.md +2 -2
- package/skill-catalogue/starter/SKILL.md +3 -2
- package/skill-catalogue/strategist/SKILL.md +12 -4
- package/skill-catalogue/writer/SKILL.md +2 -2
- package/src/admission-fixture.ts +572 -0
- package/src/admission.ts +816 -0
- package/src/agents-guide.ts +29 -0
- package/src/apply-command-options.check.ts +27 -0
- package/src/apply-plan-cli.ts +454 -14
- package/src/apply-plan.ts +112 -124
- package/src/apply-step-fixture.ts +236 -0
- package/src/apply-store.ts +584 -0
- package/src/approval-sheet.ts +164 -0
- package/src/body-command.ts +162 -0
- package/src/change-set-contract.ts +937 -0
- package/src/change-set-digest.ts +70 -0
- package/src/check-cli.ts +14 -3
- package/src/cli.ts +90 -22
- package/src/core.ts +973 -275
- package/src/dry-materialize.ts +353 -0
- package/src/generated/contract-schema.generated.ts +520 -0
- package/src/generated/package-scope.generated.ts +10 -0
- package/src/generated/plan-contracts.generated.ts +2840 -0
- package/src/host.ts +10 -0
- package/src/identity.ts +51 -0
- package/src/index.ts +72 -3
- package/src/inventory-adoption.ts +107 -29
- package/src/inventory-choice.ts +172 -0
- package/src/inventory-contract.ts +166 -0
- package/src/key-editor.ts +446 -0
- package/src/ledger-contract.ts +637 -0
- package/src/ledger-trust.ts +267 -0
- package/src/lockfile-invariants.ts +421 -0
- package/src/lockfile-readers.ts +749 -0
- package/src/lockfile-regen.ts +851 -0
- package/src/lockfile-tool-env.ts +131 -0
- package/src/materialize.ts +886 -0
- package/src/observe-repository.ts +1365 -0
- package/src/plan-bundle-setup-fixture.ts +200 -0
- package/src/plan-bundle.ts +964 -0
- package/src/plan-command.ts +509 -0
- package/src/plan-contract.ts +179 -0
- package/src/plan-digest.ts +102 -0
- package/src/plan-rules.ts +188 -0
- package/src/planned-bundle.ts +211 -0
- package/src/product-repository.ts +10 -1
- package/src/provenance-gate.ts +352 -0
- package/src/pull-request-body.ts +261 -0
- package/src/registry-snapshot.ts +534 -0
- package/src/release-age-edit.ts +430 -0
- package/src/root-entries.ts +81 -0
- package/src/setup-template-scripts.ts +571 -0
- package/src/setup-templates.ts +471 -0
- package/src/skills.ts +161 -18
- package/src/status.ts +557 -0
- package/src/types.ts +148 -13
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
// The registry snapshot step (issue #1178): the one step of applying a plan
|
|
2
|
+
// that reads the package registry. It fetches each requested package's registry
|
|
3
|
+
// document anonymously, projects it into the shared registry snapshot
|
|
4
|
+
// contract (docs/contracts/registry-snapshot.json, in the public repository,
|
|
5
|
+
// not shipped in this package; its content is packed into src/generated/ at
|
|
6
|
+
// build time), validates the whole snapshot against that contract, and only
|
|
7
|
+
// then writes it, atomically.
|
|
8
|
+
//
|
|
9
|
+
// Credentials: every read goes through an injected `Transport` whose default
|
|
10
|
+
// is Node's own `fetch`. Nothing here runs the npm CLI, reads an `.npmrc`,
|
|
11
|
+
// reads an environment variable, or sets an `Authorization` header; the only
|
|
12
|
+
// headers this step sets are `accept` and `accept-encoding: identity`, and
|
|
13
|
+
// Node's fetch adds its own default, non-credential headers. Identity asks
|
|
14
|
+
// for the body uncompressed, so when the server honours it the hash and the
|
|
15
|
+
// size cap apply to the bytes received. Redirects are refused (`redirect: "error"`, and a
|
|
16
|
+
// 3xx answer from any transport is refused too), each response is read as a
|
|
17
|
+
// stream and abandoned the moment it passes MAX_RESPONSE_BYTES (counted after
|
|
18
|
+
// any decoding, so a server that compresses anyway is still bounded), and each
|
|
19
|
+
// request, body included, is abandoned after a timeout.
|
|
20
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
21
|
+
import { closeSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, writeSync } from "node:fs";
|
|
22
|
+
import { basename, dirname, join } from "node:path";
|
|
23
|
+
import { ContractDocumentError, readContractDocument, validateAgainstContract } from "./generated/contract-schema.generated.js";
|
|
24
|
+
import { PACKAGE_SCOPE } from "./generated/package-scope.generated.js";
|
|
25
|
+
import { PLAN_CONTRACTS } from "./generated/plan-contracts.generated.js";
|
|
26
|
+
/** Where the snapshot is written by default, relative to the hub root. */
|
|
27
|
+
export const REGISTRY_SNAPSHOT_REL = "clossys/.state/apply/registry-snapshot.json";
|
|
28
|
+
/** The most bytes read from any one registry response (10 MiB). */
|
|
29
|
+
export const MAX_RESPONSE_BYTES = 10 * 1024 * 1024;
|
|
30
|
+
/** How long one request, its body included, may take. */
|
|
31
|
+
export const DEFAULT_TIMEOUT_MS = 30_000;
|
|
32
|
+
/** Node's own `fetch`. It reads no npm configuration and adds no registry credential (a proxy URL's own username and password, if any, go only to that proxy). */
|
|
33
|
+
export const nodeFetchTransport = (input, init) => fetch(input, init);
|
|
34
|
+
/**
|
|
35
|
+
* Why the snapshot step stopped. The message names a package only by its
|
|
36
|
+
* position in the request (`names[<n>]`), never by its name: a name is
|
|
37
|
+
* request text, and a request is a file anyone could have written. It
|
|
38
|
+
* never carries registry content either.
|
|
39
|
+
*/
|
|
40
|
+
export class RegistrySnapshotError extends Error {
|
|
41
|
+
}
|
|
42
|
+
function loadContract(name) {
|
|
43
|
+
const contract = Object.hasOwn(PLAN_CONTRACTS, name) ? PLAN_CONTRACTS[name] : undefined;
|
|
44
|
+
if (contract === undefined)
|
|
45
|
+
throw new Error(`no packed contract named ${JSON.stringify(name)}`);
|
|
46
|
+
return contract;
|
|
47
|
+
}
|
|
48
|
+
function eachRepeat(items, key, onRepeat) {
|
|
49
|
+
const first = new Map();
|
|
50
|
+
items.forEach((item, index) => {
|
|
51
|
+
const value = key(item);
|
|
52
|
+
const earlier = first.get(value);
|
|
53
|
+
if (earlier === undefined)
|
|
54
|
+
first.set(value, index);
|
|
55
|
+
else
|
|
56
|
+
onRepeat(index, earlier);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Every violation of the registry snapshot contract: its schema, then, only
|
|
61
|
+
* for a snapshot whose shape is known good, its code rules N1-N3 (no package
|
|
62
|
+
* named twice, no version recorded twice for one package, no `latest` or
|
|
63
|
+
* versions for a package that was not found). Implemented separately from
|
|
64
|
+
* @clossys/advisor's reader; both are tested against the one corpus,
|
|
65
|
+
* docs/contracts/registry-snapshot.fixture.json (in the public repository,
|
|
66
|
+
* not shipped in this package). Never throws.
|
|
67
|
+
*/
|
|
68
|
+
export function registrySnapshotViolations(value) {
|
|
69
|
+
const schema = validateAgainstContract(loadContract("registry-snapshot.json"), value, loadContract);
|
|
70
|
+
// The shared checker's path and message never carry document text: an undeclared field is placed at its object, by position.
|
|
71
|
+
if (schema.length > 0)
|
|
72
|
+
return schema.map((violation) => ({ rule: "schema", path: violation.path, message: violation.message }));
|
|
73
|
+
const snapshot = value;
|
|
74
|
+
const violations = [];
|
|
75
|
+
eachRepeat(snapshot.packages, (entry) => entry.name, (index, first) => violations.push({ rule: "N1", path: `packages[${index}].name`, message: `repeats packages[${first}].name` }));
|
|
76
|
+
snapshot.packages.forEach((entry, index) => {
|
|
77
|
+
eachRepeat(entry.versions, (version) => version.version, (position, first) => violations.push({ rule: "N2", path: `packages[${index}].versions[${position}].version`, message: `repeats packages[${index}].versions[${first}].version` }));
|
|
78
|
+
if (entry.status === "not-found") {
|
|
79
|
+
if (entry.latest !== null)
|
|
80
|
+
violations.push({ rule: "N3", path: `packages[${index}].latest`, message: "must be null when the package was not found" });
|
|
81
|
+
if (entry.versions.length > 0)
|
|
82
|
+
violations.push({ rule: "N3", path: `packages[${index}].versions`, message: "must be empty when the package was not found" });
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
return violations;
|
|
86
|
+
}
|
|
87
|
+
/** Compares strings as sequences of UTF-16 code units, the order the snapshot contract sorts by. */
|
|
88
|
+
function byCodeUnits(left, right) {
|
|
89
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
90
|
+
}
|
|
91
|
+
/** The snapshot in the contract's canonical order: packages sorted by name, each package's versions sorted by version. */
|
|
92
|
+
export function canonicalRegistrySnapshot(snapshot) {
|
|
93
|
+
return {
|
|
94
|
+
...snapshot,
|
|
95
|
+
packages: [...snapshot.packages]
|
|
96
|
+
.sort((left, right) => byCodeUnits(left.name, right.name))
|
|
97
|
+
.map((entry) => ({ ...entry, versions: [...entry.versions].sort((left, right) => byCodeUnits(left.version, right.version)) })),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* A package name's registry path segment. Copied, unchanged, from
|
|
102
|
+
* `registryEncodedName` in @clossys/integrator's provenance-check.ts, which
|
|
103
|
+
* this package must not depend on at runtime; a test compares the two
|
|
104
|
+
* function bodies so they cannot drift apart. The leading `@` stays literal
|
|
105
|
+
* and only the slash is percent-encoded (`@scope%2Fname`), the convention
|
|
106
|
+
* npm-compatible registries share; `encodeURIComponent` on the whole name
|
|
107
|
+
* would also encode the `@`, which none of them expect.
|
|
108
|
+
*/
|
|
109
|
+
export function registryEncodedName(name) {
|
|
110
|
+
const slash = name.indexOf("/");
|
|
111
|
+
if (slash === -1)
|
|
112
|
+
return encodeURIComponent(name);
|
|
113
|
+
return `@${encodeURIComponent(name.slice(1, slash))}%2F${encodeURIComponent(name.slice(slash + 1))}`;
|
|
114
|
+
}
|
|
115
|
+
/** The full registry document's URL for `name`: `{registry}/{encoded name}`. */
|
|
116
|
+
export function packumentUrl(registry, name) {
|
|
117
|
+
return new URL(registryEncodedName(name), registry.endsWith("/") ? registry : `${registry}/`);
|
|
118
|
+
}
|
|
119
|
+
const PACKAGE_NAME = new RegExp(loadContract("registry-snapshot.json").definitions.packageName.pattern);
|
|
120
|
+
/**
|
|
121
|
+
* The package names in a snapshot request: the report `advisor-package-request`
|
|
122
|
+
* prints, `{ state: "satisfied", names, findings: [] }`, or just `{ names }`.
|
|
123
|
+
* Every name must be a scoped package name in the packed publishing scope,
|
|
124
|
+
* named once. A refusal names positions only, never the request's text.
|
|
125
|
+
*/
|
|
126
|
+
export function requestedPackageNames(request, scope = PACKAGE_SCOPE.scope) {
|
|
127
|
+
if (typeof request !== "object" || request === null || Array.isArray(request))
|
|
128
|
+
throw new RegistrySnapshotError("the request must be a JSON object with a names array");
|
|
129
|
+
const record = request;
|
|
130
|
+
if (Object.keys(record).some((key) => key !== "state" && key !== "names" && key !== "findings")) {
|
|
131
|
+
throw new RegistrySnapshotError("the request has a field other than state, names and findings");
|
|
132
|
+
}
|
|
133
|
+
if (Object.hasOwn(record, "state") && record.state !== "satisfied") {
|
|
134
|
+
throw new RegistrySnapshotError("the request's state is not satisfied: fix the plan and run advisor-package-request again");
|
|
135
|
+
}
|
|
136
|
+
if (Object.hasOwn(record, "findings") && !(Array.isArray(record.findings) && record.findings.length === 0)) {
|
|
137
|
+
throw new RegistrySnapshotError("the request's findings must be an empty array");
|
|
138
|
+
}
|
|
139
|
+
const names = Object.hasOwn(record, "names") ? record.names : undefined;
|
|
140
|
+
if (!Array.isArray(names) || names.length === 0)
|
|
141
|
+
throw new RegistrySnapshotError("the request's names must be a non-empty array");
|
|
142
|
+
const seen = new Map();
|
|
143
|
+
for (let index = 0; index < names.length; index += 1) {
|
|
144
|
+
if (!Object.hasOwn(names, index))
|
|
145
|
+
throw new RegistrySnapshotError(`names[${index}] is missing`);
|
|
146
|
+
const name = names[index];
|
|
147
|
+
if (typeof name !== "string" || !PACKAGE_NAME.test(name) || !name.startsWith(`${scope}/`)) {
|
|
148
|
+
throw new RegistrySnapshotError(`names[${index}] is not a package name in the ${scope} scope`);
|
|
149
|
+
}
|
|
150
|
+
const earlier = seen.get(name);
|
|
151
|
+
if (earlier !== undefined)
|
|
152
|
+
throw new RegistrySnapshotError(`names[${index}] repeats names[${earlier}]`);
|
|
153
|
+
seen.set(name, index);
|
|
154
|
+
}
|
|
155
|
+
return names;
|
|
156
|
+
}
|
|
157
|
+
/** A registry document that cannot be projected. `what` is fixed text, never the document's. */
|
|
158
|
+
class PackumentShapeError extends Error {
|
|
159
|
+
}
|
|
160
|
+
function isPlainObject(value) {
|
|
161
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
162
|
+
}
|
|
163
|
+
/** An own member only: a registry document's inherited members are never read. */
|
|
164
|
+
function own(record, key) {
|
|
165
|
+
return Object.hasOwn(record, key) ? record[key] : undefined;
|
|
166
|
+
}
|
|
167
|
+
/** An own member that must be a plain object when present; absent or null reads as undefined. */
|
|
168
|
+
function optionalObject(record, key, what) {
|
|
169
|
+
const value = own(record, key);
|
|
170
|
+
if (value === undefined || value === null)
|
|
171
|
+
return undefined;
|
|
172
|
+
if (!isPlainObject(value))
|
|
173
|
+
throw new PackumentShapeError(what);
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
function optionalString(record, key, what) {
|
|
177
|
+
const value = own(record, key);
|
|
178
|
+
if (value === undefined || value === null)
|
|
179
|
+
return null;
|
|
180
|
+
if (typeof value !== "string")
|
|
181
|
+
throw new PackumentShapeError(what);
|
|
182
|
+
return value;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Projects a registry document into one snapshot entry's `latest` and
|
|
186
|
+
* `versions`, reading only what the contract records: the version the
|
|
187
|
+
* `latest` dist-tag names, and that one version's integrity, tarball,
|
|
188
|
+
* deprecation, publish time and attestation presence. Every other version,
|
|
189
|
+
* dist-tag and field is ignored. When `latest` names a version the document
|
|
190
|
+
* does not list, `versions` is empty, so a resolver refuses it by name.
|
|
191
|
+
*/
|
|
192
|
+
export function projectPackument(name, document) {
|
|
193
|
+
if (!isPlainObject(document))
|
|
194
|
+
throw new PackumentShapeError("is not a JSON object");
|
|
195
|
+
if (own(document, "name") !== name)
|
|
196
|
+
throw new PackumentShapeError("does not name the package that was requested");
|
|
197
|
+
const distTags = optionalObject(document, "dist-tags", "has dist-tags that are not an object");
|
|
198
|
+
const latest = distTags === undefined ? null : optionalString(distTags, "latest", "has a latest dist-tag that is not a string");
|
|
199
|
+
if (latest === null)
|
|
200
|
+
return { latest: null, versions: [] };
|
|
201
|
+
const versions = optionalObject(document, "versions", "has versions that are not an object");
|
|
202
|
+
const entry = versions === undefined ? undefined : own(versions, latest);
|
|
203
|
+
if (entry === undefined)
|
|
204
|
+
return { latest, versions: [] };
|
|
205
|
+
if (!isPlainObject(entry))
|
|
206
|
+
throw new PackumentShapeError("lists the latest version as something that is not an object");
|
|
207
|
+
if (own(entry, "version") !== latest)
|
|
208
|
+
throw new PackumentShapeError("lists the latest version under a different version number");
|
|
209
|
+
const dist = optionalObject(entry, "dist", "has a latest version whose dist is not an object") ?? {};
|
|
210
|
+
const tarball = own(dist, "tarball");
|
|
211
|
+
if (typeof tarball !== "string")
|
|
212
|
+
throw new PackumentShapeError("has a latest version with no tarball URL");
|
|
213
|
+
const deprecation = own(entry, "deprecated");
|
|
214
|
+
let deprecated;
|
|
215
|
+
if (deprecation === undefined || deprecation === null)
|
|
216
|
+
deprecated = false;
|
|
217
|
+
else if (typeof deprecation === "boolean")
|
|
218
|
+
deprecated = deprecation;
|
|
219
|
+
// npm treats an empty deprecation message as no deprecation, and any other message as one.
|
|
220
|
+
else if (typeof deprecation === "string")
|
|
221
|
+
deprecated = deprecation !== "";
|
|
222
|
+
else
|
|
223
|
+
throw new PackumentShapeError("marks the latest version deprecated with something that is neither text nor a boolean");
|
|
224
|
+
const attestations = own(dist, "attestations");
|
|
225
|
+
if (attestations !== undefined && attestations !== null && !isPlainObject(attestations)) {
|
|
226
|
+
throw new PackumentShapeError("has latest-version attestations that are not an object");
|
|
227
|
+
}
|
|
228
|
+
const time = optionalObject(document, "time", "has a time field that is not an object");
|
|
229
|
+
return {
|
|
230
|
+
latest,
|
|
231
|
+
versions: [
|
|
232
|
+
{
|
|
233
|
+
version: latest,
|
|
234
|
+
integrity: optionalString(dist, "integrity", "has a latest-version integrity that is not a string"),
|
|
235
|
+
tarball,
|
|
236
|
+
deprecated,
|
|
237
|
+
publishedAt: time === undefined ? null : optionalString(time, latest, "has a latest-version publish time that is not a string"),
|
|
238
|
+
// Listed only when the registry names where the attestations are: an empty object lists none.
|
|
239
|
+
hasAttestations: isPlainObject(attestations) && typeof own(attestations, "url") === "string" && /\S/.test(own(attestations, "url")),
|
|
240
|
+
},
|
|
241
|
+
],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
const TIMED_OUT = Symbol("timed out");
|
|
245
|
+
/** Settles with `promise`, or rejects with TIMED_OUT as soon as `signal` aborts, whether or not the transport honours the signal. */
|
|
246
|
+
function untilAborted(promise, signal) {
|
|
247
|
+
if (signal.aborted)
|
|
248
|
+
return Promise.reject(TIMED_OUT);
|
|
249
|
+
return new Promise((resolve, reject) => {
|
|
250
|
+
const onAbort = () => reject(TIMED_OUT);
|
|
251
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
252
|
+
promise.then((value) => {
|
|
253
|
+
signal.removeEventListener("abort", onAbort);
|
|
254
|
+
resolve(value);
|
|
255
|
+
}, (error) => {
|
|
256
|
+
signal.removeEventListener("abort", onAbort);
|
|
257
|
+
reject(error);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* The body's bytes, read chunk by chunk. The read stops, and the stream is
|
|
263
|
+
* cancelled, the moment the running total passes `cap`, so an oversize body
|
|
264
|
+
* is never buffered past it.
|
|
265
|
+
*/
|
|
266
|
+
async function readCapped(body, cap, signal) {
|
|
267
|
+
if (body === null)
|
|
268
|
+
return new Uint8Array(0);
|
|
269
|
+
const reader = body.getReader();
|
|
270
|
+
const chunks = [];
|
|
271
|
+
let total = 0;
|
|
272
|
+
try {
|
|
273
|
+
for (;;) {
|
|
274
|
+
const { done, value } = await untilAborted(reader.read(), signal);
|
|
275
|
+
if (done)
|
|
276
|
+
break;
|
|
277
|
+
if (!(value instanceof Uint8Array))
|
|
278
|
+
throw new TypeError("a response chunk is not bytes");
|
|
279
|
+
total += value.byteLength;
|
|
280
|
+
if (total > cap)
|
|
281
|
+
return "too-large";
|
|
282
|
+
chunks.push(value);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
finally {
|
|
286
|
+
reader.cancel().catch(() => undefined);
|
|
287
|
+
}
|
|
288
|
+
const bytes = new Uint8Array(total);
|
|
289
|
+
let offset = 0;
|
|
290
|
+
for (const chunk of chunks) {
|
|
291
|
+
bytes.set(chunk, offset);
|
|
292
|
+
offset += chunk.byteLength;
|
|
293
|
+
}
|
|
294
|
+
return bytes;
|
|
295
|
+
}
|
|
296
|
+
/**
|
|
297
|
+
* The request options this step sets on every registry read: `accept`, and
|
|
298
|
+
* `accept-encoding: identity` so that a server that honours it sends the body
|
|
299
|
+
* uncompressed and `responseSha256` and the size cap apply to the exact bytes
|
|
300
|
+
* received; no credential, no redirect. Node's fetch adds its own default,
|
|
301
|
+
* non-credential headers.
|
|
302
|
+
*/
|
|
303
|
+
function requestInit(signal) {
|
|
304
|
+
return { method: "GET", headers: { accept: "application/json", "accept-encoding": "identity" }, redirect: "error", credentials: "omit", signal };
|
|
305
|
+
}
|
|
306
|
+
async function fetchOne(transport, url, where, timeoutMs) {
|
|
307
|
+
const controller = new AbortController();
|
|
308
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
309
|
+
const seconds = `${timeoutMs / 1000} s`;
|
|
310
|
+
try {
|
|
311
|
+
let response;
|
|
312
|
+
try {
|
|
313
|
+
response = await untilAborted(transport(url, requestInit(controller.signal)), controller.signal);
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
if (controller.signal.aborted)
|
|
317
|
+
throw new RegistrySnapshotError(`${where}: the registry did not answer within ${seconds}`);
|
|
318
|
+
throw new RegistrySnapshotError(`${where}: the registry could not be reached, or answered with a redirect, which is refused`);
|
|
319
|
+
}
|
|
320
|
+
const { status } = response;
|
|
321
|
+
const discard = () => {
|
|
322
|
+
response.body?.cancel().catch(() => undefined);
|
|
323
|
+
};
|
|
324
|
+
if (response.redirected || (status >= 300 && status < 400)) {
|
|
325
|
+
discard();
|
|
326
|
+
throw new RegistrySnapshotError(`${where}: the registry answered with a redirect${response.redirected ? "" : ` (HTTP ${status})`}, which is refused and never followed`);
|
|
327
|
+
}
|
|
328
|
+
if (status !== 200 && status !== 404) {
|
|
329
|
+
discard();
|
|
330
|
+
throw new RegistrySnapshotError(`${where}: the registry answered HTTP ${status}; only 200 and 404 are recorded`);
|
|
331
|
+
}
|
|
332
|
+
const tooLarge = `${where}: the registry's response is larger than ${MAX_RESPONSE_BYTES / (1024 * 1024)} MiB and was not read past that`;
|
|
333
|
+
const declared = response.headers.get("content-length");
|
|
334
|
+
if (declared !== null && /^\d+$/.test(declared.trim()) && Number(declared.trim()) > MAX_RESPONSE_BYTES) {
|
|
335
|
+
discard();
|
|
336
|
+
throw new RegistrySnapshotError(tooLarge);
|
|
337
|
+
}
|
|
338
|
+
let bytes;
|
|
339
|
+
try {
|
|
340
|
+
bytes = await readCapped(response.body, MAX_RESPONSE_BYTES, controller.signal);
|
|
341
|
+
}
|
|
342
|
+
catch {
|
|
343
|
+
if (controller.signal.aborted)
|
|
344
|
+
throw new RegistrySnapshotError(`${where}: the registry did not finish its response within ${seconds}`);
|
|
345
|
+
throw new RegistrySnapshotError(`${where}: the registry's response could not be read`);
|
|
346
|
+
}
|
|
347
|
+
if (bytes === "too-large")
|
|
348
|
+
throw new RegistrySnapshotError(tooLarge);
|
|
349
|
+
return { status, bytes };
|
|
350
|
+
}
|
|
351
|
+
finally {
|
|
352
|
+
clearTimeout(timer);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function strictJsonReason(cause) {
|
|
356
|
+
if (!(cause instanceof ContractDocumentError))
|
|
357
|
+
return "is not strict JSON";
|
|
358
|
+
const where = cause.position === undefined ? "" : ` at position ${cause.position}`;
|
|
359
|
+
const why = cause.reason === "encoding" ? "is not valid UTF-8" : cause.reason === "repeated-key" ? "repeats a key in one object" : "is not valid JSON";
|
|
360
|
+
return `${why}${where}`;
|
|
361
|
+
}
|
|
362
|
+
let ownIdentity;
|
|
363
|
+
/** This package's own name and version, from the package.json it ships with. */
|
|
364
|
+
function launcherIdentity() {
|
|
365
|
+
if (ownIdentity === undefined) {
|
|
366
|
+
const manifest = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
367
|
+
if (typeof manifest.name !== "string" || typeof manifest.version !== "string")
|
|
368
|
+
throw new RegistrySnapshotError("this package's own package.json has no name and version");
|
|
369
|
+
ownIdentity = { name: manifest.name, version: manifest.version };
|
|
370
|
+
}
|
|
371
|
+
return ownIdentity;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Fetches every named package's full registry document, one at a time, and
|
|
375
|
+
* returns the snapshot in canonical order, validated against the contract.
|
|
376
|
+
* Throws RegistrySnapshotError, having fetched no further, on the first
|
|
377
|
+
* package whose read fails: a transport error, a timeout, a redirect, an
|
|
378
|
+
* answer other than 200 or 404, a body over MAX_RESPONSE_BYTES, a 200 body
|
|
379
|
+
* that is not strict JSON or not a registry document for that package, or a
|
|
380
|
+
* projection the contract refuses. A 404 records `status: "not-found"`.
|
|
381
|
+
* `names` must already have passed `requestedPackageNames()`.
|
|
382
|
+
*/
|
|
383
|
+
export async function takeRegistrySnapshot(names, options = {}) {
|
|
384
|
+
const transport = options.transport ?? nodeFetchTransport;
|
|
385
|
+
const { registry } = PACKAGE_SCOPE;
|
|
386
|
+
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
387
|
+
const fetchedBy = options.fetchedBy ?? launcherIdentity();
|
|
388
|
+
const ordered = names.map((name, index) => ({ name, index })).sort((left, right) => byCodeUnits(left.name, right.name));
|
|
389
|
+
const packages = [];
|
|
390
|
+
for (const { name, index } of ordered) {
|
|
391
|
+
// The position only: the name itself is request text.
|
|
392
|
+
const where = `names[${index}]`;
|
|
393
|
+
const { status, bytes } = await fetchOne(transport, packumentUrl(registry, name), where, timeoutMs);
|
|
394
|
+
const responseSha256 = `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
|
|
395
|
+
if (status === 404) {
|
|
396
|
+
packages.push({ name, status: "not-found", latest: null, versions: [], responseSha256 });
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
let document;
|
|
400
|
+
try {
|
|
401
|
+
document = readContractDocument(bytes);
|
|
402
|
+
}
|
|
403
|
+
catch (cause) {
|
|
404
|
+
throw new RegistrySnapshotError(`${where}: the registry's response ${strictJsonReason(cause)}`);
|
|
405
|
+
}
|
|
406
|
+
try {
|
|
407
|
+
packages.push({ name, status: "found", ...projectPackument(name, document), responseSha256 });
|
|
408
|
+
}
|
|
409
|
+
catch (cause) {
|
|
410
|
+
if (cause instanceof PackumentShapeError)
|
|
411
|
+
throw new RegistrySnapshotError(`${where}: the registry's document ${cause.message}`);
|
|
412
|
+
throw cause;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
const snapshot = canonicalRegistrySnapshot({
|
|
416
|
+
schemaVersion: 1,
|
|
417
|
+
kind: "clossys.registry-snapshot",
|
|
418
|
+
registry,
|
|
419
|
+
fetchedAt: (options.now ?? (() => new Date().toISOString()))(),
|
|
420
|
+
fetchedBy: { name: fetchedBy.name, version: fetchedBy.version },
|
|
421
|
+
packages,
|
|
422
|
+
});
|
|
423
|
+
assertValidSnapshot(snapshot);
|
|
424
|
+
return snapshot;
|
|
425
|
+
}
|
|
426
|
+
function assertValidSnapshot(value) {
|
|
427
|
+
const violations = registrySnapshotViolations(value);
|
|
428
|
+
if (violations.length > 0) {
|
|
429
|
+
const listed = violations.map((violation) => `snapshot${violation.path === "" ? "" : violation.path.startsWith("[") ? violation.path : `.${violation.path}`} ${violation.message} (rule ${violation.rule})`);
|
|
430
|
+
throw new RegistrySnapshotError(`the snapshot does not validate against the registry snapshot contract, so none is written: ${listed.join("; ")}`);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/** The snapshot's file text: two-space JSON with a final newline, in the order given. */
|
|
434
|
+
export function serializeRegistrySnapshot(snapshot) {
|
|
435
|
+
return `${JSON.stringify(snapshot, null, 2)}\n`;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* Writes `text` to `path` so that a reader sees the old file or the whole
|
|
439
|
+
* new one, never part of it: the bytes go to a new temporary file in the same
|
|
440
|
+
* directory, are flushed to disk, and the temporary file is then renamed over
|
|
441
|
+
* `path`. On any failure the temporary file is removed and `path` is left as
|
|
442
|
+
* it was.
|
|
443
|
+
*/
|
|
444
|
+
export function writeFileAtomically(path, text) {
|
|
445
|
+
const directory = dirname(path);
|
|
446
|
+
mkdirSync(directory, { recursive: true });
|
|
447
|
+
const temporary = join(directory, `.${basename(path)}.${randomBytes(8).toString("hex")}.tmp`);
|
|
448
|
+
const bytes = Buffer.from(text, "utf8");
|
|
449
|
+
let descriptor;
|
|
450
|
+
try {
|
|
451
|
+
descriptor = openSync(temporary, "wx", 0o644);
|
|
452
|
+
let written = 0;
|
|
453
|
+
while (written < bytes.length)
|
|
454
|
+
written += writeSync(descriptor, bytes, written, bytes.length - written);
|
|
455
|
+
fsyncSync(descriptor);
|
|
456
|
+
closeSync(descriptor);
|
|
457
|
+
descriptor = undefined;
|
|
458
|
+
renameSync(temporary, path);
|
|
459
|
+
}
|
|
460
|
+
catch (cause) {
|
|
461
|
+
if (descriptor !== undefined) {
|
|
462
|
+
try {
|
|
463
|
+
closeSync(descriptor);
|
|
464
|
+
}
|
|
465
|
+
catch {
|
|
466
|
+
// Already failing; the original error is the one reported.
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
rmSync(temporary, { force: true });
|
|
470
|
+
throw cause;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Serializes a snapshot, re-reads that exact text strictly and validates it
|
|
475
|
+
* against the contract, and only then writes it atomically to `path`. The
|
|
476
|
+
* bytes on disk are therefore exactly the bytes that validated.
|
|
477
|
+
*/
|
|
478
|
+
export function writeRegistrySnapshot(path, snapshot) {
|
|
479
|
+
const text = serializeRegistrySnapshot(snapshot);
|
|
480
|
+
assertValidSnapshot(readContractDocument(Buffer.from(text, "utf8")));
|
|
481
|
+
writeFileAtomically(path, text);
|
|
482
|
+
}
|
|
483
|
+
//# sourceMappingURL=registry-snapshot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry-snapshot.js","sourceRoot":"","sources":["../src/registry-snapshot.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type ExemptionSurfaceKind } from "./change-set-contract.js";
|
|
2
|
+
export type ReleaseAgeEditRefusalReason = "release-age-surface-unparseable" | "release-age-surface-conflict";
|
|
3
|
+
/** The outcome of editing: the new text, nothing to do, or a refusal that leaves the file alone. */
|
|
4
|
+
export type ReleaseAgeEdit = {
|
|
5
|
+
readonly kind: "edited";
|
|
6
|
+
readonly text: string;
|
|
7
|
+
} | {
|
|
8
|
+
readonly kind: "unchanged";
|
|
9
|
+
} | {
|
|
10
|
+
readonly kind: "refused";
|
|
11
|
+
readonly reason: ReleaseAgeEditRefusalReason;
|
|
12
|
+
};
|
|
13
|
+
export interface ReleaseAgeEditInput {
|
|
14
|
+
readonly surface: ExemptionSurfaceKind;
|
|
15
|
+
/** The surface file's text, or null when the file does not exist. */
|
|
16
|
+
readonly text: string | null;
|
|
17
|
+
/** The repository's .npmrc text (null or absent: none); read for the pnpm surface only. */
|
|
18
|
+
readonly npmrc?: string | null;
|
|
19
|
+
}
|
|
20
|
+
export interface ReleaseAgeVerifyInput {
|
|
21
|
+
readonly surface: ExemptionSurfaceKind;
|
|
22
|
+
readonly before: string | null;
|
|
23
|
+
readonly after: string;
|
|
24
|
+
readonly npmrc?: string | null;
|
|
25
|
+
}
|
|
26
|
+
/** Verified only when `after` is `before` plus exactly the one scope entry; `value` is the ledger entries row value. */
|
|
27
|
+
export type ReleaseAgeVerdict = {
|
|
28
|
+
readonly verified: true;
|
|
29
|
+
readonly value: string;
|
|
30
|
+
} | {
|
|
31
|
+
readonly verified: false;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Adds the scope entry to the surface's exemption list. A missing file or key
|
|
35
|
+
* is created or appended with a two-space list; an existing block sequence
|
|
36
|
+
* gains one line after its last item, in its own indent, and nothing else
|
|
37
|
+
* changes. An already-present entry is unchanged. Refuses a pnpm `.npmrc`
|
|
38
|
+
* that sets the same list (conflict) or has any line outside the fixed safe
|
|
39
|
+
* grammar (unparseable), and any file the restricted reader does not fully
|
|
40
|
+
* recognise (flow lists, comments inside the list, anchors, aliases, tags,
|
|
41
|
+
* block scalars, multiple documents, tabs, CRLF, repeated keys, and more).
|
|
42
|
+
*/
|
|
43
|
+
export declare function editReleaseAgeExemption(input: ReleaseAgeEditInput): ReleaseAgeEdit;
|
|
44
|
+
/**
|
|
45
|
+
* Whether `after` is `before` plus exactly the one scope entry, judged by its
|
|
46
|
+
* own structural comparison of the two texts (and, as a second check, by the
|
|
47
|
+
* edit function reproducing `after`). The entry must sit after the last
|
|
48
|
+
* existing item, in the list's indent and the surface's quoting, with every
|
|
49
|
+
* other byte, including the final newline, unchanged.
|
|
50
|
+
*/
|
|
51
|
+
export declare function verifyReleaseAgeExemption(input: ReleaseAgeVerifyInput): ReleaseAgeVerdict;
|
|
52
|
+
//# sourceMappingURL=release-age-edit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"release-age-edit.d.ts","sourceRoot":"","sources":["../src/release-age-edit.ts"],"names":[],"mappings":"AAUA,OAAO,EAAsB,KAAK,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAGzF,MAAM,MAAM,2BAA2B,GAAG,iCAAiC,GAAG,8BAA8B,CAAC;AAE7G,oGAAoG;AACpG,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;CAAE,CAAC;AAE/E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,oBAAoB,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wHAAwH;AACxH,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAA;CAAE,CAAC;AAmUnH;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,mBAAmB,GAAG,cAAc,CAkBlF;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,qBAAqB,GAAG,iBAAiB,CAgCzF"}
|