@wavehouse/chtypes 0.5.2 → 1.0.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/CHANGELOG.md +34 -0
- package/README.md +34 -38
- package/dist/abi1/buildinfo.d.ts +40 -0
- package/dist/abi1/buildinfo.d.ts.map +1 -0
- package/dist/abi1/buildinfo.js +83 -0
- package/dist/abi1/buildinfo.js.map +1 -0
- package/dist/abi1/calls.gen.d.ts +55 -0
- package/dist/abi1/calls.gen.d.ts.map +1 -0
- package/dist/abi1/calls.gen.js +110 -0
- package/dist/abi1/calls.gen.js.map +1 -0
- package/dist/abi1/decls.gen.d.ts +115 -0
- package/dist/abi1/decls.gen.d.ts.map +1 -0
- package/dist/abi1/decls.gen.js +1613 -0
- package/dist/abi1/decls.gen.js.map +1 -0
- package/dist/abi1/errmap.gen.d.ts +18 -0
- package/dist/abi1/errmap.gen.d.ts.map +1 -0
- package/dist/abi1/errmap.gen.js +66 -0
- package/dist/abi1/errmap.gen.js.map +1 -0
- package/dist/abi1/errors.d.ts +107 -0
- package/dist/abi1/errors.d.ts.map +1 -0
- package/dist/abi1/errors.js +134 -0
- package/dist/abi1/errors.js.map +1 -0
- package/dist/abi1/handles.d.ts +31 -0
- package/dist/abi1/handles.d.ts.map +1 -0
- package/dist/abi1/handles.js +76 -0
- package/dist/abi1/handles.js.map +1 -0
- package/dist/abi1/index.d.ts +17 -0
- package/dist/abi1/index.d.ts.map +1 -0
- package/dist/abi1/index.js +17 -0
- package/dist/abi1/index.js.map +1 -0
- package/dist/abi1/libc.d.ts +54 -0
- package/dist/abi1/libc.d.ts.map +1 -0
- package/dist/abi1/libc.gen.d.ts +12 -0
- package/dist/abi1/libc.gen.d.ts.map +1 -0
- package/dist/abi1/libc.gen.js +75 -0
- package/dist/abi1/libc.gen.js.map +1 -0
- package/dist/abi1/libc.js +109 -0
- package/dist/abi1/libc.js.map +1 -0
- package/dist/abi1/loader.d.ts +101 -0
- package/dist/abi1/loader.d.ts.map +1 -0
- package/dist/abi1/loader.js +274 -0
- package/dist/abi1/loader.js.map +1 -0
- package/dist/abi1/raw.d.ts +104 -0
- package/dist/abi1/raw.d.ts.map +1 -0
- package/dist/abi1/raw.js +296 -0
- package/dist/abi1/raw.js.map +1 -0
- package/dist/abi1/strictjson.d.ts +19 -0
- package/dist/abi1/strictjson.d.ts.map +1 -0
- package/dist/abi1/strictjson.js +78 -0
- package/dist/abi1/strictjson.js.map +1 -0
- package/dist/abi1/vocab.gen.d.ts +169 -0
- package/dist/abi1/vocab.gen.d.ts.map +1 -0
- package/dist/abi1/vocab.gen.js +306 -0
- package/dist/abi1/vocab.gen.js.map +1 -0
- package/dist/cli.d.ts +25 -26
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +206 -218
- package/dist/cli.js.map +1 -1
- package/dist/documents.d.ts +195 -0
- package/dist/documents.d.ts.map +1 -0
- package/dist/documents.js +389 -0
- package/dist/documents.js.map +1 -0
- package/dist/env.d.ts +16 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +57 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +19 -24
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +17 -23
- package/dist/index.js.map +1 -1
- package/dist/json.d.ts +11 -89
- package/dist/json.d.ts.map +1 -1
- package/dist/json.js +16 -180
- package/dist/json.js.map +1 -1
- package/dist/library.d.ts +53 -309
- package/dist/library.d.ts.map +1 -1
- package/dist/library.js +77 -315
- package/dist/library.js.map +1 -1
- package/dist/ocifetch/constants.gen.d.ts +84 -0
- package/dist/ocifetch/constants.gen.d.ts.map +1 -0
- package/dist/ocifetch/constants.gen.js +92 -0
- package/dist/ocifetch/constants.gen.js.map +1 -0
- package/dist/ocifetch/dsse.d.ts +114 -0
- package/dist/ocifetch/dsse.d.ts.map +1 -0
- package/dist/ocifetch/dsse.js +331 -0
- package/dist/ocifetch/dsse.js.map +1 -0
- package/dist/ocifetch/ensure.d.ts +65 -0
- package/dist/ocifetch/ensure.d.ts.map +1 -0
- package/dist/ocifetch/ensure.js +775 -0
- package/dist/ocifetch/ensure.js.map +1 -0
- package/dist/ocifetch/errors.d.ts +92 -0
- package/dist/ocifetch/errors.d.ts.map +1 -0
- package/dist/ocifetch/errors.js +101 -0
- package/dist/ocifetch/errors.js.map +1 -0
- package/dist/ocifetch/goldens.d.ts +44 -0
- package/dist/ocifetch/goldens.d.ts.map +1 -0
- package/dist/ocifetch/goldens.js +62 -0
- package/dist/ocifetch/goldens.js.map +1 -0
- package/dist/ocifetch/http.d.ts +124 -0
- package/dist/ocifetch/http.d.ts.map +1 -0
- package/dist/ocifetch/http.js +549 -0
- package/dist/ocifetch/http.js.map +1 -0
- package/dist/ocifetch/index.d.ts +17 -0
- package/dist/ocifetch/index.d.ts.map +1 -0
- package/dist/ocifetch/index.js +14 -0
- package/dist/ocifetch/index.js.map +1 -0
- package/dist/ocifetch/layout.d.ts +126 -0
- package/dist/ocifetch/layout.d.ts.map +1 -0
- package/dist/ocifetch/layout.js +375 -0
- package/dist/ocifetch/layout.js.map +1 -0
- package/dist/ocifetch/localverify.d.ts +43 -0
- package/dist/ocifetch/localverify.d.ts.map +1 -0
- package/dist/ocifetch/localverify.js +164 -0
- package/dist/ocifetch/localverify.js.map +1 -0
- package/dist/ocifetch/lock.d.ts +39 -0
- package/dist/ocifetch/lock.d.ts.map +1 -0
- package/dist/ocifetch/lock.js +140 -0
- package/dist/ocifetch/lock.js.map +1 -0
- package/dist/ocifetch/oci.d.ts +100 -0
- package/dist/ocifetch/oci.d.ts.map +1 -0
- package/dist/ocifetch/oci.js +323 -0
- package/dist/ocifetch/oci.js.map +1 -0
- package/dist/ocifetch/referrers.d.ts +55 -0
- package/dist/ocifetch/referrers.d.ts.map +1 -0
- package/dist/ocifetch/referrers.js +132 -0
- package/dist/ocifetch/referrers.js.map +1 -0
- package/dist/ocifetch/types.d.ts +167 -0
- package/dist/ocifetch/types.d.ts.map +1 -0
- package/dist/ocifetch/types.js +88 -0
- package/dist/ocifetch/types.js.map +1 -0
- package/dist/ocifetch/unpack.d.ts +55 -0
- package/dist/ocifetch/unpack.d.ts.map +1 -0
- package/dist/ocifetch/unpack.js +205 -0
- package/dist/ocifetch/unpack.js.map +1 -0
- package/dist/registry.d.ts +38 -387
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +95 -819
- package/dist/registry.js.map +1 -1
- package/dist/schema.d.ts +77 -588
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +87 -549
- package/dist/schema.js.map +1 -1
- package/dist/settings.d.ts +27 -36
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +75 -25
- package/dist/settings.js.map +1 -1
- package/dist/setup.d.ts +46 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +79 -0
- package/dist/setup.js.map +1 -0
- package/dist/tar.d.ts +27 -11
- package/dist/tar.d.ts.map +1 -1
- package/dist/tar.js +54 -32
- package/dist/tar.js.map +1 -1
- package/package.json +2 -2
- package/dist/discover.d.ts +0 -142
- package/dist/discover.d.ts.map +0 -1
- package/dist/discover.js +0 -288
- package/dist/discover.js.map +0 -1
- package/dist/error-codes.d.ts +0 -80
- package/dist/error-codes.d.ts.map +0 -1
- package/dist/error-codes.js +0 -139
- package/dist/error-codes.js.map +0 -1
- package/dist/errors.d.ts +0 -284
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -321
- package/dist/errors.js.map +0 -1
- package/dist/fetch.d.ts +0 -382
- package/dist/fetch.d.ts.map +0 -1
- package/dist/fetch.js +0 -1498
- package/dist/fetch.js.map +0 -1
- package/dist/ffi.d.ts +0 -410
- package/dist/ffi.d.ts.map +0 -1
- package/dist/ffi.js +0 -1154
- package/dist/ffi.js.map +0 -1
- package/dist/format.d.ts +0 -128
- package/dist/format.d.ts.map +0 -1
- package/dist/format.js +0 -132
- package/dist/format.js.map +0 -1
- package/dist/numeric.d.ts +0 -20
- package/dist/numeric.d.ts.map +0 -1
- package/dist/numeric.js +0 -107
- package/dist/numeric.js.map +0 -1
- package/dist/paths.d.ts +0 -55
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.js +0 -87
- package/dist/paths.js.map +0 -1
- package/dist/results.d.ts +0 -495
- package/dist/results.d.ts.map +0 -1
- package/dist/results.js +0 -406
- package/dist/results.js.map +0 -1
- package/dist/transform.d.ts +0 -73
- package/dist/transform.d.ts.map +0 -1
- package/dist/transform.js +0 -533
- package/dist/transform.js.map +0 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the v1 fetch layer: the seam (`docs/guides/fetch-v1.md`
|
|
3
|
+
* §9, the v1 fetch-layer plan's §1.3) and the pieces behind it. Nothing
|
|
4
|
+
* outside this module imports from anywhere but `index.ts`.
|
|
5
|
+
*/
|
|
6
|
+
import { PLATFORMS } from './constants.gen.js';
|
|
7
|
+
/**
|
|
8
|
+
* Every `GET …/manifests/<ref>` — by tag or by digest — sends this `Accept`
|
|
9
|
+
* header (the delivery side's review): our own host ignores it, but a
|
|
10
|
+
* mirror may need it to answer with the right media type, and a mirror can
|
|
11
|
+
* be asked for a manifest exactly as our host can.
|
|
12
|
+
*/
|
|
13
|
+
export declare const MANIFEST_ACCEPT_HEADER: string;
|
|
14
|
+
/** One of the three platform keys v1 ships: no darwin-amd64 (A18). */
|
|
15
|
+
export type PlatformKey = (typeof PLATFORMS)[number]['key'];
|
|
16
|
+
/** True for exactly the three v1 platform keys. */
|
|
17
|
+
export declare function isPlatformKey(value: string): value is PlatformKey;
|
|
18
|
+
/** `PLATFORMS`'s row for one key — never `undefined` for a `PlatformKey`. */
|
|
19
|
+
export declare function platformInfo(key: PlatformKey): {
|
|
20
|
+
readonly key: PlatformKey;
|
|
21
|
+
readonly os: string;
|
|
22
|
+
readonly architecture: string;
|
|
23
|
+
};
|
|
24
|
+
/** This host's platform key, or `undefined` when v1 does not ship this os/arch (e.g. darwin-amd64). */
|
|
25
|
+
export declare function hostPlatformKey(osName: string, archName: string): PlatformKey | undefined;
|
|
26
|
+
/** A version request exactly as given: `"26.8"`, `"26.8.15"` or `"26.8.15.10"`. */
|
|
27
|
+
export type VersionRequest = string;
|
|
28
|
+
/** The digests of every object a resolve touched, as the guide's `Resolved` names them. */
|
|
29
|
+
export interface ResolvedDigests {
|
|
30
|
+
readonly index?: string;
|
|
31
|
+
readonly manifest: string;
|
|
32
|
+
readonly layer: string;
|
|
33
|
+
readonly bundle: string;
|
|
34
|
+
readonly bundleManifest?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The signed predicate (`layout-v2.md` §4.1), verified and carried through
|
|
38
|
+
* **verbatim** — the fetch layer never interprets `abi_fingerprint`,
|
|
39
|
+
* `library_sha256`, `library_bytes` or `glibc_floor` beyond the checks
|
|
40
|
+
* `docs/guides/fetch-v1.md` §4 and §5 name.
|
|
41
|
+
*/
|
|
42
|
+
export interface ArtifactPredicate {
|
|
43
|
+
readonly abi: number;
|
|
44
|
+
readonly abi_fingerprint: string;
|
|
45
|
+
readonly clickhouse_version: string;
|
|
46
|
+
readonly channel: string;
|
|
47
|
+
readonly clickhouse_minor: string;
|
|
48
|
+
readonly clickhouse_commit: string;
|
|
49
|
+
readonly os: string;
|
|
50
|
+
readonly arch: string;
|
|
51
|
+
readonly build: string;
|
|
52
|
+
readonly core_commit: string;
|
|
53
|
+
readonly inputs_sha256: string;
|
|
54
|
+
readonly library: string;
|
|
55
|
+
readonly library_sha256: string;
|
|
56
|
+
readonly library_bytes: number;
|
|
57
|
+
readonly glibc_floor?: string;
|
|
58
|
+
}
|
|
59
|
+
/** An in-toto Statement v1, decoded and duplicate-key-checked (`dsse.ts`). */
|
|
60
|
+
export interface Statement {
|
|
61
|
+
readonly _type: string;
|
|
62
|
+
readonly subject: readonly {
|
|
63
|
+
readonly name: string;
|
|
64
|
+
readonly digest: {
|
|
65
|
+
readonly sha256: string;
|
|
66
|
+
};
|
|
67
|
+
}[];
|
|
68
|
+
readonly predicateType: string;
|
|
69
|
+
/** Opaque beyond what `dsse.ts` itself checks; callers of `fetchSigned` read this themselves. */
|
|
70
|
+
readonly predicate: Readonly<Record<string, unknown>>;
|
|
71
|
+
}
|
|
72
|
+
/** One verified Sigstore bundle's outcome, inside `verifyAnyBundle`. */
|
|
73
|
+
export interface VerifiedBundle {
|
|
74
|
+
readonly statement: Statement;
|
|
75
|
+
/** The trusted key id that verified it. */
|
|
76
|
+
readonly signedBy: string;
|
|
77
|
+
readonly bundleDigest: string;
|
|
78
|
+
}
|
|
79
|
+
/** What a fetch returns on success (`docs/guides/fetch-v1.md` §9). */
|
|
80
|
+
export interface Resolved {
|
|
81
|
+
readonly abiGeneration: 1;
|
|
82
|
+
readonly platform: PlatformKey;
|
|
83
|
+
readonly request: VersionRequest;
|
|
84
|
+
readonly version: string;
|
|
85
|
+
readonly channel?: string;
|
|
86
|
+
readonly build: string;
|
|
87
|
+
/** Absolute path to the unpacked library file. */
|
|
88
|
+
readonly libraryPath: string;
|
|
89
|
+
/** `<layout>/unpacked/sha256/<manifest-hex>`. */
|
|
90
|
+
readonly dir: string;
|
|
91
|
+
readonly digests: ResolvedDigests;
|
|
92
|
+
readonly predicate: ArtifactPredicate;
|
|
93
|
+
/** The key id that verified the signature, or `""` under allow-unsigned. */
|
|
94
|
+
readonly signedBy: string;
|
|
95
|
+
/** A base URL, `"cache"`, or `"system:<dir>"`. */
|
|
96
|
+
readonly source: string;
|
|
97
|
+
readonly alreadyInstalled: boolean;
|
|
98
|
+
readonly warnings: readonly string[];
|
|
99
|
+
}
|
|
100
|
+
/** One `verify_installed` row. */
|
|
101
|
+
export interface VerifyResult {
|
|
102
|
+
readonly platform: PlatformKey;
|
|
103
|
+
readonly dir: string;
|
|
104
|
+
readonly ok: boolean;
|
|
105
|
+
readonly detail: string;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Test-only injection point (plan §3.2 "Sleeps are asserted exactly"): every
|
|
109
|
+
* binding's fetch core takes an injected `sleep(seconds)` and `now()` so
|
|
110
|
+
* retry cases run instantly and deterministically. Production code uses
|
|
111
|
+
* `realClock()`.
|
|
112
|
+
*/
|
|
113
|
+
export interface Clock {
|
|
114
|
+
now(): number;
|
|
115
|
+
sleep(seconds: number): Promise<void>;
|
|
116
|
+
}
|
|
117
|
+
export declare function realClock(): Clock;
|
|
118
|
+
export interface TrustedKey {
|
|
119
|
+
readonly keyid: string;
|
|
120
|
+
readonly ed25519Hex: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Options shared by every seam entry point. All optional; every default
|
|
124
|
+
* matches `docs/guides/fetch-v1.md`.
|
|
125
|
+
*/
|
|
126
|
+
export interface FetchV1Options {
|
|
127
|
+
/** Overrides `DEFAULT_BASES` / `CHTYPES_ARTIFACTS_URL`, in order. */
|
|
128
|
+
readonly bases?: readonly string[];
|
|
129
|
+
/** Overrides the OCI layout root (`CHTYPES_CACHE`). */
|
|
130
|
+
readonly cacheDir?: string;
|
|
131
|
+
/** Overrides `SYSTEM_CACHE_DIRS`. */
|
|
132
|
+
readonly systemDirs?: readonly string[];
|
|
133
|
+
/** Replaces (never appends to) the default trust list. */
|
|
134
|
+
readonly trustedKeys?: readonly TrustedKey[];
|
|
135
|
+
readonly allowUnsigned?: boolean;
|
|
136
|
+
/** Sent as `Authorization: Bearer <token>` to configured base hosts only. */
|
|
137
|
+
readonly token?: string;
|
|
138
|
+
/** `resolve_installed`'s mode for `ensure`: cache/system dirs only, no network. */
|
|
139
|
+
readonly offline?: boolean;
|
|
140
|
+
/** Skip resolution; fetch the lock's pinned digests directly. */
|
|
141
|
+
readonly frozen?: boolean;
|
|
142
|
+
/** Path to the lock file (`LOCK_DEFAULT_FILE` under the caller's cwd by default). */
|
|
143
|
+
readonly lockPath?: string;
|
|
144
|
+
/** Write (or update) the lock after a successful `ensure`. */
|
|
145
|
+
readonly lockWrite?: boolean;
|
|
146
|
+
/** Every platform the index offers, not only the host's — `lockWrite` only. */
|
|
147
|
+
readonly lockAllPlatforms?: boolean;
|
|
148
|
+
/** Re-resolve every locked request and rewrite the lock, ignoring `frozen`. */
|
|
149
|
+
readonly update?: boolean;
|
|
150
|
+
/** Overrides the host platform (tests, and a cross-platform lock write). */
|
|
151
|
+
readonly platform?: PlatformKey;
|
|
152
|
+
readonly clock?: Clock;
|
|
153
|
+
/** Test-only: runs after the index's temp-write, before its atomic rename. */
|
|
154
|
+
readonly beforeIndexRename?: () => Promise<void> | void;
|
|
155
|
+
/** Test-only: an explicit `now()`-relative deadline is not used; retries read `clock`. */
|
|
156
|
+
readonly httpLog?: (event: Readonly<Record<string, unknown>>) => void;
|
|
157
|
+
}
|
|
158
|
+
/** Thrown-safe helper: the exact platform this call targets. */
|
|
159
|
+
export declare function resolvePlatformOption(option: PlatformKey | undefined, osName: string, archName: string): PlatformKey;
|
|
160
|
+
/** Every digest in this module is `sha256:<64 hex>` (OCI's own spelling); this is the one place that parses it. */
|
|
161
|
+
export declare function hexOfDigest(digest: string): string;
|
|
162
|
+
/** `<hex>` back to `sha256:<hex>`. */
|
|
163
|
+
export declare function digestOfHex(hex: string): string;
|
|
164
|
+
export declare function trimTrailingSlash(s: string): string;
|
|
165
|
+
/** `${repositoryRoot}${suffix}` with the OCI `/v2` segment inserted for http(s), never for `file:`. */
|
|
166
|
+
export declare function endpointUrl(repositoryRoot: string, suffix: string): string;
|
|
167
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/ocifetch/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the v1 fetch layer: the seam (`docs/guides/fetch-v1.md`
|
|
3
|
+
* §9, the v1 fetch-layer plan's §1.3) and the pieces behind it. Nothing
|
|
4
|
+
* outside this module imports from anywhere but `index.ts`.
|
|
5
|
+
*/
|
|
6
|
+
import { MEDIA_TYPE_INDEX, MEDIA_TYPE_MANIFEST, PLATFORMS } from './constants.gen.js';
|
|
7
|
+
/**
|
|
8
|
+
* Every `GET …/manifests/<ref>` — by tag or by digest — sends this `Accept`
|
|
9
|
+
* header (the delivery side's review): our own host ignores it, but a
|
|
10
|
+
* mirror may need it to answer with the right media type, and a mirror can
|
|
11
|
+
* be asked for a manifest exactly as our host can.
|
|
12
|
+
*/
|
|
13
|
+
export const MANIFEST_ACCEPT_HEADER = `${MEDIA_TYPE_INDEX}, ${MEDIA_TYPE_MANIFEST}`;
|
|
14
|
+
/** True for exactly the three v1 platform keys. */
|
|
15
|
+
export function isPlatformKey(value) {
|
|
16
|
+
return PLATFORMS.some((p) => p.key === value);
|
|
17
|
+
}
|
|
18
|
+
/** `PLATFORMS`'s row for one key — never `undefined` for a `PlatformKey`. */
|
|
19
|
+
export function platformInfo(key) {
|
|
20
|
+
const row = PLATFORMS.find((p) => p.key === key);
|
|
21
|
+
if (row === undefined)
|
|
22
|
+
throw new Error(`chtypes: unreachable: ${key} is not in PLATFORMS`);
|
|
23
|
+
return row;
|
|
24
|
+
}
|
|
25
|
+
/** This host's platform key, or `undefined` when v1 does not ship this os/arch (e.g. darwin-amd64). */
|
|
26
|
+
export function hostPlatformKey(osName, archName) {
|
|
27
|
+
const arch = archName === 'x64' ? 'amd64' : archName;
|
|
28
|
+
const key = `${osName}-${arch}`;
|
|
29
|
+
return isPlatformKey(key) ? key : undefined;
|
|
30
|
+
}
|
|
31
|
+
export function realClock() {
|
|
32
|
+
return {
|
|
33
|
+
now: () => Date.now(),
|
|
34
|
+
sleep: (seconds) => new Promise((resolve) => {
|
|
35
|
+
setTimeout(resolve, Math.max(0, seconds) * 1000);
|
|
36
|
+
}),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/** Thrown-safe helper: the exact platform this call targets. */
|
|
40
|
+
export function resolvePlatformOption(option, osName, archName) {
|
|
41
|
+
if (option !== undefined)
|
|
42
|
+
return option;
|
|
43
|
+
const host = hostPlatformKey(osName, archName);
|
|
44
|
+
if (host === undefined) {
|
|
45
|
+
throw new Error(`chtypes: this host (${osName}-${archName}) is not one of v1's platforms (${PLATFORMS
|
|
46
|
+
.map((p) => p.key)
|
|
47
|
+
.join(', ')})`);
|
|
48
|
+
}
|
|
49
|
+
return host;
|
|
50
|
+
}
|
|
51
|
+
/** Every digest in this module is `sha256:<64 hex>` (OCI's own spelling); this is the one place that parses it. */
|
|
52
|
+
export function hexOfDigest(digest) {
|
|
53
|
+
const [algo, hex] = digest.split(':', 2);
|
|
54
|
+
if (algo !== 'sha256' || hex === undefined || !/^[0-9a-f]{64}$/.test(hex)) {
|
|
55
|
+
throw new Error(`chtypes: not a sha256 digest: ${JSON.stringify(digest)}`);
|
|
56
|
+
}
|
|
57
|
+
return hex;
|
|
58
|
+
}
|
|
59
|
+
/** `<hex>` back to `sha256:<hex>`. */
|
|
60
|
+
export function digestOfHex(hex) {
|
|
61
|
+
return `sha256:${hex}`;
|
|
62
|
+
}
|
|
63
|
+
// --------------------------------------------------------------- URL shape
|
|
64
|
+
//
|
|
65
|
+
// A "repository root" (what `docs/guides/fetch-v1.md` §2 calls a base, and
|
|
66
|
+
// what the generic `fetchSigned` seam calls `repository`) is one string that
|
|
67
|
+
// already carries the registry origin AND the repository path, e.g.
|
|
68
|
+
// `https://registry.wavehouse.dev/chtypes/v1` — exactly `DEFAULT_BASES`'
|
|
69
|
+
// own spelling, with no `/v2` segment. The real OCI distribution path DOES
|
|
70
|
+
// carry `/v2/` (`oras`/`docker` insert it from a plain `host/repo:tag`
|
|
71
|
+
// reference the same way), so an http(s) root gets `/v2` spliced in between
|
|
72
|
+
// its origin and its own path. A `file://` root is different on purpose: the
|
|
73
|
+
// fixture trees are static mirrors of the real URL paths *including* the
|
|
74
|
+
// literal `v2` directory, so nothing is inserted — see
|
|
75
|
+
// `tests/fixtures/fetch-v1/trees/*/v2/...` (lane 0B) once it exists.
|
|
76
|
+
export function trimTrailingSlash(s) {
|
|
77
|
+
return s.endsWith('/') ? s.slice(0, -1) : s;
|
|
78
|
+
}
|
|
79
|
+
/** `${repositoryRoot}${suffix}` with the OCI `/v2` segment inserted for http(s), never for `file:`. */
|
|
80
|
+
export function endpointUrl(repositoryRoot, suffix) {
|
|
81
|
+
const root = trimTrailingSlash(repositoryRoot);
|
|
82
|
+
if (root.startsWith('file:'))
|
|
83
|
+
return `${root}${suffix}`;
|
|
84
|
+
const u = new URL(root);
|
|
85
|
+
const repoPath = trimTrailingSlash(u.pathname);
|
|
86
|
+
return `${u.origin}/v2${repoPath}${suffix}`;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ocifetch/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bytes and unpack (`docs/guides/fetch-v1.md` §5): download the layer to a
|
|
3
|
+
* temp file **while hashing**, verify size and sha256 against the manifest's
|
|
4
|
+
* own layer descriptor **before any decompression**, zstd-decode (multi-frame
|
|
5
|
+
* accepted, a window log past the limit refused before a frame's decoder
|
|
6
|
+
* commits to it), unpack with the tightened v1 tar rules (`../tar.ts`'s
|
|
7
|
+
* `extractTarStream`: regular files and directories only, no duplicate entry
|
|
8
|
+
* names, a hard cap on total unpacked bytes), then re-hash the installed
|
|
9
|
+
* library against the signed predicate.
|
|
10
|
+
*
|
|
11
|
+
* **Multi-frame zstd needs its own loop here — measured, not assumed.**
|
|
12
|
+
* Node's built-in `zlib.createZstdDecompress()` (and `zstdDecompressSync`)
|
|
13
|
+
* decode only the **first** frame of a concatenated multi-frame stream and
|
|
14
|
+
* then stop silently (no error, no second frame): verified on this Mac
|
|
15
|
+
* (Node 22.23.2) by concatenating two independently-produced zstd frames and
|
|
16
|
+
* observing the decoder emit only the first frame's content, with
|
|
17
|
+
* `bytesWritten` on the stream reporting exactly the first frame's
|
|
18
|
+
* compressed length. `bytesWritten` is therefore how many input bytes one
|
|
19
|
+
* frame consumed, so `decompressAllFrames` below runs one `createZstdDecompress`
|
|
20
|
+
* per frame, each capped at `ZSTD_d_windowLogMax`, advancing through the
|
|
21
|
+
* buffer by exactly that many bytes each time — the same "loop over frames"
|
|
22
|
+
* the plan already calls out for Rust's `ruzstd`, just also true here.
|
|
23
|
+
*
|
|
24
|
+
* Every check below runs in the order the guide names, and a failure at any
|
|
25
|
+
* step leaves nothing a later `--offline` read could mistake for a verified
|
|
26
|
+
* install: the temp layer file and a partially-unpacked destination are both
|
|
27
|
+
* the caller's (`ensure.ts`'s) to remove, since only it knows whether the
|
|
28
|
+
* destination is a fresh temp directory or an existing one being replaced.
|
|
29
|
+
*/
|
|
30
|
+
import { type ExtractedEntry } from '../tar.js';
|
|
31
|
+
import type { RequestOptions } from './http.js';
|
|
32
|
+
import { type Descriptor } from './oci.js';
|
|
33
|
+
/**
|
|
34
|
+
* Verifies already-in-memory layer bytes against their own descriptor, then
|
|
35
|
+
* zstd-decodes and unpacks into `destDir` (guide §5, steps 1-4) — the shared
|
|
36
|
+
* core both `fetchVerifyAndUnpackLayer` (downloaded bytes) and
|
|
37
|
+
* `localverify.ts` (bytes read straight from a local `blobs/sha256/<hex>`,
|
|
38
|
+
* for a pre-seeded cache entry) build on.
|
|
39
|
+
*/
|
|
40
|
+
export declare function verifyAndUnpackLayerBytes(layerBytes: Buffer, layer: Descriptor, destDir: string): Promise<readonly ExtractedEntry[]>;
|
|
41
|
+
/**
|
|
42
|
+
* Downloads `layer` (verified against its own descriptor) and unpacks it
|
|
43
|
+
* into `destDir`, which must already exist and be empty. `tempLayerPath` is
|
|
44
|
+
* a caller-owned scratch file for the compressed bytes (removed by the
|
|
45
|
+
* caller once this returns, success or failure).
|
|
46
|
+
*/
|
|
47
|
+
export declare function fetchVerifyAndUnpackLayer(bases: readonly string[], layer: Descriptor, tempLayerPath: string, destDir: string, options: RequestOptions): Promise<readonly ExtractedEntry[]>;
|
|
48
|
+
/** The sha256 (lowercase hex) and byte length of the unpacked library, as the canonical `verified.json` records them. */
|
|
49
|
+
export declare function measureLibrary(libraryPath: string): Promise<{
|
|
50
|
+
readonly sha256: string;
|
|
51
|
+
readonly bytes: number;
|
|
52
|
+
}>;
|
|
53
|
+
/** Re-hashes the installed library against the signed predicate's `library_sha256`/`library_bytes` (guide §5 step 5). */
|
|
54
|
+
export declare function verifyInstalledLibrary(libraryPath: string, expectedSha256Hex: string, expectedBytes: number): Promise<void>;
|
|
55
|
+
//# sourceMappingURL=unpack.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unpack.d.ts","sourceRoot":"","sources":["../../src/ocifetch/unpack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAMH,OAAO,EAAoB,KAAK,cAAc,EAAE,MAAM,WAAW,CAAC;AAGlE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAiB,KAAK,UAAU,EAAwC,MAAM,UAAU,CAAC;AA0FhG;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAgB1I;AAED;;;;;GAKG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,KAAK,EAAE,UAAU,EACjB,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,SAAS,cAAc,EAAE,CAAC,CAWpC;AAED,yHAAyH;AACzH,wBAAsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAatH;AAED,yHAAyH;AACzH,wBAAsB,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBjI"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bytes and unpack (`docs/guides/fetch-v1.md` §5): download the layer to a
|
|
3
|
+
* temp file **while hashing**, verify size and sha256 against the manifest's
|
|
4
|
+
* own layer descriptor **before any decompression**, zstd-decode (multi-frame
|
|
5
|
+
* accepted, a window log past the limit refused before a frame's decoder
|
|
6
|
+
* commits to it), unpack with the tightened v1 tar rules (`../tar.ts`'s
|
|
7
|
+
* `extractTarStream`: regular files and directories only, no duplicate entry
|
|
8
|
+
* names, a hard cap on total unpacked bytes), then re-hash the installed
|
|
9
|
+
* library against the signed predicate.
|
|
10
|
+
*
|
|
11
|
+
* **Multi-frame zstd needs its own loop here — measured, not assumed.**
|
|
12
|
+
* Node's built-in `zlib.createZstdDecompress()` (and `zstdDecompressSync`)
|
|
13
|
+
* decode only the **first** frame of a concatenated multi-frame stream and
|
|
14
|
+
* then stop silently (no error, no second frame): verified on this Mac
|
|
15
|
+
* (Node 22.23.2) by concatenating two independently-produced zstd frames and
|
|
16
|
+
* observing the decoder emit only the first frame's content, with
|
|
17
|
+
* `bytesWritten` on the stream reporting exactly the first frame's
|
|
18
|
+
* compressed length. `bytesWritten` is therefore how many input bytes one
|
|
19
|
+
* frame consumed, so `decompressAllFrames` below runs one `createZstdDecompress`
|
|
20
|
+
* per frame, each capped at `ZSTD_d_windowLogMax`, advancing through the
|
|
21
|
+
* buffer by exactly that many bytes each time — the same "loop over frames"
|
|
22
|
+
* the plan already calls out for Rust's `ruzstd`, just also true here.
|
|
23
|
+
*
|
|
24
|
+
* Every check below runs in the order the guide names, and a failure at any
|
|
25
|
+
* step leaves nothing a later `--offline` read could mistake for a verified
|
|
26
|
+
* install: the temp layer file and a partially-unpacked destination are both
|
|
27
|
+
* the caller's (`ensure.ts`'s) to remove, since only it knows whether the
|
|
28
|
+
* destination is a fresh temp directory or an existing one being replaced.
|
|
29
|
+
*/
|
|
30
|
+
import { createHash } from 'node:crypto';
|
|
31
|
+
import { closeSync, createReadStream, ftruncateSync, openSync, writeSync } from 'node:fs';
|
|
32
|
+
import { Readable } from 'node:stream';
|
|
33
|
+
import * as zlib from 'node:zlib';
|
|
34
|
+
import { extractTarStream } from '../tar.js';
|
|
35
|
+
import { MAX_UNPACKED_BYTES, ZSTD_WINDOW_LOG_MAX } from './constants.gen.js';
|
|
36
|
+
import { ArtifactCorruptError } from './errors.js';
|
|
37
|
+
import { fetchBlobToSink, verifyDigestAndSize } from './oci.js';
|
|
38
|
+
/**
|
|
39
|
+
* Streams into a file on disk while hashing, synchronously: `requestToSink`
|
|
40
|
+
* (`http.ts`) calls `write` from inside a plain callback with no backpressure
|
|
41
|
+
* of its own, so a sync write keeps every chunk in order with no risk of two
|
|
42
|
+
* writes racing. `reset()` is called once before the first attempt and again
|
|
43
|
+
* before every retry — a retried download restarts the file from empty,
|
|
44
|
+
* exactly as it restarts the hash. Also keeps an in-memory copy: the
|
|
45
|
+
* decompressor needs the whole compressed buffer anyway (see this module's
|
|
46
|
+
* header), so a second disk read would buy nothing.
|
|
47
|
+
*/
|
|
48
|
+
class HashingFileSink {
|
|
49
|
+
fd;
|
|
50
|
+
hash = createHash('sha256');
|
|
51
|
+
bytesWritten = 0;
|
|
52
|
+
chunks = [];
|
|
53
|
+
constructor(path) {
|
|
54
|
+
this.fd = openSync(path, 'w');
|
|
55
|
+
}
|
|
56
|
+
reset() {
|
|
57
|
+
this.hash = createHash('sha256');
|
|
58
|
+
this.bytesWritten = 0;
|
|
59
|
+
this.chunks = [];
|
|
60
|
+
ftruncateSync(this.fd, 0);
|
|
61
|
+
}
|
|
62
|
+
write(chunk) {
|
|
63
|
+
writeSync(this.fd, chunk);
|
|
64
|
+
this.hash.update(chunk);
|
|
65
|
+
this.chunks.push(chunk);
|
|
66
|
+
this.bytesWritten += chunk.length;
|
|
67
|
+
}
|
|
68
|
+
/** Closes the file and returns what was actually written — never call `write` after this. */
|
|
69
|
+
finish() {
|
|
70
|
+
const sha256 = this.hash.digest('hex');
|
|
71
|
+
const bytes = Buffer.concat(this.chunks);
|
|
72
|
+
closeSync(this.fd);
|
|
73
|
+
return { sha256, size: this.bytesWritten, bytes };
|
|
74
|
+
}
|
|
75
|
+
/** For an error path: close without finalizing the hash (which `digest()` would do anyway, uselessly). */
|
|
76
|
+
abort() {
|
|
77
|
+
try {
|
|
78
|
+
closeSync(this.fd);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// Already closed, or never fully opened — nothing left to release.
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Decodes every zstd frame in `compressed`, one `createZstdDecompress`
|
|
87
|
+
* instance per frame (see this module's header for why), each capped at
|
|
88
|
+
* `windowLogMax`. Yields decompressed chunks in order. Throws
|
|
89
|
+
* `ArtifactCorruptError` on a decode error (including a window log past the
|
|
90
|
+
* cap) or on a frame that consumes zero input bytes (would loop forever
|
|
91
|
+
* otherwise).
|
|
92
|
+
*/
|
|
93
|
+
async function* decompressAllZstdFrames(compressed, windowLogMax) {
|
|
94
|
+
let offset = 0;
|
|
95
|
+
while (offset < compressed.length) {
|
|
96
|
+
const remaining = compressed.subarray(offset);
|
|
97
|
+
const decoder = zlib.createZstdDecompress({ params: { [zlib.constants.ZSTD_d_windowLogMax]: windowLogMax } });
|
|
98
|
+
const chunks = [];
|
|
99
|
+
let consumed = 0;
|
|
100
|
+
try {
|
|
101
|
+
await new Promise((resolve, reject) => {
|
|
102
|
+
decoder.on('data', (chunk) => chunks.push(chunk));
|
|
103
|
+
decoder.on('end', () => {
|
|
104
|
+
consumed = decoder.bytesWritten;
|
|
105
|
+
resolve();
|
|
106
|
+
});
|
|
107
|
+
decoder.on('error', reject);
|
|
108
|
+
decoder.end(remaining);
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
throw new ArtifactCorruptError(`chtypes: zstd decode failed: ${errorText(err)}`, { cause: err });
|
|
113
|
+
}
|
|
114
|
+
if (consumed <= 0) {
|
|
115
|
+
throw new ArtifactCorruptError('chtypes: zstd stream made no forward progress (a malformed or empty frame)');
|
|
116
|
+
}
|
|
117
|
+
for (const chunk of chunks)
|
|
118
|
+
yield chunk;
|
|
119
|
+
offset += consumed;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Verifies already-in-memory layer bytes against their own descriptor, then
|
|
124
|
+
* zstd-decodes and unpacks into `destDir` (guide §5, steps 1-4) — the shared
|
|
125
|
+
* core both `fetchVerifyAndUnpackLayer` (downloaded bytes) and
|
|
126
|
+
* `localverify.ts` (bytes read straight from a local `blobs/sha256/<hex>`,
|
|
127
|
+
* for a pre-seeded cache entry) build on.
|
|
128
|
+
*/
|
|
129
|
+
export async function verifyAndUnpackLayerBytes(layerBytes, layer, destDir) {
|
|
130
|
+
const sha256 = createHash('sha256').update(layerBytes).digest('hex');
|
|
131
|
+
// Size and sha256 against the descriptor, BEFORE any decompression
|
|
132
|
+
// (guide §5 step 1) — `tampered-layer` must show no unpack attempted.
|
|
133
|
+
verifyDigestAndSize(layer, sha256, layerBytes.length, `layer ${layer.digest}`);
|
|
134
|
+
const decompressed = Readable.from(decompressAllZstdFrames(layerBytes, ZSTD_WINDOW_LOG_MAX));
|
|
135
|
+
try {
|
|
136
|
+
return await extractTarStream([decompressed], destDir, {
|
|
137
|
+
refuseDuplicateNames: true,
|
|
138
|
+
maxTotalBytes: MAX_UNPACKED_BYTES,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
if (err instanceof ArtifactCorruptError)
|
|
143
|
+
throw err;
|
|
144
|
+
throw new ArtifactCorruptError(`chtypes: layer ${layer.digest} failed to decode or unpack: ${errorText(err)}`, { cause: err });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Downloads `layer` (verified against its own descriptor) and unpacks it
|
|
149
|
+
* into `destDir`, which must already exist and be empty. `tempLayerPath` is
|
|
150
|
+
* a caller-owned scratch file for the compressed bytes (removed by the
|
|
151
|
+
* caller once this returns, success or failure).
|
|
152
|
+
*/
|
|
153
|
+
export async function fetchVerifyAndUnpackLayer(bases, layer, tempLayerPath, destDir, options) {
|
|
154
|
+
const sink = new HashingFileSink(tempLayerPath);
|
|
155
|
+
let downloaded;
|
|
156
|
+
try {
|
|
157
|
+
await fetchBlobToSink(bases, layer, options, sink);
|
|
158
|
+
downloaded = sink.finish();
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
sink.abort();
|
|
162
|
+
throw err;
|
|
163
|
+
}
|
|
164
|
+
return verifyAndUnpackLayerBytes(downloaded.bytes, layer, destDir);
|
|
165
|
+
}
|
|
166
|
+
/** The sha256 (lowercase hex) and byte length of the unpacked library, as the canonical `verified.json` records them. */
|
|
167
|
+
export async function measureLibrary(libraryPath) {
|
|
168
|
+
const hash = createHash('sha256');
|
|
169
|
+
let size = 0;
|
|
170
|
+
await new Promise((resolve, reject) => {
|
|
171
|
+
const s = createReadStream(libraryPath);
|
|
172
|
+
s.on('data', (chunk) => {
|
|
173
|
+
size += chunk.length;
|
|
174
|
+
hash.update(chunk);
|
|
175
|
+
});
|
|
176
|
+
s.on('end', resolve);
|
|
177
|
+
s.on('error', reject);
|
|
178
|
+
});
|
|
179
|
+
return { sha256: hash.digest('hex'), bytes: size };
|
|
180
|
+
}
|
|
181
|
+
/** Re-hashes the installed library against the signed predicate's `library_sha256`/`library_bytes` (guide §5 step 5). */
|
|
182
|
+
export async function verifyInstalledLibrary(libraryPath, expectedSha256Hex, expectedBytes) {
|
|
183
|
+
const hash = createHash('sha256');
|
|
184
|
+
let size = 0;
|
|
185
|
+
await new Promise((resolve, reject) => {
|
|
186
|
+
const s = createReadStream(libraryPath);
|
|
187
|
+
s.on('data', (chunk) => {
|
|
188
|
+
size += chunk.length;
|
|
189
|
+
hash.update(chunk);
|
|
190
|
+
});
|
|
191
|
+
s.on('end', resolve);
|
|
192
|
+
s.on('error', reject);
|
|
193
|
+
});
|
|
194
|
+
if (size !== expectedBytes) {
|
|
195
|
+
throw new ArtifactCorruptError(`chtypes: installed library is ${size} bytes, the signed predicate named ${expectedBytes}`);
|
|
196
|
+
}
|
|
197
|
+
const actual = hash.digest('hex');
|
|
198
|
+
if (actual !== expectedSha256Hex) {
|
|
199
|
+
throw new ArtifactCorruptError("chtypes: installed library's sha256 does not match the signed predicate's library_sha256");
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function errorText(err) {
|
|
203
|
+
return err instanceof Error ? err.message : String(err);
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=unpack.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unpack.js","sourceRoot":"","sources":["../../src/ocifetch/unpack.ts"],"names":[],"mappings":"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"}
|