@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.
Files changed (195) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +34 -38
  3. package/dist/abi1/buildinfo.d.ts +40 -0
  4. package/dist/abi1/buildinfo.d.ts.map +1 -0
  5. package/dist/abi1/buildinfo.js +83 -0
  6. package/dist/abi1/buildinfo.js.map +1 -0
  7. package/dist/abi1/calls.gen.d.ts +55 -0
  8. package/dist/abi1/calls.gen.d.ts.map +1 -0
  9. package/dist/abi1/calls.gen.js +110 -0
  10. package/dist/abi1/calls.gen.js.map +1 -0
  11. package/dist/abi1/decls.gen.d.ts +115 -0
  12. package/dist/abi1/decls.gen.d.ts.map +1 -0
  13. package/dist/abi1/decls.gen.js +1613 -0
  14. package/dist/abi1/decls.gen.js.map +1 -0
  15. package/dist/abi1/errmap.gen.d.ts +18 -0
  16. package/dist/abi1/errmap.gen.d.ts.map +1 -0
  17. package/dist/abi1/errmap.gen.js +66 -0
  18. package/dist/abi1/errmap.gen.js.map +1 -0
  19. package/dist/abi1/errors.d.ts +107 -0
  20. package/dist/abi1/errors.d.ts.map +1 -0
  21. package/dist/abi1/errors.js +134 -0
  22. package/dist/abi1/errors.js.map +1 -0
  23. package/dist/abi1/handles.d.ts +31 -0
  24. package/dist/abi1/handles.d.ts.map +1 -0
  25. package/dist/abi1/handles.js +76 -0
  26. package/dist/abi1/handles.js.map +1 -0
  27. package/dist/abi1/index.d.ts +17 -0
  28. package/dist/abi1/index.d.ts.map +1 -0
  29. package/dist/abi1/index.js +17 -0
  30. package/dist/abi1/index.js.map +1 -0
  31. package/dist/abi1/libc.d.ts +54 -0
  32. package/dist/abi1/libc.d.ts.map +1 -0
  33. package/dist/abi1/libc.gen.d.ts +12 -0
  34. package/dist/abi1/libc.gen.d.ts.map +1 -0
  35. package/dist/abi1/libc.gen.js +75 -0
  36. package/dist/abi1/libc.gen.js.map +1 -0
  37. package/dist/abi1/libc.js +109 -0
  38. package/dist/abi1/libc.js.map +1 -0
  39. package/dist/abi1/loader.d.ts +101 -0
  40. package/dist/abi1/loader.d.ts.map +1 -0
  41. package/dist/abi1/loader.js +274 -0
  42. package/dist/abi1/loader.js.map +1 -0
  43. package/dist/abi1/raw.d.ts +104 -0
  44. package/dist/abi1/raw.d.ts.map +1 -0
  45. package/dist/abi1/raw.js +296 -0
  46. package/dist/abi1/raw.js.map +1 -0
  47. package/dist/abi1/strictjson.d.ts +19 -0
  48. package/dist/abi1/strictjson.d.ts.map +1 -0
  49. package/dist/abi1/strictjson.js +78 -0
  50. package/dist/abi1/strictjson.js.map +1 -0
  51. package/dist/abi1/vocab.gen.d.ts +169 -0
  52. package/dist/abi1/vocab.gen.d.ts.map +1 -0
  53. package/dist/abi1/vocab.gen.js +306 -0
  54. package/dist/abi1/vocab.gen.js.map +1 -0
  55. package/dist/cli.d.ts +25 -26
  56. package/dist/cli.d.ts.map +1 -1
  57. package/dist/cli.js +206 -218
  58. package/dist/cli.js.map +1 -1
  59. package/dist/documents.d.ts +195 -0
  60. package/dist/documents.d.ts.map +1 -0
  61. package/dist/documents.js +389 -0
  62. package/dist/documents.js.map +1 -0
  63. package/dist/env.d.ts +16 -0
  64. package/dist/env.d.ts.map +1 -0
  65. package/dist/env.js +57 -0
  66. package/dist/env.js.map +1 -0
  67. package/dist/index.d.ts +19 -24
  68. package/dist/index.d.ts.map +1 -1
  69. package/dist/index.js +17 -23
  70. package/dist/index.js.map +1 -1
  71. package/dist/json.d.ts +11 -89
  72. package/dist/json.d.ts.map +1 -1
  73. package/dist/json.js +16 -180
  74. package/dist/json.js.map +1 -1
  75. package/dist/library.d.ts +53 -309
  76. package/dist/library.d.ts.map +1 -1
  77. package/dist/library.js +77 -315
  78. package/dist/library.js.map +1 -1
  79. package/dist/ocifetch/constants.gen.d.ts +84 -0
  80. package/dist/ocifetch/constants.gen.d.ts.map +1 -0
  81. package/dist/ocifetch/constants.gen.js +92 -0
  82. package/dist/ocifetch/constants.gen.js.map +1 -0
  83. package/dist/ocifetch/dsse.d.ts +114 -0
  84. package/dist/ocifetch/dsse.d.ts.map +1 -0
  85. package/dist/ocifetch/dsse.js +331 -0
  86. package/dist/ocifetch/dsse.js.map +1 -0
  87. package/dist/ocifetch/ensure.d.ts +65 -0
  88. package/dist/ocifetch/ensure.d.ts.map +1 -0
  89. package/dist/ocifetch/ensure.js +775 -0
  90. package/dist/ocifetch/ensure.js.map +1 -0
  91. package/dist/ocifetch/errors.d.ts +92 -0
  92. package/dist/ocifetch/errors.d.ts.map +1 -0
  93. package/dist/ocifetch/errors.js +101 -0
  94. package/dist/ocifetch/errors.js.map +1 -0
  95. package/dist/ocifetch/goldens.d.ts +44 -0
  96. package/dist/ocifetch/goldens.d.ts.map +1 -0
  97. package/dist/ocifetch/goldens.js +62 -0
  98. package/dist/ocifetch/goldens.js.map +1 -0
  99. package/dist/ocifetch/http.d.ts +124 -0
  100. package/dist/ocifetch/http.d.ts.map +1 -0
  101. package/dist/ocifetch/http.js +549 -0
  102. package/dist/ocifetch/http.js.map +1 -0
  103. package/dist/ocifetch/index.d.ts +17 -0
  104. package/dist/ocifetch/index.d.ts.map +1 -0
  105. package/dist/ocifetch/index.js +14 -0
  106. package/dist/ocifetch/index.js.map +1 -0
  107. package/dist/ocifetch/layout.d.ts +126 -0
  108. package/dist/ocifetch/layout.d.ts.map +1 -0
  109. package/dist/ocifetch/layout.js +375 -0
  110. package/dist/ocifetch/layout.js.map +1 -0
  111. package/dist/ocifetch/localverify.d.ts +43 -0
  112. package/dist/ocifetch/localverify.d.ts.map +1 -0
  113. package/dist/ocifetch/localverify.js +164 -0
  114. package/dist/ocifetch/localverify.js.map +1 -0
  115. package/dist/ocifetch/lock.d.ts +39 -0
  116. package/dist/ocifetch/lock.d.ts.map +1 -0
  117. package/dist/ocifetch/lock.js +140 -0
  118. package/dist/ocifetch/lock.js.map +1 -0
  119. package/dist/ocifetch/oci.d.ts +100 -0
  120. package/dist/ocifetch/oci.d.ts.map +1 -0
  121. package/dist/ocifetch/oci.js +323 -0
  122. package/dist/ocifetch/oci.js.map +1 -0
  123. package/dist/ocifetch/referrers.d.ts +55 -0
  124. package/dist/ocifetch/referrers.d.ts.map +1 -0
  125. package/dist/ocifetch/referrers.js +132 -0
  126. package/dist/ocifetch/referrers.js.map +1 -0
  127. package/dist/ocifetch/types.d.ts +167 -0
  128. package/dist/ocifetch/types.d.ts.map +1 -0
  129. package/dist/ocifetch/types.js +88 -0
  130. package/dist/ocifetch/types.js.map +1 -0
  131. package/dist/ocifetch/unpack.d.ts +55 -0
  132. package/dist/ocifetch/unpack.d.ts.map +1 -0
  133. package/dist/ocifetch/unpack.js +205 -0
  134. package/dist/ocifetch/unpack.js.map +1 -0
  135. package/dist/registry.d.ts +38 -387
  136. package/dist/registry.d.ts.map +1 -1
  137. package/dist/registry.js +95 -819
  138. package/dist/registry.js.map +1 -1
  139. package/dist/schema.d.ts +77 -588
  140. package/dist/schema.d.ts.map +1 -1
  141. package/dist/schema.js +87 -549
  142. package/dist/schema.js.map +1 -1
  143. package/dist/settings.d.ts +27 -36
  144. package/dist/settings.d.ts.map +1 -1
  145. package/dist/settings.js +75 -25
  146. package/dist/settings.js.map +1 -1
  147. package/dist/setup.d.ts +46 -0
  148. package/dist/setup.d.ts.map +1 -0
  149. package/dist/setup.js +79 -0
  150. package/dist/setup.js.map +1 -0
  151. package/dist/tar.d.ts +27 -11
  152. package/dist/tar.d.ts.map +1 -1
  153. package/dist/tar.js +54 -32
  154. package/dist/tar.js.map +1 -1
  155. package/package.json +2 -2
  156. package/dist/discover.d.ts +0 -142
  157. package/dist/discover.d.ts.map +0 -1
  158. package/dist/discover.js +0 -288
  159. package/dist/discover.js.map +0 -1
  160. package/dist/error-codes.d.ts +0 -80
  161. package/dist/error-codes.d.ts.map +0 -1
  162. package/dist/error-codes.js +0 -139
  163. package/dist/error-codes.js.map +0 -1
  164. package/dist/errors.d.ts +0 -284
  165. package/dist/errors.d.ts.map +0 -1
  166. package/dist/errors.js +0 -321
  167. package/dist/errors.js.map +0 -1
  168. package/dist/fetch.d.ts +0 -382
  169. package/dist/fetch.d.ts.map +0 -1
  170. package/dist/fetch.js +0 -1498
  171. package/dist/fetch.js.map +0 -1
  172. package/dist/ffi.d.ts +0 -410
  173. package/dist/ffi.d.ts.map +0 -1
  174. package/dist/ffi.js +0 -1154
  175. package/dist/ffi.js.map +0 -1
  176. package/dist/format.d.ts +0 -128
  177. package/dist/format.d.ts.map +0 -1
  178. package/dist/format.js +0 -132
  179. package/dist/format.js.map +0 -1
  180. package/dist/numeric.d.ts +0 -20
  181. package/dist/numeric.d.ts.map +0 -1
  182. package/dist/numeric.js +0 -107
  183. package/dist/numeric.js.map +0 -1
  184. package/dist/paths.d.ts +0 -55
  185. package/dist/paths.d.ts.map +0 -1
  186. package/dist/paths.js +0 -87
  187. package/dist/paths.js.map +0 -1
  188. package/dist/results.d.ts +0 -495
  189. package/dist/results.d.ts.map +0 -1
  190. package/dist/results.js +0 -406
  191. package/dist/results.js.map +0 -1
  192. package/dist/transform.d.ts +0 -73
  193. package/dist/transform.d.ts.map +0 -1
  194. package/dist/transform.js +0 -533
  195. 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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"}