@fireproof/core 0.19.112-dev-web → 0.19.112-dev-iife

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. package/{chunk-GZANCVTS.js → chunk-D4E6UX6S.js} +1 -8
  2. package/{chunk-GZANCVTS.js.map → chunk-D4E6UX6S.js.map} +1 -1
  3. package/{web/chunk-S4HRSKEO.js → chunk-OKACCIGZ.js} +15 -29
  4. package/chunk-OKACCIGZ.js.map +1 -0
  5. package/chunk-PZ5AY32C.js +10 -0
  6. package/gateway-3YJXDXD3.js +59 -0
  7. package/gateway-3YJXDXD3.js.map +1 -0
  8. package/{gateway@skip-iife-OZ2V32XH.js → gateway-HUSQCAA7.js} +5 -4
  9. package/gateway-HUSQCAA7.js.map +1 -0
  10. package/index.cjs +73 -285
  11. package/index.cjs.map +1 -1
  12. package/index.d.cts +1 -3
  13. package/index.d.ts +1 -3
  14. package/index.global.js +195 -171
  15. package/index.global.js.map +1 -1
  16. package/index.js +17 -17
  17. package/index.js.map +1 -1
  18. package/{key-bag-file-4TYN2H7F.js → key-bag-file-QCOF7UFH.js} +4 -3
  19. package/{key-bag-file-4TYN2H7F.js.map → key-bag-file-QCOF7UFH.js.map} +1 -1
  20. package/{key-bag-indexdb-JEOAS4WM.js → key-bag-indexdb-VHX3MZ66.js} +4 -3
  21. package/{key-bag-indexdb-JEOAS4WM.js.map → key-bag-indexdb-VHX3MZ66.js.map} +1 -1
  22. package/metafile-cjs.json +1 -1
  23. package/metafile-esm.json +1 -1
  24. package/metafile-iife.json +1 -1
  25. package/node/chunk-4A4RAVNS.js +17 -0
  26. package/node/chunk-4A4RAVNS.js.map +1 -0
  27. package/node/mem-filesystem.cjs +72 -0
  28. package/node/mem-filesystem.cjs.map +1 -0
  29. package/node/mem-filesystem.d.cts +25 -0
  30. package/node/mem-filesystem.d.ts +25 -0
  31. package/{mem-filesystem@skip-iife-CJI7IIKV.js → node/mem-filesystem.js} +3 -4
  32. package/node/mem-filesystem.js.map +1 -0
  33. package/node/metafile-cjs.json +1 -0
  34. package/node/metafile-esm.json +1 -0
  35. package/node/node-filesystem.cjs +86 -0
  36. package/node/node-filesystem.cjs.map +1 -0
  37. package/node/node-filesystem.d.cts +36 -0
  38. package/node/node-filesystem.d.ts +36 -0
  39. package/{node-filesystem@skip-iife-O74VAABQ.js → node/node-filesystem.js} +3 -4
  40. package/node/node-filesystem.js.map +1 -0
  41. package/node/types-DARSfXlb.d.cts +23 -0
  42. package/node/types-DARSfXlb.d.ts +23 -0
  43. package/package.json +1 -1
  44. package/utils-GYG2FMCZ.js +13 -0
  45. package/web/gateway-impl.cjs +319 -0
  46. package/web/gateway-impl.cjs.map +1 -0
  47. package/web/gateway-impl.d.cts +86 -0
  48. package/web/gateway-impl.d.ts +86 -0
  49. package/{gateway@skip-esm-O655UEIP.js → web/gateway-impl.js} +165 -20
  50. package/web/gateway-impl.js.map +1 -0
  51. package/web/metafile-cjs.json +1 -1
  52. package/web/metafile-esm.json +1 -1
  53. package/chunk-LNFBDD6E.js +0 -75
  54. package/chunk-LNFBDD6E.js.map +0 -1
  55. package/chunk-PB4BKL4O.js +0 -7
  56. package/chunk-PB4BKL4O.js.map +0 -1
  57. package/gateway@skip-esm-O655UEIP.js.map +0 -1
  58. package/gateway@skip-iife-OZ2V32XH.js.map +0 -1
  59. package/mem-filesystem@skip-iife-CJI7IIKV.js.map +0 -1
  60. package/node-filesystem@skip-iife-O74VAABQ.js.map +0 -1
  61. package/utils-L7MUZUJX.js +0 -14
  62. package/web/bundle-not-impl-UH74NK5L.js +0 -5
  63. package/web/bundle-not-impl-UH74NK5L.js.map +0 -1
  64. package/web/chunk-2DC5ZIR4.js +0 -7
  65. package/web/chunk-2DC5ZIR4.js.map +0 -1
  66. package/web/chunk-Q5W7UNMP.js +0 -292
  67. package/web/chunk-Q5W7UNMP.js.map +0 -1
  68. package/web/chunk-S4HRSKEO.js.map +0 -1
  69. package/web/gateway@skip-esm-GI5PRACF.js +0 -165
  70. package/web/gateway@skip-esm-GI5PRACF.js.map +0 -1
  71. package/web/index.cjs +0 -4138
  72. package/web/index.cjs.map +0 -1
  73. package/web/index.d.cts +0 -1139
  74. package/web/index.d.ts +0 -1139
  75. package/web/index.js +0 -3478
  76. package/web/index.js.map +0 -1
  77. package/web/key-bag-file-4SJQGORQ.js +0 -54
  78. package/web/key-bag-file-4SJQGORQ.js.map +0 -1
  79. package/web/key-bag-indexdb-GSQOUUVQ.js +0 -50
  80. package/web/key-bag-indexdb-GSQOUUVQ.js.map +0 -1
  81. package/web/utils-EFZJNXH5.js +0 -14
  82. /package/{utils-L7MUZUJX.js.map → chunk-PZ5AY32C.js.map} +0 -0
  83. /package/{web/utils-EFZJNXH5.js.map → utils-GYG2FMCZ.js.map} +0 -0
package/web/index.js DELETED
@@ -1,3478 +0,0 @@
1
- import {
2
- getFileName,
3
- getFileSystem,
4
- getPath,
5
- toArrayBuffer
6
- } from "./chunk-S4HRSKEO.js";
7
- import {
8
- INDEXDB_VERSION
9
- } from "./chunk-2DC5ZIR4.js";
10
- import {
11
- NotFoundError,
12
- Result,
13
- UInt8ArrayEqual,
14
- __export,
15
- dataDir,
16
- ensureLogger,
17
- ensureSuperLog,
18
- ensureSuperThis,
19
- exceptionWrapper,
20
- getKey,
21
- getName,
22
- getStore,
23
- isNotFoundError
24
- } from "./chunk-Q5W7UNMP.js";
25
-
26
- // src/database.ts
27
- import { ResolveOnce as ResolveOnce6 } from "@adviser/cement";
28
-
29
- // src/write-queue.ts
30
- function writeQueue(worker, payload = Infinity, unbounded = false) {
31
- const queue = [];
32
- let isProcessing = false;
33
- async function process() {
34
- if (isProcessing || queue.length === 0) return;
35
- isProcessing = true;
36
- const tasksToProcess = queue.splice(0, payload);
37
- const updates = tasksToProcess.map((item) => item.task);
38
- if (unbounded) {
39
- const promises = updates.map(async (update, index2) => {
40
- try {
41
- const result = await worker([update]);
42
- tasksToProcess[index2].resolve(result);
43
- } catch (error) {
44
- tasksToProcess[index2].reject(error);
45
- }
46
- });
47
- await Promise.all(promises);
48
- } else {
49
- try {
50
- const result = await worker(updates);
51
- tasksToProcess.forEach((task) => task.resolve(result));
52
- } catch (error) {
53
- tasksToProcess.forEach((task) => task.reject(error));
54
- }
55
- }
56
- isProcessing = false;
57
- void process();
58
- }
59
- return {
60
- push(task) {
61
- return new Promise((resolve, reject) => {
62
- queue.push({ task, resolve, reject });
63
- void process();
64
- });
65
- }
66
- };
67
- }
68
-
69
- // src/crdt.ts
70
- import { ResolveOnce as ResolveOnce5 } from "@adviser/cement";
71
-
72
- // src/runtime/wait-pr-multiformats/block.ts
73
- var block_exports = {};
74
- __export(block_exports, {
75
- Block: () => Block,
76
- create: () => create,
77
- createUnsafe: () => createUnsafe,
78
- decode: () => decode,
79
- encode: () => encode
80
- });
81
- import { bytes as binary, CID } from "multiformats";
82
- import { Block as mfBlock } from "multiformats/block";
83
- var Block = mfBlock;
84
- async function decode({
85
- bytes,
86
- codec: codec3,
87
- hasher: hasher7
88
- }) {
89
- if (bytes == null) throw new Error('Missing required argument "bytes"');
90
- if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
91
- const value = await Promise.resolve(codec3.decode(bytes));
92
- const hash = await hasher7.digest(bytes);
93
- const cid = CID.create(1, codec3.code, hash);
94
- return new mfBlock({ value, bytes, cid });
95
- }
96
- async function encode({
97
- value,
98
- codec: codec3,
99
- hasher: hasher7
100
- }) {
101
- if (typeof value === "undefined") throw new Error('Missing required argument "value"');
102
- if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
103
- const bytes = await Promise.resolve(codec3.encode(value));
104
- const hash = await hasher7.digest(bytes);
105
- const cid = CID.create(1, codec3.code, hash);
106
- return new mfBlock({ value, bytes, cid });
107
- }
108
- async function create({
109
- bytes,
110
- cid,
111
- hasher: hasher7,
112
- codec: codec3
113
- }) {
114
- if (bytes == null) throw new Error('Missing required argument "bytes"');
115
- if (hasher7 == null) throw new Error('Missing required argument "hasher"');
116
- const value = await Promise.resolve(codec3.decode(bytes));
117
- const hash = await hasher7.digest(bytes);
118
- if (!binary.equals(cid.multihash.bytes, hash.bytes)) {
119
- throw new Error("CID hash does not match bytes");
120
- }
121
- return createUnsafe({
122
- bytes,
123
- cid,
124
- value,
125
- codec: codec3
126
- });
127
- }
128
- async function createUnsafe({
129
- bytes,
130
- cid,
131
- value: maybeValue,
132
- codec: codec3
133
- }) {
134
- const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
135
- if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
136
- return new Block({
137
- cid,
138
- bytes,
139
- value
140
- });
141
- }
142
-
143
- // src/crdt-helpers.ts
144
- import { parse as parse3 } from "multiformats/link";
145
- import { sha256 as hasher5 } from "multiformats/hashes/sha2";
146
- import * as codec from "@ipld/dag-cbor";
147
- import { put, get, entries, root } from "@web3-storage/pail/crdt";
148
- import { EventFetcher, vis } from "@web3-storage/pail/clock";
149
- import * as Batch from "@web3-storage/pail/crdt/batch";
150
-
151
- // src/blockstore/index.ts
152
- var blockstore_exports = {};
153
- __export(blockstore_exports, {
154
- BaseBlockstore: () => BaseBlockstore,
155
- CarTransaction: () => CarTransaction,
156
- CompactionFetcher: () => CompactionFetcher,
157
- ConnectionBase: () => ConnectionBase,
158
- EncryptedBlockstore: () => EncryptedBlockstore,
159
- FragmentGateway: () => FragmentGateway,
160
- Loader: () => Loader,
161
- addCryptoKeyToGatewayMetaPayload: () => addCryptoKeyToGatewayMetaPayload,
162
- ensureStart: () => ensureStart,
163
- getGatewayFromURL: () => getGatewayFromURL,
164
- parseCarFile: () => parseCarFile,
165
- registerStoreProtocol: () => registerStoreProtocol,
166
- setCryptoKeyFromGatewayMetaPayload: () => setCryptoKeyFromGatewayMetaPayload,
167
- testStoreFactory: () => testStoreFactory,
168
- toCIDBlock: () => toCIDBlock,
169
- toStoreRuntime: () => toStoreRuntime
170
- });
171
-
172
- // src/blockstore/types.ts
173
- function toCIDBlock(block) {
174
- return block;
175
- }
176
-
177
- // src/blockstore/store-factory.ts
178
- import { KeyedResolvOnce as KeyedResolvOnce2, URI as URI5 } from "@adviser/cement";
179
-
180
- // src/runtime/files.ts
181
- var files_exports = {};
182
- __export(files_exports, {
183
- decodeFile: () => decodeFile,
184
- encodeFile: () => encodeFile
185
- });
186
- import * as UnixFS from "@ipld/unixfs";
187
- import * as raw from "multiformats/codecs/raw";
188
- import { withMaxChunkSize } from "@ipld/unixfs/file/chunker/fixed";
189
- import { withWidth } from "@ipld/unixfs/file/layout/balanced";
190
- import { exporter } from "ipfs-unixfs-exporter";
191
- var queuingStrategy = UnixFS.withCapacity();
192
- var settings = UnixFS.configure({
193
- fileChunkEncoder: raw,
194
- smallFileEncoder: raw,
195
- chunker: withMaxChunkSize(1024 * 1024),
196
- fileLayout: withWidth(1024)
197
- });
198
- async function collect(collectable) {
199
- const chunks = [];
200
- await collectable.pipeTo(
201
- new WritableStream({
202
- write(chunk) {
203
- chunks.push(chunk);
204
- }
205
- })
206
- );
207
- return chunks;
208
- }
209
- async function encodeFile(blob) {
210
- const readable = createFileEncoderStream(blob);
211
- const blocks = await collect(readable);
212
- return { cid: blocks.at(-1).cid, blocks };
213
- }
214
- async function decodeFile(blocks, cid, meta) {
215
- const entry = await exporter(cid.toString(), blocks, { length: meta.size });
216
- const chunks = [];
217
- for await (const chunk of entry.content()) {
218
- chunks.push(chunk);
219
- }
220
- return new File(chunks, entry.name, { type: meta.type, lastModified: 0 });
221
- }
222
- function createFileEncoderStream(blob) {
223
- const { readable, writable } = new TransformStream({}, queuingStrategy);
224
- const unixfsWriter = UnixFS.createWriter({ writable, settings });
225
- const fileBuilder = new UnixFSFileBuilder("", blob);
226
- void (async () => {
227
- await fileBuilder.finalize(unixfsWriter);
228
- await unixfsWriter.close();
229
- })();
230
- return readable;
231
- }
232
- var UnixFSFileBuilder = class {
233
- #file;
234
- constructor(name, file) {
235
- this.name = name;
236
- this.#file = file;
237
- }
238
- async finalize(writer) {
239
- const unixfsFileWriter = UnixFS.createFileWriter(writer);
240
- await this.#file.stream().pipeTo(
241
- new WritableStream({
242
- async write(chunk) {
243
- await unixfsFileWriter.write(chunk);
244
- }
245
- })
246
- );
247
- return await unixfsFileWriter.close();
248
- }
249
- };
250
-
251
- // src/blockstore/store.ts
252
- import { format as format2, parse as parse2 } from "@ipld/dag-json";
253
- import { exception2Result, ResolveOnce as ResolveOnce3, Result as Result5 } from "@adviser/cement";
254
-
255
- // src/types.ts
256
- function isFalsy(value) {
257
- return value === false && value === null && value === void 0;
258
- }
259
- function throwFalsy(value) {
260
- if (isFalsy(value)) {
261
- throw new Error("value is Falsy");
262
- }
263
- return value;
264
- }
265
- function falsyToUndef(value) {
266
- if (isFalsy(value)) {
267
- return void 0;
268
- }
269
- return value;
270
- }
271
-
272
- // src/blockstore/loader.ts
273
- import pLimit from "p-limit";
274
- import { CarReader } from "@ipld/car";
275
- import { ResolveOnce as ResolveOnce2 } from "@adviser/cement";
276
-
277
- // src/blockstore/loader-helpers.ts
278
- import { sha256 as hasher } from "multiformats/hashes/sha2";
279
- import * as dagCodec from "@ipld/dag-cbor";
280
- async function parseCarFile(reader, logger) {
281
- const roots = await reader.getRoots();
282
- const header = await reader.get(roots[0]);
283
- if (!header) throw logger.Error().Msg("missing header block").AsError();
284
- const dec = await decode({ bytes: header.bytes, hasher, codec: dagCodec });
285
- const fpvalue = dec.value;
286
- if (fpvalue && !fpvalue.fp) {
287
- throw logger.Error().Msg("missing fp").AsError();
288
- }
289
- return fpvalue.fp;
290
- }
291
-
292
- // src/blockstore/transaction.ts
293
- import { MemoryBlockstore } from "@web3-storage/pail/block";
294
- import { toCryptoRuntime } from "@adviser/cement";
295
- var CarTransaction = class extends MemoryBlockstore {
296
- constructor(parent, opts = { add: true, noLoader: false }) {
297
- super();
298
- if (opts.add) {
299
- parent.transactions.add(this);
300
- }
301
- this.parent = parent;
302
- }
303
- async get(cid) {
304
- return await this.superGet(cid) || falsyToUndef(await this.parent.get(cid));
305
- }
306
- async superGet(cid) {
307
- return super.get(cid);
308
- }
309
- };
310
- function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
311
- const logger = ensureLogger(sthis, component, ctx);
312
- const store = opts.store || {};
313
- return {
314
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
315
- applyMeta: (meta, snap) => {
316
- return Promise.resolve();
317
- },
318
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
319
- compact: async (blocks) => {
320
- return {};
321
- },
322
- autoCompact: 100,
323
- public: false,
324
- name: void 0,
325
- threshold: 1e3 * 1e3,
326
- ...opts,
327
- logger,
328
- keyBag: opts.keyBag || {},
329
- crypto: toCryptoRuntime(opts.crypto),
330
- store,
331
- storeRuntime: toStoreRuntime(store, sthis)
332
- };
333
- }
334
- function blockstoreFactory(sthis, opts) {
335
- if (opts.name) {
336
- return new EncryptedBlockstore(sthis, opts);
337
- } else {
338
- return new BaseBlockstore(opts);
339
- }
340
- }
341
- var BaseBlockstore = class {
342
- constructor(ebOpts = {}) {
343
- this.transactions = /* @__PURE__ */ new Set();
344
- this.sthis = ensureSuperThis(ebOpts);
345
- this.ebOpts = defaultedBlockstoreRuntime(this.sthis, ebOpts, "BaseBlockstore");
346
- this.logger = this.ebOpts.logger;
347
- }
348
- // ready: Promise<void>;
349
- ready() {
350
- return Promise.resolve();
351
- }
352
- async close() {
353
- }
354
- async destroy() {
355
- }
356
- async compact() {
357
- }
358
- async get(cid) {
359
- if (!cid) throw this.logger.Error().Msg("required cid").AsError();
360
- for (const f of this.transactions) {
361
- const v = await f.superGet(cid);
362
- if (v) return v;
363
- }
364
- }
365
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
366
- async put(cid, block) {
367
- throw this.logger.Error().Msg("use a transaction to put").AsError();
368
- }
369
- // TransactionMeta
370
- async transaction(fn, _opts) {
371
- const t = new CarTransaction(this, _opts);
372
- const done = await fn(t);
373
- this.lastTxMeta = done;
374
- return { t, meta: done };
375
- }
376
- openTransaction(opts = { add: true, noLoader: false }) {
377
- return new CarTransaction(this, opts);
378
- }
379
- async commitTransaction(t, done, opts) {
380
- if (!this.loader) throw this.logger.Error().Msg("loader required to commit").AsError();
381
- const cars = await this.loader?.commit(t, done, opts);
382
- if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
383
- setTimeout(() => void this.compact(), 10);
384
- }
385
- if (cars) {
386
- this.transactions.delete(t);
387
- return { meta: done, cars, t };
388
- }
389
- throw this.logger.Error().Msg("failed to commit car files").AsError();
390
- }
391
- async *entries() {
392
- const seen = /* @__PURE__ */ new Set();
393
- for (const t of this.transactions) {
394
- for await (const blk of t.entries()) {
395
- if (seen.has(blk.cid.toString())) continue;
396
- seen.add(blk.cid.toString());
397
- yield blk;
398
- }
399
- }
400
- }
401
- };
402
- var EncryptedBlockstore = class extends BaseBlockstore {
403
- constructor(sthis, ebOpts) {
404
- super(ebOpts);
405
- this.compacting = false;
406
- this.logger = ensureLogger(this.sthis, "EncryptedBlockstore");
407
- const { name } = ebOpts;
408
- if (!name) {
409
- throw this.logger.Error().Msg("name required").AsError();
410
- }
411
- this.name = name;
412
- this.loader = new Loader(this.name, ebOpts, sthis);
413
- }
414
- ready() {
415
- return this.loader.ready();
416
- }
417
- close() {
418
- return this.loader.close();
419
- }
420
- destroy() {
421
- return this.loader.destroy();
422
- }
423
- async get(cid) {
424
- const got = await super.get(cid);
425
- if (got) return got;
426
- if (!this.loader) {
427
- return;
428
- }
429
- return falsyToUndef(await this.loader.getBlock(cid));
430
- }
431
- async transaction(fn, opts = { noLoader: false }) {
432
- const { t, meta: done } = await super.transaction(fn);
433
- const cars = await this.loader.commit(t, done, opts);
434
- if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
435
- setTimeout(() => void this.compact(), 10);
436
- }
437
- if (cars) {
438
- this.transactions.delete(t);
439
- return { meta: done, cars, t };
440
- }
441
- throw this.logger.Error().Msg("failed to commit car files").AsError();
442
- }
443
- async getFile(car, cid) {
444
- await this.ready();
445
- if (!this.loader) throw this.logger.Error().Msg("loader required to get file, database must be named").AsError();
446
- const reader = await this.loader.loadFileCar(
447
- car
448
- /*, isPublic */
449
- );
450
- const block = await reader.get(cid);
451
- if (!block) throw this.logger.Error().Str("cid", cid.toString()).Msg(`Missing block`).AsError();
452
- return block.bytes;
453
- }
454
- async compact() {
455
- await this.ready();
456
- if (!this.loader) throw this.logger.Error().Msg("loader required to compact").AsError();
457
- if (this.loader.carLog.length < 2) return;
458
- const compactFn = this.ebOpts.compact || ((blocks) => this.defaultCompact(blocks, this.logger));
459
- if (!compactFn || this.compacting) return;
460
- const blockLog = new CompactionFetcher(this);
461
- this.compacting = true;
462
- const meta = await compactFn(blockLog);
463
- await this.loader?.commit(blockLog.loggedBlocks, meta, {
464
- compact: true,
465
- noLoader: true
466
- });
467
- this.compacting = false;
468
- }
469
- async defaultCompact(blocks, logger) {
470
- if (!this.loader) {
471
- throw logger.Error().Msg("no loader").AsError();
472
- }
473
- if (!this.lastTxMeta) {
474
- throw logger.Error().Msg("no lastTxMeta").AsError();
475
- }
476
- for await (const blk of this.loader.entries(false)) {
477
- blocks.loggedBlocks.putSync(blk.cid, blk.bytes);
478
- }
479
- for (const t of this.transactions) {
480
- for await (const blk of t.entries()) {
481
- blocks.loggedBlocks.putSync(blk.cid, blk.bytes);
482
- }
483
- }
484
- return this.lastTxMeta;
485
- }
486
- async *entries() {
487
- for await (const blk of this.loader.entries()) {
488
- yield blk;
489
- }
490
- }
491
- };
492
- var CompactionFetcher = class {
493
- constructor(blocks) {
494
- this.blockstore = blocks;
495
- this.loggedBlocks = new CarTransaction(blocks);
496
- }
497
- async get(cid) {
498
- const block = await this.blockstore.get(cid);
499
- if (block) this.loggedBlocks.putSync(cid, block.bytes);
500
- return falsyToUndef(block);
501
- }
502
- };
503
-
504
- // src/blockstore/commit-queue.ts
505
- import { Future } from "@adviser/cement";
506
- var CommitQueue = class {
507
- constructor() {
508
- this.queue = [];
509
- this.processing = false;
510
- this._waitIdleItems = /* @__PURE__ */ new Set();
511
- }
512
- waitIdle() {
513
- if (this.queue.length === 0 && !this.processing) {
514
- return Promise.resolve();
515
- }
516
- const fn = new Future();
517
- this._waitIdleItems.add(fn);
518
- return fn.asPromise();
519
- }
520
- async enqueue(fn) {
521
- return new Promise((resolve, reject) => {
522
- const queueFn = async () => {
523
- try {
524
- resolve(await fn());
525
- } catch (e) {
526
- reject(e);
527
- } finally {
528
- this.processing = false;
529
- this.processNext();
530
- }
531
- };
532
- this.queue.push(queueFn);
533
- if (!this.processing) {
534
- this.processNext();
535
- }
536
- });
537
- }
538
- processNext() {
539
- if (this.queue.length > 0 && !this.processing) {
540
- this.processing = true;
541
- const queueFn = this.queue.shift();
542
- if (queueFn) {
543
- queueFn().finally(() => {
544
- });
545
- }
546
- }
547
- if (this.queue.length === 0 && !this.processing) {
548
- const toResolve = Array.from(this._waitIdleItems);
549
- this._waitIdleItems.clear();
550
- toResolve.map((fn) => fn.resolve());
551
- }
552
- }
553
- };
554
-
555
- // src/runtime/key-bag.ts
556
- var key_bag_exports = {};
557
- __export(key_bag_exports, {
558
- KeyBag: () => KeyBag,
559
- getKeyBag: () => getKeyBag,
560
- registerKeyBagProviderFactory: () => registerKeyBagProviderFactory
561
- });
562
- import {
563
- KeyedResolvOnce,
564
- ResolveOnce,
565
- ResolveSeq,
566
- Result as Result2,
567
- runtimeFn,
568
- toCryptoRuntime as toCryptoRuntime2,
569
- URI
570
- } from "@adviser/cement";
571
- import { base58btc } from "multiformats/bases/base58";
572
- var KeyBag = class {
573
- constructor(rt) {
574
- this.rt = rt;
575
- this._warnOnce = new ResolveOnce();
576
- this._seq = new ResolveSeq();
577
- this.logger = ensureLogger(rt.sthis, "KeyBag");
578
- this.logger.Debug().Msg("KeyBag created");
579
- }
580
- async subtleKey(key) {
581
- const extractable = this.rt.url.getParam("extractKey") === "_deprecated_internal_api";
582
- if (extractable) {
583
- this._warnOnce.once(
584
- () => this.logger.Warn().Msg("extractKey is enabled via _deprecated_internal_api --- handle keys safely!!!")
585
- );
586
- }
587
- return await this.rt.crypto.importKey(
588
- "raw",
589
- // raw or jwk
590
- base58btc.decode(key),
591
- // hexStringToUint8Array(key), // raw data
592
- "AES-GCM",
593
- extractable,
594
- ["encrypt", "decrypt"]
595
- );
596
- }
597
- async ensureKeyFromUrl(url, keyFactory) {
598
- const storeKey = url.getParam("storekey");
599
- if (storeKey === "insecure") {
600
- return Result2.Ok(url);
601
- }
602
- if (!storeKey) {
603
- const keyName = `@${keyFactory()}@`;
604
- const ret = await this.getNamedKey(keyName);
605
- if (ret.isErr()) {
606
- return ret;
607
- }
608
- const urb = url.build().setParam("storekey", keyName);
609
- return Result2.Ok(urb.URI());
610
- }
611
- if (storeKey.startsWith("@") && storeKey.endsWith("@")) {
612
- const ret = await this.getNamedKey(storeKey);
613
- if (ret.isErr()) {
614
- return ret;
615
- }
616
- }
617
- return Result2.Ok(url);
618
- }
619
- async toKeyWithFingerPrint(keyStr) {
620
- const material = base58btc.decode(keyStr);
621
- const key = await this.subtleKey(keyStr);
622
- const fpr = await this.rt.crypto.digestSHA256(material);
623
- return Result2.Ok({
624
- key,
625
- fingerPrint: base58btc.encode(new Uint8Array(fpr))
626
- });
627
- }
628
- async setNamedKey(name, key) {
629
- return this._seq.add(() => this._setNamedKey(name, key));
630
- }
631
- // avoid deadlock
632
- async _setNamedKey(name, key) {
633
- const item = {
634
- name,
635
- key
636
- };
637
- const bag = await this.rt.getBag();
638
- this.logger.Debug().Str("name", name).Msg("setNamedKey");
639
- await bag.set(name, item);
640
- return await this.toKeyWithFingerPrint(item.key);
641
- }
642
- async getNamedExtractableKey(name, failIfNotFound = false) {
643
- const ret = await this.getNamedKey(name, failIfNotFound);
644
- if (ret.isErr()) {
645
- return ret;
646
- }
647
- const named = ret.Ok();
648
- return Result2.Ok({
649
- ...named,
650
- extract: async () => {
651
- const ext = new Uint8Array(await this.rt.crypto.exportKey("raw", named.key));
652
- return {
653
- key: ext,
654
- keyStr: base58btc.encode(ext)
655
- };
656
- }
657
- });
658
- }
659
- async getNamedKey(name, failIfNotFound = false) {
660
- const id = this.rt.sthis.nextId(4).str;
661
- return this._seq.add(async () => {
662
- const bag = await this.rt.getBag();
663
- const named = await bag.get(name);
664
- if (named) {
665
- const fpr = await this.toKeyWithFingerPrint(named.key);
666
- this.logger.Debug().Str("id", id).Str("name", name).Result("fpr", fpr).Msg("fingerPrint getNamedKey");
667
- return fpr;
668
- }
669
- if (failIfNotFound) {
670
- this.logger.Debug().Str("id", id).Str("name", name).Msg("failIfNotFound getNamedKey");
671
- return Result2.Err(new Error(`Key not found: ${name}`));
672
- }
673
- const ret = await this._setNamedKey(name, base58btc.encode(this.rt.crypto.randomBytes(this.rt.keyLength)));
674
- this.logger.Debug().Str("id", id).Str("name", name).Result("fpr", ret).Msg("createKey getNamedKey-post");
675
- return ret;
676
- });
677
- }
678
- };
679
- var keyBagProviderFactories = new Map(
680
- [
681
- {
682
- protocol: "file:",
683
- factory: async (url, sthis) => {
684
- const { KeyBagProviderFile } = await import("./key-bag-file-4SJQGORQ.js");
685
- return new KeyBagProviderFile(url, sthis);
686
- }
687
- },
688
- {
689
- protocol: "indexdb:",
690
- factory: async (url, sthis) => {
691
- const { KeyBagProviderIndexDB } = await import("./key-bag-indexdb-GSQOUUVQ.js");
692
- return new KeyBagProviderIndexDB(url, sthis);
693
- }
694
- }
695
- ].map((i) => [i.protocol, i])
696
- );
697
- function registerKeyBagProviderFactory(item) {
698
- const protocol = item.protocol.endsWith(":") ? item.protocol : item.protocol + ":";
699
- keyBagProviderFactories.set(protocol, {
700
- ...item,
701
- protocol
702
- });
703
- }
704
- function defaultKeyBagOpts(sthis, kbo) {
705
- if (kbo.keyRuntime) {
706
- return kbo.keyRuntime;
707
- }
708
- const logger = ensureLogger(sthis, "KeyBag");
709
- let url;
710
- if (kbo.url) {
711
- url = URI.from(kbo.url);
712
- logger.Debug().Url(url).Msg("from opts");
713
- } else {
714
- let bagFnameOrUrl = sthis.env.get("FP_KEYBAG_URL");
715
- if (runtimeFn().isBrowser) {
716
- url = URI.from(bagFnameOrUrl || "indexdb://fp-keybag");
717
- } else {
718
- if (!bagFnameOrUrl) {
719
- const home = sthis.env.get("HOME");
720
- bagFnameOrUrl = `${home}/.fireproof/keybag`;
721
- url = URI.from(`file://${bagFnameOrUrl}`);
722
- } else {
723
- url = URI.from(bagFnameOrUrl);
724
- }
725
- }
726
- logger.Debug().Url(url).Msg("from env");
727
- }
728
- const kitem = keyBagProviderFactories.get(url.protocol);
729
- if (!kitem) {
730
- throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
731
- }
732
- const getBag = async () => kitem.factory(url, sthis);
733
- if (url.hasParam("masterkey")) {
734
- throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
735
- }
736
- return {
737
- url,
738
- crypto: kbo.crypto || toCryptoRuntime2({}),
739
- sthis,
740
- logger,
741
- keyLength: kbo.keyLength || 16,
742
- getBag,
743
- id: () => {
744
- return url.toString();
745
- }
746
- };
747
- }
748
- var _keyBags = new KeyedResolvOnce();
749
- async function getKeyBag(sthis, kbo = {}) {
750
- await sthis.start();
751
- const rt = defaultKeyBagOpts(sthis, kbo);
752
- return _keyBags.get(rt.id()).once(async () => new KeyBag(rt));
753
- }
754
-
755
- // src/blockstore/commitor.ts
756
- import * as CBW from "@ipld/car/buffer-writer";
757
- import { sha256 as hasher2 } from "multiformats/hashes/sha2";
758
- import * as dagCodec2 from "@ipld/dag-cbor";
759
- async function encodeCarFile(roots, t, codec3) {
760
- let size = 0;
761
- const headerSize = CBW.headerLength({ roots });
762
- size += headerSize;
763
- for (const { cid, bytes } of t.entries()) {
764
- size += CBW.blockLength({ cid, bytes });
765
- }
766
- const buffer = new Uint8Array(size);
767
- const writer = CBW.createWriter(buffer, { headerSize });
768
- for (const r of roots) {
769
- writer.addRoot(r);
770
- }
771
- for (const { cid, bytes } of t.entries()) {
772
- writer.write({ cid, bytes });
773
- }
774
- writer.close();
775
- return await encode({ value: writer.bytes, hasher: hasher2, codec: codec3 });
776
- }
777
- async function createCarFile(encoder, cid, t) {
778
- return encodeCarFile([cid], t, encoder);
779
- }
780
- async function commitFiles(fileStore, walStore, t, done) {
781
- const { files: roots } = makeFileCarHeader(done);
782
- const cids = [];
783
- const codec3 = (await fileStore.keyedCrypto()).codec();
784
- const cars = await prepareCarFilesFiles(codec3, roots, t);
785
- for (const car of cars) {
786
- const { cid, bytes } = car;
787
- await fileStore.save({ cid, bytes });
788
- await walStore.enqueueFile(
789
- cid
790
- /*, !!opts.public*/
791
- );
792
- cids.push(cid);
793
- }
794
- return cids;
795
- }
796
- function makeFileCarHeader(result) {
797
- const files = [];
798
- for (const [, meta] of Object.entries(result.files || {})) {
799
- if (meta && typeof meta === "object" && "cid" in meta && meta !== null) {
800
- files.push(meta.cid);
801
- }
802
- }
803
- return { ...result, files };
804
- }
805
- async function prepareCarFilesFiles(encoder, roots, t) {
806
- return [await encodeCarFile(roots, t, encoder)];
807
- }
808
- function makeCarHeader(meta, cars, compact = false) {
809
- const coreHeader = compact ? { cars: [], compact: cars } : { cars, compact: [] };
810
- return { ...coreHeader, meta };
811
- }
812
- async function encodeCarHeader(fp) {
813
- return await encode({
814
- value: { fp },
815
- hasher: hasher2,
816
- codec: dagCodec2
817
- });
818
- }
819
- async function commit(params, t, done, opts = { noLoader: false, compact: false }) {
820
- const fp = makeCarHeader(done, params.carLog, !!opts.compact);
821
- const rootBlock = await encodeCarHeader(fp);
822
- const cars = await prepareCarFiles(params.encoder, params.threshold, rootBlock, t);
823
- const cids = [];
824
- for (const car of cars) {
825
- const { cid, bytes } = car;
826
- await params.carStore.save({ cid, bytes });
827
- cids.push(cid);
828
- }
829
- const newDbMeta = { cars: cids };
830
- await params.WALStore.enqueue(newDbMeta, opts);
831
- await params.metaStore.save(newDbMeta);
832
- return { cgrp: cids, header: fp };
833
- }
834
- async function prepareCarFiles(encoder, threshold, rootBlock, t) {
835
- const carFiles = [];
836
- threshold = threshold || 128e3 * 8;
837
- let clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
838
- clonedt.putSync(rootBlock.cid, rootBlock.bytes);
839
- let newsize = CBW.blockLength(toCIDBlock(rootBlock));
840
- let cidRootBlock = rootBlock;
841
- for (const { cid, bytes } of t.entries()) {
842
- newsize += CBW.blockLength(toCIDBlock({ cid, bytes }));
843
- if (newsize >= threshold) {
844
- carFiles.push(await createCarFile(encoder, cidRootBlock.cid, clonedt));
845
- clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
846
- clonedt.putSync(cid, bytes);
847
- cidRootBlock = { cid, bytes };
848
- newsize = CBW.blockLength(toCIDBlock({ cid, bytes }));
849
- } else {
850
- clonedt.putSync(cid, bytes);
851
- }
852
- }
853
- carFiles.push(await createCarFile(encoder, cidRootBlock.cid, clonedt));
854
- return carFiles;
855
- }
856
-
857
- // src/blockstore/loader.ts
858
- import { sha256 as hasher3 } from "multiformats/hashes/sha2";
859
-
860
- // src/blockstore/task-manager.ts
861
- var TaskManager = class {
862
- constructor(sthis, callback) {
863
- this.eventsWeHandled = /* @__PURE__ */ new Set();
864
- this.queue = [];
865
- this.isProcessing = false;
866
- this.logger = ensureLogger(sthis, "TaskManager");
867
- this.callback = callback;
868
- }
869
- async handleEvent(cid, parents, dbMeta) {
870
- for (const parent of parents) {
871
- this.eventsWeHandled.add(parent.toString());
872
- }
873
- this.queue.push({ cid: cid.toString(), dbMeta, retries: 0 });
874
- this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
875
- void this.processQueue();
876
- }
877
- async processQueue() {
878
- if (this.isProcessing) return;
879
- this.isProcessing = true;
880
- const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
881
- const first = filteredQueue[0];
882
- if (!first) {
883
- return;
884
- }
885
- try {
886
- await this.callback(first.dbMeta);
887
- this.eventsWeHandled.add(first.cid);
888
- this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
889
- } catch (err) {
890
- if (first.retries++ > 3) {
891
- this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
892
- this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
893
- }
894
- await new Promise((resolve) => setTimeout(resolve, 50));
895
- throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
896
- } finally {
897
- this.isProcessing = false;
898
- if (this.queue.length > 0) {
899
- void this.processQueue();
900
- }
901
- }
902
- }
903
- };
904
-
905
- // src/blockstore/loader.ts
906
- function carLogIncludesGroup(list, cids) {
907
- return list.some((arr) => {
908
- return arr.toString() === cids.toString();
909
- });
910
- }
911
- function uniqueCids(list, remove = /* @__PURE__ */ new Set()) {
912
- const byString = /* @__PURE__ */ new Map();
913
- for (const cid of list) {
914
- if (remove.has(cid.toString())) continue;
915
- byString.set(cid.toString(), cid);
916
- }
917
- return [...byString.values()];
918
- }
919
- var Loader = class {
920
- constructor(name, ebOpts, sthis) {
921
- this.commitQueue = new CommitQueue();
922
- this.isCompacting = false;
923
- this.carReaders = /* @__PURE__ */ new Map();
924
- this.seenCompacted = /* @__PURE__ */ new Set();
925
- this.processedCars = /* @__PURE__ */ new Set();
926
- this.carLog = [];
927
- this.getBlockCache = /* @__PURE__ */ new Map();
928
- this.seenMeta = /* @__PURE__ */ new Set();
929
- this.writeLimit = pLimit(1);
930
- this.onceReady = new ResolveOnce2();
931
- this.name = name;
932
- this.sthis = sthis;
933
- this.ebOpts = defaultedBlockstoreRuntime(
934
- sthis,
935
- {
936
- ...ebOpts,
937
- name
938
- },
939
- "Loader"
940
- );
941
- this.logger = this.ebOpts.logger;
942
- this.taskManager = new TaskManager(sthis, async (dbMeta) => {
943
- await this.handleDbMetasFromStore([dbMeta]);
944
- });
945
- }
946
- // readonly id = uuidv4();
947
- async keyBag() {
948
- return getKeyBag(this.sthis, this.ebOpts.keyBag);
949
- }
950
- async carStore() {
951
- return this.ebOpts.storeRuntime.makeDataStore(this);
952
- }
953
- async fileStore() {
954
- return this.ebOpts.storeRuntime.makeDataStore(this);
955
- }
956
- async WALStore() {
957
- return this.ebOpts.storeRuntime.makeWALStore(this);
958
- }
959
- async metaStore() {
960
- return this.ebOpts.storeRuntime.makeMetaStore(this);
961
- }
962
- async ready() {
963
- return this.onceReady.once(async () => {
964
- const metas = await (await this.metaStore()).load();
965
- if (this.ebOpts.meta) {
966
- await this.handleDbMetasFromStore([this.ebOpts.meta]);
967
- } else if (metas) {
968
- await this.handleDbMetasFromStore(metas);
969
- }
970
- });
971
- }
972
- async close() {
973
- const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
974
- await Promise.all(toClose.map((store) => store.close()));
975
- }
976
- async destroy() {
977
- const toDestroy = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
978
- await Promise.all(toDestroy.map((store) => store.destroy()));
979
- }
980
- // async snapToCar(carCid: AnyLink | string) {
981
- // await this.ready
982
- // if (typeof carCid === 'string') {
983
- // carCid = CID.parse(carCid)
984
- // }
985
- // const carHeader = await this.loadCarHeaderFromMeta({ car: carCid, key: this.key || null })
986
- // this.carLog = [carCid, ...carHeader.cars]
987
- // await this.getMoreReaders(carHeader.cars)
988
- // await this._applyCarHeader(carHeader, true)
989
- // }
990
- async handleDbMetasFromStore(metas) {
991
- this.logger.Debug().Any("metas", metas).Msg("handleDbMetasFromStore");
992
- for (const meta of metas) {
993
- await this.writeLimit(async () => {
994
- await this.mergeDbMetaIntoClock(meta);
995
- });
996
- }
997
- }
998
- async mergeDbMetaIntoClock(meta) {
999
- if (this.isCompacting) {
1000
- throw this.logger.Error().Msg("cannot merge while compacting").AsError();
1001
- }
1002
- if (this.seenMeta.has(meta.cars.toString())) return;
1003
- this.seenMeta.add(meta.cars.toString());
1004
- if (carLogIncludesGroup(this.carLog, meta.cars)) {
1005
- return;
1006
- }
1007
- const carHeader = await this.loadCarHeaderFromMeta(meta);
1008
- carHeader.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
1009
- await this.getMoreReaders(carHeader.cars.flat());
1010
- this.carLog = [...uniqueCids([meta.cars, ...this.carLog, ...carHeader.cars], this.seenCompacted)];
1011
- await this.ebOpts.applyMeta?.(carHeader.meta);
1012
- }
1013
- // protected async ingestKeyFromMeta(meta: DbMeta): Promise<void> {
1014
- // const { key } = meta;
1015
- // if (key) {
1016
- // await this.setKey(key);
1017
- // }
1018
- // }
1019
- async loadCarHeaderFromMeta({ cars: cids }) {
1020
- const reader = await this.loadCar(cids[0]);
1021
- return await parseCarFile(reader, this.logger);
1022
- }
1023
- // async _getKey(): Promise<string | undefined> {
1024
- // if (this.key) return this.key;
1025
- // // generate a random key
1026
- // if (!this.ebOpts.public) {
1027
- // await this.setKey(toHexString(this.ebOpts.crypto.randomBytes(32)));
1028
- // }
1029
- // return this.key || undefined;
1030
- // }
1031
- async commitFiles(t, done) {
1032
- await this.ready();
1033
- const fstore = await this.fileStore();
1034
- const wstore = await this.WALStore();
1035
- return this.commitQueue.enqueue(() => commitFiles(fstore, wstore, t, done));
1036
- }
1037
- async loadFileCar(cid) {
1038
- return await this.storesLoadCar(cid, await this.fileStore(), this.remoteFileStore);
1039
- }
1040
- async commit(t, done, opts = { noLoader: false, compact: false }) {
1041
- await this.ready();
1042
- const fstore = await this.fileStore();
1043
- const params = {
1044
- encoder: (await fstore.keyedCrypto()).codec(),
1045
- carLog: this.carLog,
1046
- carStore: fstore,
1047
- WALStore: await this.WALStore(),
1048
- metaStore: await this.metaStore(),
1049
- threshold: this.ebOpts.threshold
1050
- };
1051
- return this.commitQueue.enqueue(async () => {
1052
- await this.cacheTransaction(t);
1053
- const ret = await commit(params, t, done, opts);
1054
- await this.updateCarLog(ret.cgrp, ret.header, !!opts.compact);
1055
- return ret.cgrp;
1056
- });
1057
- }
1058
- async updateCarLog(cids, fp, compact) {
1059
- if (compact) {
1060
- const previousCompactCid = fp.compact[fp.compact.length - 1];
1061
- fp.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
1062
- this.carLog = [...uniqueCids([...this.carLog, ...fp.cars, cids], this.seenCompacted)];
1063
- await this.removeCidsForCompact(previousCompactCid[0]).catch((e) => e);
1064
- } else {
1065
- this.carLog.unshift(cids);
1066
- }
1067
- }
1068
- async cacheTransaction(t) {
1069
- for await (const block of t.entries()) {
1070
- const sBlock = block.cid.toString();
1071
- if (!this.getBlockCache.has(sBlock)) {
1072
- this.getBlockCache.set(sBlock, block);
1073
- }
1074
- }
1075
- }
1076
- async cacheCarReader(carCidStr, reader) {
1077
- if (this.processedCars.has(carCidStr)) return;
1078
- this.processedCars.add(carCidStr);
1079
- for await (const block of reader.blocks()) {
1080
- const sBlock = block.cid.toString();
1081
- if (!this.getBlockCache.has(sBlock)) {
1082
- this.getBlockCache.set(sBlock, block);
1083
- }
1084
- }
1085
- }
1086
- async removeCidsForCompact(cid) {
1087
- const carHeader = await this.loadCarHeaderFromMeta({
1088
- cars: [cid]
1089
- });
1090
- for (const cids of carHeader.compact) {
1091
- for (const cid2 of cids) {
1092
- await (await this.carStore()).remove(cid2);
1093
- }
1094
- }
1095
- }
1096
- // async flushCars() {
1097
- // await this.ready
1098
- // // for each cid in car log, make a dbMeta
1099
- // for (const cid of this.carLog) {
1100
- // const dbMeta = { car: cid, key: this.key || null } as DbMeta
1101
- // await this.remoteWAL!.enqueue(dbMeta, { public: false })
1102
- // }
1103
- // }
1104
- async *entries(cache2 = true) {
1105
- await this.ready();
1106
- if (cache2) {
1107
- for (const [, block] of this.getBlockCache) {
1108
- yield block;
1109
- }
1110
- } else {
1111
- for (const [, block] of this.getBlockCache) {
1112
- yield block;
1113
- }
1114
- for (const cids of this.carLog) {
1115
- for (const cid of cids) {
1116
- const reader = await this.loadCar(cid);
1117
- if (!reader) throw this.logger.Error().Ref("cid", cid).Msg("missing car reader").AsError();
1118
- for await (const block of reader.blocks()) {
1119
- const sCid = block.cid.toString();
1120
- if (!this.getBlockCache.has(sCid)) {
1121
- yield block;
1122
- }
1123
- }
1124
- }
1125
- }
1126
- }
1127
- }
1128
- async getBlock(cid) {
1129
- await this.ready();
1130
- const sCid = cid.toString();
1131
- if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
1132
- const getCarCid = async (carCid) => {
1133
- if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
1134
- const reader = await this.loadCar(carCid);
1135
- if (!reader) {
1136
- throw this.logger.Error().Ref("cid", carCid).Msg("missing car reader").AsError();
1137
- }
1138
- await this.cacheCarReader(carCid.toString(), reader).catch(() => {
1139
- return;
1140
- });
1141
- if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
1142
- throw this.logger.Error().Str("cid", sCid).Msg("block not in reader").AsError();
1143
- };
1144
- const getCompactCarCids = async (carCid) => {
1145
- const reader = await this.loadCar(carCid);
1146
- if (!reader) {
1147
- throw this.logger.Error().Str("cid", carCid.toString()).Msg("missing car reader").AsError();
1148
- }
1149
- const header = await parseCarFile(reader, this.logger);
1150
- const compacts = header.compact;
1151
- let got2;
1152
- const batchSize2 = 5;
1153
- for (let i = 0; i < compacts.length; i += batchSize2) {
1154
- const promises = [];
1155
- for (let j = i; j < Math.min(i + batchSize2, compacts.length); j++) {
1156
- for (const cid2 of compacts[j]) {
1157
- promises.push(getCarCid(cid2));
1158
- }
1159
- }
1160
- try {
1161
- got2 = await Promise.any(promises);
1162
- } catch {
1163
- }
1164
- if (got2) break;
1165
- }
1166
- if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
1167
- throw this.logger.Error().Str("cid", sCid).Msg("block not in compact reader").AsError();
1168
- };
1169
- let got;
1170
- const batchSize = 5;
1171
- for (let i = 0; i < this.carLog.length; i += batchSize) {
1172
- const batch = this.carLog.slice(i, i + batchSize);
1173
- const promises = batch.flatMap((slice) => slice.map(getCarCid));
1174
- try {
1175
- got = await Promise.any(promises);
1176
- } catch {
1177
- }
1178
- if (got) break;
1179
- }
1180
- if (!got) {
1181
- try {
1182
- got = await getCompactCarCids(this.carLog[this.carLog.length - 1][0]);
1183
- } catch {
1184
- }
1185
- }
1186
- return got;
1187
- }
1188
- async loadCar(cid) {
1189
- if (!this.carStore) {
1190
- throw this.logger.Error().Msg("car store not initialized").AsError();
1191
- }
1192
- const loaded = await this.storesLoadCar(cid, await this.carStore(), this.remoteCarStore);
1193
- return loaded;
1194
- }
1195
- async makeDecoderAndCarReader(cid, local, remote) {
1196
- const cidsString = cid.toString();
1197
- let loadedCar = void 0;
1198
- let activeStore = local;
1199
- try {
1200
- this.logger.Debug().Str("cid", cidsString).Msg("loading car");
1201
- loadedCar = await local.load(cid);
1202
- this.logger.Debug().Bool("loadedCar", loadedCar).Msg("loaded");
1203
- } catch (e) {
1204
- if (remote) {
1205
- const remoteCar = await remote.load(cid);
1206
- if (remoteCar) {
1207
- this.logger.Debug().Ref("cid", remoteCar.cid).Msg("saving remote car locally");
1208
- await local.save(remoteCar);
1209
- loadedCar = remoteCar;
1210
- activeStore = remote;
1211
- }
1212
- } else {
1213
- this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
1214
- }
1215
- }
1216
- if (!loadedCar) {
1217
- throw this.logger.Error().Url(local.url()).Str("cid", cidsString).Msg("missing car files").AsError();
1218
- }
1219
- const bytes = await decode({ bytes: loadedCar.bytes, hasher: hasher3, codec: (await activeStore.keyedCrypto()).codec() });
1220
- const rawReader = await CarReader.fromBytes(bytes.value);
1221
- const readerP = Promise.resolve(rawReader);
1222
- const cachedReaderP = readerP.then(async (reader) => {
1223
- await this.cacheCarReader(cidsString, reader).catch((e) => {
1224
- this.logger.Error().Err(e).Str("cid", cidsString).Msg("error caching car reader");
1225
- return;
1226
- });
1227
- return reader;
1228
- });
1229
- this.carReaders.set(cidsString, cachedReaderP);
1230
- return readerP;
1231
- }
1232
- //What if instead it returns an Array of CarHeader
1233
- async storesLoadCar(cid, local, remote) {
1234
- const cidsString = cid.toString();
1235
- let dacr = this.carReaders.get(cidsString);
1236
- if (!dacr) {
1237
- dacr = this.makeDecoderAndCarReader(cid, local, remote);
1238
- this.carReaders.set(cidsString, dacr);
1239
- }
1240
- return dacr;
1241
- }
1242
- async getMoreReaders(cids) {
1243
- const limit = pLimit(5);
1244
- const missing = cids.filter((cid) => !this.carReaders.has(cid.toString()));
1245
- await Promise.all(missing.map((cid) => limit(() => this.loadCar(cid))));
1246
- }
1247
- };
1248
-
1249
- // src/runtime/keyed-crypto.ts
1250
- var keyed_crypto_exports = {};
1251
- __export(keyed_crypto_exports, {
1252
- BlockIvKeyIdCodec: () => BlockIvKeyIdCodec,
1253
- keyedCryptoFactory: () => keyedCryptoFactory
1254
- });
1255
- import { base58btc as base58btc2 } from "multiformats/bases/base58";
1256
- import { sha256 as hasher4 } from "multiformats/hashes/sha2";
1257
- import * as CBOR from "cborg";
1258
- var generateIV = {
1259
- random: {
1260
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1261
- calc: async (ko, crypto, data) => {
1262
- return crypto.randomBytes(ko.ivLength);
1263
- },
1264
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1265
- verify: async (ko, crypto, iv, data) => {
1266
- return true;
1267
- }
1268
- },
1269
- hash: {
1270
- calc: async (ko, crypto, data) => {
1271
- const hash = await hasher4.digest(data);
1272
- const hashBytes = new Uint8Array(hash.bytes);
1273
- const hashArray = new Uint8Array(ko.ivLength);
1274
- for (let i = 0; i < hashBytes.length; i++) {
1275
- hashArray[i % ko.ivLength] ^= hashBytes[i];
1276
- }
1277
- return hashArray;
1278
- },
1279
- verify: async function(ko, crypto, iv, data) {
1280
- return ko.url.getParam("ivverify") !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
1281
- }
1282
- }
1283
- };
1284
- function getGenerateIVFn(url, opts) {
1285
- const ivhash = opts.ivCalc || url.getParam("ivhash") || "hash";
1286
- return generateIV[ivhash] || generateIV["hash"];
1287
- }
1288
- var BlockIvKeyIdCodec = class {
1289
- constructor(ko, iv, opts) {
1290
- this.code = 3147065;
1291
- this.name = "Fireproof@encrypted-block:aes-gcm";
1292
- this.ko = ko;
1293
- this.iv = iv;
1294
- this.opts = opts || {};
1295
- }
1296
- async encode(data) {
1297
- const calcIv = this.iv || await getGenerateIVFn(this.ko.url, this.opts).calc(this.ko, this.ko.crypto, data);
1298
- const { iv } = this.ko.algo(calcIv);
1299
- const fprt = await this.ko.fingerPrint();
1300
- const keyId = base58btc2.decode(fprt);
1301
- this.ko.logger.Debug().Str("fp", fprt).Msg("encode");
1302
- return CBOR.encode({
1303
- iv,
1304
- keyId,
1305
- data: await this.ko._encrypt({ iv, bytes: data })
1306
- });
1307
- }
1308
- async decode(abytes) {
1309
- let bytes;
1310
- if (abytes instanceof Uint8Array) {
1311
- bytes = abytes;
1312
- } else {
1313
- bytes = new Uint8Array(abytes);
1314
- }
1315
- const { iv, keyId, data } = CBOR.decode(bytes);
1316
- const fprt = await this.ko.fingerPrint();
1317
- this.ko.logger.Debug().Str("fp", base58btc2.encode(keyId)).Msg("decode");
1318
- if (base58btc2.encode(keyId) !== fprt) {
1319
- throw this.ko.logger.Error().Str("fp", fprt).Str("keyId", base58btc2.encode(keyId)).Msg("keyId mismatch").AsError();
1320
- }
1321
- const result = await this.ko._decrypt({ iv, bytes: data });
1322
- if (!this.opts?.noIVVerify && !await getGenerateIVFn(this.ko.url, this.opts).verify(this.ko, this.ko.crypto, iv, result)) {
1323
- throw this.ko.logger.Error().Msg("iv missmatch").AsError();
1324
- }
1325
- return result;
1326
- }
1327
- };
1328
- var keyedCrypto = class {
1329
- constructor(url, key, cyopt, sthis) {
1330
- this.ivLength = 12;
1331
- this.isEncrypting = true;
1332
- this.logger = ensureLogger(sthis, "keyedCrypto");
1333
- this.crypto = cyopt;
1334
- this.key = key;
1335
- this.url = url;
1336
- }
1337
- fingerPrint() {
1338
- return Promise.resolve(this.key.fingerPrint);
1339
- }
1340
- codec(iv, opts) {
1341
- return new BlockIvKeyIdCodec(this, iv, opts);
1342
- }
1343
- algo(iv) {
1344
- return {
1345
- name: "AES-GCM",
1346
- iv: iv || this.crypto.randomBytes(this.ivLength),
1347
- tagLength: 128
1348
- };
1349
- }
1350
- async _decrypt(data) {
1351
- this.logger.Debug().Len(data.bytes, "bytes").Len(data.iv, "iv").Str("fp", this.key.fingerPrint).Msg("decrypting");
1352
- return new Uint8Array(await this.crypto.decrypt(this.algo(data.iv), this.key.key, data.bytes));
1353
- }
1354
- async _encrypt(data) {
1355
- this.logger.Debug().Len(data.bytes).Str("fp", this.key.fingerPrint).Msg("encrypting");
1356
- const a = this.algo(data.iv);
1357
- return new Uint8Array(await this.crypto.encrypt(a, this.key.key, data.bytes));
1358
- }
1359
- };
1360
- var nullCodec = class {
1361
- constructor() {
1362
- this.code = 0;
1363
- this.name = "Fireproof@unencrypted-block";
1364
- }
1365
- encode(data) {
1366
- return data;
1367
- }
1368
- decode(data) {
1369
- return data;
1370
- }
1371
- };
1372
- var noCrypto = class {
1373
- constructor(url, cyrt, sthis) {
1374
- this.ivLength = 0;
1375
- this.code = 0;
1376
- this.name = "Fireproof@unencrypted-block";
1377
- this.isEncrypting = false;
1378
- this._fingerPrint = "noCrypto:" + Math.random();
1379
- this.logger = ensureLogger(sthis, "noCrypto");
1380
- this.crypto = cyrt;
1381
- this.url = url;
1382
- }
1383
- fingerPrint() {
1384
- return Promise.resolve(this._fingerPrint);
1385
- }
1386
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1387
- codec(iv) {
1388
- return new nullCodec();
1389
- }
1390
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1391
- algo(iv) {
1392
- return {
1393
- name: "noCrypto",
1394
- iv: new Uint8Array(),
1395
- tagLength: 0
1396
- };
1397
- }
1398
- _decrypt() {
1399
- throw this.logger.Error().Msg("noCrypto.decrypt not implemented").AsError();
1400
- }
1401
- _encrypt() {
1402
- throw this.logger.Error().Msg("noCrypto.decrypt not implemented").AsError();
1403
- }
1404
- };
1405
- async function keyedCryptoFactory(url, kb, sthis) {
1406
- const storekey = url.getParam("storekey");
1407
- if (storekey && storekey !== "insecure") {
1408
- let rkey = await kb.getNamedKey(storekey, true);
1409
- if (rkey.isErr()) {
1410
- try {
1411
- rkey = await kb.toKeyWithFingerPrint(storekey);
1412
- } catch (e) {
1413
- throw sthis.logger.Error().Err(e).Str("keybag", kb.rt.id()).Str("name", storekey).Msg("getNamedKey failed").AsError();
1414
- }
1415
- }
1416
- return new keyedCrypto(url, rkey.Ok(), kb.rt.crypto, sthis);
1417
- }
1418
- return new noCrypto(url, kb.rt.crypto, sthis);
1419
- }
1420
-
1421
- // src/blockstore/fragment-gateway.ts
1422
- import { Result as Result3 } from "@adviser/cement";
1423
- import { base58btc as base58btc3 } from "multiformats/bases/base58";
1424
- import { encode as encode3, decode as decode3 } from "cborg";
1425
- function getFragSize(url) {
1426
- const fragSize = url.getParam("fragSize");
1427
- let ret = 0;
1428
- if (fragSize) {
1429
- ret = parseInt(fragSize);
1430
- }
1431
- if (isNaN(ret) || ret <= 0) {
1432
- ret = 0;
1433
- }
1434
- return ret;
1435
- }
1436
- async function getFrags(url, innerGW, headerSize, logger) {
1437
- const fragSize = getFragSize(url);
1438
- if (!fragSize) {
1439
- const res = await innerGW.get(url);
1440
- if (res.isErr()) {
1441
- return [res];
1442
- }
1443
- const data = res.unwrap();
1444
- return [
1445
- Result3.Ok({
1446
- fid: new Uint8Array(0),
1447
- ofs: 0,
1448
- len: data.length,
1449
- data
1450
- })
1451
- ];
1452
- }
1453
- const firstRaw = await innerGW.get(url.build().setParam("ofs", "0").URI());
1454
- if (firstRaw.isErr()) {
1455
- return [firstRaw];
1456
- }
1457
- const firstFragment = decode3(firstRaw.unwrap());
1458
- const blockSize = firstFragment.data.length;
1459
- const ops = [Promise.resolve(Result3.Ok(firstFragment))];
1460
- const fidStr = base58btc3.encode(firstFragment.fid);
1461
- const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
1462
- for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
1463
- ops.push(
1464
- (async (furl, ofs2) => {
1465
- const raw2 = await innerGW.get(furl);
1466
- if (raw2.isErr()) {
1467
- return raw2;
1468
- }
1469
- const fragment = decode3(raw2.unwrap());
1470
- if (base58btc3.encode(fragment.fid) !== fidStr) {
1471
- return Result3.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
1472
- }
1473
- if (fragment.ofs !== ofs2) {
1474
- return Result3.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
1475
- }
1476
- return Result3.Ok(fragment);
1477
- })(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
1478
- );
1479
- }
1480
- return Promise.all(ops);
1481
- }
1482
- var FragmentGateway = class {
1483
- constructor(sthis, innerGW) {
1484
- this.fidLength = 4;
1485
- this.headerSize = 32;
1486
- this.sthis = ensureSuperLog(sthis, "FragmentGateway");
1487
- this.logger = this.sthis.logger;
1488
- this.innerGW = innerGW;
1489
- }
1490
- slicer(url, body) {
1491
- const fragSize = getFragSize(url);
1492
- if (!fragSize) {
1493
- return [this.innerGW.put(url, body)];
1494
- }
1495
- const blocksize = fragSize - this.headerSize;
1496
- if (blocksize <= 0) {
1497
- throw this.logger.Error().Uint64("fragSize", fragSize).Uint64("headerSize", this.headerSize).Msg("Fragment size is too small").AsError();
1498
- }
1499
- const ops = [];
1500
- const fid = this.sthis.nextId(this.fidLength);
1501
- const fragUrl = url.build().setParam("fid", fid.str).setParam("len", body.length.toString()).setParam("headerSize", this.headerSize.toString());
1502
- for (let ofs = 0; ofs < body.length; ofs += blocksize) {
1503
- const block = encode3({
1504
- fid: fid.bin,
1505
- ofs,
1506
- len: body.length,
1507
- data: body.slice(ofs, ofs + blocksize)
1508
- });
1509
- if (block.length > fragSize) {
1510
- throw this.logger.Error().Uint64("block", block.length).Uint64("fragSize", fragSize).Msg("Block size to big").AsError();
1511
- }
1512
- ops.push(this.innerGW.put(fragUrl.setParam("ofs", ofs.toString()).URI(), block));
1513
- }
1514
- return ops;
1515
- }
1516
- buildUrl(baseUrl, key) {
1517
- return this.innerGW.buildUrl(baseUrl, key);
1518
- }
1519
- async destroy(iurl) {
1520
- return this.innerGW.destroy(iurl);
1521
- }
1522
- async start(url) {
1523
- this.headerSize = encode3({
1524
- fid: this.sthis.nextId(this.fidLength).bin,
1525
- ofs: 1024 * 1024,
1526
- // 32bit
1527
- len: 16 * 1024 * 1024,
1528
- // 32bit
1529
- data: new Uint8Array(1024)
1530
- }).length - 1024;
1531
- return this.innerGW.start(url);
1532
- }
1533
- async close(url) {
1534
- return this.innerGW.close(url);
1535
- }
1536
- async put(url, body) {
1537
- await Promise.all(this.slicer(url, body));
1538
- return Result3.Ok(void 0);
1539
- }
1540
- async get(url) {
1541
- const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
1542
- let buffer = void 0;
1543
- for (const rfrag of rfrags) {
1544
- if (rfrag.isErr()) {
1545
- return Result3.Err(rfrag.Err());
1546
- }
1547
- const frag = rfrag.Ok();
1548
- buffer = buffer || new Uint8Array(frag.len);
1549
- buffer.set(frag.data, frag.ofs);
1550
- }
1551
- return Result3.Ok(buffer || new Uint8Array(0));
1552
- }
1553
- async subscribe(url, callback) {
1554
- if (this.innerGW.subscribe) {
1555
- return this.innerGW.subscribe(url, callback);
1556
- } else {
1557
- return Result3.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
1558
- }
1559
- }
1560
- async delete(url) {
1561
- const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
1562
- for (const rfrag of rfrags) {
1563
- if (rfrag.isErr()) {
1564
- return Result3.Err(rfrag.Err());
1565
- }
1566
- const frag = rfrag.Ok();
1567
- const fidStr = base58btc3.encode(frag.fid);
1568
- const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
1569
- await this.innerGW.delete(fragUrl);
1570
- }
1571
- return Result3.Ok(void 0);
1572
- }
1573
- };
1574
-
1575
- // src/blockstore/meta-key-helper.ts
1576
- import { format, parse } from "@ipld/dag-json";
1577
- import { EventBlock, decodeEventBlock } from "@web3-storage/pail/clock";
1578
- import { CID as CID2 } from "multiformats";
1579
- import { base64pad } from "multiformats/bases/base64";
1580
- import { Result as Result4 } from "@adviser/cement";
1581
- async function decodeGatewayMetaBytesToDbMeta(sthis, byteHeads) {
1582
- const crdtEntries = JSON.parse(sthis.txt.decode(byteHeads));
1583
- if (!crdtEntries.length) {
1584
- sthis.logger.Debug().Any("byteHeads", byteHeads).Msg("No CRDT entries found");
1585
- return [];
1586
- }
1587
- if (!crdtEntries.map) {
1588
- sthis.logger.Debug().Str("crdtEntries", JSON.stringify(crdtEntries)).Msg("No data in CRDT entries");
1589
- return [];
1590
- }
1591
- return Promise.all(
1592
- crdtEntries.map(async (crdtEntry) => {
1593
- const eventBlock = await decodeEventBlock(base64pad.decode(crdtEntry.data));
1594
- const dbMeta = parse(sthis.txt.decode(eventBlock.value.data.dbMeta));
1595
- return {
1596
- eventCid: eventBlock.cid,
1597
- parents: crdtEntry.parents,
1598
- dbMeta
1599
- };
1600
- })
1601
- );
1602
- }
1603
- async function setCryptoKeyFromGatewayMetaPayload(uri, sthis, data) {
1604
- try {
1605
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Setting crypto key from gateway meta payload");
1606
- const keyInfo = await decodeGatewayMetaBytesToDbMeta(sthis, data);
1607
- if (keyInfo.length) {
1608
- const dbMeta = keyInfo[0].dbMeta;
1609
- if (dbMeta.key) {
1610
- const kb = await getKeyBag(sthis);
1611
- const keyName = getStoreKeyName(uri);
1612
- const res = await kb.setNamedKey(keyName, dbMeta.key);
1613
- if (res.isErr()) {
1614
- sthis.logger.Debug().Str("keyName", keyName).Str("dbMeta.key", dbMeta.key).Msg("Failed to set named key");
1615
- throw res.Err();
1616
- }
1617
- }
1618
- sthis.logger.Debug().Str("dbMeta.key", dbMeta.key).Str("uri", uri.toString()).Msg("Set crypto key from gateway meta payload");
1619
- return Result4.Ok(dbMeta);
1620
- }
1621
- sthis.logger.Debug().Any("data", data).Msg("No crypto in gateway meta payload");
1622
- return Result4.Ok(void 0);
1623
- } catch (error) {
1624
- sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
1625
- return Result4.Err(error);
1626
- }
1627
- }
1628
- async function addCryptoKeyToGatewayMetaPayload(uri, sthis, body) {
1629
- try {
1630
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Adding crypto key to gateway meta payload");
1631
- const keyName = getStoreKeyName(uri);
1632
- const kb = await getKeyBag(sthis);
1633
- const res = await kb.getNamedExtractableKey(keyName, true);
1634
- if (res.isErr()) {
1635
- sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
1636
- throw res.Err();
1637
- }
1638
- const keyData = await res.Ok().extract();
1639
- const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
1640
- const { dbMeta, parents } = dbMetas[0];
1641
- const parentLinks = parents.map((p) => CID2.parse(p));
1642
- dbMeta.key = keyData.keyStr;
1643
- const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
1644
- const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
1645
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
1646
- return Result4.Ok(encoded);
1647
- } catch (error) {
1648
- sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
1649
- return Result4.Err(error);
1650
- }
1651
- }
1652
- function getStoreKeyName(url) {
1653
- const storeKeyName = [url.getParam("localName") || url.getParam("name")];
1654
- const idx = url.getParam("index");
1655
- if (idx) {
1656
- storeKeyName.push(idx);
1657
- }
1658
- storeKeyName.push("data");
1659
- return `@${storeKeyName.join(":")}@`;
1660
- }
1661
- async function createDbMetaEventBlock(sthis, dbMeta, parents) {
1662
- const event = await EventBlock.create(
1663
- {
1664
- dbMeta: sthis.txt.encode(format(dbMeta))
1665
- },
1666
- parents
1667
- );
1668
- return event;
1669
- }
1670
- async function encodeEventsWithParents(sthis, events, parents) {
1671
- const crdtEntries = events.map((event) => {
1672
- const base64String = base64pad.encode(event.bytes);
1673
- return {
1674
- cid: event.cid.toString(),
1675
- data: base64String,
1676
- parents: parents.map((p) => p.toString())
1677
- };
1678
- });
1679
- return sthis.txt.encode(JSON.stringify(crdtEntries));
1680
- }
1681
-
1682
- // src/blockstore/store.ts
1683
- import pRetry from "p-retry";
1684
- import pMap from "p-map";
1685
- function guardVersion(url) {
1686
- if (!url.hasParam("version")) {
1687
- return Result5.Err(`missing version: ${url.toString()}`);
1688
- }
1689
- return Result5.Ok(url);
1690
- }
1691
- var BaseStoreImpl = class {
1692
- constructor(name, url, opts, sthis, logger) {
1693
- this._onStarted = [];
1694
- this._onClosed = [];
1695
- this.name = name;
1696
- this._url = url;
1697
- this.keybag = opts.keybag;
1698
- this.sthis = sthis;
1699
- this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
1700
- this.gateway = new FragmentGateway(this.sthis, opts.gateway);
1701
- this.loader = opts.loader;
1702
- }
1703
- url() {
1704
- return this._url;
1705
- }
1706
- onStarted(fn) {
1707
- this._onStarted.push(fn);
1708
- }
1709
- onClosed(fn) {
1710
- this._onClosed.push(fn);
1711
- }
1712
- async ready() {
1713
- return;
1714
- }
1715
- async keyedCrypto() {
1716
- return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
1717
- }
1718
- async start() {
1719
- this.logger.Debug().Str("storeType", this.storeType).Msg("starting-gateway-pre");
1720
- this._url = this._url.build().setParam("store", this.storeType).URI();
1721
- const res = await this.gateway.start(this._url);
1722
- if (res.isErr()) {
1723
- this.logger.Error().Result("gw-start", res).Msg("started-gateway");
1724
- return res;
1725
- }
1726
- this._url = res.Ok();
1727
- const kb = await this.keybag();
1728
- const skRes = await kb.ensureKeyFromUrl(this._url, () => {
1729
- const idx = this._url.getParam("index");
1730
- const storeKeyName = [this.name];
1731
- if (idx) {
1732
- storeKeyName.push(idx);
1733
- }
1734
- storeKeyName.push(this.storeType);
1735
- return storeKeyName.join(":");
1736
- });
1737
- if (skRes.isErr()) {
1738
- return skRes;
1739
- }
1740
- this._url = skRes.Ok();
1741
- const version = guardVersion(this._url);
1742
- if (version.isErr()) {
1743
- this.logger.Error().Result("version", version).Msg("guardVersion");
1744
- await this.close();
1745
- return version;
1746
- }
1747
- if (this.ready) {
1748
- const fn = this.ready.bind(this);
1749
- const ready = await exception2Result(fn);
1750
- if (ready.isErr()) {
1751
- await this.close();
1752
- return ready;
1753
- }
1754
- }
1755
- this._onStarted.forEach((fn) => fn());
1756
- this.logger.Debug().Msg("started");
1757
- return version;
1758
- }
1759
- };
1760
- var MetaStoreImpl = class extends BaseStoreImpl {
1761
- // remote: boolean;
1762
- constructor(sthis, name, url, opts) {
1763
- super(name, url, { ...opts }, sthis, ensureLogger(sthis, "MetaStoreImpl"));
1764
- this.storeType = "meta";
1765
- this.subscribers = /* @__PURE__ */ new Map();
1766
- this.parents = [];
1767
- if (
1768
- /*this.remote && */
1769
- opts.gateway.subscribe
1770
- ) {
1771
- this.onStarted(async () => {
1772
- this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
1773
- opts.gateway.subscribe?.(this.url(), async (message) => {
1774
- this.logger.Debug().Msg("Received message from gateway");
1775
- const dbMetas = await decodeGatewayMetaBytesToDbMeta(this.sthis, message);
1776
- await Promise.all(
1777
- dbMetas.map((dbMeta) => this.loader?.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
1778
- );
1779
- this.updateParentsFromDbMetas(dbMetas);
1780
- });
1781
- });
1782
- }
1783
- }
1784
- updateParentsFromDbMetas(dbMetas) {
1785
- const cids = dbMetas.map((m) => m.eventCid);
1786
- const dbMetaParents = dbMetas.flatMap((m) => m.parents);
1787
- const uniqueParentsMap = new Map([...this.parents, ...cids].map((p) => [p.toString(), p]));
1788
- const dbMetaParentsSet = new Set(dbMetaParents.map((p) => p.toString()));
1789
- this.parents = Array.from(uniqueParentsMap.values()).filter((p) => !dbMetaParentsSet.has(p.toString()));
1790
- }
1791
- async handleByteHeads(byteHeads) {
1792
- return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
1793
- }
1794
- async load() {
1795
- const branch = "main";
1796
- const url = await this.gateway.buildUrl(this.url(), branch);
1797
- if (url.isErr()) {
1798
- throw this.logger.Error().Result("buildUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
1799
- }
1800
- const bytes = await this.gateway.get(url.Ok());
1801
- if (bytes.isErr()) {
1802
- if (isNotFoundError(bytes)) {
1803
- return void 0;
1804
- }
1805
- throw this.logger.Error().Url(url.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
1806
- }
1807
- const dbMetas = await this.handleByteHeads(bytes.Ok());
1808
- await this.loader?.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
1809
- this.updateParentsFromDbMetas(dbMetas);
1810
- return dbMetas.map((m) => m.dbMeta);
1811
- }
1812
- async save(meta, branch) {
1813
- branch = branch || "main";
1814
- this.logger.Debug().Str("branch", branch).Any("meta", meta).Msg("saving meta");
1815
- const event = await createDbMetaEventBlock(this.sthis, meta, this.parents);
1816
- const bytes = await encodeEventsWithParents(this.sthis, [event], this.parents);
1817
- const url = await this.gateway.buildUrl(this.url(), branch);
1818
- if (url.isErr()) {
1819
- throw this.logger.Error().Err(url.Err()).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
1820
- }
1821
- this.parents = [event.cid];
1822
- const res = await this.gateway.put(url.Ok(), bytes);
1823
- if (res.isErr()) {
1824
- throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
1825
- }
1826
- return res;
1827
- }
1828
- async close() {
1829
- await this.gateway.close(this.url());
1830
- this._onClosed.forEach((fn) => fn());
1831
- return Result5.Ok(void 0);
1832
- }
1833
- async destroy() {
1834
- return this.gateway.destroy(this.url());
1835
- }
1836
- };
1837
- var DataStoreImpl = class extends BaseStoreImpl {
1838
- // readonly tag: string = "car-base";
1839
- constructor(sthis, name, url, opts) {
1840
- super(name, url, { ...opts }, sthis, ensureLogger(sthis, "DataStoreImpl"));
1841
- this.storeType = "data";
1842
- }
1843
- async load(cid) {
1844
- this.logger.Debug().Any("cid", cid).Msg("loading");
1845
- const url = await this.gateway.buildUrl(this.url(), cid.toString());
1846
- if (url.isErr()) {
1847
- throw this.logger.Error().Err(url.Err()).Str("cid", cid.toString()).Msg("got error from gateway.buildUrl").AsError();
1848
- }
1849
- const res = await this.gateway.get(url.Ok());
1850
- if (res.isErr()) {
1851
- throw res.Err();
1852
- }
1853
- return { cid, bytes: res.Ok() };
1854
- }
1855
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1856
- async save(car, opts) {
1857
- this.logger.Debug().Any("cid", car.cid.toString()).Msg("saving");
1858
- const url = await this.gateway.buildUrl(this.url(), car.cid.toString());
1859
- if (url.isErr()) {
1860
- throw this.logger.Error().Err(url.Err()).Ref("cid", car.cid).Msg("got error from gateway.buildUrl").AsError();
1861
- }
1862
- const res = await this.gateway.put(url.Ok(), car.bytes);
1863
- if (res.isErr()) {
1864
- throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
1865
- }
1866
- return res.Ok();
1867
- }
1868
- async remove(cid) {
1869
- const url = await this.gateway.buildUrl(this.url(), cid.toString());
1870
- if (url.isErr()) {
1871
- return url;
1872
- }
1873
- return this.gateway.delete(url.Ok());
1874
- }
1875
- async close() {
1876
- await this.gateway.close(this.url());
1877
- this._onClosed.forEach((fn) => fn());
1878
- return Result5.Ok(void 0);
1879
- }
1880
- destroy() {
1881
- return this.gateway.destroy(this.url());
1882
- }
1883
- };
1884
- var WALStoreImpl = class extends BaseStoreImpl {
1885
- constructor(loader, url, opts) {
1886
- super(loader.name, url, { ...opts }, loader.sthis, ensureLogger(loader.sthis, "WALStoreImpl"));
1887
- this.storeType = "wal";
1888
- this._ready = new ResolveOnce3();
1889
- this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
1890
- this.processing = void 0;
1891
- this.processQueue = new CommitQueue();
1892
- this.loader = loader;
1893
- }
1894
- async ready() {
1895
- return this._ready.once(async () => {
1896
- const walState = await this.load().catch((e) => {
1897
- this.logger.Error().Any("error", e).Msg("error loading wal");
1898
- return void 0;
1899
- });
1900
- if (!walState) {
1901
- this.walState.operations = [];
1902
- this.walState.fileOperations = [];
1903
- } else {
1904
- this.walState.operations = walState.operations || [];
1905
- this.walState.fileOperations = walState.fileOperations || [];
1906
- }
1907
- });
1908
- }
1909
- async enqueue(dbMeta, opts) {
1910
- await this.ready();
1911
- if (opts.compact) {
1912
- this.walState.operations = [];
1913
- this.walState.noLoaderOps = [dbMeta];
1914
- } else if (opts.noLoader) {
1915
- this.walState.noLoaderOps.push(dbMeta);
1916
- } else {
1917
- this.walState.operations.push(dbMeta);
1918
- }
1919
- await this.save(this.walState);
1920
- if (!opts.noLoader) {
1921
- void this.process();
1922
- }
1923
- }
1924
- async enqueueFile(fileCid, publicFile = false) {
1925
- await this.ready();
1926
- this.walState.fileOperations.push({ cid: fileCid, public: publicFile });
1927
- }
1928
- async process() {
1929
- await this.ready();
1930
- if (!this.loader.remoteCarStore) return;
1931
- await this.processQueue.enqueue(async () => {
1932
- try {
1933
- await this._doProcess();
1934
- } catch (e) {
1935
- this.logger.Error().Any("error", e).Msg("error processing wal");
1936
- }
1937
- if (this.walState.operations.length || this.walState.fileOperations.length || this.walState.noLoaderOps.length) {
1938
- setTimeout(() => void this.process(), 0);
1939
- }
1940
- });
1941
- }
1942
- async _doProcess() {
1943
- if (!this.loader.remoteCarStore) return;
1944
- const operations = [...this.walState.operations];
1945
- const noLoaderOps = [...this.walState.noLoaderOps];
1946
- const fileOperations = [...this.walState.fileOperations];
1947
- if (operations.length + noLoaderOps.length + fileOperations.length === 0) return;
1948
- const concurrencyLimit = 3;
1949
- const retryableUpload = (fn, description) => pRetry(fn, {
1950
- retries: 5,
1951
- onFailedAttempt: (error) => {
1952
- this.logger.Warn().Msg(`Attempt ${error.attemptNumber} failed for ${description}. There are ${error.retriesLeft} retries left.`);
1953
- }
1954
- });
1955
- try {
1956
- await pMap(
1957
- noLoaderOps,
1958
- async (dbMeta) => {
1959
- await retryableUpload(async () => {
1960
- for (const cid of dbMeta.cars) {
1961
- const car = await (await this.loader.carStore()).load(cid);
1962
- if (!car) {
1963
- if (carLogIncludesGroup(this.loader.carLog, dbMeta.cars)) {
1964
- throw this.logger.Error().Ref("cid", cid).Msg("missing local car").AsError();
1965
- }
1966
- } else {
1967
- await throwFalsy(this.loader.remoteCarStore).save(car);
1968
- }
1969
- }
1970
- this.walState.noLoaderOps = this.walState.noLoaderOps.filter((op) => op !== dbMeta);
1971
- }, `noLoaderOp with dbMeta.cars=${dbMeta.cars.toString()}`);
1972
- },
1973
- { concurrency: concurrencyLimit }
1974
- );
1975
- await pMap(
1976
- operations,
1977
- async (dbMeta) => {
1978
- await retryableUpload(async () => {
1979
- for (const cid of dbMeta.cars) {
1980
- const car = await (await this.loader.carStore()).load(cid);
1981
- if (!car) {
1982
- if (carLogIncludesGroup(this.loader.carLog, dbMeta.cars)) {
1983
- throw this.logger.Error().Ref("cid", cid).Msg(`missing local car`).AsError();
1984
- }
1985
- } else {
1986
- await throwFalsy(this.loader.remoteCarStore).save(car);
1987
- }
1988
- }
1989
- this.walState.operations = this.walState.operations.filter((op) => op !== dbMeta);
1990
- }, `operation with dbMeta.cars=${dbMeta.cars.toString()}`);
1991
- },
1992
- { concurrency: concurrencyLimit }
1993
- );
1994
- await pMap(
1995
- fileOperations,
1996
- async ({ cid: fileCid, public: publicFile }) => {
1997
- await retryableUpload(async () => {
1998
- const fileBlock = await (await this.loader.fileStore()).load(fileCid);
1999
- if (!fileBlock) {
2000
- throw this.logger.Error().Ref("cid", fileCid).Msg("missing file block").AsError();
2001
- }
2002
- await this.loader.remoteFileStore?.save(fileBlock, { public: publicFile });
2003
- this.walState.fileOperations = this.walState.fileOperations.filter((op) => op.cid !== fileCid);
2004
- }, `fileOperation with cid=${fileCid.toString()}`);
2005
- },
2006
- { concurrency: concurrencyLimit }
2007
- );
2008
- if (operations.length) {
2009
- const lastOp = operations[operations.length - 1];
2010
- await retryableUpload(async () => {
2011
- await this.loader.remoteMetaStore?.save(lastOp);
2012
- }, `remoteMetaStore save with dbMeta.cars=${lastOp.cars.toString()}`);
2013
- }
2014
- } catch (error) {
2015
- this.logger.Error().Any("error", error).Msg("Processing failed");
2016
- return;
2017
- } finally {
2018
- await this.save(this.walState);
2019
- }
2020
- }
2021
- async load() {
2022
- this.logger.Debug().Msg("loading");
2023
- const filepath = await this.gateway.buildUrl(this.url(), "main");
2024
- if (filepath.isErr()) {
2025
- throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2026
- }
2027
- const bytes = await this.gateway.get(filepath.Ok());
2028
- if (bytes.isErr()) {
2029
- if (isNotFoundError(bytes)) {
2030
- return void 0;
2031
- }
2032
- throw this.logger.Error().Err(bytes.Err()).Msg("error get").AsError();
2033
- }
2034
- try {
2035
- return bytes && parse2(this.sthis.txt.decode(bytes.Ok()));
2036
- } catch (e) {
2037
- throw this.logger.Error().Err(e).Msg("error parse").AsError();
2038
- }
2039
- }
2040
- async save(state) {
2041
- const filepath = await this.gateway.buildUrl(this.url(), "main");
2042
- if (filepath.isErr()) {
2043
- throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2044
- }
2045
- let encoded;
2046
- try {
2047
- encoded = format2(state);
2048
- } catch (e) {
2049
- throw this.logger.Error().Err(e).Any("state", state).Msg("error format").AsError();
2050
- }
2051
- const res = await this.gateway.put(filepath.Ok(), this.sthis.txt.encode(encoded));
2052
- if (res.isErr()) {
2053
- throw this.logger.Error().Err(res.Err()).Str("filePath", filepath.Ok().toString()).Msg("error saving").AsError();
2054
- }
2055
- }
2056
- async close() {
2057
- await this.gateway.close(this.url());
2058
- this._onClosed.forEach((fn) => fn());
2059
- return Result5.Ok(void 0);
2060
- }
2061
- destroy() {
2062
- return this.gateway.destroy(this.url());
2063
- }
2064
- };
2065
-
2066
- // src/blockstore/store-factory.ts
2067
- function ensureIsIndex(url, isIndex) {
2068
- if (isIndex) {
2069
- return url.build().setParam("index", isIndex).URI();
2070
- }
2071
- return url.build().delParam("index").URI();
2072
- }
2073
- function ensureName(name, url) {
2074
- if (!url.hasParam("name")) {
2075
- return url.build().setParam("name", name).URI();
2076
- }
2077
- return url;
2078
- }
2079
- var storeFactory = /* @__PURE__ */ new Map();
2080
- function buildURL(optURL, loader) {
2081
- const storeOpts = loader.ebOpts.store;
2082
- const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
2083
- let obuUrl;
2084
- if (obuItem && obuItem.overrideBaseURL) {
2085
- obuUrl = URI5.from(obuItem.overrideBaseURL);
2086
- }
2087
- const ret = ensureIsIndex(
2088
- URI5.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
2089
- storeOpts.isIndex
2090
- );
2091
- return ret;
2092
- }
2093
- var onceGateway = new KeyedResolvOnce2();
2094
- async function getGatewayFromURL(url, sthis) {
2095
- return onceGateway.get(url.toString()).once(async () => {
2096
- const item = storeFactory.get(url.protocol);
2097
- if (item) {
2098
- const ret = {
2099
- gateway: await item.gateway(sthis),
2100
- test: await item.test(sthis)
2101
- };
2102
- const res = await ret.gateway.start(url);
2103
- if (res.isErr()) {
2104
- sthis.logger.Error().Result("start", res).Msg("start failed");
2105
- return void 0;
2106
- }
2107
- return ret;
2108
- }
2109
- sthis.logger.Warn().Url(url).Msg("unsupported protocol");
2110
- return void 0;
2111
- });
2112
- }
2113
- function registerStoreProtocol(item) {
2114
- let protocol = item.protocol;
2115
- if (!protocol.endsWith(":")) {
2116
- protocol += ":";
2117
- }
2118
- if (storeFactory.has(protocol)) {
2119
- if (!item.overrideBaseURL && storeFactory.get(protocol) !== item) {
2120
- throw new Error(`we need a logger here`);
2121
- return () => {
2122
- };
2123
- }
2124
- }
2125
- if (item.overrideBaseURL) {
2126
- Array.from(storeFactory.values()).forEach((items) => {
2127
- items.overrideBaseURL = void 0;
2128
- });
2129
- }
2130
- storeFactory.set(protocol, item);
2131
- return () => {
2132
- storeFactory.delete(protocol);
2133
- };
2134
- }
2135
- var onceDataStoreFactory = new KeyedResolvOnce2();
2136
- async function dataStoreFactory(loader) {
2137
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
2138
- const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
2139
- return onceDataStoreFactory.get(url.toString()).once(async () => {
2140
- const gateway = await getGatewayFromURL(url, sthis);
2141
- if (!gateway) {
2142
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2143
- }
2144
- const store = new DataStoreImpl(sthis, loader.name, url, {
2145
- gateway: gateway.gateway,
2146
- keybag: () => getKeyBag(loader.sthis, {
2147
- ...loader.ebOpts.keyBag
2148
- })
2149
- });
2150
- return store;
2151
- });
2152
- }
2153
- var onceMetaStoreFactory = new KeyedResolvOnce2();
2154
- async function metaStoreFactory(loader) {
2155
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
2156
- const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
2157
- return onceMetaStoreFactory.get(url.toString()).once(async () => {
2158
- sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
2159
- const gateway = await getGatewayFromURL(url, sthis);
2160
- if (!gateway) {
2161
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2162
- }
2163
- const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
2164
- gateway: gateway.gateway,
2165
- keybag: () => getKeyBag(loader.sthis, {
2166
- ...loader.ebOpts.keyBag
2167
- })
2168
- });
2169
- return store;
2170
- });
2171
- }
2172
- var onceRemoteWalFactory = new KeyedResolvOnce2();
2173
- async function remoteWalFactory(loader) {
2174
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
2175
- const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
2176
- return onceRemoteWalFactory.get(url.toString()).once(async () => {
2177
- const gateway = await getGatewayFromURL(url, sthis);
2178
- if (!gateway) {
2179
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2180
- }
2181
- sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
2182
- const store = new WALStoreImpl(loader, url, {
2183
- gateway: gateway.gateway,
2184
- keybag: () => getKeyBag(loader.sthis, {
2185
- ...loader.ebOpts.keyBag
2186
- })
2187
- });
2188
- return store;
2189
- });
2190
- }
2191
- async function testStoreFactory(url, sthis) {
2192
- sthis = ensureSuperLog(sthis, "testStoreFactory");
2193
- const gateway = await getGatewayFromURL(url, sthis);
2194
- if (!gateway) {
2195
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2196
- }
2197
- return gateway.test;
2198
- }
2199
- async function ensureStart(store, logger) {
2200
- const ret = await store.start();
2201
- if (ret.isErr()) {
2202
- throw logger.Error().Result("start", ret).Msg("start failed").AsError();
2203
- }
2204
- logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
2205
- return store;
2206
- }
2207
- function toStoreRuntime(opts, sthis) {
2208
- const logger = ensureLogger(sthis, "toStoreRuntime", {});
2209
- return {
2210
- makeMetaStore: async (loader) => {
2211
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeMetaStore).Msg("makeMetaStore");
2212
- return ensureStart(await (loader.ebOpts.store.makeMetaStore || metaStoreFactory)(loader), logger);
2213
- },
2214
- makeDataStore: async (loader) => {
2215
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeDataStore).Msg("makeDataStore");
2216
- return ensureStart(await (loader.ebOpts.store.makeDataStore || dataStoreFactory)(loader), logger);
2217
- },
2218
- makeWALStore: async (loader) => {
2219
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeWALStore).Msg("makeRemoteWAL");
2220
- return ensureStart(await (loader.ebOpts.store.makeWALStore || remoteWalFactory)(loader), logger);
2221
- },
2222
- encodeFile: opts.encodeFile || encodeFile,
2223
- decodeFile: opts.decodeFile || decodeFile
2224
- };
2225
- }
2226
- registerStoreProtocol({
2227
- protocol: "file:",
2228
- gateway: async (sthis) => {
2229
- const { FileGateway } = await import("./bundle-not-impl-UH74NK5L.js");
2230
- return new FileGateway(sthis);
2231
- },
2232
- test: async (sthis) => {
2233
- const { FileTestStore } = await import("./bundle-not-impl-UH74NK5L.js");
2234
- return new FileTestStore(sthis);
2235
- }
2236
- });
2237
- registerStoreProtocol({
2238
- protocol: "indexdb:",
2239
- gateway: async (sthis) => {
2240
- const { IndexDBGateway } = await import("./gateway@skip-esm-GI5PRACF.js");
2241
- return new IndexDBGateway(sthis);
2242
- },
2243
- test: async (sthis) => {
2244
- const { IndexDBTestStore } = await import("./gateway@skip-esm-GI5PRACF.js");
2245
- return new IndexDBTestStore(sthis);
2246
- }
2247
- });
2248
-
2249
- // src/blockstore/store-remote.ts
2250
- async function RemoteDataStore(sthis, name, url, opts) {
2251
- const ds = new DataStoreImpl(sthis, name, url, opts);
2252
- await ds.start();
2253
- return ds;
2254
- }
2255
- async function RemoteMetaStore(sthis, name, url, opts) {
2256
- const ms = new MetaStoreImpl(
2257
- sthis,
2258
- name,
2259
- url,
2260
- opts
2261
- /* , true*/
2262
- );
2263
- await ms.start();
2264
- return ms;
2265
- }
2266
-
2267
- // src/blockstore/connection-base.ts
2268
- var ConnectionBase = class {
2269
- constructor(url, logger) {
2270
- this.loaded = Promise.resolve();
2271
- this.logger = logger;
2272
- this.url = url;
2273
- }
2274
- async refresh() {
2275
- await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
2276
- await (await throwFalsy(this.loader).WALStore()).process();
2277
- }
2278
- async connect_X({ loader }) {
2279
- if (!loader) throw this.logger.Error().Msg("loader is required").AsError();
2280
- await this.connectMeta_X({ loader });
2281
- await this.connectStorage_X({ loader });
2282
- }
2283
- async connectMeta_X({ loader }) {
2284
- if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
2285
- this.loader = loader;
2286
- await this.onConnect();
2287
- const metaUrl = this.url.build().defParam("store", "meta").URI();
2288
- const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
2289
- if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
2290
- const dbName = metaUrl.getParam("name");
2291
- if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: name is required").AsError();
2292
- const remote = await RemoteMetaStore(loader.sthis, dbName, metaUrl, {
2293
- gateway: gateway.gateway,
2294
- keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag),
2295
- loader
2296
- });
2297
- this.loader.remoteMetaStore = remote;
2298
- this.loaded = this.loader.ready().then(async () => {
2299
- remote.load().then(async () => {
2300
- (await throwFalsy(this.loader).WALStore()).process();
2301
- });
2302
- });
2303
- }
2304
- async connectStorage_X({ loader }) {
2305
- if (!loader) throw this.logger.Error().Msg("connectStorage_X: loader is required").AsError();
2306
- this.loader = loader;
2307
- const dataUrl = this.url.build().defParam("store", "data").URI();
2308
- const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
2309
- if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
2310
- const name = dataUrl.getParam("name");
2311
- if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: name is required").AsError;
2312
- loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
2313
- gateway: gateway.gateway,
2314
- keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
2315
- });
2316
- loader.remoteFileStore = loader.remoteCarStore;
2317
- }
2318
- // move this stuff to connect
2319
- // async getDashboardURL(compact = true) {
2320
- // const baseUrl = 'https://dashboard.fireproof.storage/'
2321
- // if (!this.loader?.remoteCarStore) return new URL('/howto', baseUrl)
2322
- // // if (compact) {
2323
- // // await this.compact()
2324
- // // }
2325
- // const currents = await this.loader?.metaStore?.load()
2326
- // if (!currents) throw new Error("Can't sync empty database: save data first")
2327
- // if (currents.length > 1)
2328
- // throw new Error("Can't sync database with split heads: make an update first")
2329
- // const current = currents[0]
2330
- // const params = {
2331
- // car: current.car.toString()
2332
- // }
2333
- // if (current.key) {
2334
- // // @ts-ignore
2335
- // params.key = current.key.toString()
2336
- // }
2337
- // // @ts-ignore
2338
- // if (this.name) {
2339
- // // @ts-ignore
2340
- // params.name = this.name
2341
- // }
2342
- // const url = new URL('/import#' + new URLSearchParams(params).toString(), baseUrl)
2343
- // console.log('Import to dashboard: ' + url.toString())
2344
- // return url
2345
- // }
2346
- // openDashboard() {
2347
- // void this.getDashboardURL().then(url => {
2348
- // if (url) window.open(url.toString(), '_blank')
2349
- // })
2350
- // }
2351
- };
2352
-
2353
- // src/crdt-helpers.ts
2354
- function time(tag) {
2355
- }
2356
- function timeEnd(tag) {
2357
- }
2358
- function toString(key, logger) {
2359
- switch (typeof key) {
2360
- case "string":
2361
- case "number":
2362
- return key.toString();
2363
- default:
2364
- throw logger.Error().Msg("Invalid key type").AsError();
2365
- }
2366
- }
2367
- async function applyBulkUpdateToCrdt(store, tblocks, head, updates, logger) {
2368
- let result = null;
2369
- if (updates.length > 1) {
2370
- const batch = await Batch.create(tblocks, head);
2371
- for (const update of updates) {
2372
- const link = await writeDocContent(store, tblocks, update, logger);
2373
- await batch.put(toString(update.id, logger), link);
2374
- }
2375
- result = await batch.commit();
2376
- } else if (updates.length === 1) {
2377
- const link = await writeDocContent(store, tblocks, updates[0], logger);
2378
- result = await put(tblocks, head, toString(updates[0].id, logger), link);
2379
- }
2380
- if (!result) throw logger.Error().Uint64("updates.len", updates.length).Msg("Missing result").AsError();
2381
- if (result.event) {
2382
- for (const { cid, bytes } of [
2383
- ...result.additions,
2384
- // ...result.removals,
2385
- result.event
2386
- ]) {
2387
- tblocks.putSync(cid, bytes);
2388
- }
2389
- }
2390
- return { head: result.head };
2391
- }
2392
- async function writeDocContent(store, blocks, update, logger) {
2393
- let value;
2394
- if (update.del) {
2395
- value = { del: true };
2396
- } else {
2397
- if (!update.value) throw logger.Error().Msg("Missing value").AsError();
2398
- await processFiles(store, blocks, update.value, logger);
2399
- value = { doc: update.value };
2400
- }
2401
- const block = await encode({ value, hasher: hasher5, codec });
2402
- blocks.putSync(block.cid, block.bytes);
2403
- return block.cid;
2404
- }
2405
- async function processFiles(store, blocks, doc, logger) {
2406
- if (doc._files) {
2407
- await processFileset(logger, store, blocks, doc._files);
2408
- }
2409
- if (doc._publicFiles) {
2410
- await processFileset(
2411
- logger,
2412
- store,
2413
- blocks,
2414
- doc._publicFiles
2415
- /*, true*/
2416
- );
2417
- }
2418
- }
2419
- async function processFileset(logger, store, blocks, files) {
2420
- const dbBlockstore = blocks.parent;
2421
- if (!dbBlockstore.loader) throw logger.Error().Msg("Missing loader, database name is required").AsError();
2422
- const t = new CarTransaction(dbBlockstore);
2423
- const didPut = [];
2424
- for (const filename in files) {
2425
- if (File === files[filename].constructor) {
2426
- const file = files[filename];
2427
- const { cid, blocks: fileBlocks } = await store.encodeFile(file);
2428
- didPut.push(filename);
2429
- for (const block of fileBlocks) {
2430
- t.putSync(block.cid, block.bytes);
2431
- }
2432
- files[filename] = { cid, type: file.type, size: file.size };
2433
- } else {
2434
- const { cid, type, size, car } = files[filename];
2435
- if (cid && type && size && car) {
2436
- files[filename] = { cid, type, size, car };
2437
- }
2438
- }
2439
- }
2440
- if (didPut.length) {
2441
- const car = await dbBlockstore.loader.commitFiles(
2442
- t,
2443
- { files }
2444
- );
2445
- if (car) {
2446
- for (const name of didPut) {
2447
- files[name] = { car, ...files[name] };
2448
- }
2449
- }
2450
- }
2451
- }
2452
- async function getValueFromCrdt(blocks, head, key, logger) {
2453
- if (!head.length) throw logger.Debug().Msg("Getting from an empty database").AsError();
2454
- const link = await get(blocks, head, key);
2455
- if (!link) throw logger.Error().Str("key", key).Msg(`Missing key`).AsError();
2456
- return await getValueFromLink(blocks, link, logger);
2457
- }
2458
- function readFiles(blocks, { doc }) {
2459
- if (!doc) return;
2460
- if (doc._files) {
2461
- readFileset(blocks, doc._files);
2462
- }
2463
- if (doc._publicFiles) {
2464
- readFileset(blocks, doc._publicFiles, true);
2465
- }
2466
- }
2467
- function readFileset(blocks, files, isPublic = false) {
2468
- for (const filename in files) {
2469
- const fileMeta = files[filename];
2470
- if (fileMeta.cid) {
2471
- if (isPublic) {
2472
- fileMeta.url = `https://${fileMeta.cid.toString()}.ipfs.w3s.link/`;
2473
- }
2474
- if (fileMeta.car) {
2475
- fileMeta.file = async () => await blocks.ebOpts.storeRuntime.decodeFile(
2476
- {
2477
- get: async (cid) => {
2478
- return await blocks.getFile(throwFalsy(fileMeta.car), cid);
2479
- }
2480
- },
2481
- fileMeta.cid,
2482
- fileMeta
2483
- );
2484
- }
2485
- }
2486
- files[filename] = fileMeta;
2487
- }
2488
- }
2489
- async function getValueFromLink(blocks, link, logger) {
2490
- const block = await blocks.get(link);
2491
- if (!block) throw logger.Error().Str("link", link.toString()).Msg(`Missing linked block`).AsError();
2492
- const { value } = await decode({ bytes: block.bytes, hasher: hasher5, codec });
2493
- const cvalue = {
2494
- ...value,
2495
- cid: link
2496
- };
2497
- readFiles(blocks, cvalue);
2498
- return cvalue;
2499
- }
2500
- var DirtyEventFetcher = class extends EventFetcher {
2501
- constructor(logger, blocks) {
2502
- super(blocks);
2503
- this.logger = logger;
2504
- }
2505
- async get(link) {
2506
- try {
2507
- return super.get(link);
2508
- } catch (e) {
2509
- this.logger.Error().Ref("link", link.toString()).Err(e).Msg("Missing event");
2510
- return { value: void 0 };
2511
- }
2512
- }
2513
- };
2514
- async function clockChangesSince(blocks, head, since, opts, logger) {
2515
- const eventsFetcher = opts.dirty ? new DirtyEventFetcher(logger, blocks) : new EventFetcher(blocks);
2516
- const keys = /* @__PURE__ */ new Set();
2517
- const updates = await gatherUpdates(
2518
- blocks,
2519
- eventsFetcher,
2520
- head,
2521
- since,
2522
- [],
2523
- keys,
2524
- /* @__PURE__ */ new Set(),
2525
- opts.limit || Infinity,
2526
- logger
2527
- );
2528
- return { result: updates.reverse(), head };
2529
- }
2530
- async function gatherUpdates(blocks, eventsFetcher, head, since, updates = [], keys, didLinks, limit, logger) {
2531
- if (limit <= 0) return updates;
2532
- const sHead = head.map((l) => l.toString());
2533
- for (const link of since) {
2534
- if (sHead.includes(link.toString())) {
2535
- return updates;
2536
- }
2537
- }
2538
- for (const link of head) {
2539
- if (didLinks.has(link.toString())) continue;
2540
- didLinks.add(link.toString());
2541
- const { value: event } = await eventsFetcher.get(link);
2542
- if (!event) continue;
2543
- const { type } = event.data;
2544
- let ops = [];
2545
- if (type === "batch") {
2546
- ops = event.data.ops;
2547
- } else if (type === "put") {
2548
- ops = [event.data];
2549
- }
2550
- for (let i = ops.length - 1; i >= 0; i--) {
2551
- const { key, value } = ops[i];
2552
- if (!keys.has(key)) {
2553
- const docValue = await getValueFromLink(blocks, value, logger);
2554
- updates.push({ id: key, value: docValue.doc, del: docValue.del, clock: link });
2555
- limit--;
2556
- keys.add(key);
2557
- }
2558
- }
2559
- if (event.parents) {
2560
- updates = await gatherUpdates(blocks, eventsFetcher, event.parents, since, updates, keys, didLinks, limit, logger);
2561
- }
2562
- }
2563
- return updates;
2564
- }
2565
- async function* getAllEntries(blocks, head, logger) {
2566
- for await (const [key, link] of entries(blocks, head)) {
2567
- const docValue = await getValueFromLink(blocks, link, logger);
2568
- yield { id: key, value: docValue.doc, del: docValue.del };
2569
- }
2570
- }
2571
- async function* clockVis(blocks, head) {
2572
- for await (const line of vis(blocks, head)) {
2573
- yield line;
2574
- }
2575
- }
2576
- var isCompacting = false;
2577
- async function doCompact(blockLog, head, logger) {
2578
- if (isCompacting) {
2579
- return;
2580
- }
2581
- isCompacting = true;
2582
- time("compact head");
2583
- for (const cid of head) {
2584
- const bl = await blockLog.get(cid);
2585
- if (!bl) throw logger.Error().Ref("cid", cid).Msg("Missing head block").AsError();
2586
- }
2587
- timeEnd("compact head");
2588
- time("compact all entries");
2589
- for await (const _entry of getAllEntries(blockLog, head, logger)) {
2590
- continue;
2591
- }
2592
- timeEnd("compact all entries");
2593
- time("compact clock vis");
2594
- for await (const _line of vis(blockLog, head)) {
2595
- }
2596
- timeEnd("compact clock vis");
2597
- time("compact root");
2598
- const result = await root(blockLog, head);
2599
- timeEnd("compact root");
2600
- time("compact root blocks");
2601
- for (const { cid, bytes } of [...result.additions, ...result.removals]) {
2602
- blockLog.loggedBlocks.putSync(cid, bytes);
2603
- }
2604
- timeEnd("compact root blocks");
2605
- time("compact changes");
2606
- await clockChangesSince(blockLog, head, [], {}, logger);
2607
- timeEnd("compact changes");
2608
- isCompacting = false;
2609
- }
2610
- async function getBlock(blocks, cidString) {
2611
- const block = await blocks.get(parse3(cidString));
2612
- if (!block) throw new Error(`Missing block ${cidString}`);
2613
- const { cid, value } = await decode({ bytes: block.bytes, codec, hasher: hasher5 });
2614
- return new Block({ cid, value, bytes: block.bytes });
2615
- }
2616
-
2617
- // src/indexer-helpers.ts
2618
- import { sha256 as hasher6 } from "multiformats/hashes/sha2";
2619
- import * as codec2 from "@ipld/dag-cbor";
2620
- import charwise from "charwise";
2621
- import * as DbIndex from "prolly-trees/db-index";
2622
- import { bf, simpleCompare } from "prolly-trees/utils";
2623
- import { nocache as cache } from "prolly-trees/cache";
2624
- var IndexTree = class {
2625
- };
2626
- function refCompare(aRef, bRef) {
2627
- if (Number.isNaN(aRef)) return -1;
2628
- if (Number.isNaN(bRef)) throw new Error("ref may not be Infinity or NaN");
2629
- if (aRef === Infinity) return 1;
2630
- return simpleCompare(aRef, bRef);
2631
- }
2632
- function compare(a, b) {
2633
- const [aKey, aRef] = a;
2634
- const [bKey, bRef] = b;
2635
- const comp = simpleCompare(aKey, bKey);
2636
- if (comp !== 0) return comp;
2637
- return refCompare(aRef, bRef);
2638
- }
2639
- var byKeyOpts = { cache, chunker: bf(30), codec: codec2, hasher: hasher6, compare };
2640
- var byIdOpts = { cache, chunker: bf(30), codec: codec2, hasher: hasher6, compare: simpleCompare };
2641
- function indexEntriesForChanges(changes, mapFn) {
2642
- const indexEntries = [];
2643
- changes.forEach(({ id: key, value, del }) => {
2644
- if (del || !value) return;
2645
- let mapCalled = false;
2646
- const mapReturn = mapFn({ ...value, _id: key }, (k, v) => {
2647
- mapCalled = true;
2648
- if (typeof k === "undefined") return;
2649
- indexEntries.push({
2650
- key: [charwise.encode(k), key],
2651
- value: v || null
2652
- });
2653
- });
2654
- if (!mapCalled && mapReturn) {
2655
- indexEntries.push({
2656
- key: [charwise.encode(mapReturn), key],
2657
- value: null
2658
- });
2659
- }
2660
- });
2661
- return indexEntries;
2662
- }
2663
- function makeProllyGetBlock(blocks) {
2664
- return async (address) => {
2665
- const block = await blocks.get(address);
2666
- if (!block) throw new Error(`Missing block ${address.toString()}`);
2667
- const { cid, bytes } = block;
2668
- return create({ cid, bytes, hasher: hasher6, codec: codec2 });
2669
- };
2670
- }
2671
- async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
2672
- if (!indexEntries.length) return inIndex;
2673
- if (!inIndex.root) {
2674
- if (!inIndex.cid) {
2675
- let returnRootBlock = void 0;
2676
- let returnNode = void 0;
2677
- for await (const node of await DbIndex.create({
2678
- get: makeProllyGetBlock(tblocks),
2679
- list: indexEntries,
2680
- ...opts
2681
- })) {
2682
- const block = await node.block;
2683
- await tblocks.put(block.cid, block.bytes);
2684
- returnRootBlock = block;
2685
- returnNode = node;
2686
- }
2687
- if (!returnNode || !returnRootBlock) throw new Error("failed to create index");
2688
- return { root: returnNode, cid: returnRootBlock.cid };
2689
- } else {
2690
- inIndex.root = await DbIndex.load({ cid: inIndex.cid, get: makeProllyGetBlock(tblocks), ...opts });
2691
- }
2692
- }
2693
- const { root: root3, blocks: newBlocks } = await inIndex.root.bulk(indexEntries);
2694
- if (root3) {
2695
- for await (const block of newBlocks) {
2696
- await tblocks.put(block.cid, block.bytes);
2697
- }
2698
- return { root: root3, cid: (await root3.block).cid };
2699
- } else {
2700
- return { root: void 0, cid: void 0 };
2701
- }
2702
- }
2703
- async function loadIndex(tblocks, cid, opts) {
2704
- return await DbIndex.load({ cid, get: makeProllyGetBlock(tblocks), ...opts });
2705
- }
2706
- async function applyQuery(crdt, resp, query) {
2707
- if (query.descending) {
2708
- resp.result = resp.result.reverse();
2709
- }
2710
- if (query.limit) {
2711
- resp.result = resp.result.slice(0, query.limit);
2712
- }
2713
- if (query.includeDocs) {
2714
- resp.result = await Promise.all(
2715
- resp.result.map(async (row) => {
2716
- const val = await crdt.get(row.id);
2717
- const doc = val ? { ...val.doc, _id: row.id } : void 0;
2718
- return { ...row, doc };
2719
- })
2720
- );
2721
- }
2722
- return {
2723
- rows: resp.result.map(({ key, ...row }) => {
2724
- return {
2725
- key: charwise.decode(key),
2726
- ...row
2727
- };
2728
- })
2729
- };
2730
- }
2731
- function encodeRange(range) {
2732
- return [charwise.encode(range[0]), charwise.encode(range[1])];
2733
- }
2734
- function encodeKey(key) {
2735
- return charwise.encode(key);
2736
- }
2737
-
2738
- // src/indexer.ts
2739
- function index(sthis, { _crdt }, name, mapFn, meta) {
2740
- if (mapFn && meta) throw _crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
2741
- if (mapFn && mapFn.constructor.name !== "Function") throw _crdt.logger.Error().Msg("mapFn must be a function").AsError();
2742
- if (_crdt.indexers.has(name)) {
2743
- const idx = _crdt.indexers.get(name);
2744
- idx.applyMapFn(name, mapFn, meta);
2745
- } else {
2746
- const idx = new Index(sthis, _crdt, name, mapFn, meta);
2747
- _crdt.indexers.set(name, idx);
2748
- }
2749
- return _crdt.indexers.get(name);
2750
- }
2751
- var Index = class {
2752
- constructor(sthis, crdt, name, mapFn, meta) {
2753
- this.mapFnString = "";
2754
- this.byKey = new IndexTree();
2755
- this.byId = new IndexTree();
2756
- this.includeDocsDefault = false;
2757
- this.logger = ensureLogger(sthis, "Index");
2758
- this.blockstore = crdt.indexBlockstore;
2759
- this.crdt = crdt;
2760
- this.applyMapFn(name, mapFn, meta);
2761
- this.name = name;
2762
- if (!(this.mapFnString || this.initError)) throw this.logger.Error().Msg("missing mapFnString").AsError();
2763
- }
2764
- ready() {
2765
- return Promise.all([this.blockstore.ready(), this.crdt.ready()]).then(() => {
2766
- });
2767
- }
2768
- close() {
2769
- return Promise.all([this.blockstore.close(), this.crdt.close()]).then(() => {
2770
- });
2771
- }
2772
- destroy() {
2773
- return Promise.all([this.blockstore.destroy(), this.crdt.destroy()]).then(() => {
2774
- });
2775
- }
2776
- applyMapFn(name, mapFn, meta) {
2777
- if (mapFn && meta) throw this.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
2778
- if (this.name && this.name !== name) throw this.logger.Error().Msg("cannot change name").AsError();
2779
- this.name = name;
2780
- try {
2781
- if (meta) {
2782
- if (this.indexHead && this.indexHead.map((c) => c.toString()).join() !== meta.head.map((c) => c.toString()).join()) {
2783
- throw this.logger.Error().Msg("cannot apply different head meta").AsError();
2784
- }
2785
- if (this.mapFnString) {
2786
- if (this.mapFnString !== meta.map) {
2787
- this.logger.Warn().Msg(`cannot apply different mapFn meta: old mapFnString ${this.mapFnString} new mapFnString ${meta.map}`);
2788
- } else {
2789
- this.byId.cid = meta.byId;
2790
- this.byKey.cid = meta.byKey;
2791
- this.indexHead = meta.head;
2792
- }
2793
- } else {
2794
- this.mapFnString = meta.map;
2795
- this.byId.cid = meta.byId;
2796
- this.byKey.cid = meta.byKey;
2797
- this.indexHead = meta.head;
2798
- }
2799
- } else {
2800
- if (this.mapFn) {
2801
- if (mapFn) {
2802
- if (this.mapFn.toString() !== mapFn.toString()) {
2803
- throw this.logger.Error().Msg("cannot apply different mapFn app2").AsError();
2804
- }
2805
- }
2806
- } else {
2807
- if (!mapFn) {
2808
- mapFn = (doc) => doc[name] ?? void 0;
2809
- }
2810
- if (this.mapFnString) {
2811
- if (this.mapFnString !== mapFn.toString()) {
2812
- throw this.logger.Error().Str("mapFnString", this.mapFnString).Str("mapFn", mapFn.toString()).Msg("cannot apply different mapFn app").AsError();
2813
- }
2814
- } else {
2815
- this.mapFnString = mapFn.toString();
2816
- }
2817
- this.mapFn = mapFn;
2818
- }
2819
- }
2820
- const matches = /=>\s*(.*)/.test(this.mapFnString);
2821
- this.includeDocsDefault = matches;
2822
- } catch (e) {
2823
- this.initError = e;
2824
- }
2825
- }
2826
- async query(opts = {}) {
2827
- await this.ready();
2828
- await this._updateIndex();
2829
- await this._hydrateIndex();
2830
- if (!this.byKey.root) {
2831
- return await applyQuery(this.crdt, { result: [] }, opts);
2832
- }
2833
- if (this.includeDocsDefault && opts.includeDocs === void 0) opts.includeDocs = true;
2834
- if (opts.range) {
2835
- const eRange = encodeRange(opts.range);
2836
- return await applyQuery(this.crdt, await throwFalsy(this.byKey.root).range(eRange[0], eRange[1]), opts);
2837
- }
2838
- if (opts.key) {
2839
- const encodedKey = encodeKey(opts.key);
2840
- return await applyQuery(this.crdt, await throwFalsy(this.byKey.root).get(encodedKey), opts);
2841
- }
2842
- if (Array.isArray(opts.keys)) {
2843
- const results = await Promise.all(
2844
- opts.keys.map(async (key) => {
2845
- const encodedKey = encodeKey(key);
2846
- return (await applyQuery(this.crdt, await throwFalsy(this.byKey.root).get(encodedKey), opts)).rows;
2847
- })
2848
- );
2849
- return { rows: results.flat() };
2850
- }
2851
- if (opts.prefix) {
2852
- if (!Array.isArray(opts.prefix)) opts.prefix = [opts.prefix];
2853
- const start = [...opts.prefix, NaN];
2854
- const end = [...opts.prefix, Infinity];
2855
- const encodedR = encodeRange([start, end]);
2856
- return await applyQuery(this.crdt, await this.byKey.root.range(...encodedR), opts);
2857
- }
2858
- const all = await this.byKey.root.getAllEntries();
2859
- return await applyQuery(
2860
- this.crdt,
2861
- {
2862
- // @ts-expect-error getAllEntries returns a different type than range
2863
- result: all.result.map(({ key: [k, id], value }) => ({
2864
- key: k,
2865
- id,
2866
- value
2867
- }))
2868
- },
2869
- opts
2870
- );
2871
- }
2872
- _resetIndex() {
2873
- this.byId = new IndexTree();
2874
- this.byKey = new IndexTree();
2875
- this.indexHead = void 0;
2876
- }
2877
- async _hydrateIndex() {
2878
- if (this.byId.root && this.byKey.root) return;
2879
- if (!this.byId.cid || !this.byKey.cid) return;
2880
- this.byId.root = await loadIndex(this.blockstore, this.byId.cid, byIdOpts);
2881
- this.byKey.root = await loadIndex(this.blockstore, this.byKey.cid, byKeyOpts);
2882
- }
2883
- async _updateIndex() {
2884
- await this.ready();
2885
- if (this.initError) throw this.initError;
2886
- if (!this.mapFn) throw this.logger.Error().Msg("No map function defined").AsError();
2887
- let result, head;
2888
- if (!this.indexHead || this.indexHead.length === 0) {
2889
- ({ result, head } = await this.crdt.allDocs());
2890
- } else {
2891
- ({ result, head } = await this.crdt.changes(this.indexHead));
2892
- }
2893
- if (result.length === 0) {
2894
- this.indexHead = head;
2895
- }
2896
- let staleKeyIndexEntries = [];
2897
- let removeIdIndexEntries = [];
2898
- if (this.byId.root) {
2899
- const removeIds = result.map(({ id: key }) => key);
2900
- const { result: oldChangeEntries } = await this.byId.root.getMany(removeIds);
2901
- staleKeyIndexEntries = oldChangeEntries.map((key) => ({ key, del: true }));
2902
- removeIdIndexEntries = oldChangeEntries.map((key) => ({ key: key[1], del: true }));
2903
- }
2904
- const indexEntries = indexEntriesForChanges(result, this.mapFn);
2905
- const byIdIndexEntries = indexEntries.map(({ key }) => ({
2906
- key: key[1],
2907
- value: key
2908
- }));
2909
- const indexerMeta = { indexes: /* @__PURE__ */ new Map() };
2910
- for (const [name, indexer] of this.crdt.indexers) {
2911
- if (indexer.indexHead) {
2912
- indexerMeta.indexes?.set(name, {
2913
- byId: indexer.byId.cid,
2914
- byKey: indexer.byKey.cid,
2915
- head: indexer.indexHead,
2916
- map: indexer.mapFnString,
2917
- name: indexer.name
2918
- });
2919
- }
2920
- }
2921
- if (result.length === 0) {
2922
- return indexerMeta;
2923
- }
2924
- const { meta } = await this.blockstore.transaction(async (tblocks) => {
2925
- this.byId = await bulkIndex(tblocks, this.byId, removeIdIndexEntries.concat(byIdIndexEntries), byIdOpts);
2926
- this.byKey = await bulkIndex(tblocks, this.byKey, staleKeyIndexEntries.concat(indexEntries), byKeyOpts);
2927
- this.indexHead = head;
2928
- if (this.byId.cid && this.byKey.cid) {
2929
- const idxMeta = {
2930
- byId: this.byId.cid,
2931
- byKey: this.byKey.cid,
2932
- head,
2933
- map: this.mapFnString,
2934
- name: this.name
2935
- };
2936
- indexerMeta.indexes?.set(this.name, idxMeta);
2937
- }
2938
- return indexerMeta;
2939
- });
2940
- return meta;
2941
- }
2942
- };
2943
-
2944
- // src/crdt-clock.ts
2945
- import { advance } from "@web3-storage/pail/clock";
2946
- import { root as root2 } from "@web3-storage/pail/crdt";
2947
- import { ResolveOnce as ResolveOnce4 } from "@adviser/cement";
2948
-
2949
- // src/apply-head-queue.ts
2950
- function applyHeadQueue(worker, logger) {
2951
- const queue = [];
2952
- let isProcessing = false;
2953
- async function* process() {
2954
- if (isProcessing || queue.length === 0) return;
2955
- isProcessing = true;
2956
- const allUpdates = [];
2957
- try {
2958
- while (queue.length > 0) {
2959
- queue.sort((a, b) => b.updates ? 1 : -1);
2960
- const task = queue.shift();
2961
- if (!task) continue;
2962
- await worker(task.newHead, task.prevHead, task.updates !== void 0).catch((e) => {
2963
- throw logger.Error().Err(e).Msg("int_applyHead worker error").AsError();
2964
- });
2965
- if (task.updates) {
2966
- allUpdates.push(...task.updates);
2967
- }
2968
- if (!queue.some((t) => t.updates) || task.updates) {
2969
- const allTasksHaveUpdates = queue.every((task2) => task2.updates !== null);
2970
- yield { updates: allUpdates, all: allTasksHaveUpdates };
2971
- allUpdates.length = 0;
2972
- }
2973
- }
2974
- } finally {
2975
- isProcessing = false;
2976
- const generator = process();
2977
- let result = await generator.next();
2978
- while (!result.done) {
2979
- result = await generator.next();
2980
- }
2981
- }
2982
- }
2983
- return {
2984
- push(task) {
2985
- queue.push(task);
2986
- return process();
2987
- },
2988
- size() {
2989
- return queue.length;
2990
- }
2991
- };
2992
- }
2993
-
2994
- // src/crdt-clock.ts
2995
- var CRDTClock = class {
2996
- constructor(blockstore) {
2997
- // todo: track local and remote clocks independently, merge on read
2998
- // that way we can drop the whole remote if we need to
2999
- // should go with making sure the local clock only references locally available blockstore on write
3000
- this.head = [];
3001
- this.zoomers = /* @__PURE__ */ new Set();
3002
- this.watchers = /* @__PURE__ */ new Set();
3003
- this.emptyWatchers = /* @__PURE__ */ new Set();
3004
- this._ready = new ResolveOnce4();
3005
- this.blockstore = blockstore;
3006
- this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
3007
- this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
3008
- }
3009
- async ready() {
3010
- return this._ready.once(async () => {
3011
- await this.blockstore.ready();
3012
- });
3013
- }
3014
- async close() {
3015
- await this.blockstore.close();
3016
- }
3017
- setHead(head) {
3018
- this.head = head;
3019
- }
3020
- async applyHead(newHead, prevHead, updates) {
3021
- for await (const { updates: updatesAcc, all } of this.applyHeadQueue.push({
3022
- newHead,
3023
- prevHead,
3024
- updates
3025
- })) {
3026
- return this.processUpdates(updatesAcc, all, prevHead);
3027
- }
3028
- }
3029
- async processUpdates(updatesAcc, all, prevHead) {
3030
- let internalUpdates = updatesAcc;
3031
- if (this.watchers.size && !all) {
3032
- const changes = await clockChangesSince(throwFalsy(this.blockstore), this.head, prevHead, {}, this.logger);
3033
- internalUpdates = changes.result;
3034
- }
3035
- this.zoomers.forEach((fn) => fn());
3036
- this.notifyWatchers(internalUpdates || []);
3037
- }
3038
- notifyWatchers(updates) {
3039
- this.emptyWatchers.forEach((fn) => fn());
3040
- this.watchers.forEach((fn) => fn(updates || []));
3041
- }
3042
- onTick(fn) {
3043
- this.watchers.add(fn);
3044
- }
3045
- onTock(fn) {
3046
- this.emptyWatchers.add(fn);
3047
- }
3048
- onZoom(fn) {
3049
- this.zoomers.add(fn);
3050
- }
3051
- async int_applyHead(newHead, prevHead, localUpdates) {
3052
- const noLoader = !localUpdates;
3053
- const ogHead = sortClockHead(this.head);
3054
- newHead = sortClockHead(newHead);
3055
- if (compareClockHeads(ogHead, newHead)) {
3056
- return;
3057
- }
3058
- const ogPrev = sortClockHead(prevHead);
3059
- if (compareClockHeads(ogHead, ogPrev)) {
3060
- this.setHead(newHead);
3061
- return;
3062
- }
3063
- if (!this.blockstore) {
3064
- throw this.logger.Error().Msg("missing blockstore").AsError();
3065
- }
3066
- await validateBlocks(this.logger, newHead, this.blockstore);
3067
- if (!this.transaction) {
3068
- this.transaction = this.blockstore.openTransaction({ noLoader, add: false });
3069
- }
3070
- const tblocks = this.transaction;
3071
- const advancedHead = await advanceBlocks(this.logger, newHead, tblocks, this.head);
3072
- const result = await root2(tblocks, advancedHead);
3073
- for (const { cid, bytes } of [
3074
- ...result.additions
3075
- // ...result.removals
3076
- ]) {
3077
- tblocks.putSync(cid, bytes);
3078
- }
3079
- if (!noLoader) {
3080
- await this.blockstore.commitTransaction(tblocks, { head: advancedHead }, { add: false, noLoader });
3081
- this.transaction = void 0;
3082
- }
3083
- this.setHead(advancedHead);
3084
- }
3085
- };
3086
- function sortClockHead(clockHead) {
3087
- return clockHead.sort((a, b) => a.toString().localeCompare(b.toString()));
3088
- }
3089
- async function validateBlocks(logger, newHead, blockstore) {
3090
- if (!blockstore) throw logger.Error().Msg("missing blockstore");
3091
- newHead.map(async (cid) => {
3092
- const got = await blockstore.get(cid);
3093
- if (!got) {
3094
- throw logger.Error().Str("cid", cid.toString()).Msg("int_applyHead missing block").AsError();
3095
- }
3096
- });
3097
- }
3098
- function compareClockHeads(head1, head2) {
3099
- return head1.toString() === head2.toString();
3100
- }
3101
- async function advanceBlocks(logger, newHead, tblocks, head) {
3102
- for (const cid of newHead) {
3103
- try {
3104
- head = await advance(tblocks, head, cid);
3105
- } catch (e) {
3106
- logger.Debug().Err(e).Msg("failed to advance head");
3107
- continue;
3108
- }
3109
- }
3110
- return head;
3111
- }
3112
-
3113
- // src/crdt.ts
3114
- var CRDT = class {
3115
- constructor(sthis, name, opts = {}) {
3116
- this.indexers = /* @__PURE__ */ new Map();
3117
- this.onceReady = new ResolveOnce5();
3118
- this.sthis = sthis;
3119
- this.name = name;
3120
- this.logger = ensureLogger(sthis, "CRDT");
3121
- this.opts = opts;
3122
- this.blockstore = blockstoreFactory(sthis, {
3123
- name,
3124
- applyMeta: async (meta) => {
3125
- const crdtMeta = meta;
3126
- if (!crdtMeta.head) throw this.logger.Error().Msg("missing head").AsError();
3127
- await this.clock.applyHead(crdtMeta.head, []);
3128
- },
3129
- compact: async (blocks) => {
3130
- await doCompact(blocks, this.clock.head, this.logger);
3131
- return { head: this.clock.head };
3132
- },
3133
- autoCompact: this.opts.autoCompact || 100,
3134
- store: { ...this.opts.store, isIndex: void 0 },
3135
- public: this.opts.public,
3136
- meta: this.opts.meta,
3137
- threshold: this.opts.threshold
3138
- });
3139
- this.indexBlockstore = blockstoreFactory(sthis, {
3140
- name,
3141
- applyMeta: async (meta) => {
3142
- const idxCarMeta = meta;
3143
- if (!idxCarMeta.indexes) throw this.logger.Error().Msg("missing indexes").AsError();
3144
- for (const [name2, idx] of Object.entries(idxCarMeta.indexes)) {
3145
- index(this.sthis, { _crdt: this }, name2, void 0, idx);
3146
- }
3147
- },
3148
- store: { ...this.opts.store, isIndex: this.opts.store?.isIndex || "idx" },
3149
- public: this.opts.public
3150
- });
3151
- this.clock = new CRDTClock(this.blockstore);
3152
- this.clock.onZoom(() => {
3153
- for (const idx of this.indexers.values()) {
3154
- idx._resetIndex();
3155
- }
3156
- });
3157
- }
3158
- async bulk(updates) {
3159
- await this.ready();
3160
- const prevHead = [...this.clock.head];
3161
- const done = await this.blockstore.transaction(async (blocks) => {
3162
- const { head } = await applyBulkUpdateToCrdt(
3163
- this.blockstore.ebOpts.storeRuntime,
3164
- blocks,
3165
- this.clock.head,
3166
- updates,
3167
- this.logger
3168
- );
3169
- updates = updates.map((dupdate) => {
3170
- readFiles(this.blockstore, { doc: dupdate.value });
3171
- return dupdate;
3172
- });
3173
- return { head };
3174
- });
3175
- await this.clock.applyHead(done.meta.head, prevHead, updates);
3176
- return done.meta;
3177
- }
3178
- async ready() {
3179
- return this.onceReady.once(async () => {
3180
- try {
3181
- await Promise.all([this.blockstore.ready(), this.indexBlockstore.ready(), this.clock.ready()]);
3182
- } catch (e) {
3183
- throw this.logger.Error().Err(e).Msg(`CRDT is not ready`).AsError();
3184
- }
3185
- });
3186
- }
3187
- async close() {
3188
- await Promise.all([this.blockstore.close(), this.indexBlockstore.close(), this.clock.close()]);
3189
- }
3190
- async destroy() {
3191
- await Promise.all([this.blockstore.destroy(), this.indexBlockstore.destroy()]);
3192
- }
3193
- // if (snap) await this.clock.applyHead(crdtMeta.head, this.clock.head)
3194
- async allDocs() {
3195
- await this.ready();
3196
- const result = [];
3197
- for await (const entry of getAllEntries(this.blockstore, this.clock.head, this.logger)) {
3198
- result.push(entry);
3199
- }
3200
- return { result, head: this.clock.head };
3201
- }
3202
- async vis() {
3203
- await this.ready();
3204
- const txt = [];
3205
- for await (const line of clockVis(this.blockstore, this.clock.head)) {
3206
- txt.push(line);
3207
- }
3208
- return txt.join("\n");
3209
- }
3210
- async getBlock(cidString) {
3211
- await this.ready();
3212
- return await getBlock(this.blockstore, cidString);
3213
- }
3214
- async get(key) {
3215
- await this.ready();
3216
- const result = await getValueFromCrdt(this.blockstore, this.clock.head, key, this.logger);
3217
- if (result.del) return void 0;
3218
- return result;
3219
- }
3220
- async changes(since = [], opts = {}) {
3221
- await this.ready();
3222
- return await clockChangesSince(this.blockstore, this.clock.head, since, opts, this.logger);
3223
- }
3224
- async compact() {
3225
- const blocks = this.blockstore;
3226
- return await blocks.compact();
3227
- }
3228
- };
3229
-
3230
- // src/database.ts
3231
- var Database = class {
3232
- constructor(name, opts) {
3233
- this.opts = {};
3234
- this._listening = false;
3235
- this._listeners = /* @__PURE__ */ new Set();
3236
- this._noupdate_listeners = /* @__PURE__ */ new Set();
3237
- this._ready = new ResolveOnce6();
3238
- this.name = name;
3239
- this.opts = opts || this.opts;
3240
- this.sthis = ensureSuperThis(this.opts);
3241
- this.logger = ensureLogger(this.sthis, "Database");
3242
- this._crdt = new CRDT(this.sthis, name, this.opts);
3243
- this.blockstore = this._crdt.blockstore;
3244
- this._writeQueue = writeQueue(async (updates) => {
3245
- return await this._crdt.bulk(updates);
3246
- });
3247
- this._crdt.clock.onTock(() => {
3248
- this._no_update_notify();
3249
- });
3250
- }
3251
- static {
3252
- this.databases = /* @__PURE__ */ new Map();
3253
- }
3254
- async close() {
3255
- await this.ready();
3256
- await this._crdt.close();
3257
- await this.blockstore.close();
3258
- }
3259
- async destroy() {
3260
- await this.ready();
3261
- await this._crdt.destroy();
3262
- await this.blockstore.destroy();
3263
- }
3264
- async ready() {
3265
- return this._ready.once(async () => {
3266
- await this.sthis.start();
3267
- await this._crdt.ready();
3268
- await this.blockstore.ready();
3269
- });
3270
- }
3271
- async get(id) {
3272
- if (!id) throw this.logger.Error().Str("db", this.name).Msg(`Doc id is required`).AsError();
3273
- await this.ready();
3274
- this.logger.Debug().Str("id", id).Msg("get");
3275
- const got = await this._crdt.get(id).catch((e) => {
3276
- throw new NotFoundError(`Not found: ${id} - ${e.message}`);
3277
- });
3278
- if (!got) throw new NotFoundError(`Not found: ${id}`);
3279
- const { doc } = got;
3280
- return { ...doc, _id: id };
3281
- }
3282
- async put(doc) {
3283
- await this.ready();
3284
- this.logger.Debug().Str("id", doc._id).Msg("put");
3285
- const { _id, ...value } = doc;
3286
- const docId = _id || this.sthis.timeOrderedNextId().str;
3287
- const result = await this._writeQueue.push({
3288
- id: docId,
3289
- value: {
3290
- ...value,
3291
- _id: docId
3292
- }
3293
- });
3294
- return { id: docId, clock: result?.head, name: this.name };
3295
- }
3296
- async del(id) {
3297
- await this.ready();
3298
- this.logger.Debug().Str("id", id).Msg("del");
3299
- const result = await this._writeQueue.push({ id, del: true });
3300
- return { id, clock: result?.head, name: this.name };
3301
- }
3302
- async changes(since = [], opts = {}) {
3303
- await this.ready();
3304
- this.logger.Debug().Any("since", since).Any("opts", opts).Msg("changes");
3305
- const { result, head } = await this._crdt.changes(since, opts);
3306
- const rows = result.map(({ id: key, value, del, clock }) => ({
3307
- key,
3308
- value: del ? { _id: key, _deleted: true } : { _id: key, ...value },
3309
- clock
3310
- }));
3311
- return { rows, clock: head, name: this.name };
3312
- }
3313
- async allDocs(opts = {}) {
3314
- await this.ready();
3315
- this.logger.Debug().Msg("allDocs");
3316
- const { result, head } = await this._crdt.allDocs();
3317
- const rows = result.map(({ id: key, value, del }) => ({
3318
- key,
3319
- value: del ? { _id: key, _deleted: true } : { _id: key, ...value }
3320
- }));
3321
- return { rows, clock: head, name: this.name };
3322
- }
3323
- async allDocuments() {
3324
- return this.allDocs();
3325
- }
3326
- subscribe(listener, updates) {
3327
- this.logger.Debug().Bool("updates", updates).Msg("subscribe");
3328
- if (updates) {
3329
- if (!this._listening) {
3330
- this._listening = true;
3331
- this._crdt.clock.onTick((updates2) => {
3332
- void this._notify(updates2);
3333
- });
3334
- }
3335
- this._listeners.add(listener);
3336
- return () => {
3337
- this._listeners.delete(listener);
3338
- };
3339
- } else {
3340
- this._noupdate_listeners.add(listener);
3341
- return () => {
3342
- this._noupdate_listeners.delete(listener);
3343
- };
3344
- }
3345
- }
3346
- // todo if we add this onto dbs in fireproof.ts then we can make index.ts a separate package
3347
- async query(field, opts = {}) {
3348
- await this.ready();
3349
- this.logger.Debug().Any("field", field).Any("opts", opts).Msg("query");
3350
- const _crdt = this._crdt;
3351
- const idx = typeof field === "string" ? index(this.sthis, { _crdt }, field) : index(this.sthis, { _crdt }, makeName(field.toString()), field);
3352
- return await idx.query(opts);
3353
- }
3354
- async compact() {
3355
- await this.ready();
3356
- await this._crdt.compact();
3357
- }
3358
- async _notify(updates) {
3359
- await this.ready();
3360
- if (this._listeners.size) {
3361
- const docs = updates.map(({ id, value }) => ({ ...value, _id: id }));
3362
- for (const listener of this._listeners) {
3363
- await (async () => await listener(docs))().catch((e) => {
3364
- this.logger.Error().Err(e).Msg("subscriber error");
3365
- });
3366
- }
3367
- }
3368
- }
3369
- async _no_update_notify() {
3370
- await this.ready();
3371
- if (this._noupdate_listeners.size) {
3372
- for (const listener of this._noupdate_listeners) {
3373
- await (async () => await listener([]))().catch((e) => {
3374
- this.logger.Error().Err(e).Msg("subscriber error");
3375
- });
3376
- }
3377
- }
3378
- }
3379
- };
3380
- function toSortedArray(set) {
3381
- if (!set) return [];
3382
- return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
3383
- }
3384
- function fireproof(name, opts) {
3385
- const key = JSON.stringify(
3386
- toSortedArray({
3387
- name,
3388
- stores: toSortedArray(opts?.store?.stores)
3389
- })
3390
- );
3391
- let db = Database.databases.get(key);
3392
- if (!db) {
3393
- db = new Database(name, opts);
3394
- Database.databases.set(key, db);
3395
- }
3396
- return db;
3397
- }
3398
- function makeName(fnString) {
3399
- const regex = /\(([^,()]+,\s*[^,()]+|\[[^\]]+\],\s*[^,()]+)\)/g;
3400
- let found = null;
3401
- const matches = Array.from(fnString.matchAll(regex), (match) => match[1].trim());
3402
- if (matches.length === 0) {
3403
- found = /=>\s*{?\s*([^{}]+)\s*}?/.exec(fnString);
3404
- if (found && found[1].includes("return")) {
3405
- found = null;
3406
- }
3407
- }
3408
- if (!found) {
3409
- return fnString;
3410
- } else {
3411
- return found[1];
3412
- }
3413
- }
3414
-
3415
- // src/runtime/index.ts
3416
- var runtime_exports = {};
3417
- __export(runtime_exports, {
3418
- FILESTORE_VERSION: () => FILESTORE_VERSION,
3419
- INDEXDB_VERSION: () => INDEXDB_VERSION,
3420
- files: () => files_exports,
3421
- getFileName: () => getFileName,
3422
- getFileSystem: () => getFileSystem,
3423
- getPath: () => getPath,
3424
- kb: () => key_bag_exports,
3425
- kc: () => keyed_crypto_exports,
3426
- mf: () => wait_pr_multiformats_exports,
3427
- runtimeFn: () => runtimeFn2,
3428
- toArrayBuffer: () => toArrayBuffer
3429
- });
3430
-
3431
- // src/runtime/wait-pr-multiformats/index.ts
3432
- var wait_pr_multiformats_exports = {};
3433
- __export(wait_pr_multiformats_exports, {
3434
- block: () => block_exports,
3435
- codec: () => codec_interface_exports
3436
- });
3437
-
3438
- // src/runtime/wait-pr-multiformats/codec-interface.ts
3439
- var codec_interface_exports = {};
3440
-
3441
- // src/runtime/index.ts
3442
- import { runtimeFn as runtimeFn2 } from "@adviser/cement";
3443
-
3444
- // src/runtime/gateways/file/version.ts
3445
- var FILESTORE_VERSION = "v0.19-file";
3446
-
3447
- // src/version.ts
3448
- var PACKAGE_VERSION = Object.keys({
3449
- "0.19.112-dev-web": "xxxx"
3450
- })[0];
3451
- export {
3452
- CRDT,
3453
- Database,
3454
- Index,
3455
- NotFoundError,
3456
- PACKAGE_VERSION,
3457
- Result,
3458
- UInt8ArrayEqual,
3459
- blockstore_exports as blockstore,
3460
- blockstore_exports as bs,
3461
- dataDir,
3462
- ensureLogger,
3463
- ensureSuperLog,
3464
- ensureSuperThis,
3465
- exceptionWrapper,
3466
- falsyToUndef,
3467
- fireproof,
3468
- getKey,
3469
- getName,
3470
- getStore,
3471
- index,
3472
- isFalsy,
3473
- isNotFoundError,
3474
- runtime_exports as rt,
3475
- runtime_exports as runtime,
3476
- throwFalsy
3477
- };
3478
- //# sourceMappingURL=index.js.map