@cloudbitmaps/core 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -4
- package/dist/chunk-7GT632UF.js +641 -0
- package/dist/chunk-7GT632UF.js.map +7 -0
- package/dist/chunk-CGILDXGP.js +73 -0
- package/dist/chunk-CGILDXGP.js.map +7 -0
- package/dist/chunk-GKHERVVQ.js +121 -0
- package/dist/chunk-GKHERVVQ.js.map +7 -0
- package/dist/{chunk-OSU7W2Y3.js → chunk-MVUD4R72.js} +200 -756
- package/dist/chunk-MVUD4R72.js.map +7 -0
- package/dist/core/audit.d.ts +53 -15
- package/dist/core/bit-route.d.ts +2 -0
- package/dist/core/blob.d.ts +4 -0
- package/dist/core/budget.d.ts +8 -3
- package/dist/core/check.d.ts +49 -0
- package/dist/core/combine-many.d.ts +11 -0
- package/dist/core/consistency.d.ts +11 -2
- package/dist/core/cooperative.d.ts +7 -0
- package/dist/core/crbm-storage-source.d.ts +7 -4
- package/dist/core/crypto.d.ts +5 -0
- package/dist/core/discover.d.ts +5 -3
- package/dist/core/engine.d.ts +4 -4
- package/dist/core/erase-id.d.ts +35 -12
- package/dist/core/erasure.d.ts +61 -27
- package/dist/core/errors.d.ts +30 -0
- package/dist/core/leases.d.ts +2 -0
- package/dist/core/load-input.d.ts +48 -0
- package/dist/core/load.d.ts +23 -2
- package/dist/core/metrics.d.ts +21 -0
- package/dist/core/pinned-storage-source.d.ts +27 -8
- package/dist/core/pointer-id.d.ts +9 -0
- package/dist/core/ports.d.ts +100 -7
- package/dist/core/preflight.d.ts +80 -0
- package/dist/core/retention-sweep.d.ts +60 -15
- package/dist/core/retention.d.ts +17 -6
- package/dist/core/retry.d.ts +1 -2
- package/dist/core/rollback.d.ts +22 -12
- package/dist/core/validate.d.ts +33 -2
- package/dist/driver-kit.d.ts +3 -3
- package/dist/driver-kit.js +61 -20
- package/dist/driver-kit.js.map +2 -2
- package/dist/drivers/_shared/object-registry.d.ts +24 -1
- package/dist/drivers/_shared/options.d.ts +15 -7
- package/dist/drivers/backends.d.ts +17 -2
- package/dist/drivers/crypto.d.ts +17 -2
- package/dist/export/index.d.ts +16 -2
- package/dist/index.d.ts +10 -9
- package/dist/index.js +1743 -1701
- package/dist/index.js.map +4 -4
- package/dist/node.d.ts +14 -0
- package/dist/node.js +1064 -0
- package/dist/node.js.map +7 -0
- package/package.json +11 -2
- package/dist/chunk-OSU7W2Y3.js.map +0 -7
|
@@ -5,6 +5,7 @@ var NAMES = /* @__PURE__ */ new WeakMap();
|
|
|
5
5
|
var CloudRoaringError = class extends Error {
|
|
6
6
|
/** Cross-bundle brand — see {@link errorKind}. Non-enumerable-ish (symbol key ⇒ not in JSON). */
|
|
7
7
|
[ERROR_BRAND] = true;
|
|
8
|
+
/** Builds the error from `message`, and sets `name` to the class's name as written. */
|
|
8
9
|
constructor(message) {
|
|
9
10
|
super(message);
|
|
10
11
|
this.name = NAMES.get(new.target) ?? new.target.name;
|
|
@@ -24,6 +25,7 @@ var LeaseExpiredError = class extends CloudRoaringError {
|
|
|
24
25
|
until;
|
|
25
26
|
/** `'expired'` when the clock reached `until`, `'released'` after `release()`. */
|
|
26
27
|
reason;
|
|
28
|
+
/** Builds the error from its `message`, the epoch-ms the lease ran until, and why it ended. */
|
|
27
29
|
constructor(message, until, reason) {
|
|
28
30
|
super(message);
|
|
29
31
|
this.until = until;
|
|
@@ -33,11 +35,13 @@ var LeaseExpiredError = class extends CloudRoaringError {
|
|
|
33
35
|
var LeaseLimitError = class extends CloudRoaringError {
|
|
34
36
|
};
|
|
35
37
|
var StaleOperandError = class extends CloudRoaringError {
|
|
38
|
+
/** The stable code `'stale-operand'`, to match on. */
|
|
36
39
|
code = "stale-operand";
|
|
37
40
|
/** The operand's name in the call that found it stale. */
|
|
38
41
|
operand;
|
|
39
42
|
/** Why it is stale. */
|
|
40
43
|
reason;
|
|
44
|
+
/** Builds the error from its `message`, the operand's name and why it is stale. */
|
|
41
45
|
constructor(message, operand, reason) {
|
|
42
46
|
super(message);
|
|
43
47
|
this.operand = operand;
|
|
@@ -58,6 +62,7 @@ var BudgetExceededError = class extends CloudRoaringError {
|
|
|
58
62
|
* lower bound on the resident bytes it needs (`'maxBufferedBytes'`), or `limit + 1` (`'maxScanSegments'`).
|
|
59
63
|
*/
|
|
60
64
|
spent;
|
|
65
|
+
/** Builds the error from its `message` and the `option`, `limit` and `spent` it reports. */
|
|
61
66
|
constructor(message, details) {
|
|
62
67
|
super(message);
|
|
63
68
|
this.option = details.option;
|
|
@@ -70,6 +75,7 @@ var KeyUnavailableError = class extends CloudRoaringError {
|
|
|
70
75
|
var TransientError = class extends CloudRoaringError {
|
|
71
76
|
/** A second brand so a transient fault is classifiable cross-bundle. */
|
|
72
77
|
[TRANSIENT_BRAND] = true;
|
|
78
|
+
/** Builds the error from `message`; `options.cause`, when given, is kept as `cause`. */
|
|
73
79
|
constructor(message, options) {
|
|
74
80
|
super(message);
|
|
75
81
|
if (options && "cause" in options) this.cause = options.cause;
|
|
@@ -97,6 +103,15 @@ function isCloudRoaringError(err) {
|
|
|
97
103
|
function isWriteConflictError(err) {
|
|
98
104
|
return isCloudRoaringError(err) && err.name === "WriteConflictError";
|
|
99
105
|
}
|
|
106
|
+
var UNSETTLED_BRAND = /* @__PURE__ */ Symbol.for("cloudbitmaps.error.unsettled-conflict");
|
|
107
|
+
function unsettledConflict(message) {
|
|
108
|
+
const err = new WriteConflictError(message);
|
|
109
|
+
Object.defineProperty(err, UNSETTLED_BRAND, { value: true });
|
|
110
|
+
return err;
|
|
111
|
+
}
|
|
112
|
+
function isUnsettledConflict(err) {
|
|
113
|
+
return isWriteConflictError(err) && hasBrand(err, UNSETTLED_BRAND);
|
|
114
|
+
}
|
|
100
115
|
function isTransientError(err) {
|
|
101
116
|
return hasBrand(err, TRANSIENT_BRAND);
|
|
102
117
|
}
|
|
@@ -134,39 +149,6 @@ function errorKind(err) {
|
|
|
134
149
|
return typeof name === "string" && Object.hasOwn(KIND_NAMES, name) ? name : "CloudRoaringError";
|
|
135
150
|
}
|
|
136
151
|
|
|
137
|
-
// src/core/bit-route.ts
|
|
138
|
-
var U32_MAX = 4294967295;
|
|
139
|
-
var CHUNK_COUNT = 65536;
|
|
140
|
-
var LOW_16 = 65535;
|
|
141
|
-
var idErrors = /* @__PURE__ */ new WeakSet();
|
|
142
|
-
function isBadIdError(err) {
|
|
143
|
-
return err instanceof ValidationError && idErrors.has(err);
|
|
144
|
-
}
|
|
145
|
-
function badId(id) {
|
|
146
|
-
let got;
|
|
147
|
-
if (id === null) got = "null";
|
|
148
|
-
else if (id === void 0) got = "undefined";
|
|
149
|
-
else if (typeof id === "object") got = "an object";
|
|
150
|
-
else if (typeof id !== "number") got = `${/^[aeiou]/.test(typeof id) ? "an" : "a"} ${typeof id}`;
|
|
151
|
-
else if (!Number.isFinite(id)) got = "NaN or an infinity";
|
|
152
|
-
else if (id < 0) got = "a negative number";
|
|
153
|
-
else if (!Number.isInteger(id)) got = "a number with a fraction";
|
|
154
|
-
else got = `a number above ${U32_MAX} (ids are 32-bit)`;
|
|
155
|
-
const err = new ValidationError(`an id must be an integer from 0 to ${U32_MAX}; got ${got}`);
|
|
156
|
-
idErrors.add(err);
|
|
157
|
-
return err;
|
|
158
|
-
}
|
|
159
|
-
function splitId(id) {
|
|
160
|
-
if (!Number.isInteger(id) || id < 0 || id > U32_MAX) {
|
|
161
|
-
throw badId(id);
|
|
162
|
-
}
|
|
163
|
-
return { chunkKey: id >>> 16, remainder: id & LOW_16 };
|
|
164
|
-
}
|
|
165
|
-
var MAX_REMAINDER = CHUNK_COUNT - 1;
|
|
166
|
-
function joinId(chunkKey, remainder) {
|
|
167
|
-
return ((chunkKey & LOW_16) << 16 >>> 0) + (remainder & LOW_16);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
152
|
// src/core/check.ts
|
|
171
153
|
function shown(value) {
|
|
172
154
|
if (typeof value === "string") return JSON.stringify(value);
|
|
@@ -190,6 +172,11 @@ function requireInteger(value, bounds) {
|
|
|
190
172
|
}
|
|
191
173
|
return value;
|
|
192
174
|
}
|
|
175
|
+
function checkRequireEncryption(value) {
|
|
176
|
+
if (value !== void 0 && typeof value !== "boolean") {
|
|
177
|
+
throw new ValidationError(`requireEncryption must be a boolean; got ${shown(value)}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
193
180
|
function requirePositiveInteger(value, what) {
|
|
194
181
|
return requireInteger(value, { min: 1, what });
|
|
195
182
|
}
|
|
@@ -202,69 +189,71 @@ function requireFiniteNumber(value, bounds) {
|
|
|
202
189
|
}
|
|
203
190
|
return value;
|
|
204
191
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
results[i] = await fn(items[i], i);
|
|
219
|
-
} catch (err) {
|
|
220
|
-
if (!failed) {
|
|
221
|
-
failed = true;
|
|
222
|
-
firstError = err;
|
|
223
|
-
}
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
const workers = Array.from({ length: Math.min(limit, items.length) }, () => worker());
|
|
229
|
-
await Promise.all(workers);
|
|
230
|
-
if (failed) throw firstError;
|
|
231
|
-
return results;
|
|
192
|
+
function refuseUnknownOptions(name, options, keys, hint) {
|
|
193
|
+
if (options === null || typeof options !== "object") {
|
|
194
|
+
throw new ValidationError(
|
|
195
|
+
`${name} needs an options object \u2014 got ${options === null ? "null" : typeof options}`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
const unknown = Object.keys(options).filter((k) => !keys.includes(k));
|
|
199
|
+
if (unknown.length > 0) {
|
|
200
|
+
const list = (ks) => ks.map((k) => `\`${k}\``).join(", ");
|
|
201
|
+
throw new ValidationError(
|
|
202
|
+
`${name} does not take ${list(unknown)}. It takes ${list(keys)}${hint === void 0 ? "" : `; ${hint}`}.`
|
|
203
|
+
);
|
|
204
|
+
}
|
|
232
205
|
}
|
|
233
|
-
function
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
return Promise.reject(err);
|
|
206
|
+
function requireBool(name, value) {
|
|
207
|
+
if (value === void 0) return void 0;
|
|
208
|
+
if (typeof value !== "boolean") {
|
|
209
|
+
throw new ValidationError(`${name} must be a boolean; got ${shown(value)}`);
|
|
238
210
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
}
|
|
211
|
+
return value;
|
|
212
|
+
}
|
|
213
|
+
function requireNonEmptyString(name, value) {
|
|
214
|
+
if (value === void 0) return void 0;
|
|
215
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
216
|
+
throw new ValidationError(
|
|
217
|
+
`${name} must be a non-empty string; got ${typeof value === "string" ? "an empty string" : shown(value)}`
|
|
218
|
+
);
|
|
248
219
|
}
|
|
249
|
-
return
|
|
220
|
+
return value;
|
|
250
221
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
222
|
+
|
|
223
|
+
// src/core/bit-route.ts
|
|
224
|
+
var U32_MAX = 4294967295;
|
|
225
|
+
var CHUNK_COUNT = 65536;
|
|
226
|
+
var LOW_16 = 65535;
|
|
227
|
+
var idErrors = /* @__PURE__ */ new WeakSet();
|
|
228
|
+
function isBadIdError(err) {
|
|
229
|
+
return err instanceof ValidationError && idErrors.has(err);
|
|
230
|
+
}
|
|
231
|
+
function badId(id) {
|
|
232
|
+
let got;
|
|
233
|
+
if (id === null) got = "null";
|
|
234
|
+
else if (id === void 0) got = "undefined";
|
|
235
|
+
else if (typeof id === "object") got = "an object";
|
|
236
|
+
else if (typeof id !== "number") got = `${/^[aeiou]/.test(typeof id) ? "an" : "a"} ${typeof id}`;
|
|
237
|
+
else if (!Number.isFinite(id)) got = "NaN or an infinity";
|
|
238
|
+
else if (id < 0) got = "a negative number";
|
|
239
|
+
else if (!Number.isInteger(id)) got = "a number with a fraction";
|
|
240
|
+
else got = `a number above ${U32_MAX} (ids are 32-bit)`;
|
|
241
|
+
const err = new ValidationError(`an id must be an integer from 0 to ${U32_MAX}; got ${got}`);
|
|
242
|
+
idErrors.add(err);
|
|
243
|
+
return err;
|
|
244
|
+
}
|
|
245
|
+
function refusalOfId(id) {
|
|
246
|
+
return badId(id);
|
|
247
|
+
}
|
|
248
|
+
function splitId(id) {
|
|
249
|
+
if (!Number.isInteger(id) || id < 0 || id > U32_MAX) {
|
|
250
|
+
throw badId(id);
|
|
251
|
+
}
|
|
252
|
+
return { chunkKey: id >>> 16, remainder: id & LOW_16 };
|
|
253
|
+
}
|
|
254
|
+
var MAX_REMAINDER = CHUNK_COUNT - 1;
|
|
255
|
+
function joinId(chunkKey, remainder) {
|
|
256
|
+
return ((chunkKey & LOW_16) << 16 >>> 0) + (remainder & LOW_16);
|
|
268
257
|
}
|
|
269
258
|
|
|
270
259
|
// src/core/name-codec.ts
|
|
@@ -359,6 +348,7 @@ function validatePart(value, field) {
|
|
|
359
348
|
);
|
|
360
349
|
}
|
|
361
350
|
}
|
|
351
|
+
var REF_KEYS = ["segment", "namespace", "currentGen", "status"];
|
|
362
352
|
function requireRefObject(ref, hint = "") {
|
|
363
353
|
if (typeof ref !== "object" || ref === null) {
|
|
364
354
|
throw new ValidationError(`a segment ref is an object such as { segment: 'name' }${hint}`);
|
|
@@ -366,6 +356,7 @@ function requireRefObject(ref, hint = "") {
|
|
|
366
356
|
}
|
|
367
357
|
function validateSegmentRef(ref) {
|
|
368
358
|
requireRefObject(ref);
|
|
359
|
+
refuseUnknownKeys(ref);
|
|
369
360
|
validatePart(ref.segment, "segment");
|
|
370
361
|
if (ref.namespace !== void 0) validatePart(ref.namespace, "namespace");
|
|
371
362
|
}
|
|
@@ -381,8 +372,56 @@ function validateUserNamespace(namespace) {
|
|
|
381
372
|
);
|
|
382
373
|
}
|
|
383
374
|
}
|
|
384
|
-
|
|
375
|
+
var PORT_KEYS = [
|
|
376
|
+
"generation",
|
|
377
|
+
"chunkKey",
|
|
378
|
+
"wrappedDeks",
|
|
379
|
+
"keyId",
|
|
380
|
+
"retention",
|
|
381
|
+
"residency",
|
|
382
|
+
"summary",
|
|
383
|
+
"knownGens",
|
|
384
|
+
"leases",
|
|
385
|
+
"createdAt",
|
|
386
|
+
"updatedAt",
|
|
387
|
+
"token",
|
|
388
|
+
"pointerId"
|
|
389
|
+
];
|
|
390
|
+
var SEGMENT_HANDLE_MARK = /* @__PURE__ */ Symbol.for("cloudbitmaps.roaring.segment/1");
|
|
391
|
+
function unknownKeysOf(ref, extraKeys) {
|
|
392
|
+
return Object.keys(ref).filter(
|
|
393
|
+
(k) => !REF_KEYS.includes(k) && !extraKeys.includes(k)
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
function refuseUnknownKeys(ref) {
|
|
397
|
+
const unknown = unknownKeysOf(ref, PORT_KEYS);
|
|
398
|
+
if (unknown.length === 0) return;
|
|
399
|
+
const list = unknown.map((k) => `"${k}"`).join(", ");
|
|
400
|
+
throw new ValidationError(
|
|
401
|
+
`a driver port: unknown ${unknown.length === 1 ? "key" : "keys"} ${list} in the segment ref; it takes { segment, namespace } and a generation key's \`generation\`, a chunk ref's \`chunkKey\`, a \`segments()\` row's \`currentGen\` and \`status\`, or a registry row's own fields (a segment addressed without its namespace is a different segment)`
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
function refuseUnknownRefKeys(ref, verb, extraKeys = []) {
|
|
405
|
+
if (ref[SEGMENT_HANDLE_MARK] === true) {
|
|
406
|
+
throw new ValidationError(
|
|
407
|
+
`${verb}: a segment handle is not a ref; pass { segment, namespace }`
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
if (Array.isArray(ref)) {
|
|
411
|
+
throw new ValidationError(
|
|
412
|
+
`${verb}: a segment ref is an object such as { segment: 'name' }, not an array`
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
const unknown = unknownKeysOf(ref, extraKeys);
|
|
416
|
+
if (unknown.length === 0) return;
|
|
417
|
+
const list = unknown.map((k) => `"${k}"`).join(", ");
|
|
418
|
+
throw new ValidationError(
|
|
419
|
+
`${verb}: unknown ${unknown.length === 1 ? "key" : "keys"} ${list} in the segment ref; a ref takes { segment, namespace } (and a \`segments()\` row's \`currentGen\` and \`status\`, which are read for nothing); a segment addressed without its namespace is a different segment`
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
function validateUserRef(ref, verb, extraKeys = []) {
|
|
385
423
|
requireRefObject(ref, "; store.segment() takes the bare name");
|
|
424
|
+
if (verb !== void 0) refuseUnknownRefKeys(ref, verb, extraKeys);
|
|
386
425
|
validatePart(ref.segment, "segment");
|
|
387
426
|
if (ref.namespace !== void 0) validateUserNamespace(ref.namespace);
|
|
388
427
|
}
|
|
@@ -445,6 +484,22 @@ function isStorageBackend(value) {
|
|
|
445
484
|
return typeof value === "object" && value !== null && value[STORAGE_BACKEND_BRAND] === true;
|
|
446
485
|
}
|
|
447
486
|
|
|
487
|
+
// src/core/token.ts
|
|
488
|
+
var INCARNATION_TOKEN = /^([0-9a-f]{32})\.(0|[1-9]\d*)\.([0-9a-f]{16})$/;
|
|
489
|
+
function incarnationOf(token) {
|
|
490
|
+
return INCARNATION_TOKEN.exec(token)?.[1];
|
|
491
|
+
}
|
|
492
|
+
function incarnationField(token) {
|
|
493
|
+
const incarnation = token === void 0 ? void 0 : incarnationOf(token);
|
|
494
|
+
return incarnation === void 0 ? {} : { incarnation };
|
|
495
|
+
}
|
|
496
|
+
function sameIncarnation(a, b) {
|
|
497
|
+
const ia = incarnationOf(a.token);
|
|
498
|
+
const ib = incarnationOf(b.token);
|
|
499
|
+
if (ia !== void 0 || ib !== void 0) return ia === ib;
|
|
500
|
+
return a.createdAt === b.createdAt;
|
|
501
|
+
}
|
|
502
|
+
|
|
448
503
|
// src/core/pointer-id.ts
|
|
449
504
|
var RESOLVED_FIELDS = [
|
|
450
505
|
"currentGen",
|
|
@@ -468,6 +523,11 @@ function pointerIdOf(row) {
|
|
|
468
523
|
}
|
|
469
524
|
return pointerId;
|
|
470
525
|
}
|
|
526
|
+
function pointerSetBy(now, before, generation, sent) {
|
|
527
|
+
if (now === null || now.status === "destroyed" || now.currentGen !== generation) return false;
|
|
528
|
+
if (before !== null && !sameIncarnation(before, now)) return false;
|
|
529
|
+
return sent.has(now.pointerId);
|
|
530
|
+
}
|
|
471
531
|
|
|
472
532
|
// src/core/crypto.ts
|
|
473
533
|
var UTF82 = new TextEncoder();
|
|
@@ -560,22 +620,6 @@ async function withRetry(op, policy, deps) {
|
|
|
560
620
|
throw lastErr;
|
|
561
621
|
}
|
|
562
622
|
|
|
563
|
-
// src/core/token.ts
|
|
564
|
-
var INCARNATION_TOKEN = /^([0-9a-f]{32})\.(0|[1-9]\d*)\.([0-9a-f]{16})$/;
|
|
565
|
-
function incarnationOf(token) {
|
|
566
|
-
return INCARNATION_TOKEN.exec(token)?.[1];
|
|
567
|
-
}
|
|
568
|
-
function incarnationField(token) {
|
|
569
|
-
const incarnation = token === void 0 ? void 0 : incarnationOf(token);
|
|
570
|
-
return incarnation === void 0 ? {} : { incarnation };
|
|
571
|
-
}
|
|
572
|
-
function sameIncarnation(a, b) {
|
|
573
|
-
const ia = incarnationOf(a.token);
|
|
574
|
-
const ib = incarnationOf(b.token);
|
|
575
|
-
if (ia !== void 0 || ib !== void 0) return ia === ib;
|
|
576
|
-
return a.createdAt === b.createdAt;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
623
|
// src/core/leases.ts
|
|
580
624
|
var MAX_LEASE_MS = 14 * 864e5;
|
|
581
625
|
var LEASE_SKEW_MS = 6e4;
|
|
@@ -742,53 +786,6 @@ async function releaseLease(ref, deps, holder) {
|
|
|
742
786
|
);
|
|
743
787
|
}
|
|
744
788
|
|
|
745
|
-
// src/drivers/_shared/keys.ts
|
|
746
|
-
var DEFAULT_NAMESPACE = "_default";
|
|
747
|
-
function namespaceKeyPart(namespace) {
|
|
748
|
-
return namespace === void 0 ? DEFAULT_NAMESPACE : encodeNameForKey(namespace);
|
|
749
|
-
}
|
|
750
|
-
function namespacePathPart(namespace) {
|
|
751
|
-
return namespace === void 0 ? DEFAULT_NAMESPACE : encodeNameForPath(namespace);
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
// src/drivers/_shared/options.ts
|
|
755
|
-
function refuseUnknownOptions(name, options, keys, hint) {
|
|
756
|
-
if (options === null || typeof options !== "object") {
|
|
757
|
-
throw new ValidationError(
|
|
758
|
-
`${name} needs an options object \u2014 got ${options === null ? "null" : typeof options}`
|
|
759
|
-
);
|
|
760
|
-
}
|
|
761
|
-
const unknown = Object.keys(options).filter((k) => !keys.includes(k));
|
|
762
|
-
if (unknown.length > 0) {
|
|
763
|
-
const list = (ks) => ks.map((k) => `\`${k}\``).join(", ");
|
|
764
|
-
throw new ValidationError(
|
|
765
|
-
`${name} does not take ${list(unknown)}. It takes ${list(keys)}${hint === void 0 ? "" : `; ${hint}`}.`
|
|
766
|
-
);
|
|
767
|
-
}
|
|
768
|
-
}
|
|
769
|
-
function checkNow(name, now) {
|
|
770
|
-
if (now !== void 0 && typeof now !== "function") {
|
|
771
|
-
throw new ValidationError(`${name}: \`now\` must be a function returning epoch milliseconds`);
|
|
772
|
-
}
|
|
773
|
-
}
|
|
774
|
-
function requirePositiveInt(name, value) {
|
|
775
|
-
return value === void 0 ? void 0 : requirePositiveInteger(value, name);
|
|
776
|
-
}
|
|
777
|
-
function requireBool(name, value) {
|
|
778
|
-
if (value === void 0) return void 0;
|
|
779
|
-
if (typeof value !== "boolean") {
|
|
780
|
-
throw new ValidationError(`${name} must be a boolean; got ${shown2(value)}`);
|
|
781
|
-
}
|
|
782
|
-
return value;
|
|
783
|
-
}
|
|
784
|
-
function shown2(value) {
|
|
785
|
-
if (typeof value === "string") return JSON.stringify(value);
|
|
786
|
-
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") {
|
|
787
|
-
return String(value);
|
|
788
|
-
}
|
|
789
|
-
return value === null ? "null" : typeof value;
|
|
790
|
-
}
|
|
791
|
-
|
|
792
789
|
// src/core/crbm/frame.ts
|
|
793
790
|
var PREAMBLE_BYTES = 8;
|
|
794
791
|
var FOOTER_BYTES = 104;
|
|
@@ -1067,35 +1064,6 @@ function ownSummary(ref, generation, description, aead) {
|
|
|
1067
1064
|
return summary;
|
|
1068
1065
|
}
|
|
1069
1066
|
|
|
1070
|
-
// src/core/known-generations-shape.ts
|
|
1071
|
-
var ENTRY_KEYS = ["generation", "footerCrc"];
|
|
1072
|
-
function knownGensShapeFault(value, max, show = String) {
|
|
1073
|
-
if (value === void 0) return void 0;
|
|
1074
|
-
if (!Array.isArray(value)) return "must be an array";
|
|
1075
|
-
const list = value;
|
|
1076
|
-
if (list.length > max) return `has ${list.length} entries, cap ${max}`;
|
|
1077
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1078
|
-
for (const e of list) {
|
|
1079
|
-
if (typeof e !== "object" || e === null || Array.isArray(e))
|
|
1080
|
-
return "an entry must be an object";
|
|
1081
|
-
const entry = e;
|
|
1082
|
-
const extra = Object.keys(entry).filter((k) => !ENTRY_KEYS.includes(k));
|
|
1083
|
-
if (extra.length > 0) {
|
|
1084
|
-
return `an entry carries an undeclared field (${show(extra.join(", "))})`;
|
|
1085
|
-
}
|
|
1086
|
-
const { generation, footerCrc } = entry;
|
|
1087
|
-
if (!Number.isSafeInteger(generation) || generation < 0) {
|
|
1088
|
-
return `a generation must be a non-negative safe integer (got ${show(generation)})`;
|
|
1089
|
-
}
|
|
1090
|
-
if (!Number.isInteger(footerCrc) || footerCrc < 0 || footerCrc > 4294967295) {
|
|
1091
|
-
return `a footerCrc must be an integer from 0 to 2^32 - 1 (got ${show(footerCrc)})`;
|
|
1092
|
-
}
|
|
1093
|
-
if (seen.has(generation)) return `generation ${String(generation)} is repeated`;
|
|
1094
|
-
seen.add(generation);
|
|
1095
|
-
}
|
|
1096
|
-
return void 0;
|
|
1097
|
-
}
|
|
1098
|
-
|
|
1099
1067
|
// src/core/order.ts
|
|
1100
1068
|
var ascending = (a, b) => a - b;
|
|
1101
1069
|
|
|
@@ -1248,553 +1216,33 @@ function leasedByRow(record) {
|
|
|
1248
1216
|
return new Set((record.leases ?? []).map((e) => e.generation));
|
|
1249
1217
|
}
|
|
1250
1218
|
|
|
1251
|
-
// src/
|
|
1252
|
-
var
|
|
1253
|
-
|
|
1254
|
-
"namespace",
|
|
1255
|
-
"segment",
|
|
1256
|
-
"currentGen",
|
|
1257
|
-
"wrappedDeks",
|
|
1258
|
-
"keyId",
|
|
1259
|
-
"status",
|
|
1260
|
-
"retention",
|
|
1261
|
-
"residency",
|
|
1262
|
-
"summary",
|
|
1263
|
-
"createdAt",
|
|
1264
|
-
"updatedAt",
|
|
1265
|
-
"token",
|
|
1266
|
-
"knownGens",
|
|
1267
|
-
"leases",
|
|
1268
|
-
"pointerId"
|
|
1269
|
-
];
|
|
1270
|
-
var DRIVER_MANAGED = ["token", "pointerId"];
|
|
1271
|
-
var ENVELOPE_FIELDS = ["schemaVersion", "deleted", "record"];
|
|
1272
|
-
var MAX_GOVERNANCE_BYTES = 64 * 1024;
|
|
1273
|
-
var MAX_WRAPPED_DEKS = 8;
|
|
1274
|
-
var MAX_WRAPPED_DEK_BYTES = 4 * 1024;
|
|
1275
|
-
var SEALED_SUMMARY_MIN_BYTES = 12 + 8 + 8 + 4 + 4 + 16;
|
|
1276
|
-
var SEALED_SUMMARY_MAX_BYTES = SEALED_SUMMARY_MIN_BYTES + MAX_METADATA_BYTES;
|
|
1277
|
-
var BASE642 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
|
|
1278
|
-
function validateGeneration(gen) {
|
|
1279
|
-
if (gen === null) return;
|
|
1280
|
-
if (!Number.isSafeInteger(gen) || gen < 0) {
|
|
1281
|
-
throw new ValidationError(
|
|
1282
|
-
`currentGen must be a non-negative safe integer or null (no Storage generation yet); got ${gen}`
|
|
1283
|
-
);
|
|
1284
|
-
}
|
|
1285
|
-
}
|
|
1286
|
-
function validatePatchGeneration(patch) {
|
|
1287
|
-
if (!("currentGen" in patch)) return;
|
|
1288
|
-
if (patch.currentGen === void 0) {
|
|
1289
|
-
throw new ValidationError(
|
|
1290
|
-
`currentGen was present in the patch but undefined. Pass \`null\` to clear the pointer (the segment has no Storage generation), or omit the key to leave it unchanged \u2014 an undefined value is refused because it would un-publish the segment's Storage data.`
|
|
1291
|
-
);
|
|
1292
|
-
}
|
|
1293
|
-
validateGeneration(patch.currentGen);
|
|
1294
|
-
}
|
|
1295
|
-
function validateStatus(status) {
|
|
1296
|
-
if (!STATUSES.includes(status)) {
|
|
1297
|
-
throw new ValidationError(`status must be one of ${STATUSES.join("/")}; got ${status}`);
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
function validateGovernance(meta, field) {
|
|
1301
|
-
if (meta === void 0) return;
|
|
1302
|
-
if (meta === null || typeof meta !== "object" || Array.isArray(meta)) {
|
|
1303
|
-
throw new ValidationError(
|
|
1304
|
-
`${field} must be a plain object (got ${meta === null ? "null" : typeof meta})`
|
|
1305
|
-
);
|
|
1306
|
-
}
|
|
1307
|
-
let json;
|
|
1308
|
-
try {
|
|
1309
|
-
json = JSON.stringify(meta);
|
|
1310
|
-
} catch {
|
|
1311
|
-
throw new ValidationError(`${field} must be JSON-serializable`);
|
|
1312
|
-
}
|
|
1313
|
-
if (json.length > MAX_GOVERNANCE_BYTES) {
|
|
1314
|
-
throw new ValidationError(`${field} is ${json.length}B, exceeds cap ${MAX_GOVERNANCE_BYTES}B`);
|
|
1315
|
-
}
|
|
1316
|
-
}
|
|
1317
|
-
function validateWrappedDeks(value, origin) {
|
|
1318
|
-
if (value === void 0) return;
|
|
1319
|
-
const fail = (msg) => {
|
|
1320
|
-
throw origin === "stored" ? new IntegrityError(msg) : new ValidationError(msg);
|
|
1321
|
-
};
|
|
1322
|
-
if (!Array.isArray(value)) fail("wrappedDeks must be an array");
|
|
1323
|
-
const list = value;
|
|
1324
|
-
if (list.length === 0) fail("wrappedDeks must be non-empty when present");
|
|
1325
|
-
if (list.length > MAX_WRAPPED_DEKS)
|
|
1326
|
-
fail(`wrappedDeks has ${list.length} entries, cap ${MAX_WRAPPED_DEKS}`);
|
|
1327
|
-
for (const w of list) {
|
|
1328
|
-
if (w === null || typeof w !== "object") fail("wrappedDeks entry must be an object");
|
|
1329
|
-
const { keyId, wrapped } = w;
|
|
1330
|
-
if (typeof keyId !== "string" || keyId.length === 0)
|
|
1331
|
-
fail("wrappedDeks entry needs a non-empty keyId");
|
|
1332
|
-
if (typeof wrapped !== "string" || wrapped.length === 0)
|
|
1333
|
-
fail("wrappedDeks entry needs a non-empty wrapped blob");
|
|
1334
|
-
if (wrapped.length > MAX_WRAPPED_DEK_BYTES)
|
|
1335
|
-
fail(`wrappedDeks entry is ${wrapped.length}B, cap ${MAX_WRAPPED_DEK_BYTES}B`);
|
|
1336
|
-
}
|
|
1337
|
-
}
|
|
1338
|
-
var BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
1339
|
-
function base64PadBitsAreZero(text) {
|
|
1340
|
-
const pad = text.endsWith("==") ? 2 : text.endsWith("=") ? 1 : 0;
|
|
1341
|
-
if (pad === 0) return true;
|
|
1342
|
-
const last = BASE64_ALPHABET.indexOf(text[text.length - pad - 1]);
|
|
1343
|
-
return pad === 2 ? (last & 15) === 0 : (last & 3) === 0;
|
|
1344
|
-
}
|
|
1345
|
-
function validateSummary(value, origin, ctx) {
|
|
1346
|
-
if (value === void 0) return void 0;
|
|
1347
|
-
const fail = (msg) => {
|
|
1348
|
-
const where = ctx === void 0 ? "" : `: ${ctx}`;
|
|
1349
|
-
throw origin === "stored" ? new IntegrityError(`registry record summary: ${msg}${where}`) : new ValidationError(`summary: ${msg}${where}`);
|
|
1350
|
-
};
|
|
1351
|
-
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
1352
|
-
fail(
|
|
1353
|
-
`must be an object (got ${value === null ? "null" : Array.isArray(value) ? "an array" : typeof value})`
|
|
1354
|
-
);
|
|
1355
|
-
}
|
|
1356
|
-
const s = value;
|
|
1357
|
-
const keys = Object.keys(s);
|
|
1358
|
-
const isSealed = keys.includes("sealed");
|
|
1359
|
-
const allowed = isSealed ? ["generation", "sealed"] : ["generation", "cardinality", "fingerprint", "tailBytes", "metadata"];
|
|
1360
|
-
const extra = keys.filter((k) => !allowed.includes(k));
|
|
1361
|
-
if (extra.length > 0) {
|
|
1362
|
-
fail(
|
|
1363
|
-
`has fields its ${isSealed ? "sealed" : "clear"} shape does not declare (${extra.join(", ")})`
|
|
1364
|
-
);
|
|
1365
|
-
}
|
|
1366
|
-
const generation = s.generation;
|
|
1367
|
-
if (!Number.isSafeInteger(generation) || generation < 0) {
|
|
1368
|
-
fail(`generation must be a non-negative safe integer (got ${String(generation)})`);
|
|
1369
|
-
}
|
|
1370
|
-
if (isSealed) {
|
|
1371
|
-
const sealed = s.sealed;
|
|
1372
|
-
if (typeof sealed !== "string" || !BASE642.test(sealed) || !base64PadBitsAreZero(sealed)) {
|
|
1373
|
-
fail("sealed must be canonical, padded standard base64");
|
|
1374
|
-
}
|
|
1375
|
-
const text = sealed;
|
|
1376
|
-
const bytes = text.length / 4 * 3 - (text.endsWith("==") ? 2 : text.endsWith("=") ? 1 : 0);
|
|
1377
|
-
if (bytes < SEALED_SUMMARY_MIN_BYTES || bytes > SEALED_SUMMARY_MAX_BYTES) {
|
|
1378
|
-
fail(
|
|
1379
|
-
`sealed is ${bytes}B, outside ${SEALED_SUMMARY_MIN_BYTES}..${SEALED_SUMMARY_MAX_BYTES}B (a nonce, a fixed-width count, fingerprint and tail size, a tag, and metadata up to its cap)`
|
|
1380
|
-
);
|
|
1381
|
-
}
|
|
1382
|
-
return Object.freeze({ generation, sealed: text });
|
|
1383
|
-
}
|
|
1384
|
-
const n = s.cardinality;
|
|
1385
|
-
if (!Number.isInteger(n) || n < 0 || n > MAX_SUMMARY_CARDINALITY) {
|
|
1386
|
-
fail(`cardinality must be an integer from 0 to 2^32 (got ${String(n)})`);
|
|
1387
|
-
}
|
|
1388
|
-
const fingerprint = s.fingerprint;
|
|
1389
|
-
const parts = fingerprintParts(fingerprint);
|
|
1390
|
-
if (parts === void 0) {
|
|
1391
|
-
fail(
|
|
1392
|
-
`fingerprint must be an object's, <size>:<footer checksum> in decimal (got ${shown3(JSON.stringify(fingerprint))})`
|
|
1393
|
-
);
|
|
1394
|
-
}
|
|
1395
|
-
const tailBytes = s.tailBytes;
|
|
1396
|
-
if (!tailBytesFit(tailBytes, parts.size)) {
|
|
1397
|
-
fail(
|
|
1398
|
-
`tailBytes must be an integer from the footer's size to the object's size less its preamble, and at most the cap of one open's tail read (got ${shown3(JSON.stringify(tailBytes))} for an object of ${parts.size} bytes)`
|
|
1399
|
-
);
|
|
1400
|
-
}
|
|
1401
|
-
if (s.metadata === void 0) {
|
|
1402
|
-
return Object.freeze({
|
|
1403
|
-
generation,
|
|
1404
|
-
cardinality: n,
|
|
1405
|
-
fingerprint,
|
|
1406
|
-
tailBytes
|
|
1407
|
-
});
|
|
1408
|
-
}
|
|
1409
|
-
const canonical = canonicalMetadataJson(s.metadata, fail);
|
|
1410
|
-
if (canonical === "{}") fail("metadata is empty; a generation without metadata carries none");
|
|
1411
|
-
if (origin === "stored") return s;
|
|
1412
|
-
const metadata = Object.freeze(JSON.parse(canonical));
|
|
1413
|
-
return Object.freeze({
|
|
1414
|
-
generation,
|
|
1415
|
-
cardinality: n,
|
|
1416
|
-
fingerprint,
|
|
1417
|
-
tailBytes,
|
|
1418
|
-
metadata
|
|
1419
|
-
});
|
|
1420
|
-
}
|
|
1421
|
-
function validateSummaryNames(summary, currentGen) {
|
|
1422
|
-
if (summary !== void 0 && summary.generation !== currentGen) {
|
|
1423
|
-
throw new ValidationError(
|
|
1424
|
-
`summary describes generation ${summary.generation}, but the row points at ${String(currentGen)}`
|
|
1425
|
-
);
|
|
1426
|
-
}
|
|
1427
|
-
}
|
|
1428
|
-
function summaryAgreesWithKeys(summary, wrappedDeks) {
|
|
1429
|
-
return "sealed" in summary === (wrappedDeks !== void 0);
|
|
1430
|
-
}
|
|
1431
|
-
function validateSummaryKeys(summary, wrappedDeks) {
|
|
1432
|
-
if (summary !== void 0 && !summaryAgreesWithKeys(summary, wrappedDeks)) {
|
|
1433
|
-
throw new ValidationError(
|
|
1434
|
-
wrappedDeks === void 0 ? "summary is sealed, but the row has no wrapped keys to open it with" : "summary is in the clear, but the row is encrypted: an encrypted segment's summary must be sealed"
|
|
1435
|
-
);
|
|
1436
|
-
}
|
|
1437
|
-
}
|
|
1438
|
-
function validateKnownGens(value, origin, ctx) {
|
|
1439
|
-
if (value === void 0) return void 0;
|
|
1440
|
-
const fail = (msg) => {
|
|
1441
|
-
const where = ctx === void 0 ? "" : `: ${ctx}`;
|
|
1442
|
-
throw origin === "stored" ? new IntegrityError(`registry record knownGens: ${msg}${where}`) : new ValidationError(`knownGens: ${msg}`);
|
|
1443
|
-
};
|
|
1444
|
-
const max = origin === "stored" ? MAX_STORED_KNOWN_GENERATIONS : MAX_KNOWN_GENERATIONS;
|
|
1445
|
-
const fault = knownGensShapeFault(value, max, shown3);
|
|
1446
|
-
if (fault !== void 0) fail(fault);
|
|
1447
|
-
const out = [];
|
|
1448
|
-
for (const entry of value) {
|
|
1449
|
-
out.push(
|
|
1450
|
-
origin === "stored" ? entry : Object.freeze({ generation: entry.generation, footerCrc: entry.footerCrc })
|
|
1451
|
-
);
|
|
1452
|
-
}
|
|
1453
|
-
return origin === "stored" ? out : Object.freeze(out);
|
|
1454
|
-
}
|
|
1455
|
-
var HOLDER = /^[0-9a-f]{16}$/;
|
|
1456
|
-
var LEASE_ENTRY_KEYS = ["holder", "generation", "until"];
|
|
1457
|
-
function validateLeases(value, origin, ctx) {
|
|
1219
|
+
// src/core/known-generations-shape.ts
|
|
1220
|
+
var ENTRY_KEYS = ["generation", "footerCrc"];
|
|
1221
|
+
function knownGensShapeFault(value, max, show = String) {
|
|
1458
1222
|
if (value === void 0) return void 0;
|
|
1459
|
-
|
|
1460
|
-
const where = ctx === void 0 ? "" : `: ${ctx}`;
|
|
1461
|
-
throw origin === "stored" ? new IntegrityError(`registry record leases: ${msg}${where}`) : new ValidationError(`leases: ${msg}`);
|
|
1462
|
-
};
|
|
1463
|
-
if (!Array.isArray(value)) fail("must be an array");
|
|
1223
|
+
if (!Array.isArray(value)) return "must be an array";
|
|
1464
1224
|
const list = value;
|
|
1465
|
-
|
|
1466
|
-
if (list.length > max) fail(`has ${list.length} entries, cap ${max}`);
|
|
1225
|
+
if (list.length > max) return `has ${list.length} entries, cap ${max}`;
|
|
1467
1226
|
const seen = /* @__PURE__ */ new Set();
|
|
1468
|
-
const out = [];
|
|
1469
1227
|
for (const e of list) {
|
|
1470
|
-
if (typeof e !== "object" || e === null || Array.isArray(e))
|
|
1228
|
+
if (typeof e !== "object" || e === null || Array.isArray(e))
|
|
1229
|
+
return "an entry must be an object";
|
|
1471
1230
|
const entry = e;
|
|
1472
|
-
const extra = Object.keys(entry).filter((k) => !
|
|
1473
|
-
if (extra.length > 0)
|
|
1474
|
-
|
|
1475
|
-
if (typeof holder !== "string" || !HOLDER.test(holder)) {
|
|
1476
|
-
fail("a holder must be 16 lowercase hex digits");
|
|
1477
|
-
}
|
|
1478
|
-
if (seen.has(holder)) fail("holders must be unique");
|
|
1479
|
-
seen.add(holder);
|
|
1480
|
-
for (const [name, n] of [
|
|
1481
|
-
["generation", generation],
|
|
1482
|
-
["until", until]
|
|
1483
|
-
]) {
|
|
1484
|
-
if (!Number.isSafeInteger(n) || n < 0) {
|
|
1485
|
-
fail(`${name} must be a non-negative safe integer (got ${String(n)})`);
|
|
1486
|
-
}
|
|
1231
|
+
const extra = Object.keys(entry).filter((k) => !ENTRY_KEYS.includes(k));
|
|
1232
|
+
if (extra.length > 0) {
|
|
1233
|
+
return `an entry carries an undeclared field (${show(extra.join(", "))})`;
|
|
1487
1234
|
}
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
generation,
|
|
1492
|
-
until
|
|
1493
|
-
})
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
if (origin === "stored") return out;
|
|
1497
|
-
return out.length === 0 ? void 0 : Object.freeze(out);
|
|
1498
|
-
}
|
|
1499
|
-
function validateLeasesPointer(leases, currentGen) {
|
|
1500
|
-
if (leases !== void 0 && leases.length > 0 && currentGen === null) {
|
|
1501
|
-
throw new ValidationError("leases: a row with no pointer has no generation to lease");
|
|
1502
|
-
}
|
|
1503
|
-
}
|
|
1504
|
-
function validateKnownGensFit(knownGens, currentGen, summary) {
|
|
1505
|
-
if (knownGens === void 0) return;
|
|
1506
|
-
if (currentGen === null) {
|
|
1507
|
-
throw new ValidationError("knownGens: a row with no pointer has no generation to know");
|
|
1508
|
-
}
|
|
1509
|
-
const last = knownGens[knownGens.length - 1];
|
|
1510
|
-
if (last === void 0 || last.generation !== currentGen) {
|
|
1511
|
-
throw new ValidationError(
|
|
1512
|
-
`knownGens must end with the row's pointer ${currentGen}, in the order the generations were made current (its last entry is ${last === void 0 ? "missing" : last.generation})`
|
|
1513
|
-
);
|
|
1514
|
-
}
|
|
1515
|
-
if (summary !== void 0 && summary.generation === currentGen && "fingerprint" in summary && fingerprintParts(summary.fingerprint)?.footerCrc !== last.footerCrc) {
|
|
1516
|
-
throw new ValidationError(
|
|
1517
|
-
`knownGens records footerCrc ${last.footerCrc} for generation ${currentGen}, but the summary's fingerprint ${summary.fingerprint} carries another: both describe the one current object`
|
|
1518
|
-
);
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
function refuseDriverManaged(write, what) {
|
|
1522
|
-
const named = DRIVER_MANAGED.filter((field) => field in write);
|
|
1523
|
-
if (named.length > 0) {
|
|
1524
|
-
throw new ValidationError(
|
|
1525
|
-
`${what} names ${named.join(" and ")}, which the registry sets on every write and a caller never does`
|
|
1526
|
-
);
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
function validateKeyId(keyId) {
|
|
1530
|
-
if (keyId !== void 0 && (typeof keyId !== "string" || keyId.length === 0)) {
|
|
1531
|
-
throw new ValidationError("keyId must be a non-empty string, or absent");
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
function validateNewRegistryRecord(rec) {
|
|
1535
|
-
refuseDriverManaged(rec, "a new record");
|
|
1536
|
-
validateKeyId(rec.keyId);
|
|
1537
|
-
validateGeneration(rec.currentGen);
|
|
1538
|
-
if (rec.status !== void 0) validateStatus(rec.status);
|
|
1539
|
-
validateWrappedDeks(rec.wrappedDeks, "caller");
|
|
1540
|
-
validateGovernance(rec.retention, "retention");
|
|
1541
|
-
validateGovernance(rec.residency, "residency");
|
|
1542
|
-
const knownGens = validateKnownGens(rec.knownGens, "caller");
|
|
1543
|
-
const withKnown = knownGens === void 0 ? rec : { ...rec, knownGens };
|
|
1544
|
-
const summary = "summary" in rec ? validateSummary(rec.summary, "caller") : void 0;
|
|
1545
|
-
validateKnownGensFit(knownGens, rec.currentGen, summary);
|
|
1546
|
-
if (!("summary" in rec)) return withKnown;
|
|
1547
|
-
validateSummaryNames(summary, rec.currentGen);
|
|
1548
|
-
validateSummaryKeys(summary, rec.wrappedDeks);
|
|
1549
|
-
return { ...withKnown, summary };
|
|
1550
|
-
}
|
|
1551
|
-
function validateRegistryPatch(patch) {
|
|
1552
|
-
refuseDriverManaged(patch, "a patch");
|
|
1553
|
-
if ("keyId" in patch) validateKeyId(patch.keyId);
|
|
1554
|
-
validatePatchGeneration(patch);
|
|
1555
|
-
if (patch.status !== void 0) validateStatus(patch.status);
|
|
1556
|
-
if ("wrappedDeks" in patch) validateWrappedDeks(patch.wrappedDeks, "caller");
|
|
1557
|
-
if ("retention" in patch) validateGovernance(patch.retention, "retention");
|
|
1558
|
-
if ("residency" in patch) validateGovernance(patch.residency, "residency");
|
|
1559
|
-
const withKnown = patch.knownGens === void 0 ? patch : { ...patch, knownGens: validateKnownGens(patch.knownGens, "caller") };
|
|
1560
|
-
const withLeases = "leases" in withKnown ? { ...withKnown, leases: validateLeases(withKnown.leases, "caller") } : withKnown;
|
|
1561
|
-
if (!("summary" in patch)) return withLeases;
|
|
1562
|
-
return { ...withLeases, summary: validateSummary(patch.summary, "caller") };
|
|
1563
|
-
}
|
|
1564
|
-
var REGISTRY_SCHEMA_VERSION = 5;
|
|
1565
|
-
function assertRegistrySchemaVersion(raw, ctx) {
|
|
1566
|
-
if (raw === void 0) {
|
|
1567
|
-
throw new IntegrityError(`registry row has no schemaVersion: ${ctx}`);
|
|
1568
|
-
}
|
|
1569
|
-
if (typeof raw !== "number" || !Number.isInteger(raw) || raw < 1) {
|
|
1570
|
-
throw new IntegrityError(`registry row has a malformed schemaVersion (${shown3(raw)}): ${ctx}`);
|
|
1571
|
-
}
|
|
1572
|
-
if (raw < REGISTRY_SCHEMA_VERSION) {
|
|
1573
|
-
throw new UnsupportedError(
|
|
1574
|
-
`registry row schemaVersion ${raw} is one this build does not read: it reads schema ${REGISTRY_SCHEMA_VERSION} only. Export the segments with the release that wrote the row and load them with this one into a new prefix (steps: https://github.com/cloudbitmaps/cloudbitmaps/blob/main/CHANGELOG.md, the Breaking entry on registry schema 5): ${ctx}`
|
|
1575
|
-
);
|
|
1576
|
-
}
|
|
1577
|
-
if (raw > REGISTRY_SCHEMA_VERSION) {
|
|
1578
|
-
throw new UnsupportedError(
|
|
1579
|
-
`registry row schemaVersion ${raw} is newer than this build reads (v${REGISTRY_SCHEMA_VERSION}): ${ctx}`
|
|
1580
|
-
);
|
|
1581
|
-
}
|
|
1582
|
-
return raw;
|
|
1583
|
-
}
|
|
1584
|
-
function serializeRegistryEnvelope(env) {
|
|
1585
|
-
return JSON.stringify({
|
|
1586
|
-
schemaVersion: REGISTRY_SCHEMA_VERSION,
|
|
1587
|
-
deleted: env.deleted,
|
|
1588
|
-
record: env.record
|
|
1589
|
-
});
|
|
1590
|
-
}
|
|
1591
|
-
var INCARNATION_BYTES = 16;
|
|
1592
|
-
var WRITE_BYTES = 8;
|
|
1593
|
-
function tokenParts(token, ctx, what = "token") {
|
|
1594
|
-
const match = typeof token === "string" ? INCARNATION_TOKEN.exec(token) : null;
|
|
1595
|
-
if (match === null) {
|
|
1596
|
-
throw new IntegrityError(
|
|
1597
|
-
`registry row ${what} is not one a shipped registry writes (${shown3(JSON.stringify(token))}): ${ctx}`
|
|
1598
|
-
);
|
|
1599
|
-
}
|
|
1600
|
-
const counter = Number(match[2]);
|
|
1601
|
-
if (!Number.isSafeInteger(counter)) {
|
|
1602
|
-
throw new IntegrityError(`registry row ${what}'s counter is out of safe-integer range: ${ctx}`);
|
|
1603
|
-
}
|
|
1604
|
-
return { incarnation: match[1], counter };
|
|
1605
|
-
}
|
|
1606
|
-
function checkPointerId(pointerId, token, ctx) {
|
|
1607
|
-
const parts = tokenParts(pointerId, ctx, "pointerId");
|
|
1608
|
-
if (parts.incarnation !== token.incarnation) {
|
|
1609
|
-
throw new IntegrityError(
|
|
1610
|
-
`registry row pointerId names another incarnation than its token: ${ctx}`
|
|
1611
|
-
);
|
|
1612
|
-
}
|
|
1613
|
-
if (parts.counter > token.counter) {
|
|
1614
|
-
throw new IntegrityError(`registry row pointerId is a write after its token: ${ctx}`);
|
|
1615
|
-
}
|
|
1616
|
-
}
|
|
1617
|
-
function drawHex(entropy, bytes) {
|
|
1618
|
-
const drawn = entropy(bytes);
|
|
1619
|
-
if (!(drawn instanceof Uint8Array) || drawn.length !== bytes) {
|
|
1620
|
-
throw new ValidationError(
|
|
1621
|
-
`the registry's entropy source must return ${bytes} bytes as a Uint8Array`
|
|
1622
|
-
);
|
|
1623
|
-
}
|
|
1624
|
-
let hex = "";
|
|
1625
|
-
for (const b of drawn) hex += b.toString(16).padStart(2, "0");
|
|
1626
|
-
return hex;
|
|
1627
|
-
}
|
|
1628
|
-
function drawIncarnation(entropy) {
|
|
1629
|
-
return drawHex(entropy, INCARNATION_BYTES);
|
|
1630
|
-
}
|
|
1631
|
-
function drawWrite(entropy) {
|
|
1632
|
-
return drawHex(entropy, WRITE_BYTES);
|
|
1633
|
-
}
|
|
1634
|
-
function nextRegistryToken(record, entropy) {
|
|
1635
|
-
const { incarnation, counter } = tokenParts(record.token, record.segment);
|
|
1636
|
-
return `${incarnation}.${counter + 1}.${drawWrite(entropy)}`;
|
|
1637
|
-
}
|
|
1638
|
-
function newIncarnationToken(entropy, tombstone) {
|
|
1639
|
-
const counter = tombstone === void 0 ? 0 : tokenParts(tombstone.token, tombstone.segment).counter + 1;
|
|
1640
|
-
return `${drawIncarnation(entropy)}.${counter}.${drawWrite(entropy)}`;
|
|
1641
|
-
}
|
|
1642
|
-
function shown3(v) {
|
|
1643
|
-
const text = String(v);
|
|
1644
|
-
return text.length > 64 ? `${text.slice(0, 64)}\u2026` : text;
|
|
1645
|
-
}
|
|
1646
|
-
function parseRegistryEnvelope(text, ctx, expected) {
|
|
1647
|
-
let parsed;
|
|
1648
|
-
try {
|
|
1649
|
-
parsed = JSON.parse(text);
|
|
1650
|
-
} catch {
|
|
1651
|
-
throw new IntegrityError(`registry row is not valid JSON: ${ctx}`);
|
|
1652
|
-
}
|
|
1653
|
-
if (parsed === null || typeof parsed !== "object") {
|
|
1654
|
-
throw new IntegrityError(`registry row has a malformed envelope: ${ctx}`);
|
|
1655
|
-
}
|
|
1656
|
-
const env = parsed;
|
|
1657
|
-
assertRegistrySchemaVersion(env.schemaVersion, ctx);
|
|
1658
|
-
const extra = Object.keys(env).filter((k) => !ENVELOPE_FIELDS.includes(k));
|
|
1659
|
-
if (extra.length > 0) {
|
|
1660
|
-
throw new IntegrityError(
|
|
1661
|
-
`registry row has fields its envelope does not declare (${shown3(extra.join(", "))}): ${ctx}`
|
|
1662
|
-
);
|
|
1663
|
-
}
|
|
1664
|
-
if (typeof env.deleted !== "boolean" || env.record === null || typeof env.record !== "object") {
|
|
1665
|
-
throw new IntegrityError(`registry row has a malformed envelope: ${ctx}`);
|
|
1666
|
-
}
|
|
1667
|
-
const r = env.record;
|
|
1668
|
-
assertStoredRecordShape(r, ctx);
|
|
1669
|
-
if (typeof r.token !== "string") {
|
|
1670
|
-
throw new IntegrityError(`registry row is missing its token: ${ctx}`);
|
|
1671
|
-
}
|
|
1672
|
-
checkPointerId(r.pointerId, tokenParts(r.token, ctx), ctx);
|
|
1673
|
-
if (expected !== void 0 && (r.segment !== expected.segment || (r.namespace ?? void 0) !== (expected.namespace ?? void 0))) {
|
|
1674
|
-
throw new IntegrityError(
|
|
1675
|
-
`registry row names another segment than the one it is stored for: ${ctx}`
|
|
1676
|
-
);
|
|
1677
|
-
}
|
|
1678
|
-
return { deleted: env.deleted, record: env.record };
|
|
1679
|
-
}
|
|
1680
|
-
function recordFromNew(ref, rec, now, token) {
|
|
1681
|
-
return {
|
|
1682
|
-
namespace: ref.namespace,
|
|
1683
|
-
segment: ref.segment,
|
|
1684
|
-
currentGen: rec.currentGen,
|
|
1685
|
-
wrappedDeks: rec.wrappedDeks,
|
|
1686
|
-
keyId: rec.keyId,
|
|
1687
|
-
status: rec.status ?? "active",
|
|
1688
|
-
retention: rec.retention,
|
|
1689
|
-
residency: rec.residency,
|
|
1690
|
-
summary: rec.summary,
|
|
1691
|
-
knownGens: rec.knownGens,
|
|
1692
|
-
// A new row has no holder: a lease is written only against a row that already exists.
|
|
1693
|
-
leases: void 0,
|
|
1694
|
-
createdAt: now,
|
|
1695
|
-
updatedAt: now,
|
|
1696
|
-
token,
|
|
1697
|
-
pointerId: token
|
|
1698
|
-
};
|
|
1699
|
-
}
|
|
1700
|
-
function assertStoredRecordShape(r, ctx) {
|
|
1701
|
-
if (typeof r.segment !== "string" || typeof r.pointerId !== "string" || r.namespace !== void 0 && typeof r.namespace !== "string" || r.currentGen !== null && typeof r.currentGen !== "number" || typeof r.status !== "string" || typeof r.createdAt !== "number" || typeof r.updatedAt !== "number") {
|
|
1702
|
-
throw new IntegrityError(`registry record is missing required fields: ${ctx}`);
|
|
1703
|
-
}
|
|
1704
|
-
if (r.currentGen !== null && (!Number.isSafeInteger(r.currentGen) || r.currentGen < 0)) {
|
|
1705
|
-
throw new IntegrityError(
|
|
1706
|
-
`registry record has an invalid currentGen (${shown3(r.currentGen)}): ${ctx}`
|
|
1707
|
-
);
|
|
1708
|
-
}
|
|
1709
|
-
if (!STATUSES.includes(r.status)) {
|
|
1710
|
-
throw new IntegrityError(`registry record has an unknown status (${shown3(r.status)}): ${ctx}`);
|
|
1711
|
-
}
|
|
1712
|
-
const declared = RECORD_FIELDS;
|
|
1713
|
-
const extra = Object.keys(r).filter((k) => !declared.includes(k));
|
|
1714
|
-
if (extra.length > 0) {
|
|
1715
|
-
throw new IntegrityError(
|
|
1716
|
-
`registry record has fields a schema-${REGISTRY_SCHEMA_VERSION} row does not declare (${shown3(extra.join(", "))}): ${ctx}`
|
|
1717
|
-
);
|
|
1718
|
-
}
|
|
1719
|
-
if (r.keyId !== void 0 && typeof r.keyId !== "string") {
|
|
1720
|
-
throw new IntegrityError(`registry record has an invalid keyId: ${ctx}`);
|
|
1721
|
-
}
|
|
1722
|
-
validateWrappedDeks(r.wrappedDeks, "stored");
|
|
1723
|
-
for (const field of ["retention", "residency"]) {
|
|
1724
|
-
const meta = r[field];
|
|
1725
|
-
if (meta !== void 0 && (meta === null || typeof meta !== "object" || Array.isArray(meta))) {
|
|
1726
|
-
throw new IntegrityError(`registry record has a non-object ${field}: ${ctx}`);
|
|
1235
|
+
const { generation, footerCrc } = entry;
|
|
1236
|
+
if (!Number.isSafeInteger(generation) || generation < 0) {
|
|
1237
|
+
return `a generation must be a non-negative safe integer (got ${show(generation)})`;
|
|
1727
1238
|
}
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
validateKnownGens(r.knownGens, "stored", ctx);
|
|
1731
|
-
validateLeases(r.leases, "stored", ctx);
|
|
1732
|
-
}
|
|
1733
|
-
function applyRegistryPatch(prev, patch, now, token) {
|
|
1734
|
-
const currentGen = "currentGen" in patch ? patch.currentGen ?? null : prev.currentGen;
|
|
1735
|
-
const wrappedDeks = "wrappedDeks" in patch ? patch.wrappedDeks : prev.wrappedDeks;
|
|
1736
|
-
let summary;
|
|
1737
|
-
if ("summary" in patch) {
|
|
1738
|
-
validateSummaryNames(patch.summary, currentGen);
|
|
1739
|
-
validateSummaryKeys(patch.summary, wrappedDeks);
|
|
1740
|
-
summary = patch.summary;
|
|
1741
|
-
} else {
|
|
1742
|
-
const kept = currentGen === prev.currentGen ? prev.summary : void 0;
|
|
1743
|
-
summary = kept !== void 0 && summaryAgreesWithKeys(kept, wrappedDeks) ? kept : void 0;
|
|
1744
|
-
}
|
|
1745
|
-
let knownGens;
|
|
1746
|
-
if ("knownGens" in patch) {
|
|
1747
|
-
validateKnownGensFit(patch.knownGens, currentGen, summary);
|
|
1748
|
-
knownGens = patch.knownGens;
|
|
1749
|
-
} else {
|
|
1750
|
-
knownGens = currentGen === prev.currentGen ? prev.knownGens : void 0;
|
|
1751
|
-
}
|
|
1752
|
-
let leases;
|
|
1753
|
-
if ("leases" in patch) {
|
|
1754
|
-
leases = patch.leases;
|
|
1755
|
-
validateLeasesPointer(leases, currentGen);
|
|
1756
|
-
const most = Math.max(MAX_LEASES_PER_SEGMENT, prev.leases?.length ?? 0);
|
|
1757
|
-
if (leases !== void 0 && leases.length > most) {
|
|
1758
|
-
throw new ValidationError(`leases: has ${leases.length} entries, cap ${most}`);
|
|
1239
|
+
if (!Number.isInteger(footerCrc) || footerCrc < 0 || footerCrc > 4294967295) {
|
|
1240
|
+
return `a footerCrc must be an integer from 0 to 2^32 - 1 (got ${show(footerCrc)})`;
|
|
1759
1241
|
}
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
}
|
|
1763
|
-
return {
|
|
1764
|
-
namespace: prev.namespace,
|
|
1765
|
-
segment: prev.segment,
|
|
1766
|
-
currentGen,
|
|
1767
|
-
wrappedDeks,
|
|
1768
|
-
keyId: "keyId" in patch ? patch.keyId : prev.keyId,
|
|
1769
|
-
status: patch.status ?? prev.status,
|
|
1770
|
-
retention: "retention" in patch ? patch.retention : prev.retention,
|
|
1771
|
-
residency: "residency" in patch ? patch.residency : prev.residency,
|
|
1772
|
-
summary,
|
|
1773
|
-
knownGens,
|
|
1774
|
-
leases,
|
|
1775
|
-
createdAt: prev.createdAt,
|
|
1776
|
-
updatedAt: now,
|
|
1777
|
-
token,
|
|
1778
|
-
pointerId: renewsPointer(patch) ? token : prev.pointerId
|
|
1779
|
-
};
|
|
1780
|
-
}
|
|
1781
|
-
|
|
1782
|
-
// src/drivers/_shared/entropy.ts
|
|
1783
|
-
function webCrypto() {
|
|
1784
|
-
const c = globalThis.crypto;
|
|
1785
|
-
return c !== void 0 && typeof c.getRandomValues === "function" ? c : void 0;
|
|
1786
|
-
}
|
|
1787
|
-
var webCryptoEntropy = (length) => {
|
|
1788
|
-
const c = webCrypto();
|
|
1789
|
-
if (c === void 0) {
|
|
1790
|
-
throw new UnsupportedError(
|
|
1791
|
-
"this runtime has no Web Crypto (crypto.getRandomValues), which a registry needs for the token of every row it writes: run on a runtime that has it"
|
|
1792
|
-
);
|
|
1242
|
+
if (seen.has(generation)) return `generation ${String(generation)} is repeated`;
|
|
1243
|
+
seen.add(generation);
|
|
1793
1244
|
}
|
|
1794
|
-
return
|
|
1795
|
-
};
|
|
1796
|
-
function entropyIsAvailable(entropy) {
|
|
1797
|
-
return entropy !== webCryptoEntropy || webCrypto() !== void 0;
|
|
1245
|
+
return void 0;
|
|
1798
1246
|
}
|
|
1799
1247
|
|
|
1800
1248
|
export {
|
|
@@ -1813,23 +1261,29 @@ export {
|
|
|
1813
1261
|
KeyUnavailableError,
|
|
1814
1262
|
TransientError,
|
|
1815
1263
|
isWriteConflictError,
|
|
1264
|
+
unsettledConflict,
|
|
1265
|
+
isUnsettledConflict,
|
|
1816
1266
|
isTransientError,
|
|
1817
1267
|
isNotFoundError,
|
|
1818
1268
|
isIntegrityError,
|
|
1819
1269
|
isValidationError,
|
|
1820
1270
|
isKeyUnavailableError,
|
|
1821
1271
|
errorKind,
|
|
1272
|
+
shown,
|
|
1822
1273
|
requireInteger,
|
|
1274
|
+
checkRequireEncryption,
|
|
1823
1275
|
requirePositiveInteger,
|
|
1824
1276
|
requireFiniteNumber,
|
|
1277
|
+
refuseUnknownOptions,
|
|
1278
|
+
requireBool,
|
|
1279
|
+
requireNonEmptyString,
|
|
1825
1280
|
U32_MAX,
|
|
1826
1281
|
CHUNK_COUNT,
|
|
1827
1282
|
isBadIdError,
|
|
1283
|
+
refusalOfId,
|
|
1828
1284
|
splitId,
|
|
1829
1285
|
MAX_REMAINDER,
|
|
1830
1286
|
joinId,
|
|
1831
|
-
mapWithConcurrency,
|
|
1832
|
-
boundedAll,
|
|
1833
1287
|
PREAMBLE_BYTES,
|
|
1834
1288
|
FOOTER_BYTES,
|
|
1835
1289
|
encodeNameForKey,
|
|
@@ -1842,6 +1296,8 @@ export {
|
|
|
1842
1296
|
RESERVED_NAMESPACE_PREFIX,
|
|
1843
1297
|
isReservedNamespace,
|
|
1844
1298
|
validateUserNamespace,
|
|
1299
|
+
PORT_KEYS,
|
|
1300
|
+
refuseUnknownRefKeys,
|
|
1845
1301
|
validateUserRef,
|
|
1846
1302
|
validateChunkKeyOrder,
|
|
1847
1303
|
validateChunkRef,
|
|
@@ -1850,15 +1306,7 @@ export {
|
|
|
1850
1306
|
STORAGE_BACKEND,
|
|
1851
1307
|
brandAsBackend,
|
|
1852
1308
|
isStorageBackend,
|
|
1853
|
-
|
|
1854
|
-
metadataBytes,
|
|
1855
|
-
copiedMetadata,
|
|
1856
|
-
metadataFromBytes,
|
|
1857
|
-
sizePart,
|
|
1858
|
-
fingerprintFor,
|
|
1859
|
-
fingerprintParts,
|
|
1860
|
-
footerCrcOf,
|
|
1861
|
-
compactFingerprint,
|
|
1309
|
+
INCARNATION_TOKEN,
|
|
1862
1310
|
incarnationOf,
|
|
1863
1311
|
incarnationField,
|
|
1864
1312
|
sameIncarnation,
|
|
@@ -1866,14 +1314,28 @@ export {
|
|
|
1866
1314
|
renewsPointer,
|
|
1867
1315
|
renewPointer,
|
|
1868
1316
|
pointerIdOf,
|
|
1317
|
+
pointerSetBy,
|
|
1869
1318
|
aadFor,
|
|
1870
1319
|
sameKeys,
|
|
1320
|
+
MAX_METADATA_BYTES,
|
|
1321
|
+
canonicalMetadataJson,
|
|
1322
|
+
metadataBytes,
|
|
1323
|
+
copiedMetadata,
|
|
1324
|
+
metadataFromBytes,
|
|
1325
|
+
sizePart,
|
|
1326
|
+
fingerprintFor,
|
|
1327
|
+
fingerprintParts,
|
|
1328
|
+
footerCrcOf,
|
|
1329
|
+
compactFingerprint,
|
|
1330
|
+
MAX_SUMMARY_CARDINALITY,
|
|
1331
|
+
tailBytesFit,
|
|
1871
1332
|
sizeOfFingerprint,
|
|
1872
1333
|
usableSummary,
|
|
1873
1334
|
summaryAgrees,
|
|
1874
1335
|
metadataToCarry,
|
|
1875
1336
|
summaryOf,
|
|
1876
1337
|
ownSummary,
|
|
1338
|
+
ascending,
|
|
1877
1339
|
DEFAULT_RETRY_POLICY,
|
|
1878
1340
|
jitteredWait,
|
|
1879
1341
|
retryRead,
|
|
@@ -1882,6 +1344,7 @@ export {
|
|
|
1882
1344
|
MAX_LEASE_MS,
|
|
1883
1345
|
LEASE_SKEW_MS,
|
|
1884
1346
|
MAX_LEASES_PER_SEGMENT,
|
|
1347
|
+
MAX_STORED_LEASES,
|
|
1885
1348
|
UNANSWERED_RESENDS,
|
|
1886
1349
|
UNANSWERED_BASE_MS,
|
|
1887
1350
|
isLive,
|
|
@@ -1890,8 +1353,7 @@ export {
|
|
|
1890
1353
|
leaseChurn,
|
|
1891
1354
|
takeLease,
|
|
1892
1355
|
releaseLease,
|
|
1893
|
-
|
|
1894
|
-
ascending,
|
|
1356
|
+
MAX_KNOWN_GENERATIONS,
|
|
1895
1357
|
MAX_STORED_KNOWN_GENERATIONS,
|
|
1896
1358
|
usableKnownGens,
|
|
1897
1359
|
windowOf,
|
|
@@ -1903,24 +1365,6 @@ export {
|
|
|
1903
1365
|
describingKnown,
|
|
1904
1366
|
isFullLedger,
|
|
1905
1367
|
fallbackBound,
|
|
1906
|
-
|
|
1907
|
-
validateRegistryPatch,
|
|
1908
|
-
serializeRegistryEnvelope,
|
|
1909
|
-
drawIncarnation,
|
|
1910
|
-
drawWrite,
|
|
1911
|
-
nextRegistryToken,
|
|
1912
|
-
newIncarnationToken,
|
|
1913
|
-
parseRegistryEnvelope,
|
|
1914
|
-
recordFromNew,
|
|
1915
|
-
applyRegistryPatch,
|
|
1916
|
-
webCryptoEntropy,
|
|
1917
|
-
entropyIsAvailable,
|
|
1918
|
-
DEFAULT_NAMESPACE,
|
|
1919
|
-
namespaceKeyPart,
|
|
1920
|
-
namespacePathPart,
|
|
1921
|
-
refuseUnknownOptions,
|
|
1922
|
-
checkNow,
|
|
1923
|
-
requirePositiveInt,
|
|
1924
|
-
requireBool
|
|
1368
|
+
knownGensShapeFault
|
|
1925
1369
|
};
|
|
1926
|
-
//# sourceMappingURL=chunk-
|
|
1370
|
+
//# sourceMappingURL=chunk-MVUD4R72.js.map
|