@moyodb/sdk 1.0.0 → 1.0.1
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 +2 -2
- package/dist/LICENSE +202 -0
- package/dist/assets/worker-KDc8Khl_.js +4 -0
- package/dist/assets/worker-KDc8Khl_.js.map +1 -0
- package/dist/codec.d.ts.map +1 -1
- package/dist/compression.d.ts.map +1 -1
- package/dist/engine/README.md +11 -10
- package/dist/engine/moyodb_engine.d.ts +29 -19
- package/dist/engine/moyodb_engine.js +78 -28
- package/dist/engine/moyodb_engine_bg.wasm +0 -0
- package/dist/engine/moyodb_engine_bg.wasm.d.ts +4 -2
- package/dist/engine/snippets/moyodb-engine-8ebe6af0cc2e81b7/js/opfs_shim.js +151 -62
- package/dist/errors.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/indexing.d.ts +8 -0
- package/dist/indexing.d.ts.map +1 -1
- package/dist/moyodb-sdk.js +764 -583
- package/dist/moyodb-sdk.js.map +1 -1
- package/dist/registry.d.ts +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/subscriptions.d.ts.map +1 -1
- package/dist/types.d.ts +6 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/worker-api.d.ts +3 -4
- package/dist/worker-api.d.ts.map +1 -1
- package/dist/worker-client.d.ts +8 -0
- package/dist/worker-client.d.ts.map +1 -1
- package/dist/worker-protocol.d.ts +28 -0
- package/dist/worker-protocol.d.ts.map +1 -1
- package/dist/worker-server.d.ts.map +1 -1
- package/package.json +4 -2
- package/dist/assets/worker-R2dy1Ju5.js +0 -4
- package/dist/assets/worker-R2dy1Ju5.js.map +0 -1
|
@@ -6,12 +6,16 @@ const CONTROL_VERSION = 1;
|
|
|
6
6
|
const CONTROL_CHECKSUM_OFFSET = 24;
|
|
7
7
|
const CONTROL_NAME_OFFSET = 32;
|
|
8
8
|
const CONTROL_MAGIC = new Uint8Array([66, 68, 66, 82, 79, 79, 84, 49]);
|
|
9
|
-
|
|
9
|
+
// Chromium rejects a SyncAccessHandle.write larger than a signed 32-bit count.
|
|
10
|
+
const OPFS_MAX_WRITE_SIZE = 0x7fffffff;
|
|
10
11
|
const TEXT_ENCODER = new TextEncoder();
|
|
11
12
|
const TEXT_DECODER = new TextDecoder();
|
|
12
13
|
let rootDir = null;
|
|
13
14
|
let nextSessionId = 1;
|
|
14
15
|
const sessions = new Map();
|
|
16
|
+
// Exclusive session handles keep cached sizes valid across Rust backend clones.
|
|
17
|
+
// Length checks for validation and statistics still query OPFS.
|
|
18
|
+
const appendOffsets = new WeakMap();
|
|
15
19
|
function namedError(name, message) {
|
|
16
20
|
const error = new Error(message);
|
|
17
21
|
error.name = name;
|
|
@@ -67,7 +71,7 @@ function writeU64(view, offset, value) {
|
|
|
67
71
|
view.setBigUint64(offset, BigInt(value), true);
|
|
68
72
|
}
|
|
69
73
|
function readU64(view, offset) {
|
|
70
|
-
return
|
|
74
|
+
return view.getBigUint64(offset, true);
|
|
71
75
|
}
|
|
72
76
|
function fnv1a32(bytes, zeroOffset = -1, zeroLength = 0) {
|
|
73
77
|
let hash = 0x811c9dc5;
|
|
@@ -82,12 +86,14 @@ function fnv1a32(bytes, zeroOffset = -1, zeroLength = 0) {
|
|
|
82
86
|
function isGenerationNameValid(name) {
|
|
83
87
|
return typeof name === 'string' && /^gen-[a-z0-9]+-[a-z0-9]+$/i.test(name);
|
|
84
88
|
}
|
|
85
|
-
//
|
|
86
|
-
// normally would let callers publish state that is not on disk.
|
|
89
|
+
// Returns only after all bytes are written. The caller must flush for durability.
|
|
87
90
|
export function writeAll(handle, bytes, at) {
|
|
88
91
|
let writtenTotal = 0;
|
|
89
92
|
while (writtenTotal < bytes.length) {
|
|
90
|
-
|
|
93
|
+
// Preserve the engine's batch; split only at the browser size limit or
|
|
94
|
+
// after a short write. Suffix views borrow the original buffer.
|
|
95
|
+
const end = Math.min(bytes.length, writtenTotal + OPFS_MAX_WRITE_SIZE);
|
|
96
|
+
const chunk = writtenTotal === 0 && end === bytes.length ? bytes : bytes.subarray(writtenTotal, end);
|
|
91
97
|
const rawWritten = handle.write(chunk, { at: at + writtenTotal });
|
|
92
98
|
const written = Number(rawWritten);
|
|
93
99
|
if (!Number.isSafeInteger(written) || written < 0 || written > chunk.length) {
|
|
@@ -100,7 +106,7 @@ export function writeAll(handle, bytes, at) {
|
|
|
100
106
|
}
|
|
101
107
|
return writtenTotal;
|
|
102
108
|
}
|
|
103
|
-
//
|
|
109
|
+
// Reads until the buffer is full or a read returns zero. The unread suffix is unchanged.
|
|
104
110
|
export function readAll(handle, buffer, at) {
|
|
105
111
|
let readTotal = 0;
|
|
106
112
|
while (readTotal < buffer.length) {
|
|
@@ -138,8 +144,8 @@ export function encodeControlSlot(generationCounter, activeGeneration) {
|
|
|
138
144
|
view.setUint32(CONTROL_CHECKSUM_OFFSET, checksum, true);
|
|
139
145
|
return slot;
|
|
140
146
|
}
|
|
141
|
-
//
|
|
142
|
-
//
|
|
147
|
+
// Reject incomplete slots and bad magic or checksums. Validate the remaining
|
|
148
|
+
// fields after the checksum passes, so torn fields cannot mask a valid slot.
|
|
143
149
|
export function decodeControlSlot(slotIndex, bytes) {
|
|
144
150
|
if (bytes.length < CONTROL_SLOT_SIZE) {
|
|
145
151
|
return null;
|
|
@@ -174,9 +180,9 @@ export function decodeControlSlot(slotIndex, bytes) {
|
|
|
174
180
|
activeGeneration
|
|
175
181
|
};
|
|
176
182
|
}
|
|
177
|
-
// `absent
|
|
178
|
-
// `invalid
|
|
179
|
-
// `valid
|
|
183
|
+
// `absent`: empty file.
|
|
184
|
+
// `invalid`: nonempty file with no valid slot.
|
|
185
|
+
// `valid`: `control` is the valid slot with the highest generation counter.
|
|
180
186
|
export function readControlStateFromAccessHandle(accessHandle) {
|
|
181
187
|
const size = Number(accessHandle.getSize());
|
|
182
188
|
if (!Number.isSafeInteger(size) || size < 0) {
|
|
@@ -207,21 +213,18 @@ async function readControlFile(dbRoot) {
|
|
|
207
213
|
accessHandle.close();
|
|
208
214
|
}
|
|
209
215
|
}
|
|
210
|
-
async function hasLegacyDataFiles(dbRoot) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
216
|
+
async function hasLegacyDataFiles(dbRoot, fileKind = 0) {
|
|
217
|
+
if (fileKind === FILE_NAMES.length) {
|
|
218
|
+
return false;
|
|
219
|
+
}
|
|
220
|
+
if (await lookupFileHandle(dbRoot, FILE_NAMES[fileKind])) {
|
|
221
|
+
return true;
|
|
215
222
|
}
|
|
216
|
-
return
|
|
223
|
+
return await hasLegacyDataFiles(dbRoot, fileKind + 1);
|
|
217
224
|
}
|
|
218
|
-
//
|
|
219
|
-
//
|
|
220
|
-
//
|
|
221
|
-
// generation (see opfsCleanupInactiveEntries and opfsOpenActiveDb). So an
|
|
222
|
-
// unreadable control file next to legacy files can only be a torn first
|
|
223
|
-
// publication, and legacy is still authoritative. Without legacy files it is
|
|
224
|
-
// real corruption of the pointer to live data.
|
|
225
|
+
// Legacy files remain authoritative after a torn first publication. They must
|
|
226
|
+
// be removed before a published generation accepts writes, so later control
|
|
227
|
+
// damage cannot make stale legacy files appear current.
|
|
225
228
|
async function resolveActiveGeneration(dbRoot) {
|
|
226
229
|
const state = await readControlFile(dbRoot);
|
|
227
230
|
if (state.status === 'valid') {
|
|
@@ -251,7 +254,11 @@ async function writeControlState(dbRoot, activeGeneration, expectedCurrentGenera
|
|
|
251
254
|
);
|
|
252
255
|
}
|
|
253
256
|
const nextSlot = current.control ? (current.control.slotIndex === 0 ? 1 : 0) : 0;
|
|
254
|
-
const
|
|
257
|
+
const generationCounter = current.control?.generationCounter ?? 0n;
|
|
258
|
+
if (generationCounter === 0xffffffffffffffffn) {
|
|
259
|
+
throw namedError('StorageError', 'control generation counter exhausted');
|
|
260
|
+
}
|
|
261
|
+
const nextGenerationCounter = generationCounter + 1n;
|
|
255
262
|
const encoded = encodeControlSlot(nextGenerationCounter, activeGeneration);
|
|
256
263
|
writeAll(accessHandle, encoded, nextSlot * CONTROL_SLOT_SIZE);
|
|
257
264
|
accessHandle.flush();
|
|
@@ -274,19 +281,29 @@ function createGenerationName() {
|
|
|
274
281
|
const randomPart = Array.from(randomBytes, (byte) => byte.toString(16).padStart(2, '0')).join('');
|
|
275
282
|
return `gen-${timePart}-${randomPart}`;
|
|
276
283
|
}
|
|
284
|
+
async function createGenerationDirectory(dbRoot) {
|
|
285
|
+
const generationName = createGenerationName();
|
|
286
|
+
if (await lookupDirectoryHandle(dbRoot, generationName)) {
|
|
287
|
+
return await createGenerationDirectory(dbRoot);
|
|
288
|
+
}
|
|
289
|
+
await dbRoot.getDirectoryHandle(generationName, { create: true });
|
|
290
|
+
return generationName;
|
|
291
|
+
}
|
|
277
292
|
async function getDbRoot(encodedDbName, createIfMissing) {
|
|
278
293
|
const stackdb = await getOrCreateStackdbRoot();
|
|
279
|
-
|
|
294
|
+
if (createIfMissing) {
|
|
295
|
+
// Creation also opens existing directories, avoiding a separate lookup.
|
|
296
|
+
return await stackdb.getDirectoryHandle(encodedDbName, { create: true });
|
|
297
|
+
}
|
|
298
|
+
const dbRoot = await lookupDirectoryHandle(stackdb, encodedDbName);
|
|
280
299
|
if (!dbRoot) {
|
|
281
|
-
|
|
282
|
-
throw new Error(`database ${encodedDbName} does not exist`);
|
|
283
|
-
}
|
|
284
|
-
dbRoot = await stackdb.getDirectoryHandle(encodedDbName, { create: true });
|
|
300
|
+
throw new Error(`database ${encodedDbName} does not exist`);
|
|
285
301
|
}
|
|
286
302
|
return dbRoot;
|
|
287
303
|
}
|
|
288
304
|
async function removeLegacyDataFiles(dbRoot) {
|
|
289
|
-
|
|
305
|
+
await FILE_NAMES.reduce(async (previous, fileName) => {
|
|
306
|
+
await previous;
|
|
290
307
|
try {
|
|
291
308
|
await dbRoot.removeEntry(fileName);
|
|
292
309
|
} catch (err) {
|
|
@@ -294,7 +311,7 @@ async function removeLegacyDataFiles(dbRoot) {
|
|
|
294
311
|
throw err;
|
|
295
312
|
}
|
|
296
313
|
}
|
|
297
|
-
}
|
|
314
|
+
}, Promise.resolve());
|
|
298
315
|
}
|
|
299
316
|
async function resolveActiveDataDir(dbRoot) {
|
|
300
317
|
const activeGeneration = await resolveActiveGeneration(dbRoot);
|
|
@@ -309,8 +326,7 @@ async function resolveActiveDataDir(dbRoot) {
|
|
|
309
326
|
if (!activeDir) {
|
|
310
327
|
throw corruptionError(`active generation ${activeGeneration} is missing`);
|
|
311
328
|
}
|
|
312
|
-
//
|
|
313
|
-
// files. They must be gone before this generation accepts writes.
|
|
329
|
+
// Remove stale legacy files before writes can make this generation newer.
|
|
314
330
|
await removeLegacyDataFiles(dbRoot);
|
|
315
331
|
return {
|
|
316
332
|
dirHandle: activeDir,
|
|
@@ -324,9 +340,10 @@ function closeSession(sessionId) {
|
|
|
324
340
|
return;
|
|
325
341
|
}
|
|
326
342
|
for (const handle of session.handles.values()) {
|
|
343
|
+
appendOffsets.delete(handle);
|
|
327
344
|
try {
|
|
328
345
|
handle.close();
|
|
329
|
-
} catch
|
|
346
|
+
} catch {}
|
|
330
347
|
}
|
|
331
348
|
sessions.delete(sessionId);
|
|
332
349
|
}
|
|
@@ -339,24 +356,34 @@ function closeSessionsForDb(encodedDbName) {
|
|
|
339
356
|
}
|
|
340
357
|
}
|
|
341
358
|
async function openSessionForDir(dbPath, dirHandle, generationName) {
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
359
|
+
// Acquire independent files concurrently. Publish the session only after
|
|
360
|
+
// all handles are acquired; failures must release every acquired handle.
|
|
361
|
+
const opened = await Promise.allSettled(
|
|
362
|
+
FILE_NAMES.map(async (fileName) => {
|
|
346
363
|
const fileHandle = await dirHandle.getFileHandle(fileName, { create: true });
|
|
347
364
|
if (typeof fileHandle.createSyncAccessHandle !== 'function') {
|
|
348
365
|
throw new Error('createSyncAccessHandle is unavailable');
|
|
349
366
|
}
|
|
350
|
-
|
|
351
|
-
|
|
367
|
+
return await fileHandle.createSyncAccessHandle();
|
|
368
|
+
})
|
|
369
|
+
);
|
|
370
|
+
const handles = new Map();
|
|
371
|
+
for (let fileKind = 0; fileKind < opened.length; fileKind += 1) {
|
|
372
|
+
const result = opened[fileKind];
|
|
373
|
+
if (result.status === 'fulfilled') {
|
|
374
|
+
handles.set(fileKind, result.value);
|
|
352
375
|
}
|
|
353
|
-
}
|
|
376
|
+
}
|
|
377
|
+
const failed = opened.find((result) => result.status === 'rejected');
|
|
378
|
+
if (failed) {
|
|
379
|
+
// Waiting for all results also captures late successes for cleanup.
|
|
354
380
|
for (const handle of handles.values()) {
|
|
355
381
|
try {
|
|
356
382
|
handle.close();
|
|
357
|
-
} catch
|
|
383
|
+
} catch {}
|
|
358
384
|
}
|
|
359
|
-
|
|
385
|
+
// Error precedence follows FILE_NAMES order, regardless of completion order.
|
|
386
|
+
throw failed.reason;
|
|
360
387
|
}
|
|
361
388
|
const sessionId = nextSessionId;
|
|
362
389
|
nextSessionId += 1;
|
|
@@ -381,11 +408,29 @@ function getAccessHandle(sessionId, fileKind) {
|
|
|
381
408
|
}
|
|
382
409
|
return handle;
|
|
383
410
|
}
|
|
411
|
+
function rememberFileSize(handle, size) {
|
|
412
|
+
if (typeof size === 'number' && Number.isSafeInteger(size) && size >= 0) {
|
|
413
|
+
appendOffsets.set(handle, size);
|
|
414
|
+
} else {
|
|
415
|
+
appendOffsets.delete(handle);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
function readFileSize(handle) {
|
|
419
|
+
try {
|
|
420
|
+
const size = handle.getSize();
|
|
421
|
+
rememberFileSize(handle, size);
|
|
422
|
+
return size;
|
|
423
|
+
} catch (error) {
|
|
424
|
+
appendOffsets.delete(handle);
|
|
425
|
+
throw error;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
384
428
|
function lookupOpenFileSize(path) {
|
|
385
429
|
for (const session of sessions.values()) {
|
|
386
430
|
for (let fileKind = 0; fileKind < FILE_NAMES.length; fileKind += 1) {
|
|
387
431
|
if (`${session.path}/${FILE_NAMES[fileKind]}` === path) {
|
|
388
|
-
|
|
432
|
+
const handle = session.handles.get(fileKind);
|
|
433
|
+
return Number((handle ? readFileSize(handle) : 0) ?? 0);
|
|
389
434
|
}
|
|
390
435
|
}
|
|
391
436
|
}
|
|
@@ -426,6 +471,14 @@ export async function opfsReadActiveGeneration(encodedDbName) {
|
|
|
426
471
|
const dbRoot = await getDbRoot(encodedDbName, false);
|
|
427
472
|
return await resolveActiveGeneration(dbRoot);
|
|
428
473
|
}
|
|
474
|
+
// The WASM view is valid only during this synchronous call. Zero the unread
|
|
475
|
+
// suffix to preserve the backend read contract when the destination is reused.
|
|
476
|
+
export function opfsReadAtInto(sessionId, fileKind, offset, buffer) {
|
|
477
|
+
const handle = getAccessHandle(sessionId, fileKind);
|
|
478
|
+
const read = readAll(handle, buffer, Number(offset));
|
|
479
|
+
buffer.fill(0, read);
|
|
480
|
+
return read;
|
|
481
|
+
}
|
|
429
482
|
export function opfsReadAt(sessionId, fileKind, offset, len) {
|
|
430
483
|
const handle = getAccessHandle(sessionId, fileKind);
|
|
431
484
|
const buffer = new Uint8Array(len);
|
|
@@ -433,32 +486,67 @@ export function opfsReadAt(sessionId, fileKind, offset, len) {
|
|
|
433
486
|
return buffer;
|
|
434
487
|
}
|
|
435
488
|
export function opfsWriteAt(sessionId, fileKind, offset, bytes) {
|
|
436
|
-
|
|
489
|
+
const handle = getAccessHandle(sessionId, fileKind);
|
|
490
|
+
try {
|
|
491
|
+
const at = Number(offset);
|
|
492
|
+
const written = writeAll(handle, bytes, at);
|
|
493
|
+
// Empty writes cannot extend the file. A successful overwrite alone
|
|
494
|
+
// cannot establish the full file length.
|
|
495
|
+
if (written > 0) {
|
|
496
|
+
const previous = appendOffsets.get(handle);
|
|
497
|
+
const end = at + written;
|
|
498
|
+
if (previous !== undefined && Number.isSafeInteger(at) && at >= 0 && Number.isSafeInteger(end)) {
|
|
499
|
+
appendOffsets.set(handle, Math.max(previous, end));
|
|
500
|
+
} else {
|
|
501
|
+
appendOffsets.delete(handle);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
return written;
|
|
505
|
+
} catch (error) {
|
|
506
|
+
// A failed write may leave a prefix. The next append must read the
|
|
507
|
+
// actual file length, even when the thrown value is not an Error.
|
|
508
|
+
appendOffsets.delete(handle);
|
|
509
|
+
throw error;
|
|
510
|
+
}
|
|
437
511
|
}
|
|
438
512
|
export function opfsFlush(sessionId, fileKind) {
|
|
439
|
-
getAccessHandle(sessionId, fileKind)
|
|
513
|
+
const handle = getAccessHandle(sessionId, fileKind);
|
|
514
|
+
try {
|
|
515
|
+
handle.flush();
|
|
516
|
+
} catch (error) {
|
|
517
|
+
appendOffsets.delete(handle);
|
|
518
|
+
throw error;
|
|
519
|
+
}
|
|
440
520
|
}
|
|
441
521
|
export function opfsLen(sessionId, fileKind) {
|
|
442
|
-
return BigInt(getAccessHandle(sessionId, fileKind)
|
|
522
|
+
return BigInt(readFileSize(getAccessHandle(sessionId, fileKind)));
|
|
523
|
+
}
|
|
524
|
+
export function opfsAppendOffset(sessionId, fileKind) {
|
|
525
|
+
const handle = getAccessHandle(sessionId, fileKind);
|
|
526
|
+
const size = appendOffsets.get(handle);
|
|
527
|
+
return size === undefined ? opfsLen(sessionId, fileKind) : BigInt(size);
|
|
443
528
|
}
|
|
444
529
|
export function opfsTruncate(sessionId, fileKind, size) {
|
|
445
|
-
getAccessHandle(sessionId, fileKind)
|
|
530
|
+
const handle = getAccessHandle(sessionId, fileKind);
|
|
531
|
+
try {
|
|
532
|
+
const length = Number(size);
|
|
533
|
+
handle.truncate(length);
|
|
534
|
+
rememberFileSize(handle, length);
|
|
535
|
+
} catch (error) {
|
|
536
|
+
appendOffsets.delete(handle);
|
|
537
|
+
throw error;
|
|
538
|
+
}
|
|
446
539
|
}
|
|
447
540
|
export function opfsCloseSession(sessionId) {
|
|
448
541
|
closeSession(sessionId);
|
|
449
542
|
}
|
|
450
543
|
export async function opfsPrepareRebuildTarget(encodedDbName) {
|
|
451
544
|
const dbRoot = await getDbRoot(encodedDbName, true);
|
|
452
|
-
|
|
453
|
-
while (await lookupDirectoryHandle(dbRoot, generationName)) {
|
|
454
|
-
generationName = createGenerationName();
|
|
455
|
-
}
|
|
456
|
-
await dbRoot.getDirectoryHandle(generationName, { create: true });
|
|
545
|
+
const generationName = await createGenerationDirectory(dbRoot);
|
|
457
546
|
return { generationName };
|
|
458
547
|
}
|
|
459
|
-
//
|
|
460
|
-
//
|
|
461
|
-
// the caller may switch its live engine only after that.
|
|
548
|
+
// Resolves after the control file is flushed and verified to select the new
|
|
549
|
+
// generation. The caller may then switch its live engine.
|
|
462
550
|
export async function opfsSwapActiveGeneration(encodedDbName, generationName, expectedCurrentGeneration) {
|
|
463
551
|
if (!isGenerationNameValid(generationName)) {
|
|
464
552
|
throw new Error(`invalid generation name ${generationName}`);
|
|
@@ -470,8 +558,8 @@ export async function opfsSwapActiveGeneration(encodedDbName, generationName, ex
|
|
|
470
558
|
}
|
|
471
559
|
await writeControlState(dbRoot, generationName, expectedCurrentGeneration ?? null);
|
|
472
560
|
}
|
|
473
|
-
// Legacy
|
|
474
|
-
// generation
|
|
561
|
+
// Legacy-file removal must succeed to prevent stale fallback after control
|
|
562
|
+
// damage. Inactive generation cleanup is best effort.
|
|
475
563
|
export async function opfsCleanupInactiveEntries(encodedDbName) {
|
|
476
564
|
const dbRoot = await lookupDirectoryHandle(await getOrCreateStackdbRoot(), encodedDbName);
|
|
477
565
|
if (!dbRoot) {
|
|
@@ -487,11 +575,12 @@ export async function opfsCleanupInactiveEntries(encodedDbName) {
|
|
|
487
575
|
staleDirectories.push(name);
|
|
488
576
|
}
|
|
489
577
|
}
|
|
490
|
-
|
|
578
|
+
await staleDirectories.reduce(async (previous, name) => {
|
|
579
|
+
await previous;
|
|
491
580
|
try {
|
|
492
581
|
await dbRoot.removeEntry(name, { recursive: true });
|
|
493
|
-
} catch
|
|
494
|
-
}
|
|
582
|
+
} catch {}
|
|
583
|
+
}, Promise.resolve());
|
|
495
584
|
}
|
|
496
585
|
export async function opfsDbDirectorySize(encodedDbName) {
|
|
497
586
|
const dbRoot = await lookupDirectoryHandle(await getOrCreateStackdbRoot(), encodedDbName);
|
package/dist/errors.d.ts
CHANGED
|
@@ -65,9 +65,9 @@ export declare class ChangeFeedCompactedError extends MoyoDbError {
|
|
|
65
65
|
constructor(message: string);
|
|
66
66
|
}
|
|
67
67
|
/**
|
|
68
|
-
* The
|
|
69
|
-
*
|
|
70
|
-
*
|
|
68
|
+
* The engine state could not be trusted, or automatic recovery failed.
|
|
69
|
+
* A failed commit may already be durable. The worker attempts recovery before
|
|
70
|
+
* a new transaction and after a failed commit. Recovery discards all open transactions.
|
|
71
71
|
*/
|
|
72
72
|
export declare class RecoveryRequiredError extends MoyoDbError {
|
|
73
73
|
constructor(message: string);
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAMR,EAAE,EAMF,WAAW,EASd,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAMR,EAAE,EAMF,WAAW,EASd,MAAM,SAAS,CAAC;AA+zBjB,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,EAAE,CAAC,CA+DjF;AACD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAI1D;AACD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAG5D;AACD,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,mBAAmB,SAAS,CAAC"}
|
package/dist/indexing.d.ts
CHANGED
|
@@ -27,7 +27,15 @@ export declare function decodeIndexEntryKey(bytes: Uint8Array): DecodedIndexEntr
|
|
|
27
27
|
export declare function indexKeyExactRange(logicalIndexKey: Uint8Array): Range;
|
|
28
28
|
export declare function indexRangeToPhysicalRange(range?: Range): Range;
|
|
29
29
|
export declare function extractLogicalIndexKey(def: NormalizedIndexDef, valueBytes: Uint8Array): Uint8Array | null;
|
|
30
|
+
/**
|
|
31
|
+
* Reuse the decoded document only within one synchronous mutation plan.
|
|
32
|
+
* Lazy decoding preserves validation order. Do not retain the extractor
|
|
33
|
+
* across operations or an await.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createIndexKeyExtractor(valueBytes: Uint8Array): (def: NormalizedIndexDef) => Uint8Array | null;
|
|
36
|
+
export declare function extractLogicalIndexKeyFromDocument(def: NormalizedIndexDef, documentValue: unknown): Uint8Array | null;
|
|
30
37
|
export declare function serializeNormalizedIndexDefinitions(defs: ReadonlyArray<NormalizedIndexDef>): string;
|
|
31
38
|
export declare function cloneNormalizedIndexDefinitions(defs: ReadonlyArray<NormalizedIndexDef>): NormalizedIndexDef[];
|
|
32
39
|
export declare function toPublicIndexDefinitions(defs: ReadonlyArray<NormalizedIndexDef>): IndexDef[];
|
|
40
|
+
export declare function decodeIndexedDocument(bytes: Uint8Array): unknown;
|
|
33
41
|
//# sourceMappingURL=indexing.d.ts.map
|
package/dist/indexing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"indexing.d.ts","sourceRoot":"","sources":["../src/indexing.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAU/C,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAC1D,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACzB;AACD,MAAM,WAAW,oBAAoB;IACjC,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;CAC1B;AACD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AACD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIxD;AACD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,EAAE,CAuD9E;AACD,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAc7G;AACD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3E;AACD,wBAAgB,mBAAmB,CAC/B,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACb,kBAAkB,GAAG,IAAI,CAE3B;AACD,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAE5G;AACD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAE9E;AACD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,kBAAkB,GAAG,UAAU,CAE5E;AACD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,kBAAkB,CAS9E;AACD,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAG,UAAU,CAEnG;AACD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,oBAAoB,
|
|
1
|
+
{"version":3,"file":"indexing.d.ts","sourceRoot":"","sources":["../src/indexing.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAU/C,eAAO,MAAM,oBAAoB,wBAAwB,CAAC;AAC1D,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACzB;AACD,MAAM,WAAW,oBAAoB;IACjC,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;CAC1B;AACD,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD;AACD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAIxD;AACD,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,EAAE,CAuD9E;AACD,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,kBAAkB,EAAE,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAc7G;AACD,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3E;AACD,wBAAgB,mBAAmB,CAC/B,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,EACvC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,GACb,kBAAkB,GAAG,IAAI,CAE3B;AACD,wBAAgB,eAAe,CAAC,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAE5G;AACD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,CAE9E;AACD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,kBAAkB,GAAG,UAAU,CAE5E;AACD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,UAAU,GAAG,kBAAkB,CAS9E;AACD,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAG,UAAU,CAEnG;AACD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,oBAAoB,CAc3E;AACD,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,UAAU,GAAG,KAAK,CAErE;AACD,wBAAgB,yBAAyB,CAAC,KAAK,GAAE,KAAU,GAAG,KAAK,CA4BlE;AACD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,kBAAkB,EAAE,UAAU,EAAE,UAAU,GAAG,UAAU,GAAG,IAAI,CAEzG;AACD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,UAAU,GAAG,CAAC,GAAG,EAAE,kBAAkB,KAAK,UAAU,GAAG,IAAI,CAU9G;AACD,wBAAgB,kCAAkC,CAAC,GAAG,EAAE,kBAAkB,EAAE,aAAa,EAAE,OAAO,GAAG,UAAU,GAAG,IAAI,CAiBrH;AACD,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAEnG;AACD,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,GAAG,kBAAkB,EAAE,CAS7G;AACD,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,aAAa,CAAC,kBAAkB,CAAC,GAAG,QAAQ,EAAE,CAE5F;AAmED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAMhE"}
|