@wavehouse/chtypes 0.5.2 → 1.0.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/CHANGELOG.md +26 -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 +99 -0
- package/dist/abi1/loader.d.ts.map +1 -0
- package/dist/abi1/loader.js +261 -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 +94 -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 +37 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +60 -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
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"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"}
|
package/dist/settings.d.ts
CHANGED
|
@@ -1,43 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Settings, the per-call zone and the other call inputs, serialized for the
|
|
3
|
+
* library exactly as `docs/reference/bindings-v1.md` §2 and §3 say.
|
|
3
4
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* nothing anywhere says so.
|
|
5
|
+
* Settings values are strings, and only strings. The map becomes a JSON object
|
|
6
|
+
* of string values through the stock encoder and is passed verbatim: no
|
|
7
|
+
* boolean or integer spelling, no float. A value that is not a string is the
|
|
8
|
+
* language's own type error (`TypeError`).
|
|
9
9
|
*
|
|
10
|
-
* The
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* The per-call zone is a settings key and nothing more: `sessionTimezone` is
|
|
11
|
+
* written into the object as `session_timezone`, verbatim, with no default,
|
|
12
|
+
* validation or canonicalization (the library validates it with its own zone
|
|
13
|
+
* database). Passing it alongside a `session_timezone` key in `settings` is a
|
|
14
|
+
* `UsageError`, raised before any call and whether or not the two agree.
|
|
13
15
|
*/
|
|
14
|
-
|
|
16
|
+
/** Settings and query parameters: names to string values. */
|
|
17
|
+
export type Settings = Readonly<Record<string, string>>;
|
|
18
|
+
/** Bytes in: a statement, expression, type, name or literal. A string is encoded as UTF-8; pass a `Uint8Array` for bytes that are not text. */
|
|
19
|
+
export type BytesIn = Uint8Array | string;
|
|
20
|
+
/** The bytes of a `BytesIn`: UTF-8 for a string, the same bytes for a `Uint8Array`. */
|
|
21
|
+
export declare function bytesIn(value: BytesIn): Buffer;
|
|
15
22
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* Accepted everywhere settings travel: the compile profile
|
|
20
|
-
* (`Library#compileDdl`), the per-call map (`Schema#row` / `Schema#rows`), the
|
|
21
|
-
* process seed (`Library#setDefaultSettings`) and the engine's
|
|
22
|
-
* MergeTree-namespace settings (`Schema#setEngine`). Precedence on the row
|
|
23
|
-
* path: per-call > compile profile > library defaults > ClickHouse defaults —
|
|
24
|
-
* except a TYPE GATE declared in the compile profile, which binds at compile
|
|
25
|
-
* and then outranks the per-call map, as a real server's CREATE does.
|
|
26
|
-
*
|
|
27
|
-
* An unknown setting name is refused WHOLESALE with the server's own code 115
|
|
28
|
-
* on every channel — nothing is applied, nothing is silently dropped.
|
|
29
|
-
*/
|
|
30
|
-
export type Settings = Readonly<Record<string, SettingValue>>;
|
|
31
|
-
/**
|
|
32
|
-
* Serialize settings to the `settings_json` object the C ABI expects — every
|
|
33
|
-
* value crossing as a JSON string.
|
|
34
|
-
*
|
|
35
|
-
* @param settings - the settings map; `undefined` encodes as `"{}"`, the
|
|
36
|
-
* structurally settings-free path.
|
|
37
|
-
* @returns the JSON text to hand to a `chs_*` entry point.
|
|
38
|
-
* @throws {ChtypesError} when a value is neither `string` nor `bigint` — a JS
|
|
39
|
-
* `number` is rejected at runtime because a 19-digit nanosecond epoch does
|
|
40
|
-
* not survive an IEEE double and the setting would be silently ignored.
|
|
23
|
+
* The `settings` input of a call: nothing (length 0) when there is neither a
|
|
24
|
+
* map nor a zone, else a JSON object of string values with the zone, when
|
|
25
|
+
* given, written in as `session_timezone`.
|
|
41
26
|
*/
|
|
42
|
-
export declare function encodeSettings(settings
|
|
27
|
+
export declare function encodeSettings(settings: Settings | undefined, sessionTimezone: string | undefined): Buffer;
|
|
28
|
+
/** Query parameters: a JSON object of string values, or nothing when absent. */
|
|
29
|
+
export declare function encodeParams(params: Settings | undefined): Buffer;
|
|
30
|
+
/** The INSERT column list: a JSON array of names, each an object carrying `name` when its bytes are valid UTF-8 and `name_b64` otherwise, or nothing (length 0) when absent. */
|
|
31
|
+
export declare function encodeColumns(columns: readonly BytesIn[] | undefined): Buffer;
|
|
32
|
+
/** The process default settings, as `chs_set_defaults` takes them. */
|
|
33
|
+
export declare function validateDefaults(defaults: Settings): void;
|
|
43
34
|
//# sourceMappingURL=settings.d.ts.map
|
package/dist/settings.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,6DAA6D;AAC7D,MAAM,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAExD,+IAA+I;AAC/I,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AAI1C,uFAAuF;AACvF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE9C;AAQD;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,EAAE,eAAe,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAe1G;AAED,gFAAgF;AAChF,wBAAgB,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAIjE;AAaD,gLAAgL;AAChL,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,OAAO,EAAE,GAAG,SAAS,GAAG,MAAM,CAO7E;AAED,sEAAsE;AACtE,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAEzD"}
|
package/dist/settings.js
CHANGED
|
@@ -1,33 +1,83 @@
|
|
|
1
|
-
import { ChtypesError } from './errors.js';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* Settings, the per-call zone and the other call inputs, serialized for the
|
|
3
|
+
* library exactly as `docs/reference/bindings-v1.md` §2 and §3 say.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
5
|
+
* Settings values are strings, and only strings. The map becomes a JSON object
|
|
6
|
+
* of string values through the stock encoder and is passed verbatim: no
|
|
7
|
+
* boolean or integer spelling, no float. A value that is not a string is the
|
|
8
|
+
* language's own type error (`TypeError`).
|
|
9
|
+
*
|
|
10
|
+
* The per-call zone is a settings key and nothing more: `sessionTimezone` is
|
|
11
|
+
* written into the object as `session_timezone`, verbatim, with no default,
|
|
12
|
+
* validation or canonicalization (the library validates it with its own zone
|
|
13
|
+
* database). Passing it alongside a `session_timezone` key in `settings` is a
|
|
14
|
+
* `UsageError`, raised before any call and whether or not the two agree.
|
|
15
|
+
*/
|
|
16
|
+
import { asBuffer, usageError } from './abi1/index.js';
|
|
17
|
+
const ZONE_KEY = 'session_timezone';
|
|
18
|
+
/** The bytes of a `BytesIn`: UTF-8 for a string, the same bytes for a `Uint8Array`. */
|
|
19
|
+
export function bytesIn(value) {
|
|
20
|
+
return typeof value === 'string' ? Buffer.from(value, 'utf8') : asBuffer(value);
|
|
21
|
+
}
|
|
22
|
+
function checkStrings(what, map) {
|
|
23
|
+
for (const [k, v] of Object.entries(map)) {
|
|
24
|
+
if (typeof v !== 'string')
|
|
25
|
+
throw new TypeError(`chtypes: ${what}[${JSON.stringify(k)}] must be a string, got ${typeof v}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The `settings` input of a call: nothing (length 0) when there is neither a
|
|
30
|
+
* map nor a zone, else a JSON object of string values with the zone, when
|
|
31
|
+
* given, written in as `session_timezone`.
|
|
12
32
|
*/
|
|
13
|
-
export function encodeSettings(settings) {
|
|
14
|
-
if (settings === undefined)
|
|
15
|
-
return
|
|
33
|
+
export function encodeSettings(settings, sessionTimezone) {
|
|
34
|
+
if (settings === undefined && sessionTimezone === undefined)
|
|
35
|
+
return Buffer.alloc(0);
|
|
16
36
|
const out = {};
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
else if (typeof value === 'bigint') {
|
|
22
|
-
out[key] = value.toString();
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
throw new ChtypesError(`chtypes: setting ${JSON.stringify(key)} must be a string or a bigint, got ` +
|
|
26
|
-
`${typeof value}. A JS number cannot carry a 19-digit nanosecond epoch: ` +
|
|
27
|
-
`1700000000123456789 becomes 1.7e+18 and the setting is silently ignored ` +
|
|
28
|
-
`(the C ABI contract §Settings).`);
|
|
37
|
+
if (settings !== undefined) {
|
|
38
|
+
checkStrings('settings', settings);
|
|
39
|
+
if (sessionTimezone !== undefined && Object.hasOwn(settings, ZONE_KEY)) {
|
|
40
|
+
throw usageError(`the zone was given twice: sessionTimezone and a ${ZONE_KEY} key in settings; pass only one`);
|
|
29
41
|
}
|
|
42
|
+
Object.assign(out, settings);
|
|
30
43
|
}
|
|
31
|
-
|
|
44
|
+
if (sessionTimezone !== undefined) {
|
|
45
|
+
if (typeof sessionTimezone !== 'string')
|
|
46
|
+
throw new TypeError(`chtypes: sessionTimezone must be a string, got ${typeof sessionTimezone}`);
|
|
47
|
+
out[ZONE_KEY] = sessionTimezone;
|
|
48
|
+
}
|
|
49
|
+
return Buffer.from(JSON.stringify(out), 'utf8');
|
|
50
|
+
}
|
|
51
|
+
/** Query parameters: a JSON object of string values, or nothing when absent. */
|
|
52
|
+
export function encodeParams(params) {
|
|
53
|
+
if (params === undefined)
|
|
54
|
+
return Buffer.alloc(0);
|
|
55
|
+
checkStrings('params', params);
|
|
56
|
+
return Buffer.from(JSON.stringify({ ...params }), 'utf8');
|
|
57
|
+
}
|
|
58
|
+
const utf8 = new TextDecoder('utf-8', { fatal: true });
|
|
59
|
+
function isValidUtf8(bytes) {
|
|
60
|
+
try {
|
|
61
|
+
utf8.decode(bytes);
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** The INSERT column list: a JSON array of names, each an object carrying `name` when its bytes are valid UTF-8 and `name_b64` otherwise, or nothing (length 0) when absent. */
|
|
69
|
+
export function encodeColumns(columns) {
|
|
70
|
+
if (columns === undefined)
|
|
71
|
+
return Buffer.alloc(0);
|
|
72
|
+
const names = columns.map((c) => {
|
|
73
|
+
if (typeof c === 'string')
|
|
74
|
+
return { name: c };
|
|
75
|
+
return isValidUtf8(c) ? { name: Buffer.from(c.buffer, c.byteOffset, c.byteLength).toString('utf8') } : { name_b64: asBuffer(c).toString('base64') };
|
|
76
|
+
});
|
|
77
|
+
return Buffer.from(JSON.stringify(names), 'utf8');
|
|
78
|
+
}
|
|
79
|
+
/** The process default settings, as `chs_set_defaults` takes them. */
|
|
80
|
+
export function validateDefaults(defaults) {
|
|
81
|
+
checkStrings('defaults', defaults);
|
|
32
82
|
}
|
|
33
83
|
//# sourceMappingURL=settings.js.map
|
package/dist/settings.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"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"}
|
package/dist/setup.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The process setup (`docs/reference/bindings-v1.md` §6): the image zone and
|
|
3
|
+
* the default settings, chosen once, before traffic.
|
|
4
|
+
*
|
|
5
|
+
* 1. `setup` records; it does not load. Called before any library is open it
|
|
6
|
+
* records the zone spelling and the defaults. Called again with the same
|
|
7
|
+
* zone, byte for byte, and the same defaults, it is a no-op. Called with
|
|
8
|
+
* a different zone or different defaults it is a `UsageError` naming
|
|
9
|
+
* both, and the first setup stands.
|
|
10
|
+
* 2. The first open commits it. If `setup` was never called, the first open
|
|
11
|
+
* records the empty setup: the empty zone, which the library reads as
|
|
12
|
+
* UTC, and no defaults. From then on `setup` succeeds only with exactly
|
|
13
|
+
* the setup in effect.
|
|
14
|
+
* 3. Every image is set up at loader step 7, once, from this record
|
|
15
|
+
* (`./abi1/loader.ts`); nothing sets either again for that image.
|
|
16
|
+
*
|
|
17
|
+
* This is state of the isolate: every worker thread calls it identically, and
|
|
18
|
+
* a worker whose zone differs is refused by the library at its first open.
|
|
19
|
+
*/
|
|
20
|
+
import { type Settings } from './settings.js';
|
|
21
|
+
/** What `setup` takes: the image zone (an IANA name) and the default settings every call starts from. */
|
|
22
|
+
export interface SetupOptions {
|
|
23
|
+
readonly timezone?: string;
|
|
24
|
+
readonly defaults?: Settings;
|
|
25
|
+
}
|
|
26
|
+
/** The setup in effect, as step 7 applies it. */
|
|
27
|
+
export interface ProcessSetup {
|
|
28
|
+
readonly timezone: string;
|
|
29
|
+
readonly defaults: Readonly<Record<string, string>>;
|
|
30
|
+
}
|
|
31
|
+
/** Record the process setup, once. Call it before the first open; see this module's header for the rule. */
|
|
32
|
+
export declare function setup(options?: SetupOptions): void;
|
|
33
|
+
/** The setup in effect, committing the empty setup if none was recorded: what the first open does. */
|
|
34
|
+
export declare function commitSetup(): ProcessSetup;
|
|
35
|
+
/** Test only: forget the recorded setup. Not part of the public API. */
|
|
36
|
+
export declare function resetSetupForTests(): void;
|
|
37
|
+
//# sourceMappingURL=setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAGH,OAAO,EAAE,KAAK,QAAQ,EAAoB,MAAM,eAAe,CAAC;AAEhE,yGAAyG;AACzG,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CAC9B;AAED,iDAAiD;AACjD,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAiBD,4GAA4G;AAC5G,wBAAgB,KAAK,CAAC,OAAO,GAAE,YAAiB,GAAG,IAAI,CAatD;AAED,sGAAsG;AACtG,wBAAgB,WAAW,IAAI,YAAY,CAG1C;AAED,wEAAwE;AACxE,wBAAgB,kBAAkB,IAAI,IAAI,CAEzC"}
|
package/dist/setup.js
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The process setup (`docs/reference/bindings-v1.md` §6): the image zone and
|
|
3
|
+
* the default settings, chosen once, before traffic.
|
|
4
|
+
*
|
|
5
|
+
* 1. `setup` records; it does not load. Called before any library is open it
|
|
6
|
+
* records the zone spelling and the defaults. Called again with the same
|
|
7
|
+
* zone, byte for byte, and the same defaults, it is a no-op. Called with
|
|
8
|
+
* a different zone or different defaults it is a `UsageError` naming
|
|
9
|
+
* both, and the first setup stands.
|
|
10
|
+
* 2. The first open commits it. If `setup` was never called, the first open
|
|
11
|
+
* records the empty setup: the empty zone, which the library reads as
|
|
12
|
+
* UTC, and no defaults. From then on `setup` succeeds only with exactly
|
|
13
|
+
* the setup in effect.
|
|
14
|
+
* 3. Every image is set up at loader step 7, once, from this record
|
|
15
|
+
* (`./abi1/loader.ts`); nothing sets either again for that image.
|
|
16
|
+
*
|
|
17
|
+
* This is state of the isolate: every worker thread calls it identically, and
|
|
18
|
+
* a worker whose zone differs is refused by the library at its first open.
|
|
19
|
+
*/
|
|
20
|
+
import { usageError } from './abi1/index.js';
|
|
21
|
+
import { validateDefaults } from './settings.js';
|
|
22
|
+
let recorded;
|
|
23
|
+
function describe(s) {
|
|
24
|
+
const keys = Object.keys(s.defaults).sort();
|
|
25
|
+
const defaults = keys.length === 0 ? 'no defaults' : `defaults ${JSON.stringify(Object.fromEntries(keys.map((k) => [k, s.defaults[k]])))}`;
|
|
26
|
+
return `zone ${s.timezone === '' ? '(empty, UTC)' : JSON.stringify(s.timezone)} and ${defaults}`;
|
|
27
|
+
}
|
|
28
|
+
function same(a, b) {
|
|
29
|
+
if (a.timezone !== b.timezone)
|
|
30
|
+
return false;
|
|
31
|
+
const ak = Object.keys(a.defaults);
|
|
32
|
+
const bk = Object.keys(b.defaults);
|
|
33
|
+
return ak.length === bk.length && ak.every((k) => Object.hasOwn(b.defaults, k) && a.defaults[k] === b.defaults[k]);
|
|
34
|
+
}
|
|
35
|
+
/** Record the process setup, once. Call it before the first open; see this module's header for the rule. */
|
|
36
|
+
export function setup(options = {}) {
|
|
37
|
+
const timezone = options.timezone ?? '';
|
|
38
|
+
if (typeof timezone !== 'string')
|
|
39
|
+
throw new TypeError(`chtypes: setup timezone must be a string, got ${typeof timezone}`);
|
|
40
|
+
const defaults = options.defaults ?? {};
|
|
41
|
+
validateDefaults(defaults);
|
|
42
|
+
const next = { timezone, defaults: { ...defaults } };
|
|
43
|
+
if (recorded === undefined) {
|
|
44
|
+
recorded = next;
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
if (!same(recorded, next)) {
|
|
48
|
+
throw usageError(`setup was already fixed at ${describe(recorded)}; it was asked for ${describe(next)}. The first setup stands: call setup before the first open, once.`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** The setup in effect, committing the empty setup if none was recorded: what the first open does. */
|
|
52
|
+
export function commitSetup() {
|
|
53
|
+
recorded ??= { timezone: '', defaults: {} };
|
|
54
|
+
return recorded;
|
|
55
|
+
}
|
|
56
|
+
/** Test only: forget the recorded setup. Not part of the public API. */
|
|
57
|
+
export function resetSetupForTests() {
|
|
58
|
+
recorded = undefined;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAiB,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAchE,IAAI,QAAkC,CAAC;AAEvC,SAAS,QAAQ,CAAC,CAAe;IAC/B,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3I,OAAO,QAAQ,CAAC,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,QAAQ,EAAE,CAAC;AACnG,CAAC;AAED,SAAS,IAAI,CAAC,CAAe,EAAE,CAAe;IAC5C,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACnC,OAAO,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,MAAM,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACrH,CAAC;AAED,4GAA4G;AAC5G,MAAM,UAAU,KAAK,CAAC,OAAO,GAAiB,EAAE;IAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;IACxC,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,MAAM,IAAI,SAAS,CAAC,iDAAiD,OAAO,QAAQ,EAAE,CAAC,CAAC;IAC1H,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;IACxC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAiB,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,GAAG,QAAQ,EAAE,EAAE,CAAC;IACnE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,QAAQ,GAAG,IAAI,CAAC;QAChB,OAAO;IACT,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,CAAC;QAC1B,MAAM,UAAU,CAAC,8BAA8B,QAAQ,CAAC,QAAQ,CAAC,sBAAsB,QAAQ,CAAC,IAAI,CAAC,mEAAmE,CAAC,CAAC;IAC5K,CAAC;AACH,CAAC;AAED,sGAAsG;AACtG,MAAM,UAAU,WAAW;IACzB,QAAQ,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;IAC5C,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,kBAAkB;IAChC,QAAQ,GAAG,SAAS,CAAC;AACvB,CAAC"}
|
package/dist/tar.d.ts
CHANGED
|
@@ -5,11 +5,12 @@
|
|
|
5
5
|
* that extracts regular files under one directory is a page of code.
|
|
6
6
|
*
|
|
7
7
|
* Files only. Directories are created; everything else — symlinks, hard
|
|
8
|
-
* links, devices, FIFOs —
|
|
9
|
-
* `manifest.json`, one library and two
|
|
10
|
-
* an attack, not a feature. Every entry
|
|
11
|
-
*
|
|
12
|
-
* name that escapes is refused
|
|
8
|
+
* links, devices, FIFOs — refuses the whole install rather than being
|
|
9
|
+
* skipped or followed: an artifact is `manifest.json`, one library and two
|
|
10
|
+
* text files, and a link inside one is an attack, not a feature. Every entry
|
|
11
|
+
* name is confined to the destination (no absolute names, no `..`
|
|
12
|
+
* components, no escape once resolved), and a name that escapes is refused
|
|
13
|
+
* as corrupt rather than clamped.
|
|
13
14
|
*
|
|
14
15
|
* The archive is consumed as a stream: a 300 MB library is written to disk
|
|
15
16
|
* as it inflates and never sits in memory whole.
|
|
@@ -20,13 +21,28 @@ export interface ExtractedEntry {
|
|
|
20
21
|
readonly name: string;
|
|
21
22
|
readonly size: number;
|
|
22
23
|
}
|
|
24
|
+
/** The v1 rules that are off by default: a duplicate entry name and a cap on total unpacked bytes. `ocifetch/unpack.ts` turns both on. */
|
|
25
|
+
export interface TarExtractOptions {
|
|
26
|
+
/** Refuse a second entry (file or directory) with the same confined name — `CORRUPT`. Off by default. */
|
|
27
|
+
readonly refuseDuplicateNames?: boolean;
|
|
28
|
+
/** A hard cap on total bytes written across every entry, enforced as the stream is written — `CORRUPT` over it. Unset: no cap. */
|
|
29
|
+
readonly maxTotalBytes?: number;
|
|
30
|
+
}
|
|
23
31
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
32
|
+
* Unpacks an **already-decompressed** (or still-to-decompress, via extra
|
|
33
|
+
* pipeline stages) tar byte stream into `dest`, which must already exist.
|
|
34
|
+
* `sources` is one readable, or a readable followed by transform stages (a
|
|
35
|
+
* decompressor) — passed to `pipeline` **as one array**, never chained with
|
|
36
|
+
* `.pipe()` first: `pipeline` is what makes an upstream failure (a truncated
|
|
37
|
+
* read, a zstd window-log refusal) actually reject this call, where `.pipe()`
|
|
38
|
+
* alone would leave the error unheard.
|
|
39
|
+
*
|
|
40
|
+
* The v1 fetch layer's own entry point (`ocifetch/unpack.ts` pipes its
|
|
41
|
+
* verified temp file through a zstd decompressor into this), so no
|
|
42
|
+
* compression format is assumed here.
|
|
26
43
|
*
|
|
27
|
-
* @throws {ArtifactCorruptError}
|
|
28
|
-
*
|
|
29
|
-
* would land outside `dest`.
|
|
44
|
+
* @throws {ArtifactCorruptError} for a header that fails its checksum, a truncated archive, an entry name that would land outside `dest`, an entry that is not a regular file or directory, plus
|
|
45
|
+
* `options`'s own.
|
|
30
46
|
*/
|
|
31
|
-
export declare function
|
|
47
|
+
export declare function extractTarStream(sources: NodeJS.ReadableStream | readonly NodeJS.ReadableStream[], dest: string, options?: TarExtractOptions): Promise<ExtractedEntry[]>;
|
|
32
48
|
//# sourceMappingURL=tar.d.ts.map
|
package/dist/tar.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tar.d.ts","sourceRoot":"","sources":["../src/tar.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tar.d.ts","sourceRoot":"","sources":["../src/tar.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAYH,4CAA4C;AAC5C,MAAM,WAAW,cAAc;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,0IAA0I;AAC1I,MAAM,WAAW,iBAAiB;IAChC,yGAAyG;IACzG,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IACxC,kIAAkI;IAClI,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,MAAM,CAAC,cAAc,GAAG,SAAS,MAAM,CAAC,cAAc,EAAE,EACjE,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC,cAAc,EAAE,CAAC,CAW3B"}
|
package/dist/tar.js
CHANGED
|
@@ -5,50 +5,59 @@
|
|
|
5
5
|
* that extracts regular files under one directory is a page of code.
|
|
6
6
|
*
|
|
7
7
|
* Files only. Directories are created; everything else — symlinks, hard
|
|
8
|
-
* links, devices, FIFOs —
|
|
9
|
-
* `manifest.json`, one library and two
|
|
10
|
-
* an attack, not a feature. Every entry
|
|
11
|
-
*
|
|
12
|
-
* name that escapes is refused
|
|
8
|
+
* links, devices, FIFOs — refuses the whole install rather than being
|
|
9
|
+
* skipped or followed: an artifact is `manifest.json`, one library and two
|
|
10
|
+
* text files, and a link inside one is an attack, not a feature. Every entry
|
|
11
|
+
* name is confined to the destination (no absolute names, no `..`
|
|
12
|
+
* components, no escape once resolved), and a name that escapes is refused
|
|
13
|
+
* as corrupt rather than clamped.
|
|
13
14
|
*
|
|
14
15
|
* The archive is consumed as a stream: a 300 MB library is written to disk
|
|
15
16
|
* as it inflates and never sits in memory whole.
|
|
16
17
|
*/
|
|
17
|
-
import { createReadStream } from 'node:fs';
|
|
18
18
|
import { mkdir, open as openFile } from 'node:fs/promises';
|
|
19
19
|
import path from 'node:path';
|
|
20
20
|
import { Writable } from 'node:stream';
|
|
21
21
|
import { pipeline } from 'node:stream/promises';
|
|
22
|
-
import {
|
|
23
|
-
import { ArtifactCorruptError, FetchError } from './errors.js';
|
|
22
|
+
import { ArtifactCorruptError } from './ocifetch/errors.js';
|
|
24
23
|
const BLOCK = 512;
|
|
25
24
|
/** pax records and long names are tiny; a megabyte of them is not a tarball. */
|
|
26
25
|
const MAX_META = 1 << 20;
|
|
27
26
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
27
|
+
* Unpacks an **already-decompressed** (or still-to-decompress, via extra
|
|
28
|
+
* pipeline stages) tar byte stream into `dest`, which must already exist.
|
|
29
|
+
* `sources` is one readable, or a readable followed by transform stages (a
|
|
30
|
+
* decompressor) — passed to `pipeline` **as one array**, never chained with
|
|
31
|
+
* `.pipe()` first: `pipeline` is what makes an upstream failure (a truncated
|
|
32
|
+
* read, a zstd window-log refusal) actually reject this call, where `.pipe()`
|
|
33
|
+
* alone would leave the error unheard.
|
|
30
34
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
35
|
+
* The v1 fetch layer's own entry point (`ocifetch/unpack.ts` pipes its
|
|
36
|
+
* verified temp file through a zstd decompressor into this), so no
|
|
37
|
+
* compression format is assumed here.
|
|
38
|
+
*
|
|
39
|
+
* @throws {ArtifactCorruptError} for a header that fails its checksum, a truncated archive, an entry name that would land outside `dest`, an entry that is not a regular file or directory, plus
|
|
40
|
+
* `options`'s own.
|
|
34
41
|
*/
|
|
35
|
-
export async function
|
|
36
|
-
const extractor = new TarExtractor(path.resolve(dest));
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
});
|
|
46
|
-
}
|
|
42
|
+
export async function extractTarStream(sources, dest, options = {}) {
|
|
43
|
+
const extractor = new TarExtractor(path.resolve(dest), options);
|
|
44
|
+
const stages = Array.isArray(sources) ? sources : [sources];
|
|
45
|
+
// The array-form overload is typed as a fixed tuple
|
|
46
|
+
// `[Source, ...Transform[], Destination]`; `stages` is a plain array of
|
|
47
|
+
// dynamic length, which TS cannot shape-check against it, so this is a
|
|
48
|
+
// deliberate escape to the one overload that accepts a runtime array —
|
|
49
|
+
// the runtime behavior (verified: an upstream stage's error rejects this
|
|
50
|
+
// call) is what matters, not which overload TS resolves to.
|
|
51
|
+
await pipeline([...stages, extractor]);
|
|
47
52
|
return extractor.entries;
|
|
48
53
|
}
|
|
49
54
|
class TarExtractor extends Writable {
|
|
50
55
|
dest;
|
|
51
56
|
entries = [];
|
|
57
|
+
refuseDuplicateNames;
|
|
58
|
+
maxTotalBytes;
|
|
59
|
+
seenNames = new Set();
|
|
60
|
+
totalBytes = 0;
|
|
52
61
|
head = Buffer.alloc(BLOCK);
|
|
53
62
|
headFill = 0;
|
|
54
63
|
/** Data bytes still to consume for the current entry, then the block padding after them. */
|
|
@@ -60,9 +69,11 @@ class TarExtractor extends Writable {
|
|
|
60
69
|
nextSize = null;
|
|
61
70
|
zeroBlocks = 0;
|
|
62
71
|
ended = false;
|
|
63
|
-
constructor(dest) {
|
|
72
|
+
constructor(dest, options = {}) {
|
|
64
73
|
super();
|
|
65
74
|
this.dest = dest;
|
|
75
|
+
this.refuseDuplicateNames = options.refuseDuplicateNames ?? false;
|
|
76
|
+
this.maxTotalBytes = options.maxTotalBytes;
|
|
66
77
|
}
|
|
67
78
|
_write(chunk, _encoding, callback) {
|
|
68
79
|
this.consume(chunk).then(() => callback(), (err) => callback(err instanceof Error ? err : new Error(String(err))));
|
|
@@ -146,10 +157,15 @@ class TarExtractor extends Writable {
|
|
|
146
157
|
this.nextSize = null;
|
|
147
158
|
if (flag === 0x30 /* 0 */ || flag === 0x00 || flag === 0x37 /* 7 */) {
|
|
148
159
|
const target = this.confine(name, false);
|
|
160
|
+
const relName = path.relative(this.dest, target).split(path.sep).join('/');
|
|
161
|
+
if (this.refuseDuplicateNames && this.seenNames.has(relName)) {
|
|
162
|
+
throw new ArtifactCorruptError(`chtypes: tarball has a duplicate entry ${JSON.stringify(relName)}`);
|
|
163
|
+
}
|
|
164
|
+
this.seenNames.add(relName);
|
|
149
165
|
await mkdir(path.dirname(target), { recursive: true });
|
|
150
166
|
const handle = await openFile(target, 'w');
|
|
151
167
|
this.pending = { kind: 'file', handle };
|
|
152
|
-
this.entries.push({ name:
|
|
168
|
+
this.entries.push({ name: relName, size });
|
|
153
169
|
}
|
|
154
170
|
else if (flag === 0x35 /* 5 */) {
|
|
155
171
|
const target = this.confine(name, true);
|
|
@@ -158,8 +174,11 @@ class TarExtractor extends Writable {
|
|
|
158
174
|
this.pending = { kind: 'skip' };
|
|
159
175
|
}
|
|
160
176
|
else {
|
|
161
|
-
// Links, devices, FIFOs:
|
|
162
|
-
|
|
177
|
+
// Links, devices, FIFOs: an artifact is a manifest, one library and
|
|
178
|
+
// two text files, and a link inside one is an attack, not a feature
|
|
179
|
+
// — refused, never silently skipped (Go's untarGz default case and
|
|
180
|
+
// Python's _extract refuse the same way, naming the type).
|
|
181
|
+
throw new ArtifactCorruptError(`chtypes: tarball entry ${JSON.stringify(name)} is not a regular file or directory (type ${JSON.stringify(String.fromCharCode(flag))}); links and devices are refused, not unpacked`);
|
|
163
182
|
}
|
|
164
183
|
}
|
|
165
184
|
this.remaining = size;
|
|
@@ -172,6 +191,12 @@ class TarExtractor extends Writable {
|
|
|
172
191
|
if (p === null)
|
|
173
192
|
return;
|
|
174
193
|
if (p.kind === 'file') {
|
|
194
|
+
if (this.maxTotalBytes !== undefined) {
|
|
195
|
+
this.totalBytes += slice.length;
|
|
196
|
+
if (this.totalBytes > this.maxTotalBytes) {
|
|
197
|
+
throw new ArtifactCorruptError(`chtypes: tarball's unpacked size exceeds the ${this.maxTotalBytes}-byte limit`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
175
200
|
let written = 0;
|
|
176
201
|
while (written < slice.length) {
|
|
177
202
|
const r = await p.handle.write(slice, written, slice.length - written);
|
|
@@ -304,7 +329,4 @@ function paxRecords(payload) {
|
|
|
304
329
|
}
|
|
305
330
|
return out;
|
|
306
331
|
}
|
|
307
|
-
function errorText(err) {
|
|
308
|
-
return err instanceof Error ? err.message : String(err);
|
|
309
|
-
}
|
|
310
332
|
//# sourceMappingURL=tar.js.map
|