@korajs/store 1.0.0-beta.0 → 1.0.0-beta.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/dist/adapters/better-sqlite3.d.cts +1 -1
- package/dist/adapters/better-sqlite3.d.ts +1 -1
- package/dist/adapters/indexeddb.d.cts +1 -1
- package/dist/adapters/indexeddb.d.ts +1 -1
- package/dist/adapters/sqlite-wasm.d.cts +1 -1
- package/dist/adapters/sqlite-wasm.d.ts +1 -1
- package/dist/{backup-5XZ7THNJ.js → backup-ZV4Y424B.js} +3 -3
- package/dist/blob-fs.cjs +166 -0
- package/dist/blob-fs.cjs.map +1 -0
- package/dist/blob-fs.d.cts +29 -0
- package/dist/blob-fs.d.ts +29 -0
- package/dist/blob-fs.js +128 -0
- package/dist/blob-fs.js.map +1 -0
- package/dist/{chunk-ETDJEH2I.js → chunk-6NKLDBTY.js} +11 -1
- package/dist/{chunk-ETDJEH2I.js.map → chunk-6NKLDBTY.js.map} +1 -1
- package/dist/{chunk-EIVXWF4B.js → chunk-FFYA7J5H.js} +2 -2
- package/dist/chunk-W4MTTNEZ.js +55 -0
- package/dist/chunk-W4MTTNEZ.js.map +1 -0
- package/dist/{chunk-5R4QMY3Z.js → chunk-X57MWW35.js} +2 -2
- package/dist/{chunk-OUQDC5Z6.js → chunk-ZLWAYQEQ.js} +28 -12
- package/dist/chunk-ZLWAYQEQ.js.map +1 -0
- package/dist/content-addressed-blob-store-Dcj3SB9r.d.cts +60 -0
- package/dist/content-addressed-blob-store-Dcj3SB9r.d.ts +60 -0
- package/dist/{export-audit-VPGQWNR6.js → export-audit-AJ7RORNK.js} +3 -3
- package/dist/index.cjs +632 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +397 -6
- package/dist/index.d.ts +397 -6
- package/dist/index.js +561 -26
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +25 -5
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.d.cts +3 -3
- package/dist/internal.d.ts +3 -3
- package/dist/internal.js +3 -3
- package/dist/{types-CyjXwrjW.d.cts → types-5h4Hqcwc.d.ts} +10 -3
- package/dist/{types-DAxCladl.d.ts → types-DfPiPwKr.d.cts} +10 -3
- package/dist/{types-CJOVKxLw.d.ts → types-k6AZgiH4.d.cts} +6 -1
- package/dist/{types-CJOVKxLw.d.cts → types-k6AZgiH4.d.ts} +6 -1
- package/package.json +13 -2
- package/dist/chunk-OUQDC5Z6.js.map +0 -1
- /package/dist/{backup-5XZ7THNJ.js.map → backup-ZV4Y424B.js.map} +0 -0
- /package/dist/{chunk-EIVXWF4B.js.map → chunk-FFYA7J5H.js.map} +0 -0
- /package/dist/{chunk-5R4QMY3Z.js.map → chunk-X57MWW35.js.map} +0 -0
- /package/dist/{export-audit-VPGQWNR6.js.map → export-audit-AJ7RORNK.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -239,6 +239,9 @@ function serializeValue(value, descriptor) {
|
|
|
239
239
|
case "boolean":
|
|
240
240
|
return value ? 1 : 0;
|
|
241
241
|
case "array":
|
|
242
|
+
case "object":
|
|
243
|
+
case "json":
|
|
244
|
+
case "blob":
|
|
242
245
|
return JSON.stringify(value);
|
|
243
246
|
case "richtext":
|
|
244
247
|
return encodeRichtext(value);
|
|
@@ -255,6 +258,13 @@ function deserializeValue(value, descriptor) {
|
|
|
255
258
|
return JSON.parse(value);
|
|
256
259
|
}
|
|
257
260
|
return value;
|
|
261
|
+
case "object":
|
|
262
|
+
case "json":
|
|
263
|
+
case "blob":
|
|
264
|
+
if (typeof value === "string") {
|
|
265
|
+
return JSON.parse(value);
|
|
266
|
+
}
|
|
267
|
+
return value;
|
|
258
268
|
case "richtext":
|
|
259
269
|
return decodeRichtext(value);
|
|
260
270
|
default:
|
|
@@ -973,10 +983,14 @@ var init_export_audit = __esm({
|
|
|
973
983
|
var index_exports = {};
|
|
974
984
|
__export(index_exports, {
|
|
975
985
|
AdapterError: () => AdapterError,
|
|
986
|
+
BlobIntegrityError: () => BlobIntegrityError,
|
|
976
987
|
COMPACTION_BASELINE_META_KEY: () => COMPACTION_BASELINE_META_KEY,
|
|
977
988
|
Collection: () => Collection,
|
|
989
|
+
DEFAULT_CHUNK_SIZE: () => DEFAULT_CHUNK_SIZE,
|
|
978
990
|
InvalidStateTransitionError: () => InvalidStateTransitionError,
|
|
979
991
|
LAST_ACKED_SERVER_VECTOR_META_KEY: () => LAST_ACKED_SERVER_VECTOR_META_KEY,
|
|
992
|
+
MemoryBlobStore: () => MemoryBlobStore,
|
|
993
|
+
OpfsBlobStore: () => OpfsBlobStore,
|
|
980
994
|
OptimisticLockError: () => OptimisticLockError,
|
|
981
995
|
PersistenceError: () => PersistenceError,
|
|
982
996
|
QueryBuilder: () => QueryBuilder,
|
|
@@ -994,26 +1008,44 @@ __export(index_exports, {
|
|
|
994
1008
|
WorkerTimeoutError: () => WorkerTimeoutError,
|
|
995
1009
|
asRichTextSyncEngine: () => asRichTextSyncEngine,
|
|
996
1010
|
assertQueryReady: () => assertQueryReady,
|
|
1011
|
+
chunkBlob: () => chunkBlob,
|
|
1012
|
+
collectBlobGarbage: () => collectBlobGarbage,
|
|
997
1013
|
collectOperationsAheadOfServer: () => collectOperationsAheadOfServer,
|
|
998
1014
|
compactOperationLog: () => compactOperationLog,
|
|
999
1015
|
computeAckCompactionWatermark: () => computeAckCompactionWatermark,
|
|
1016
|
+
createChunkPortPair: () => createChunkPortPair,
|
|
1017
|
+
createMemoryServerBlobStore: () => createMemoryServerBlobStore,
|
|
1018
|
+
createOpfsBlobDirectory: () => createOpfsBlobDirectory,
|
|
1019
|
+
createOpfsBlobStore: () => createOpfsBlobStore,
|
|
1020
|
+
createRemoteChunkProvider: () => createRemoteChunkProvider,
|
|
1000
1021
|
createRichTextController: () => createRichTextController,
|
|
1001
1022
|
decodeAuditExport: () => decodeAuditExport,
|
|
1002
1023
|
decodeRichtext: () => decodeRichtext,
|
|
1003
1024
|
deserializeVersionVectorFromMeta: () => deserializeVersionVectorFromMeta,
|
|
1004
1025
|
encodeRichtext: () => encodeRichtext,
|
|
1005
1026
|
exportBackup: () => exportBackup,
|
|
1027
|
+
extractBlobRefs: () => extractBlobRefs,
|
|
1028
|
+
fetchBlobManifest: () => fetchBlobManifest,
|
|
1006
1029
|
getSharedQueryStoreCache: () => getSharedQueryStoreCache,
|
|
1007
1030
|
mergeVersionVectors: () => mergeVersionVectors,
|
|
1031
|
+
parseBlobManifest: () => parseBlobManifest,
|
|
1008
1032
|
persistedAuditTraceFromEvent: () => persistedAuditTraceFromEvent,
|
|
1009
1033
|
pluralize: () => pluralize,
|
|
1034
|
+
prepareBlobForSend: () => prepareBlobForSend,
|
|
1035
|
+
putBlobForTransfer: () => putBlobForTransfer,
|
|
1010
1036
|
readAuditExportManifest: () => readAuditExportManifest,
|
|
1011
1037
|
readBackupManifest: () => readBackupManifest,
|
|
1038
|
+
reassembleBlob: () => reassembleBlob,
|
|
1039
|
+
receiveBlob: () => receiveBlob,
|
|
1040
|
+
resolveBlobManifest: () => resolveBlobManifest,
|
|
1012
1041
|
restoreBackup: () => restoreBackup,
|
|
1013
1042
|
richtextStatesEqual: () => richtextStatesEqual,
|
|
1014
1043
|
richtextToPlainText: () => richtextToPlainText,
|
|
1044
|
+
serializeBlobManifest: () => serializeBlobManifest,
|
|
1015
1045
|
serializeVersionVectorToMeta: () => serializeVersionVectorToMeta,
|
|
1046
|
+
serveBlobChunks: () => serveBlobChunks,
|
|
1016
1047
|
singularize: () => singularize,
|
|
1048
|
+
toServerBlobCallbacks: () => toServerBlobCallbacks,
|
|
1017
1049
|
validateStateTransition: () => validateStateTransition,
|
|
1018
1050
|
validateUpdateStateMachine: () => validateUpdateStateMachine,
|
|
1019
1051
|
verifyAuditExportChecksum: () => verifyAuditExportChecksum,
|
|
@@ -1613,6 +1645,11 @@ async function executeInsert(ctx, data) {
|
|
|
1613
1645
|
validated[fieldName] = Date.now();
|
|
1614
1646
|
}
|
|
1615
1647
|
}
|
|
1648
|
+
const writeData = await (0, import_core9.transformSecretFieldsForWrite)(
|
|
1649
|
+
validated,
|
|
1650
|
+
ctx.definition,
|
|
1651
|
+
ctx.secretKeyProvider
|
|
1652
|
+
);
|
|
1616
1653
|
const causalDeps = resolveCausalDeps(ctx);
|
|
1617
1654
|
let operation;
|
|
1618
1655
|
let record;
|
|
@@ -1627,7 +1664,7 @@ async function executeInsert(ctx, data) {
|
|
|
1627
1664
|
// Binary richtext values are tagged as canonical JSON BEFORE the
|
|
1628
1665
|
// operation is content-hashed, so the hash input, persisted JSON,
|
|
1629
1666
|
// and wire payload are the identical value.
|
|
1630
|
-
data: encodeRichtextFieldsForOpData(
|
|
1667
|
+
data: encodeRichtextFieldsForOpData(writeData, ctx.definition.fields),
|
|
1631
1668
|
previousData: null,
|
|
1632
1669
|
sequenceNumber,
|
|
1633
1670
|
causalDeps,
|
|
@@ -1636,7 +1673,7 @@ async function executeInsert(ctx, data) {
|
|
|
1636
1673
|
ctx.clock
|
|
1637
1674
|
);
|
|
1638
1675
|
ctx.causalTracker?.afterOperation(ctx.collection, operation.id, ctx.inTransaction);
|
|
1639
|
-
const serializedData = serializeRecord(
|
|
1676
|
+
const serializedData = serializeRecord(writeData, ctx.definition.fields);
|
|
1640
1677
|
const version = serializeRowVersion(operation.timestamp);
|
|
1641
1678
|
record = {
|
|
1642
1679
|
id: recordId,
|
|
@@ -1661,7 +1698,7 @@ async function executeInsert(ctx, data) {
|
|
|
1661
1698
|
ctx.onMutation(ctx.collection, operation);
|
|
1662
1699
|
return {
|
|
1663
1700
|
id: recordId,
|
|
1664
|
-
...
|
|
1701
|
+
...writeData,
|
|
1665
1702
|
createdAt: operation.timestamp.wallTime,
|
|
1666
1703
|
updatedAt: operation.timestamp.wallTime
|
|
1667
1704
|
};
|
|
@@ -1789,6 +1826,11 @@ async function executeUpdate(ctx, id, data) {
|
|
|
1789
1826
|
resolvedData[key] = value;
|
|
1790
1827
|
}
|
|
1791
1828
|
}
|
|
1829
|
+
const writeData = await (0, import_core11.transformSecretFieldsForWrite)(
|
|
1830
|
+
resolvedData,
|
|
1831
|
+
ctx.definition,
|
|
1832
|
+
ctx.secretKeyProvider
|
|
1833
|
+
);
|
|
1792
1834
|
const hasAtomicOps = Object.keys(atomicOps).length > 0;
|
|
1793
1835
|
const causalDeps = resolveCausalDeps(ctx);
|
|
1794
1836
|
let operation;
|
|
@@ -1803,7 +1845,7 @@ async function executeUpdate(ctx, id, data) {
|
|
|
1803
1845
|
// Binary richtext values (new and previous) are tagged as canonical
|
|
1804
1846
|
// JSON BEFORE the operation is content-hashed, so the hash input,
|
|
1805
1847
|
// persisted JSON, and wire payload are the identical value.
|
|
1806
|
-
data: encodeRichtextFieldsForOpData(
|
|
1848
|
+
data: encodeRichtextFieldsForOpData(writeData, ctx.definition.fields),
|
|
1807
1849
|
previousData: encodeRichtextFieldsForOpData(previousData, ctx.definition.fields),
|
|
1808
1850
|
sequenceNumber,
|
|
1809
1851
|
causalDeps,
|
|
@@ -1813,7 +1855,7 @@ async function executeUpdate(ctx, id, data) {
|
|
|
1813
1855
|
ctx.clock
|
|
1814
1856
|
);
|
|
1815
1857
|
ctx.causalTracker?.afterOperation(ctx.collection, operation.id, ctx.inTransaction);
|
|
1816
|
-
const serializedChanges = serializeRecord(
|
|
1858
|
+
const serializedChanges = serializeRecord(writeData, ctx.definition.fields);
|
|
1817
1859
|
const version = serializeRowVersion(operation.timestamp);
|
|
1818
1860
|
const mergedFieldVersions = parseFieldVersions(currentRow._field_versions);
|
|
1819
1861
|
for (const changedField of Object.keys(serializedChanges)) {
|
|
@@ -1847,7 +1889,7 @@ async function executeUpdate(ctx, id, data) {
|
|
|
1847
1889
|
// src/collection/collection.ts
|
|
1848
1890
|
init_serializer();
|
|
1849
1891
|
var Collection = class {
|
|
1850
|
-
constructor(name, definition, schema, adapter, clock, nodeId, allocateSequenceNumber, onMutation, relationEnforcer, mutationHandler, causalTracker) {
|
|
1892
|
+
constructor(name, definition, schema, adapter, clock, nodeId, allocateSequenceNumber, onMutation, relationEnforcer, mutationHandler, causalTracker, secretKeyProvider) {
|
|
1851
1893
|
this.name = name;
|
|
1852
1894
|
this.definition = definition;
|
|
1853
1895
|
this.schema = schema;
|
|
@@ -1859,6 +1901,7 @@ var Collection = class {
|
|
|
1859
1901
|
this.relationEnforcer = relationEnforcer;
|
|
1860
1902
|
this.mutationHandler = mutationHandler;
|
|
1861
1903
|
this.causalTracker = causalTracker;
|
|
1904
|
+
this.secretKeyProvider = secretKeyProvider;
|
|
1862
1905
|
}
|
|
1863
1906
|
name;
|
|
1864
1907
|
definition;
|
|
@@ -1871,6 +1914,7 @@ var Collection = class {
|
|
|
1871
1914
|
relationEnforcer;
|
|
1872
1915
|
mutationHandler;
|
|
1873
1916
|
causalTracker;
|
|
1917
|
+
secretKeyProvider;
|
|
1874
1918
|
mutationContext() {
|
|
1875
1919
|
return {
|
|
1876
1920
|
collection: this.name,
|
|
@@ -1883,7 +1927,8 @@ var Collection = class {
|
|
|
1883
1927
|
onMutation: this.onMutation,
|
|
1884
1928
|
relationEnforcer: this.relationEnforcer,
|
|
1885
1929
|
causalTracker: this.causalTracker,
|
|
1886
|
-
inTransaction: false
|
|
1930
|
+
inTransaction: false,
|
|
1931
|
+
secretKeyProvider: this.secretKeyProvider
|
|
1887
1932
|
};
|
|
1888
1933
|
}
|
|
1889
1934
|
async insert(data) {
|
|
@@ -3661,6 +3706,7 @@ var Store = class {
|
|
|
3661
3706
|
localMutationHandler;
|
|
3662
3707
|
relationEnforcer = null;
|
|
3663
3708
|
causalTracker = null;
|
|
3709
|
+
secretKeyProvider;
|
|
3664
3710
|
constructor(config) {
|
|
3665
3711
|
this.schema = config.schema;
|
|
3666
3712
|
this.adapter = config.adapter;
|
|
@@ -3669,6 +3715,7 @@ var Store = class {
|
|
|
3669
3715
|
this.isolation = config.isolation ?? "shared";
|
|
3670
3716
|
this.emitter = config.emitter ?? null;
|
|
3671
3717
|
this.localMutationHandler = config.localMutationHandler ?? null;
|
|
3718
|
+
this.secretKeyProvider = config.secretKeyProvider;
|
|
3672
3719
|
this.subscriptionManager = new SubscriptionManager({
|
|
3673
3720
|
onQuerySubscribed: config.onQuerySubscribed
|
|
3674
3721
|
});
|
|
@@ -3711,7 +3758,8 @@ var Store = class {
|
|
|
3711
3758
|
},
|
|
3712
3759
|
this.relationEnforcer,
|
|
3713
3760
|
this.localMutationHandler,
|
|
3714
|
-
this.causalTracker
|
|
3761
|
+
this.causalTracker,
|
|
3762
|
+
this.secretKeyProvider
|
|
3715
3763
|
);
|
|
3716
3764
|
this.collections.set(name, col);
|
|
3717
3765
|
}
|
|
@@ -4172,7 +4220,8 @@ var Store = class {
|
|
|
4172
4220
|
relationEnforcer: this.relationEnforcer,
|
|
4173
4221
|
causalTracker: this.causalTracker,
|
|
4174
4222
|
inTransaction: options?.inTransaction ?? false,
|
|
4175
|
-
extraCausalDeps: options?.extraCausalDeps
|
|
4223
|
+
extraCausalDeps: options?.extraCausalDeps,
|
|
4224
|
+
secretKeyProvider: this.secretKeyProvider
|
|
4176
4225
|
};
|
|
4177
4226
|
}
|
|
4178
4227
|
/**
|
|
@@ -5075,13 +5124,569 @@ init_backup();
|
|
|
5075
5124
|
init_audit_trace_store();
|
|
5076
5125
|
init_audit_json();
|
|
5077
5126
|
init_export_audit();
|
|
5127
|
+
|
|
5128
|
+
// src/blob/content-addressed-blob-store.ts
|
|
5129
|
+
var import_core21 = require("@korajs/core");
|
|
5130
|
+
var BlobIntegrityError = class extends Error {
|
|
5131
|
+
constructor(expectedHash, actualHash) {
|
|
5132
|
+
super(`Blob integrity check failed: content under hash ${expectedHash} hashes to ${actualHash}`);
|
|
5133
|
+
this.expectedHash = expectedHash;
|
|
5134
|
+
this.actualHash = actualHash;
|
|
5135
|
+
this.name = "BlobIntegrityError";
|
|
5136
|
+
}
|
|
5137
|
+
expectedHash;
|
|
5138
|
+
actualHash;
|
|
5139
|
+
};
|
|
5140
|
+
var MemoryBlobStore = class {
|
|
5141
|
+
blobs = /* @__PURE__ */ new Map();
|
|
5142
|
+
async put(bytes, metadata = {}) {
|
|
5143
|
+
const ref = await (0, import_core21.createBlobRef)(bytes, metadata);
|
|
5144
|
+
if (!this.blobs.has(ref.hash)) {
|
|
5145
|
+
const stored = new Uint8Array(bytes.byteLength);
|
|
5146
|
+
stored.set(bytes);
|
|
5147
|
+
this.blobs.set(ref.hash, stored);
|
|
5148
|
+
}
|
|
5149
|
+
return ref;
|
|
5150
|
+
}
|
|
5151
|
+
async get(hash) {
|
|
5152
|
+
const stored = this.blobs.get(hash);
|
|
5153
|
+
if (stored === void 0) {
|
|
5154
|
+
return null;
|
|
5155
|
+
}
|
|
5156
|
+
const actualHash = await (0, import_core21.hashBlob)(stored);
|
|
5157
|
+
if (actualHash !== hash) {
|
|
5158
|
+
throw new BlobIntegrityError(hash, actualHash);
|
|
5159
|
+
}
|
|
5160
|
+
const out = new Uint8Array(stored.byteLength);
|
|
5161
|
+
out.set(stored);
|
|
5162
|
+
return out;
|
|
5163
|
+
}
|
|
5164
|
+
async has(hash) {
|
|
5165
|
+
return this.blobs.has(hash);
|
|
5166
|
+
}
|
|
5167
|
+
async delete(hash) {
|
|
5168
|
+
return this.blobs.delete(hash);
|
|
5169
|
+
}
|
|
5170
|
+
async size() {
|
|
5171
|
+
return this.blobs.size;
|
|
5172
|
+
}
|
|
5173
|
+
async list() {
|
|
5174
|
+
return [...this.blobs.keys()];
|
|
5175
|
+
}
|
|
5176
|
+
};
|
|
5177
|
+
|
|
5178
|
+
// src/blob/opfs-blob-store.ts
|
|
5179
|
+
var import_core22 = require("@korajs/core");
|
|
5180
|
+
var OpfsBlobStore = class {
|
|
5181
|
+
constructor(dir) {
|
|
5182
|
+
this.dir = dir;
|
|
5183
|
+
}
|
|
5184
|
+
dir;
|
|
5185
|
+
shardFor(hash) {
|
|
5186
|
+
return hash.slice(0, 2);
|
|
5187
|
+
}
|
|
5188
|
+
async put(bytes, metadata = {}) {
|
|
5189
|
+
const ref = await (0, import_core22.createBlobRef)(bytes, metadata);
|
|
5190
|
+
const shard = this.shardFor(ref.hash);
|
|
5191
|
+
if (await this.dir.has(shard, ref.hash)) {
|
|
5192
|
+
return ref;
|
|
5193
|
+
}
|
|
5194
|
+
const out = new Uint8Array(bytes.byteLength);
|
|
5195
|
+
out.set(bytes);
|
|
5196
|
+
await this.dir.write(shard, ref.hash, out);
|
|
5197
|
+
return ref;
|
|
5198
|
+
}
|
|
5199
|
+
async get(hash) {
|
|
5200
|
+
const bytes = await this.dir.read(this.shardFor(hash), hash);
|
|
5201
|
+
if (bytes === null) {
|
|
5202
|
+
return null;
|
|
5203
|
+
}
|
|
5204
|
+
const actual = await (0, import_core22.hashBlob)(bytes);
|
|
5205
|
+
if (actual !== hash) {
|
|
5206
|
+
throw new BlobIntegrityError(hash, actual);
|
|
5207
|
+
}
|
|
5208
|
+
return bytes;
|
|
5209
|
+
}
|
|
5210
|
+
async has(hash) {
|
|
5211
|
+
return this.dir.has(this.shardFor(hash), hash);
|
|
5212
|
+
}
|
|
5213
|
+
async delete(hash) {
|
|
5214
|
+
return this.dir.remove(this.shardFor(hash), hash);
|
|
5215
|
+
}
|
|
5216
|
+
async size() {
|
|
5217
|
+
return this.dir.count();
|
|
5218
|
+
}
|
|
5219
|
+
async list() {
|
|
5220
|
+
return this.dir.keys();
|
|
5221
|
+
}
|
|
5222
|
+
};
|
|
5223
|
+
function getStorageManager() {
|
|
5224
|
+
const nav = globalThis.navigator;
|
|
5225
|
+
if (!nav?.storage || typeof nav.storage.getDirectory !== "function") {
|
|
5226
|
+
throw new Error(
|
|
5227
|
+
"OPFS is unavailable in this environment. The OPFS blob store requires a browser with Origin Private File System support; use MemoryBlobStore or a server-side store elsewhere."
|
|
5228
|
+
);
|
|
5229
|
+
}
|
|
5230
|
+
return nav.storage;
|
|
5231
|
+
}
|
|
5232
|
+
function isNotFoundError(error) {
|
|
5233
|
+
return typeof error === "object" && error !== null && error.name === "NotFoundError";
|
|
5234
|
+
}
|
|
5235
|
+
async function createOpfsBlobDirectory(rootDirName = "kora-blobs") {
|
|
5236
|
+
const storage = getStorageManager();
|
|
5237
|
+
if (typeof storage.persist === "function") {
|
|
5238
|
+
try {
|
|
5239
|
+
await storage.persist();
|
|
5240
|
+
} catch {
|
|
5241
|
+
}
|
|
5242
|
+
}
|
|
5243
|
+
const opfsRoot = await storage.getDirectory();
|
|
5244
|
+
const root = await opfsRoot.getDirectoryHandle(rootDirName, { create: true });
|
|
5245
|
+
async function shardHandle(shard, create) {
|
|
5246
|
+
try {
|
|
5247
|
+
return await root.getDirectoryHandle(shard, { create });
|
|
5248
|
+
} catch (error) {
|
|
5249
|
+
if (isNotFoundError(error)) {
|
|
5250
|
+
return null;
|
|
5251
|
+
}
|
|
5252
|
+
throw error;
|
|
5253
|
+
}
|
|
5254
|
+
}
|
|
5255
|
+
return {
|
|
5256
|
+
async read(shard, name) {
|
|
5257
|
+
const dir = await shardHandle(shard, false);
|
|
5258
|
+
if (!dir) {
|
|
5259
|
+
return null;
|
|
5260
|
+
}
|
|
5261
|
+
let handle;
|
|
5262
|
+
try {
|
|
5263
|
+
handle = await dir.getFileHandle(name, { create: false });
|
|
5264
|
+
} catch (error) {
|
|
5265
|
+
if (isNotFoundError(error)) {
|
|
5266
|
+
return null;
|
|
5267
|
+
}
|
|
5268
|
+
throw error;
|
|
5269
|
+
}
|
|
5270
|
+
const file = await handle.getFile();
|
|
5271
|
+
return new Uint8Array(await file.arrayBuffer());
|
|
5272
|
+
},
|
|
5273
|
+
async write(shard, name, bytes) {
|
|
5274
|
+
const dir = await root.getDirectoryHandle(shard, { create: true });
|
|
5275
|
+
const handle = await dir.getFileHandle(name, { create: true });
|
|
5276
|
+
const writable = await handle.createWritable({ keepExistingData: false });
|
|
5277
|
+
try {
|
|
5278
|
+
await writable.write(bytes);
|
|
5279
|
+
} finally {
|
|
5280
|
+
await writable.close();
|
|
5281
|
+
}
|
|
5282
|
+
},
|
|
5283
|
+
async remove(shard, name) {
|
|
5284
|
+
const dir = await shardHandle(shard, false);
|
|
5285
|
+
if (!dir) {
|
|
5286
|
+
return false;
|
|
5287
|
+
}
|
|
5288
|
+
try {
|
|
5289
|
+
await dir.removeEntry(name);
|
|
5290
|
+
return true;
|
|
5291
|
+
} catch (error) {
|
|
5292
|
+
if (isNotFoundError(error)) {
|
|
5293
|
+
return false;
|
|
5294
|
+
}
|
|
5295
|
+
throw error;
|
|
5296
|
+
}
|
|
5297
|
+
},
|
|
5298
|
+
async has(shard, name) {
|
|
5299
|
+
const dir = await shardHandle(shard, false);
|
|
5300
|
+
if (!dir) {
|
|
5301
|
+
return false;
|
|
5302
|
+
}
|
|
5303
|
+
try {
|
|
5304
|
+
await dir.getFileHandle(name, { create: false });
|
|
5305
|
+
return true;
|
|
5306
|
+
} catch (error) {
|
|
5307
|
+
if (isNotFoundError(error)) {
|
|
5308
|
+
return false;
|
|
5309
|
+
}
|
|
5310
|
+
throw error;
|
|
5311
|
+
}
|
|
5312
|
+
},
|
|
5313
|
+
async count() {
|
|
5314
|
+
let total = 0;
|
|
5315
|
+
for await (const shard of root.keys()) {
|
|
5316
|
+
const dir = await shardHandle(shard, false);
|
|
5317
|
+
if (!dir) {
|
|
5318
|
+
continue;
|
|
5319
|
+
}
|
|
5320
|
+
for await (const name of dir.keys()) {
|
|
5321
|
+
if (!name.endsWith(".tmp")) {
|
|
5322
|
+
total++;
|
|
5323
|
+
}
|
|
5324
|
+
}
|
|
5325
|
+
}
|
|
5326
|
+
return total;
|
|
5327
|
+
},
|
|
5328
|
+
async keys() {
|
|
5329
|
+
const names = [];
|
|
5330
|
+
for await (const shard of root.keys()) {
|
|
5331
|
+
const dir = await shardHandle(shard, false);
|
|
5332
|
+
if (!dir) {
|
|
5333
|
+
continue;
|
|
5334
|
+
}
|
|
5335
|
+
for await (const name of dir.keys()) {
|
|
5336
|
+
if (!name.endsWith(".tmp")) {
|
|
5337
|
+
names.push(name);
|
|
5338
|
+
}
|
|
5339
|
+
}
|
|
5340
|
+
}
|
|
5341
|
+
return names;
|
|
5342
|
+
}
|
|
5343
|
+
};
|
|
5344
|
+
}
|
|
5345
|
+
async function createOpfsBlobStore(rootDirName = "kora-blobs") {
|
|
5346
|
+
return new OpfsBlobStore(await createOpfsBlobDirectory(rootDirName));
|
|
5347
|
+
}
|
|
5348
|
+
|
|
5349
|
+
// src/blob/blob-chunking.ts
|
|
5350
|
+
var import_core23 = require("@korajs/core");
|
|
5351
|
+
var DEFAULT_CHUNK_SIZE = 256 * 1024;
|
|
5352
|
+
async function chunkBlob(bytes, chunkSize = DEFAULT_CHUNK_SIZE, metadata = {}) {
|
|
5353
|
+
if (chunkSize <= 0) {
|
|
5354
|
+
throw new Error(`chunkBlob requires a positive chunkSize, got ${chunkSize}`);
|
|
5355
|
+
}
|
|
5356
|
+
const chunkHashes = [];
|
|
5357
|
+
const chunks = /* @__PURE__ */ new Map();
|
|
5358
|
+
for (let offset = 0; offset < bytes.byteLength; offset += chunkSize) {
|
|
5359
|
+
const end = Math.min(offset + chunkSize, bytes.byteLength);
|
|
5360
|
+
const chunk = new Uint8Array(end - offset);
|
|
5361
|
+
chunk.set(bytes.subarray(offset, end));
|
|
5362
|
+
const hash = await (0, import_core23.hashBlob)(chunk);
|
|
5363
|
+
chunkHashes.push(hash);
|
|
5364
|
+
if (!chunks.has(hash)) {
|
|
5365
|
+
chunks.set(hash, chunk);
|
|
5366
|
+
}
|
|
5367
|
+
}
|
|
5368
|
+
const blobHash = await (0, import_core23.hashBlob)(bytes);
|
|
5369
|
+
const manifest = {
|
|
5370
|
+
blobHash,
|
|
5371
|
+
size: bytes.byteLength,
|
|
5372
|
+
chunkSize,
|
|
5373
|
+
chunkHashes
|
|
5374
|
+
};
|
|
5375
|
+
if (metadata.mimeType !== void 0) {
|
|
5376
|
+
manifest.mimeType = metadata.mimeType;
|
|
5377
|
+
}
|
|
5378
|
+
if (metadata.filename !== void 0) {
|
|
5379
|
+
manifest.filename = metadata.filename;
|
|
5380
|
+
}
|
|
5381
|
+
return { manifest, chunks };
|
|
5382
|
+
}
|
|
5383
|
+
async function reassembleBlob(manifest, chunkStore) {
|
|
5384
|
+
const parts = [];
|
|
5385
|
+
let total = 0;
|
|
5386
|
+
for (const hash of manifest.chunkHashes) {
|
|
5387
|
+
const chunk = await chunkStore.get(hash);
|
|
5388
|
+
if (chunk === null) {
|
|
5389
|
+
throw new Error(`Cannot reassemble blob ${manifest.blobHash}: missing chunk ${hash}`);
|
|
5390
|
+
}
|
|
5391
|
+
parts.push(chunk);
|
|
5392
|
+
total += chunk.byteLength;
|
|
5393
|
+
}
|
|
5394
|
+
const out = new Uint8Array(total);
|
|
5395
|
+
let offset = 0;
|
|
5396
|
+
for (const part of parts) {
|
|
5397
|
+
out.set(part, offset);
|
|
5398
|
+
offset += part.byteLength;
|
|
5399
|
+
}
|
|
5400
|
+
const actual = await (0, import_core23.hashBlob)(out);
|
|
5401
|
+
if (actual !== manifest.blobHash) {
|
|
5402
|
+
throw new BlobIntegrityError(manifest.blobHash, actual);
|
|
5403
|
+
}
|
|
5404
|
+
return out;
|
|
5405
|
+
}
|
|
5406
|
+
|
|
5407
|
+
// src/blob/blob-transfer.ts
|
|
5408
|
+
var import_core24 = require("@korajs/core");
|
|
5409
|
+
async function receiveBlob(manifest, provider, stores) {
|
|
5410
|
+
let chunksFetched = 0;
|
|
5411
|
+
let chunksSkipped = 0;
|
|
5412
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5413
|
+
for (const hash of manifest.chunkHashes) {
|
|
5414
|
+
if (seen.has(hash)) {
|
|
5415
|
+
continue;
|
|
5416
|
+
}
|
|
5417
|
+
seen.add(hash);
|
|
5418
|
+
if (await stores.chunkStore.has(hash)) {
|
|
5419
|
+
chunksSkipped++;
|
|
5420
|
+
continue;
|
|
5421
|
+
}
|
|
5422
|
+
const bytes = await provider.getChunk(hash);
|
|
5423
|
+
if (bytes === null) {
|
|
5424
|
+
throw new Error(`Blob transfer failed: provider could not supply chunk ${hash}`);
|
|
5425
|
+
}
|
|
5426
|
+
const actual = await (0, import_core24.hashBlob)(bytes);
|
|
5427
|
+
if (actual !== hash) {
|
|
5428
|
+
throw new BlobIntegrityError(hash, actual);
|
|
5429
|
+
}
|
|
5430
|
+
await stores.chunkStore.put(bytes);
|
|
5431
|
+
chunksFetched++;
|
|
5432
|
+
}
|
|
5433
|
+
const full = await reassembleBlob(manifest, stores.chunkStore);
|
|
5434
|
+
const ref = await stores.blobStore.put(full, {
|
|
5435
|
+
mimeType: manifest.mimeType,
|
|
5436
|
+
filename: manifest.filename
|
|
5437
|
+
});
|
|
5438
|
+
return { ref, chunksFetched, chunksSkipped };
|
|
5439
|
+
}
|
|
5440
|
+
async function prepareBlobForSend(bytes, chunkStore, options = {}) {
|
|
5441
|
+
const { manifest, chunks } = await chunkBlob(bytes, options.chunkSize, {
|
|
5442
|
+
mimeType: options.mimeType,
|
|
5443
|
+
filename: options.filename
|
|
5444
|
+
});
|
|
5445
|
+
for (const chunk of chunks.values()) {
|
|
5446
|
+
await chunkStore.put(chunk);
|
|
5447
|
+
}
|
|
5448
|
+
const provider = {
|
|
5449
|
+
getChunk: (hash) => chunkStore.get(hash)
|
|
5450
|
+
};
|
|
5451
|
+
return { manifest, provider };
|
|
5452
|
+
}
|
|
5453
|
+
|
|
5454
|
+
// src/blob/blob-manifest-transfer.ts
|
|
5455
|
+
var import_core25 = require("@korajs/core");
|
|
5456
|
+
function serializeBlobManifest(manifest) {
|
|
5457
|
+
const canonical = {
|
|
5458
|
+
blobHash: manifest.blobHash,
|
|
5459
|
+
size: manifest.size,
|
|
5460
|
+
chunkSize: manifest.chunkSize,
|
|
5461
|
+
chunkHashes: manifest.chunkHashes
|
|
5462
|
+
};
|
|
5463
|
+
if (manifest.mimeType !== void 0) {
|
|
5464
|
+
canonical.mimeType = manifest.mimeType;
|
|
5465
|
+
}
|
|
5466
|
+
if (manifest.filename !== void 0) {
|
|
5467
|
+
canonical.filename = manifest.filename;
|
|
5468
|
+
}
|
|
5469
|
+
return new TextEncoder().encode(JSON.stringify(canonical));
|
|
5470
|
+
}
|
|
5471
|
+
function parseBlobManifest(bytes) {
|
|
5472
|
+
const parsed = JSON.parse(new TextDecoder().decode(bytes));
|
|
5473
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
5474
|
+
throw new Error("Invalid blob manifest: not an object");
|
|
5475
|
+
}
|
|
5476
|
+
const obj = parsed;
|
|
5477
|
+
if (typeof obj.blobHash !== "string") {
|
|
5478
|
+
throw new Error("Invalid blob manifest: missing blobHash");
|
|
5479
|
+
}
|
|
5480
|
+
if (typeof obj.size !== "number" || typeof obj.chunkSize !== "number") {
|
|
5481
|
+
throw new Error("Invalid blob manifest: missing size or chunkSize");
|
|
5482
|
+
}
|
|
5483
|
+
if (!Array.isArray(obj.chunkHashes) || obj.chunkHashes.some((h) => typeof h !== "string")) {
|
|
5484
|
+
throw new Error("Invalid blob manifest: chunkHashes must be an array of strings");
|
|
5485
|
+
}
|
|
5486
|
+
const manifest = {
|
|
5487
|
+
blobHash: obj.blobHash,
|
|
5488
|
+
size: obj.size,
|
|
5489
|
+
chunkSize: obj.chunkSize,
|
|
5490
|
+
chunkHashes: obj.chunkHashes
|
|
5491
|
+
};
|
|
5492
|
+
if (typeof obj.mimeType === "string") {
|
|
5493
|
+
manifest.mimeType = obj.mimeType;
|
|
5494
|
+
}
|
|
5495
|
+
if (typeof obj.filename === "string") {
|
|
5496
|
+
manifest.filename = obj.filename;
|
|
5497
|
+
}
|
|
5498
|
+
return manifest;
|
|
5499
|
+
}
|
|
5500
|
+
async function putBlobForTransfer(store, bytes, options = {}) {
|
|
5501
|
+
const { manifest, chunks } = await chunkBlob(bytes, options.chunkSize, {
|
|
5502
|
+
...options.mimeType !== void 0 ? { mimeType: options.mimeType } : {},
|
|
5503
|
+
...options.filename !== void 0 ? { filename: options.filename } : {}
|
|
5504
|
+
});
|
|
5505
|
+
for (const chunk of chunks.values()) {
|
|
5506
|
+
await store.put(chunk);
|
|
5507
|
+
}
|
|
5508
|
+
const baseRef = await store.put(bytes, {
|
|
5509
|
+
...options.mimeType !== void 0 ? { mimeType: options.mimeType } : {},
|
|
5510
|
+
...options.filename !== void 0 ? { filename: options.filename } : {}
|
|
5511
|
+
});
|
|
5512
|
+
const manifestRef = await store.put(serializeBlobManifest(manifest));
|
|
5513
|
+
return { ref: { ...baseRef, manifestHash: manifestRef.hash }, manifest };
|
|
5514
|
+
}
|
|
5515
|
+
async function fetchBlobManifest(provider, manifestHash) {
|
|
5516
|
+
const bytes = await provider.getChunk(manifestHash);
|
|
5517
|
+
if (bytes === null) {
|
|
5518
|
+
throw new Error(`Blob manifest ${manifestHash} could not be fetched from the provider`);
|
|
5519
|
+
}
|
|
5520
|
+
const actual = await (0, import_core25.hashBlob)(bytes);
|
|
5521
|
+
if (actual !== manifestHash) {
|
|
5522
|
+
throw new BlobIntegrityError(manifestHash, actual);
|
|
5523
|
+
}
|
|
5524
|
+
return parseBlobManifest(bytes);
|
|
5525
|
+
}
|
|
5526
|
+
async function resolveBlobManifest(provider, ref) {
|
|
5527
|
+
if (ref.manifestHash === void 0) {
|
|
5528
|
+
throw new Error(
|
|
5529
|
+
`Blob ${ref.hash} has no manifest to resolve. Store it with putBlobForTransfer (or app.blobs.put) so its reference carries a manifestHash, or pull with an explicit manifest.`
|
|
5530
|
+
);
|
|
5531
|
+
}
|
|
5532
|
+
return fetchBlobManifest(provider, ref.manifestHash);
|
|
5533
|
+
}
|
|
5534
|
+
|
|
5535
|
+
// src/blob/server-blob-callbacks.ts
|
|
5536
|
+
var import_core26 = require("@korajs/core");
|
|
5537
|
+
function toServerBlobCallbacks(store) {
|
|
5538
|
+
return {
|
|
5539
|
+
resolveBlobChunk: (hash) => store.get(hash),
|
|
5540
|
+
async persistBlobChunk(hash, bytes) {
|
|
5541
|
+
const actual = await (0, import_core26.hashBlob)(bytes);
|
|
5542
|
+
if (actual !== hash) {
|
|
5543
|
+
return;
|
|
5544
|
+
}
|
|
5545
|
+
await store.put(bytes);
|
|
5546
|
+
}
|
|
5547
|
+
};
|
|
5548
|
+
}
|
|
5549
|
+
function createMemoryServerBlobStore() {
|
|
5550
|
+
const store = new MemoryBlobStore();
|
|
5551
|
+
return { store, callbacks: toServerBlobCallbacks(store) };
|
|
5552
|
+
}
|
|
5553
|
+
|
|
5554
|
+
// src/blob/blob-gc.ts
|
|
5555
|
+
var import_core27 = require("@korajs/core");
|
|
5556
|
+
function extractBlobRefs(record) {
|
|
5557
|
+
const refs = [];
|
|
5558
|
+
for (const value of Object.values(record)) {
|
|
5559
|
+
if ((0, import_core27.isBlobRef)(value)) {
|
|
5560
|
+
refs.push(value);
|
|
5561
|
+
}
|
|
5562
|
+
}
|
|
5563
|
+
return refs;
|
|
5564
|
+
}
|
|
5565
|
+
async function collectBlobGarbage(store, liveRefs, options = {}) {
|
|
5566
|
+
const live = /* @__PURE__ */ new Set();
|
|
5567
|
+
for (const ref of liveRefs) {
|
|
5568
|
+
live.add(ref.hash);
|
|
5569
|
+
if (ref.manifestHash === void 0) {
|
|
5570
|
+
continue;
|
|
5571
|
+
}
|
|
5572
|
+
live.add(ref.manifestHash);
|
|
5573
|
+
try {
|
|
5574
|
+
const manifestBytes = await store.get(ref.manifestHash);
|
|
5575
|
+
if (manifestBytes !== null) {
|
|
5576
|
+
const manifest = parseBlobManifest(manifestBytes);
|
|
5577
|
+
for (const chunkHash of manifest.chunkHashes) {
|
|
5578
|
+
live.add(chunkHash);
|
|
5579
|
+
}
|
|
5580
|
+
}
|
|
5581
|
+
} catch {
|
|
5582
|
+
}
|
|
5583
|
+
}
|
|
5584
|
+
const all = await store.list();
|
|
5585
|
+
const collectedHashes = [];
|
|
5586
|
+
for (const hash of all) {
|
|
5587
|
+
if (live.has(hash)) {
|
|
5588
|
+
continue;
|
|
5589
|
+
}
|
|
5590
|
+
collectedHashes.push(hash);
|
|
5591
|
+
if (!options.dryRun) {
|
|
5592
|
+
await store.delete(hash);
|
|
5593
|
+
}
|
|
5594
|
+
}
|
|
5595
|
+
return {
|
|
5596
|
+
scanned: all.length,
|
|
5597
|
+
live: live.size,
|
|
5598
|
+
collected: collectedHashes.length,
|
|
5599
|
+
collectedHashes
|
|
5600
|
+
};
|
|
5601
|
+
}
|
|
5602
|
+
|
|
5603
|
+
// src/blob/blob-chunk-transport.ts
|
|
5604
|
+
var import_core28 = require("@korajs/core");
|
|
5605
|
+
function createRemoteChunkProvider(port, options = {}) {
|
|
5606
|
+
const timeoutMs = options.timeoutMs ?? 3e4;
|
|
5607
|
+
const pending = /* @__PURE__ */ new Map();
|
|
5608
|
+
port.onMessage((message) => {
|
|
5609
|
+
if (message.type !== "blob-chunk-response") {
|
|
5610
|
+
return;
|
|
5611
|
+
}
|
|
5612
|
+
const entry = pending.get(message.requestId);
|
|
5613
|
+
if (!entry) {
|
|
5614
|
+
return;
|
|
5615
|
+
}
|
|
5616
|
+
pending.delete(message.requestId);
|
|
5617
|
+
clearTimeout(entry.timer);
|
|
5618
|
+
entry.resolve(message.bytes);
|
|
5619
|
+
});
|
|
5620
|
+
return {
|
|
5621
|
+
pendingCount: () => pending.size,
|
|
5622
|
+
getChunk(hash) {
|
|
5623
|
+
const requestId = (0, import_core28.generateUUIDv7)();
|
|
5624
|
+
return new Promise((resolve, reject) => {
|
|
5625
|
+
const timer = setTimeout(() => {
|
|
5626
|
+
pending.delete(requestId);
|
|
5627
|
+
reject(new Error(`Blob chunk request for ${hash} timed out after ${timeoutMs}ms`));
|
|
5628
|
+
}, timeoutMs);
|
|
5629
|
+
pending.set(requestId, { resolve, reject, timer });
|
|
5630
|
+
port.send({ type: "blob-chunk-request", requestId, hash });
|
|
5631
|
+
});
|
|
5632
|
+
}
|
|
5633
|
+
};
|
|
5634
|
+
}
|
|
5635
|
+
function serveBlobChunks(port, blobStore) {
|
|
5636
|
+
port.onMessage((message) => {
|
|
5637
|
+
if (message.type !== "blob-chunk-request") {
|
|
5638
|
+
return;
|
|
5639
|
+
}
|
|
5640
|
+
void blobStore.get(message.hash).then(
|
|
5641
|
+
(bytes) => {
|
|
5642
|
+
port.send({ type: "blob-chunk-response", requestId: message.requestId, bytes });
|
|
5643
|
+
},
|
|
5644
|
+
() => {
|
|
5645
|
+
port.send({ type: "blob-chunk-response", requestId: message.requestId, bytes: null });
|
|
5646
|
+
}
|
|
5647
|
+
);
|
|
5648
|
+
});
|
|
5649
|
+
}
|
|
5650
|
+
function createChunkPortPair() {
|
|
5651
|
+
const handlersA = [];
|
|
5652
|
+
const handlersB = [];
|
|
5653
|
+
const a = {
|
|
5654
|
+
send(message) {
|
|
5655
|
+
queueMicrotask(() => {
|
|
5656
|
+
for (const handler of handlersB) {
|
|
5657
|
+
handler(message);
|
|
5658
|
+
}
|
|
5659
|
+
});
|
|
5660
|
+
},
|
|
5661
|
+
onMessage(handler) {
|
|
5662
|
+
handlersA.push(handler);
|
|
5663
|
+
}
|
|
5664
|
+
};
|
|
5665
|
+
const b = {
|
|
5666
|
+
send(message) {
|
|
5667
|
+
queueMicrotask(() => {
|
|
5668
|
+
for (const handler of handlersA) {
|
|
5669
|
+
handler(message);
|
|
5670
|
+
}
|
|
5671
|
+
});
|
|
5672
|
+
},
|
|
5673
|
+
onMessage(handler) {
|
|
5674
|
+
handlersB.push(handler);
|
|
5675
|
+
}
|
|
5676
|
+
};
|
|
5677
|
+
return { a, b };
|
|
5678
|
+
}
|
|
5078
5679
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5079
5680
|
0 && (module.exports = {
|
|
5080
5681
|
AdapterError,
|
|
5682
|
+
BlobIntegrityError,
|
|
5081
5683
|
COMPACTION_BASELINE_META_KEY,
|
|
5082
5684
|
Collection,
|
|
5685
|
+
DEFAULT_CHUNK_SIZE,
|
|
5083
5686
|
InvalidStateTransitionError,
|
|
5084
5687
|
LAST_ACKED_SERVER_VECTOR_META_KEY,
|
|
5688
|
+
MemoryBlobStore,
|
|
5689
|
+
OpfsBlobStore,
|
|
5085
5690
|
OptimisticLockError,
|
|
5086
5691
|
PersistenceError,
|
|
5087
5692
|
QueryBuilder,
|
|
@@ -5099,26 +5704,44 @@ init_export_audit();
|
|
|
5099
5704
|
WorkerTimeoutError,
|
|
5100
5705
|
asRichTextSyncEngine,
|
|
5101
5706
|
assertQueryReady,
|
|
5707
|
+
chunkBlob,
|
|
5708
|
+
collectBlobGarbage,
|
|
5102
5709
|
collectOperationsAheadOfServer,
|
|
5103
5710
|
compactOperationLog,
|
|
5104
5711
|
computeAckCompactionWatermark,
|
|
5712
|
+
createChunkPortPair,
|
|
5713
|
+
createMemoryServerBlobStore,
|
|
5714
|
+
createOpfsBlobDirectory,
|
|
5715
|
+
createOpfsBlobStore,
|
|
5716
|
+
createRemoteChunkProvider,
|
|
5105
5717
|
createRichTextController,
|
|
5106
5718
|
decodeAuditExport,
|
|
5107
5719
|
decodeRichtext,
|
|
5108
5720
|
deserializeVersionVectorFromMeta,
|
|
5109
5721
|
encodeRichtext,
|
|
5110
5722
|
exportBackup,
|
|
5723
|
+
extractBlobRefs,
|
|
5724
|
+
fetchBlobManifest,
|
|
5111
5725
|
getSharedQueryStoreCache,
|
|
5112
5726
|
mergeVersionVectors,
|
|
5727
|
+
parseBlobManifest,
|
|
5113
5728
|
persistedAuditTraceFromEvent,
|
|
5114
5729
|
pluralize,
|
|
5730
|
+
prepareBlobForSend,
|
|
5731
|
+
putBlobForTransfer,
|
|
5115
5732
|
readAuditExportManifest,
|
|
5116
5733
|
readBackupManifest,
|
|
5734
|
+
reassembleBlob,
|
|
5735
|
+
receiveBlob,
|
|
5736
|
+
resolveBlobManifest,
|
|
5117
5737
|
restoreBackup,
|
|
5118
5738
|
richtextStatesEqual,
|
|
5119
5739
|
richtextToPlainText,
|
|
5740
|
+
serializeBlobManifest,
|
|
5120
5741
|
serializeVersionVectorToMeta,
|
|
5742
|
+
serveBlobChunks,
|
|
5121
5743
|
singularize,
|
|
5744
|
+
toServerBlobCallbacks,
|
|
5122
5745
|
validateStateTransition,
|
|
5123
5746
|
validateUpdateStateMachine,
|
|
5124
5747
|
verifyAuditExportChecksum,
|