@fireproof/core 0.19.9-dev-frag → 0.19.11-dev-dryrun2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +27 -0
  2. package/{chunk-YS4GL6OK.js → chunk-OFGPKRCM.js} +30 -6
  3. package/chunk-OFGPKRCM.js.map +1 -0
  4. package/{chunk-JO5AVWG7.js → chunk-WS3YRPIA.js} +14 -6
  5. package/chunk-WS3YRPIA.js.map +1 -0
  6. package/deno.json +20 -0
  7. package/{gateway-YSNUK2L3.js → gateway-5FCWPX5W.js} +4 -5
  8. package/{gateway-YSNUK2L3.js.map → gateway-5FCWPX5W.js.map} +1 -1
  9. package/{gateway-IZRHJWPE.js → gateway-H7UD6TNB.js} +3 -4
  10. package/gateway-H7UD6TNB.js.map +1 -0
  11. package/index.cjs +468 -338
  12. package/index.cjs.map +1 -1
  13. package/index.d.cts +80 -52
  14. package/index.d.ts +80 -52
  15. package/index.global.js +21378 -15079
  16. package/index.global.js.map +1 -1
  17. package/index.js +389 -293
  18. package/index.js.map +1 -1
  19. package/{key-bag-file-NMEBFSPM.js → key-bag-file-WADZBHYG.js} +3 -3
  20. package/{key-bag-indexdb-X5V6GNBZ.js → key-bag-indexdb-PGVAI3FJ.js} +3 -3
  21. package/key-bag-indexdb-PGVAI3FJ.js.map +1 -0
  22. package/{mem-filesystem-B6C6QOIP.js → mem-filesystem-YPPJV7Q2.js} +3 -3
  23. package/metafile-cjs.json +1 -1
  24. package/metafile-esm.json +1 -1
  25. package/metafile-iife.json +1 -1
  26. package/{node-filesystem-5JLBSHKQ.js → node-filesystem-INX4ZTHE.js} +8 -4
  27. package/node-filesystem-INX4ZTHE.js.map +1 -0
  28. package/package.json +8 -5
  29. package/tests/blockstore/keyed-crypto.test.ts +34 -4
  30. package/tests/blockstore/store.test.ts +18 -13
  31. package/tests/fireproof/all-gateway.test.ts +394 -0
  32. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.car +0 -0
  33. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.ts +316 -0
  34. package/tests/fireproof/fireproof.test.ts +18 -18
  35. package/tests/fireproof/hello.test.ts +33 -19
  36. package/tests/fireproof/utils.test.ts +19 -0
  37. package/tests/helpers.ts +7 -4
  38. package/tests/www/todo-local.html +1 -1
  39. package/tests/www/todo.html +12 -15
  40. package/{utils-IZPK4QS7.js → utils-QO2HIWGI.js} +3 -3
  41. package/chunk-JO5AVWG7.js.map +0 -1
  42. package/chunk-YS4GL6OK.js.map +0 -1
  43. package/gateway-IZRHJWPE.js.map +0 -1
  44. package/key-bag-indexdb-X5V6GNBZ.js.map +0 -1
  45. package/node-filesystem-5JLBSHKQ.js.map +0 -1
  46. /package/{key-bag-file-NMEBFSPM.js.map → key-bag-file-WADZBHYG.js.map} +0 -0
  47. /package/{mem-filesystem-B6C6QOIP.js.map → mem-filesystem-YPPJV7Q2.js.map} +0 -0
  48. /package/{utils-IZPK4QS7.js.map → utils-QO2HIWGI.js.map} +0 -0
package/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  getFileSystem,
7
7
  getPath,
8
8
  toArrayBuffer
9
- } from "./chunk-JO5AVWG7.js";
9
+ } from "./chunk-WS3YRPIA.js";
10
10
  import {
11
11
  INDEXDB_VERSION
12
12
  } from "./chunk-PB4BKL4O.js";
@@ -19,16 +19,15 @@ import {
19
19
  ensureLogger,
20
20
  ensureSuperLog,
21
21
  ensureSuperThis,
22
- exception2Result,
23
22
  exceptionWrapper,
24
23
  getKey,
25
24
  getName,
26
25
  getStore,
27
26
  isNotFoundError
28
- } from "./chunk-YS4GL6OK.js";
27
+ } from "./chunk-OFGPKRCM.js";
29
28
 
30
29
  // src/database.ts
31
- import { ResolveOnce as ResolveOnce5 } from "@adviser/cement";
30
+ import { ResolveOnce as ResolveOnce6 } from "@adviser/cement";
32
31
 
33
32
  // src/write-queue.ts
34
33
  function writeQueue(worker, payload = Infinity, unbounded = false) {
@@ -71,7 +70,7 @@ function writeQueue(worker, payload = Infinity, unbounded = false) {
71
70
  }
72
71
 
73
72
  // src/crdt.ts
74
- import { ResolveOnce as ResolveOnce4 } from "@adviser/cement";
73
+ import { ResolveOnce as ResolveOnce5 } from "@adviser/cement";
75
74
 
76
75
  // src/runtime/wait-pr-multiformats/block.ts
77
76
  var block_exports = {};
@@ -145,7 +144,7 @@ async function createUnsafe({
145
144
  }
146
145
 
147
146
  // src/crdt-helpers.ts
148
- import { parse as parse2 } from "multiformats/link";
147
+ import { parse as parse3 } from "multiformats/link";
149
148
  import { sha256 as hasher5 } from "multiformats/hashes/sha2";
150
149
  import * as codec from "@ipld/dag-cbor";
151
150
  import { put, get, entries, root } from "@web3-storage/pail/crdt";
@@ -162,10 +161,12 @@ __export(blockstore_exports, {
162
161
  EncryptedBlockstore: () => EncryptedBlockstore,
163
162
  FragmentGateway: () => FragmentGateway,
164
163
  Loader: () => Loader,
164
+ addCryptoKeyToGatewayMetaPayload: () => addCryptoKeyToGatewayMetaPayload,
165
165
  ensureStart: () => ensureStart,
166
166
  getGatewayFromURL: () => getGatewayFromURL,
167
167
  parseCarFile: () => parseCarFile,
168
168
  registerStoreProtocol: () => registerStoreProtocol,
169
+ setCryptoKeyFromGatewayMetaPayload: () => setCryptoKeyFromGatewayMetaPayload,
169
170
  testStoreFactory: () => testStoreFactory,
170
171
  toCIDBlock: () => toCIDBlock,
171
172
  toStoreRuntime: () => toStoreRuntime
@@ -177,7 +178,7 @@ function toCIDBlock(block) {
177
178
  }
178
179
 
179
180
  // src/blockstore/store-factory.ts
180
- import { KeyedResolvOnce as KeyedResolvOnce2, URI as URI3 } from "@adviser/cement";
181
+ import { KeyedResolvOnce as KeyedResolvOnce2, URI as URI5 } from "@adviser/cement";
181
182
 
182
183
  // src/runtime/files.ts
183
184
  var files_exports = {};
@@ -252,8 +253,8 @@ var UnixFSFileBuilder = class {
252
253
 
253
254
  // src/blockstore/store.ts
254
255
  import pLimit2 from "p-limit";
255
- import { format, parse } from "@ipld/dag-json";
256
- import { ResolveOnce as ResolveOnce2, Result as Result3 } from "@adviser/cement";
256
+ import { format as format2, parse as parse2 } from "@ipld/dag-json";
257
+ import { exception2Result, ResolveOnce as ResolveOnce3, Result as Result5 } from "@adviser/cement";
257
258
 
258
259
  // src/types.ts
259
260
  function isFalsy(value) {
@@ -275,7 +276,7 @@ function falsyToUndef(value) {
275
276
  // src/blockstore/loader.ts
276
277
  import pLimit from "p-limit";
277
278
  import { CarReader } from "@ipld/car";
278
- import { ResolveOnce } from "@adviser/cement";
279
+ import { ResolveOnce as ResolveOnce2 } from "@adviser/cement";
279
280
 
280
281
  // src/blockstore/loader-helpers.ts
281
282
  import { sha256 as hasher } from "multiformats/hashes/sha2";
@@ -547,6 +548,7 @@ __export(key_bag_exports, {
547
548
  });
548
549
  import {
549
550
  KeyedResolvOnce,
551
+ ResolveOnce,
550
552
  ResolveSeq,
551
553
  Result as Result2,
552
554
  runtimeFn,
@@ -557,21 +559,25 @@ import { base58btc } from "multiformats/bases/base58";
557
559
  var KeyBag = class {
558
560
  constructor(rt) {
559
561
  this.rt = rt;
562
+ this._warnOnce = new ResolveOnce();
560
563
  this._seq = new ResolveSeq();
561
- this.logger = ensureLogger(rt.sthis, "KeyBag", {
562
- id: rt.id()
563
- });
564
+ this.logger = ensureLogger(rt.sthis, "KeyBag");
564
565
  this.logger.Debug().Msg("KeyBag created");
565
566
  }
566
567
  async subtleKey(key) {
568
+ const extractable = this.rt.url.getParam("extractKey") === "_deprecated_internal_api";
569
+ if (extractable) {
570
+ this._warnOnce.once(
571
+ () => this.logger.Warn().Msg("extractKey is enabled via _deprecated_internal_api --- handle keys safely!!!")
572
+ );
573
+ }
567
574
  return await this.rt.crypto.importKey(
568
575
  "raw",
569
576
  // raw or jwk
570
577
  base58btc.decode(key),
571
578
  // hexStringToUint8Array(key), // raw data
572
579
  "AES-GCM",
573
- false,
574
- // extractable
580
+ extractable,
575
581
  ["encrypt", "decrypt"]
576
582
  );
577
583
  }
@@ -620,6 +626,23 @@ var KeyBag = class {
620
626
  await bag.set(name, item);
621
627
  return await this.toKeyWithFingerPrint(item.key);
622
628
  }
629
+ async getNamedExtractableKey(name, failIfNotFound = false) {
630
+ const ret = await this.getNamedKey(name, failIfNotFound);
631
+ if (ret.isErr()) {
632
+ return ret;
633
+ }
634
+ const named = ret.Ok();
635
+ return Result2.Ok({
636
+ ...named,
637
+ extract: async () => {
638
+ const ext = new Uint8Array(await this.rt.crypto.exportKey("raw", named.key));
639
+ return {
640
+ key: ext,
641
+ keyStr: base58btc.encode(ext)
642
+ };
643
+ }
644
+ });
645
+ }
623
646
  async getNamedKey(name, failIfNotFound = false) {
624
647
  const id = this.rt.sthis.nextId(4).str;
625
648
  return this._seq.add(async () => {
@@ -645,14 +668,14 @@ var keyBagProviderFactories = new Map(
645
668
  {
646
669
  protocol: "file:",
647
670
  factory: async (url, sthis) => {
648
- const { KeyBagProviderFile } = await import("./key-bag-file-NMEBFSPM.js");
671
+ const { KeyBagProviderFile } = await import("./key-bag-file-WADZBHYG.js");
649
672
  return new KeyBagProviderFile(url, sthis);
650
673
  }
651
674
  },
652
675
  {
653
676
  protocol: "indexdb:",
654
677
  factory: async (url, sthis) => {
655
- const { KeyBagProviderIndexDB } = await import("./key-bag-indexdb-X5V6GNBZ.js");
678
+ const { KeyBagProviderIndexDB } = await import("./key-bag-indexdb-PGVAI3FJ.js");
656
679
  return new KeyBagProviderIndexDB(url, sthis);
657
680
  }
658
681
  }
@@ -689,23 +712,11 @@ function defaultKeyBagOpts(sthis, kbo) {
689
712
  }
690
713
  logger.Debug().Url(url).Msg("from env");
691
714
  }
692
- let keyProviderFactory;
693
- switch (url.protocol) {
694
- case "file:":
695
- keyProviderFactory = async () => {
696
- const { KeyBagProviderFile } = await import("./key-bag-file-NMEBFSPM.js");
697
- return new KeyBagProviderFile(url, sthis);
698
- };
699
- break;
700
- case "indexdb:":
701
- keyProviderFactory = async () => {
702
- const { KeyBagProviderIndexDB } = await import("./key-bag-indexdb-X5V6GNBZ.js");
703
- return new KeyBagProviderIndexDB(url, sthis);
704
- };
705
- break;
706
- default:
707
- throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
715
+ const kitem = keyBagProviderFactories.get(url.protocol);
716
+ if (!kitem) {
717
+ throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
708
718
  }
719
+ const getBag = async () => kitem.factory(url, sthis);
709
720
  if (url.hasParam("masterkey")) {
710
721
  throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
711
722
  }
@@ -715,7 +726,7 @@ function defaultKeyBagOpts(sthis, kbo) {
715
726
  sthis,
716
727
  logger,
717
728
  keyLength: kbo.keyLength || 16,
718
- getBag: keyProviderFactory,
729
+ getBag,
719
730
  id: () => {
720
731
  return url.toString();
721
732
  }
@@ -809,7 +820,7 @@ async function commit(params, t, done, opts = { noLoader: false, compact: false
809
820
  }
810
821
  async function prepareCarFiles(encoder, threshold, rootBlock, t) {
811
822
  const carFiles = [];
812
- threshold = threshold || 1e3 * 1e3;
823
+ threshold = threshold || 128e3 * 8;
813
824
  let clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
814
825
  clonedt.putSync(rootBlock.cid, rootBlock.bytes);
815
826
  let newsize = CBW.blockLength(toCIDBlock(rootBlock));
@@ -832,6 +843,53 @@ async function prepareCarFiles(encoder, threshold, rootBlock, t) {
832
843
 
833
844
  // src/blockstore/loader.ts
834
845
  import { sha256 as hasher3 } from "multiformats/hashes/sha2";
846
+
847
+ // src/blockstore/task-manager.ts
848
+ var TaskManager = class {
849
+ constructor(sthis, callback) {
850
+ this.eventsWeHandled = /* @__PURE__ */ new Set();
851
+ this.queue = [];
852
+ this.isProcessing = false;
853
+ this.logger = ensureLogger(sthis, "TaskManager");
854
+ this.callback = callback;
855
+ }
856
+ async handleEvent(cid, parents, dbMeta) {
857
+ for (const parent of parents) {
858
+ this.eventsWeHandled.add(parent.toString());
859
+ }
860
+ this.queue.push({ cid: cid.toString(), dbMeta, retries: 0 });
861
+ this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
862
+ void this.processQueue();
863
+ }
864
+ async processQueue() {
865
+ if (this.isProcessing) return;
866
+ this.isProcessing = true;
867
+ const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
868
+ const first = filteredQueue[0];
869
+ if (!first) {
870
+ return;
871
+ }
872
+ try {
873
+ await this.callback(first.dbMeta);
874
+ this.eventsWeHandled.add(first.cid);
875
+ this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
876
+ } catch (err) {
877
+ if (first.retries++ > 3) {
878
+ this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
879
+ this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
880
+ }
881
+ await new Promise((resolve) => setTimeout(resolve, 50));
882
+ throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
883
+ } finally {
884
+ this.isProcessing = false;
885
+ if (this.queue.length > 0) {
886
+ void this.processQueue();
887
+ }
888
+ }
889
+ }
890
+ };
891
+
892
+ // src/blockstore/loader.ts
835
893
  function carLogIncludesGroup(list, cids) {
836
894
  return list.some((arr) => {
837
895
  return arr.toString() === cids.toString();
@@ -856,7 +914,7 @@ var Loader = class {
856
914
  this.getBlockCache = /* @__PURE__ */ new Map();
857
915
  this.seenMeta = /* @__PURE__ */ new Set();
858
916
  this.writeLimit = pLimit(1);
859
- this.onceReady = new ResolveOnce();
917
+ this.onceReady = new ResolveOnce2();
860
918
  this.name = name;
861
919
  this.sthis = sthis;
862
920
  this.ebOpts = defaultedBlockstoreRuntime(
@@ -868,6 +926,9 @@ var Loader = class {
868
926
  "Loader"
869
927
  );
870
928
  this.logger = this.ebOpts.logger;
929
+ this.taskManager = new TaskManager(sthis, async (dbMeta) => {
930
+ await this.handleDbMetasFromStore([dbMeta]);
931
+ });
871
932
  }
872
933
  // readonly id = uuidv4();
873
934
  async keyBag() {
@@ -887,8 +948,10 @@ var Loader = class {
887
948
  }
888
949
  async ready() {
889
950
  return this.onceReady.once(async () => {
890
- const metas = this.ebOpts.meta ? [this.ebOpts.meta] : await (await this.metaStore()).load("main");
891
- if (metas) {
951
+ const metas = await (await this.metaStore()).load();
952
+ if (this.ebOpts.meta) {
953
+ await this.handleDbMetasFromStore([this.ebOpts.meta]);
954
+ } else if (metas) {
892
955
  await this.handleDbMetasFromStore(metas);
893
956
  }
894
957
  });
@@ -969,7 +1032,8 @@ var Loader = class {
969
1032
  carLog: this.carLog,
970
1033
  carStore: fstore,
971
1034
  WALStore: await this.WALStore(),
972
- metaStore: await this.metaStore()
1035
+ metaStore: await this.metaStore(),
1036
+ threshold: this.ebOpts.threshold
973
1037
  };
974
1038
  return this.commitQueue.enqueue(async () => {
975
1039
  await this.cacheTransaction(t);
@@ -1193,7 +1257,7 @@ var generateIV = {
1193
1257
  calc: async (ko, crypto, data) => {
1194
1258
  const hash = await hasher4.digest(data);
1195
1259
  const hashBytes = new Uint8Array(hash.bytes);
1196
- const hashArray = new Uint8Array(ko.ivLength * 8);
1260
+ const hashArray = new Uint8Array(ko.ivLength);
1197
1261
  for (let i = 0; i < hashBytes.length; i++) {
1198
1262
  hashArray[i % ko.ivLength] ^= hashBytes[i];
1199
1263
  }
@@ -1271,7 +1335,7 @@ var keyedCrypto = class {
1271
1335
  };
1272
1336
  }
1273
1337
  async _decrypt(data) {
1274
- this.logger.Debug().Len(data.bytes).Str("fp", this.key.fingerPrint).Msg("decrypting");
1338
+ this.logger.Debug().Len(data.bytes, "bytes").Len(data.iv, "iv").Str("fp", this.key.fingerPrint).Msg("decrypting");
1275
1339
  return new Uint8Array(await this.crypto.decrypt(this.algo(data.iv), this.key.key, data.bytes));
1276
1340
  }
1277
1341
  async _encrypt(data) {
@@ -1342,6 +1406,7 @@ async function keyedCryptoFactory(url, kb, sthis) {
1342
1406
  }
1343
1407
 
1344
1408
  // src/blockstore/fragment-gateway.ts
1409
+ import { Result as Result3 } from "@adviser/cement";
1345
1410
  import { base58btc as base58btc3 } from "multiformats/bases/base58";
1346
1411
  import { encode as encode3, decode as decode3 } from "cborg";
1347
1412
  function getFragSize(url) {
@@ -1364,7 +1429,7 @@ async function getFrags(url, innerGW, headerSize, logger) {
1364
1429
  }
1365
1430
  const data = res.unwrap();
1366
1431
  return [
1367
- Result.Ok({
1432
+ Result3.Ok({
1368
1433
  fid: new Uint8Array(0),
1369
1434
  ofs: 0,
1370
1435
  len: data.length,
@@ -1378,7 +1443,7 @@ async function getFrags(url, innerGW, headerSize, logger) {
1378
1443
  }
1379
1444
  const firstFragment = decode3(firstRaw.unwrap());
1380
1445
  const blockSize = firstFragment.data.length;
1381
- const ops = [Promise.resolve(Result.Ok(firstFragment))];
1446
+ const ops = [Promise.resolve(Result3.Ok(firstFragment))];
1382
1447
  const fidStr = base58btc3.encode(firstFragment.fid);
1383
1448
  const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
1384
1449
  for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
@@ -1390,12 +1455,12 @@ async function getFrags(url, innerGW, headerSize, logger) {
1390
1455
  }
1391
1456
  const fragment = decode3(raw2.unwrap());
1392
1457
  if (base58btc3.encode(fragment.fid) !== fidStr) {
1393
- return Result.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
1458
+ return Result3.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
1394
1459
  }
1395
1460
  if (fragment.ofs !== ofs2) {
1396
- return Result.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
1461
+ return Result3.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
1397
1462
  }
1398
- return Result.Ok(fragment);
1463
+ return Result3.Ok(fragment);
1399
1464
  })(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
1400
1465
  );
1401
1466
  }
@@ -1457,42 +1522,156 @@ var FragmentGateway = class {
1457
1522
  }
1458
1523
  async put(url, body) {
1459
1524
  await Promise.all(this.slicer(url, body));
1460
- return Result.Ok(void 0);
1525
+ return Result3.Ok(void 0);
1461
1526
  }
1462
1527
  async get(url) {
1463
1528
  const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
1464
1529
  let buffer = void 0;
1465
1530
  for (const rfrag of rfrags) {
1466
1531
  if (rfrag.isErr()) {
1467
- return Result.Err(rfrag.Err());
1532
+ return Result3.Err(rfrag.Err());
1468
1533
  }
1469
1534
  const frag = rfrag.Ok();
1470
1535
  buffer = buffer || new Uint8Array(frag.len);
1471
1536
  buffer.set(frag.data, frag.ofs);
1472
1537
  }
1473
- return Result.Ok(buffer || new Uint8Array(0));
1538
+ return Result3.Ok(buffer || new Uint8Array(0));
1539
+ }
1540
+ async subscribe(url, callback) {
1541
+ if (this.innerGW.subscribe) {
1542
+ return this.innerGW.subscribe(url, callback);
1543
+ } else {
1544
+ return Result3.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
1545
+ }
1474
1546
  }
1475
1547
  async delete(url) {
1476
1548
  const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
1477
1549
  for (const rfrag of rfrags) {
1478
1550
  if (rfrag.isErr()) {
1479
- return Result.Err(rfrag.Err());
1551
+ return Result3.Err(rfrag.Err());
1480
1552
  }
1481
1553
  const frag = rfrag.Ok();
1482
1554
  const fidStr = base58btc3.encode(frag.fid);
1483
1555
  const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
1484
1556
  await this.innerGW.delete(fragUrl);
1485
1557
  }
1486
- return Result.Ok(void 0);
1558
+ return Result3.Ok(void 0);
1487
1559
  }
1488
1560
  };
1489
1561
 
1562
+ // src/blockstore/meta-key-helper.ts
1563
+ import { format, parse } from "@ipld/dag-json";
1564
+ import { EventBlock, decodeEventBlock } from "@web3-storage/pail/clock";
1565
+ import { CID as CID2 } from "multiformats";
1566
+ import { base64pad } from "multiformats/bases/base64";
1567
+ import { Result as Result4 } from "@adviser/cement";
1568
+ async function decodeGatewayMetaBytesToDbMeta(sthis, byteHeads) {
1569
+ const crdtEntries = JSON.parse(sthis.txt.decode(byteHeads));
1570
+ if (!crdtEntries.length) {
1571
+ sthis.logger.Debug().Str("byteHeads", new TextDecoder().decode(byteHeads)).Msg("No CRDT entries found");
1572
+ return [];
1573
+ }
1574
+ if (!crdtEntries.map) {
1575
+ sthis.logger.Debug().Str("crdtEntries", JSON.stringify(crdtEntries)).Msg("No data in CRDT entries");
1576
+ return [];
1577
+ }
1578
+ return Promise.all(
1579
+ crdtEntries.map(async (crdtEntry) => {
1580
+ const eventBlock = await decodeEventBlock(base64pad.decode(crdtEntry.data));
1581
+ const dbMeta = parse(sthis.txt.decode(eventBlock.value.data.dbMeta));
1582
+ return {
1583
+ eventCid: eventBlock.cid,
1584
+ parents: crdtEntry.parents,
1585
+ dbMeta
1586
+ };
1587
+ })
1588
+ );
1589
+ }
1590
+ async function setCryptoKeyFromGatewayMetaPayload(uri, sthis, data) {
1591
+ try {
1592
+ sthis.logger.Debug().Str("uri", uri.toString()).Msg("Setting crypto key from gateway meta payload");
1593
+ const keyInfo = await decodeGatewayMetaBytesToDbMeta(sthis, data);
1594
+ if (keyInfo.length) {
1595
+ const dbMeta = keyInfo[0].dbMeta;
1596
+ if (dbMeta.key) {
1597
+ const kb = await getKeyBag(sthis);
1598
+ const keyName = getStoreKeyName(uri);
1599
+ const res = await kb.setNamedKey(keyName, dbMeta.key);
1600
+ if (res.isErr()) {
1601
+ sthis.logger.Debug().Str("keyName", keyName).Str("dbMeta.key", dbMeta.key).Msg("Failed to set named key");
1602
+ throw res.Err();
1603
+ }
1604
+ }
1605
+ sthis.logger.Debug().Str("dbMeta.key", dbMeta.key).Str("uri", uri.toString()).Msg("Set crypto key from gateway meta payload");
1606
+ return Result4.Ok(dbMeta);
1607
+ }
1608
+ sthis.logger.Debug().Str("data", new TextDecoder().decode(data)).Msg("No crypto in gateway meta payload");
1609
+ return Result4.Ok(void 0);
1610
+ } catch (error) {
1611
+ sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
1612
+ return Result4.Err(error);
1613
+ }
1614
+ }
1615
+ async function addCryptoKeyToGatewayMetaPayload(uri, sthis, body) {
1616
+ try {
1617
+ sthis.logger.Debug().Str("uri", uri.toString()).Msg("Adding crypto key to gateway meta payload");
1618
+ const keyName = getStoreKeyName(uri);
1619
+ const kb = await getKeyBag(sthis);
1620
+ const res = await kb.getNamedExtractableKey(keyName, true);
1621
+ if (res.isErr()) {
1622
+ sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
1623
+ throw res.Err();
1624
+ }
1625
+ const keyData = await res.Ok().extract();
1626
+ const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
1627
+ const { dbMeta, parents } = dbMetas[0];
1628
+ const parentLinks = parents.map((p) => CID2.parse(p));
1629
+ dbMeta.key = keyData.keyStr;
1630
+ const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
1631
+ const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
1632
+ sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
1633
+ return Result4.Ok(encoded);
1634
+ } catch (error) {
1635
+ sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
1636
+ return Result4.Err(error);
1637
+ }
1638
+ }
1639
+ function getStoreKeyName(url) {
1640
+ const storeKeyName = [url.getParam("localName") || url.getParam("name")];
1641
+ const idx = url.getParam("index");
1642
+ if (idx) {
1643
+ storeKeyName.push(idx);
1644
+ }
1645
+ storeKeyName.push("data");
1646
+ return `@${storeKeyName.join(":")}@`;
1647
+ }
1648
+ async function createDbMetaEventBlock(sthis, dbMeta, parents) {
1649
+ const event = await EventBlock.create(
1650
+ {
1651
+ dbMeta: sthis.txt.encode(format(dbMeta))
1652
+ },
1653
+ parents
1654
+ );
1655
+ return event;
1656
+ }
1657
+ async function encodeEventsWithParents(sthis, events, parents) {
1658
+ const crdtEntries = events.map((event) => {
1659
+ const base64String = base64pad.encode(event.bytes);
1660
+ return {
1661
+ cid: event.cid.toString(),
1662
+ data: base64String,
1663
+ parents: parents.map((p) => p.toString())
1664
+ };
1665
+ });
1666
+ return sthis.txt.encode(JSON.stringify(crdtEntries));
1667
+ }
1668
+
1490
1669
  // src/blockstore/store.ts
1491
1670
  function guardVersion(url) {
1492
1671
  if (!url.hasParam("version")) {
1493
- return Result3.Err(`missing version: ${url.toString()}`);
1672
+ return Result5.Err(`missing version: ${url.toString()}`);
1494
1673
  }
1495
- return Result3.Ok(url);
1674
+ return Result5.Ok(url);
1496
1675
  }
1497
1676
  var BaseStoreImpl = class {
1498
1677
  constructor(name, url, opts, sthis, logger) {
@@ -1504,6 +1683,7 @@ var BaseStoreImpl = class {
1504
1683
  this.sthis = sthis;
1505
1684
  this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
1506
1685
  this.gateway = new FragmentGateway(this.sthis, opts.gateway);
1686
+ this.loader = opts.loader;
1507
1687
  }
1508
1688
  url() {
1509
1689
  return this._url;
@@ -1514,6 +1694,9 @@ var BaseStoreImpl = class {
1514
1694
  onClosed(fn) {
1515
1695
  this._onClosed.push(fn);
1516
1696
  }
1697
+ async ready() {
1698
+ return;
1699
+ }
1517
1700
  async keyedCrypto() {
1518
1701
  return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
1519
1702
  }
@@ -1560,67 +1743,44 @@ var BaseStoreImpl = class {
1560
1743
  }
1561
1744
  };
1562
1745
  var MetaStoreImpl = class extends BaseStoreImpl {
1746
+ // remote: boolean;
1563
1747
  constructor(sthis, name, url, opts) {
1564
- super(
1565
- name,
1566
- url,
1567
- {
1568
- ...opts
1569
- },
1570
- sthis,
1571
- ensureLogger(sthis, "MetaStoreImpl")
1572
- );
1748
+ super(name, url, { ...opts }, sthis, ensureLogger(sthis, "MetaStoreImpl"));
1573
1749
  this.storeType = "meta";
1574
1750
  this.subscribers = /* @__PURE__ */ new Map();
1575
- }
1576
- onLoad(branch, loadHandler) {
1577
- const subscribers = this.subscribers.get(branch) || [];
1578
- subscribers.push(loadHandler);
1579
- this.subscribers.set(branch, subscribers);
1580
- return () => {
1581
- const subscribers2 = this.subscribers.get(branch) || [];
1582
- const idx = subscribers2.indexOf(loadHandler);
1583
- if (idx > -1) subscribers2.splice(idx, 1);
1584
- };
1585
- }
1586
- makeHeader({ cars }) {
1587
- const toEncode = { cars };
1588
- return format(toEncode);
1589
- }
1590
- parseHeader(headerData) {
1591
- const got = parse(headerData);
1592
- return got;
1593
- }
1594
- async handleSubscribers(dbMetas, branch) {
1595
- try {
1596
- const subscribers = this.subscribers.get(branch) || [];
1597
- await Promise.all(subscribers.map((subscriber) => subscriber(dbMetas)));
1598
- } catch (e) {
1599
- this.logger.Error().Err(e).Msg("handleSubscribers").AsError();
1751
+ this.parents = [];
1752
+ if (
1753
+ /*this.remote && */
1754
+ opts.gateway.subscribe
1755
+ ) {
1756
+ this.onStarted(async () => {
1757
+ this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
1758
+ opts.gateway.subscribe?.(this.url(), async (message) => {
1759
+ this.logger.Debug().Msg("Received message from gateway");
1760
+ const dbMetas = await decodeGatewayMetaBytesToDbMeta(this.sthis, message);
1761
+ await Promise.all(
1762
+ dbMetas.map((dbMeta) => this.loader?.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
1763
+ );
1764
+ this.updateParentsFromDbMetas(dbMetas);
1765
+ });
1766
+ });
1600
1767
  }
1601
1768
  }
1602
- async handleByteHeads(byteHeads, branch = "main") {
1603
- let dbMetas;
1604
- try {
1605
- dbMetas = this.dbMetasForByteHeads(byteHeads);
1606
- } catch (e) {
1607
- throw this.logger.Error().Err(e).Msg("parseHeader").AsError();
1608
- }
1609
- await this.handleSubscribers(dbMetas, branch);
1610
- return dbMetas;
1769
+ updateParentsFromDbMetas(dbMetas) {
1770
+ const cids = dbMetas.map((m) => m.eventCid);
1771
+ const dbMetaParents = dbMetas.flatMap((m) => m.parents);
1772
+ const uniqueParentsMap = new Map([...this.parents, ...cids].map((p) => [p.toString(), p]));
1773
+ const dbMetaParentsSet = new Set(dbMetaParents.map((p) => p.toString()));
1774
+ this.parents = Array.from(uniqueParentsMap.values()).filter((p) => !dbMetaParentsSet.has(p.toString()));
1611
1775
  }
1612
- dbMetasForByteHeads(byteHeads) {
1613
- return byteHeads.map((bytes) => {
1614
- const txt = this.sthis.txt.decode(bytes);
1615
- return this.parseHeader(txt);
1616
- });
1776
+ async handleByteHeads(byteHeads) {
1777
+ return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
1617
1778
  }
1618
- async load(branch) {
1619
- branch = branch || "main";
1620
- this.logger.Debug().Str("branch", branch).Msg("loading");
1779
+ async load() {
1780
+ const branch = "main";
1621
1781
  const url = await this.gateway.buildUrl(this.url(), branch);
1622
1782
  if (url.isErr()) {
1623
- throw this.logger.Error().Result("buidUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
1783
+ throw this.logger.Error().Result("buildUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
1624
1784
  }
1625
1785
  const bytes = await this.gateway.get(url.Ok());
1626
1786
  if (bytes.isErr()) {
@@ -1629,27 +1789,31 @@ var MetaStoreImpl = class extends BaseStoreImpl {
1629
1789
  }
1630
1790
  throw this.logger.Error().Url(url.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
1631
1791
  }
1632
- return this.handleByteHeads([bytes.Ok()], branch);
1792
+ const dbMetas = await this.handleByteHeads(bytes.Ok());
1793
+ await this.loader?.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
1794
+ this.updateParentsFromDbMetas(dbMetas);
1795
+ return dbMetas.map((m) => m.dbMeta);
1633
1796
  }
1634
1797
  async save(meta, branch) {
1635
1798
  branch = branch || "main";
1636
1799
  this.logger.Debug().Str("branch", branch).Any("meta", meta).Msg("saving meta");
1637
- const bytes = this.makeHeader(meta);
1800
+ const event = await createDbMetaEventBlock(this.sthis, meta, this.parents);
1801
+ const bytes = await encodeEventsWithParents(this.sthis, [event], this.parents);
1638
1802
  const url = await this.gateway.buildUrl(this.url(), branch);
1639
1803
  if (url.isErr()) {
1640
1804
  throw this.logger.Error().Err(url.Err()).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
1641
1805
  }
1642
- const res = await this.gateway.put(url.Ok(), this.sthis.txt.encode(bytes));
1806
+ this.parents = [event.cid];
1807
+ const res = await this.gateway.put(url.Ok(), bytes);
1643
1808
  if (res.isErr()) {
1644
1809
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
1645
1810
  }
1646
- await this.handleSubscribers([meta], branch);
1647
1811
  return res;
1648
1812
  }
1649
1813
  async close() {
1650
1814
  await this.gateway.close(this.url());
1651
1815
  this._onClosed.forEach((fn) => fn());
1652
- return Result3.Ok(void 0);
1816
+ return Result5.Ok(void 0);
1653
1817
  }
1654
1818
  async destroy() {
1655
1819
  return this.gateway.destroy(this.url());
@@ -1658,15 +1822,7 @@ var MetaStoreImpl = class extends BaseStoreImpl {
1658
1822
  var DataStoreImpl = class extends BaseStoreImpl {
1659
1823
  // readonly tag: string = "car-base";
1660
1824
  constructor(sthis, name, url, opts) {
1661
- super(
1662
- name,
1663
- url,
1664
- {
1665
- ...opts
1666
- },
1667
- sthis,
1668
- ensureLogger(sthis, "DataStoreImpl")
1669
- );
1825
+ super(name, url, { ...opts }, sthis, ensureLogger(sthis, "DataStoreImpl"));
1670
1826
  this.storeType = "data";
1671
1827
  }
1672
1828
  async load(cid) {
@@ -1704,7 +1860,7 @@ var DataStoreImpl = class extends BaseStoreImpl {
1704
1860
  async close() {
1705
1861
  await this.gateway.close(this.url());
1706
1862
  this._onClosed.forEach((fn) => fn());
1707
- return Result3.Ok(void 0);
1863
+ return Result5.Ok(void 0);
1708
1864
  }
1709
1865
  destroy() {
1710
1866
  return this.gateway.destroy(this.url());
@@ -1712,46 +1868,43 @@ var DataStoreImpl = class extends BaseStoreImpl {
1712
1868
  };
1713
1869
  var WALStoreImpl = class extends BaseStoreImpl {
1714
1870
  constructor(loader, url, opts) {
1715
- super(
1716
- loader.name,
1717
- url,
1718
- {
1719
- ...opts
1720
- },
1721
- loader.sthis,
1722
- ensureLogger(loader.sthis, "WALStoreImpl")
1723
- );
1871
+ super(loader.name, url, { ...opts }, loader.sthis, ensureLogger(loader.sthis, "WALStoreImpl"));
1724
1872
  this.storeType = "wal";
1725
- this._ready = new ResolveOnce2();
1873
+ this._ready = new ResolveOnce3();
1726
1874
  this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
1727
1875
  this.processing = void 0;
1728
1876
  this.processQueue = new CommitQueue();
1729
- this.ready = async () => {
1730
- return this._ready.once(async () => {
1731
- const walState = await this.load().catch((e) => {
1732
- this.logger.Error().Any("error", e).Msg("error loading wal");
1733
- return void 0;
1734
- });
1735
- if (!walState) {
1736
- this.walState.operations = [];
1737
- this.walState.fileOperations = [];
1738
- } else {
1739
- this.walState.operations = walState.operations || [];
1740
- this.walState.fileOperations = walState.fileOperations || [];
1741
- }
1742
- });
1743
- };
1744
1877
  this.loader = loader;
1745
1878
  }
1879
+ async ready() {
1880
+ return this._ready.once(async () => {
1881
+ const walState = await this.load().catch((e) => {
1882
+ this.logger.Error().Any("error", e).Msg("error loading wal");
1883
+ return void 0;
1884
+ });
1885
+ if (!walState) {
1886
+ this.walState.operations = [];
1887
+ this.walState.fileOperations = [];
1888
+ } else {
1889
+ this.walState.operations = walState.operations || [];
1890
+ this.walState.fileOperations = walState.fileOperations || [];
1891
+ }
1892
+ });
1893
+ }
1746
1894
  async enqueue(dbMeta, opts) {
1747
1895
  await this.ready();
1748
- if (opts.noLoader) {
1896
+ if (opts.compact) {
1897
+ this.walState.operations = [];
1898
+ this.walState.noLoaderOps = [dbMeta];
1899
+ } else if (opts.noLoader) {
1749
1900
  this.walState.noLoaderOps.push(dbMeta);
1750
1901
  } else {
1751
1902
  this.walState.operations.push(dbMeta);
1752
1903
  }
1753
1904
  await this.save(this.walState);
1754
- void this.process();
1905
+ if (!opts.noLoader) {
1906
+ void this.process();
1907
+ }
1755
1908
  }
1756
1909
  async enqueueFile(fileCid, publicFile = false) {
1757
1910
  await this.ready();
@@ -1778,7 +1931,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
1778
1931
  const fileOperations = [...this.walState.fileOperations];
1779
1932
  const uploads = [];
1780
1933
  const noLoaderOps = [...this.walState.noLoaderOps];
1781
- const limit = pLimit2(5);
1934
+ const limit = pLimit2(3);
1782
1935
  if (operations.length + fileOperations.length + noLoaderOps.length === 0) return;
1783
1936
  for (const dbMeta of noLoaderOps) {
1784
1937
  const uploadP = limit(async () => {
@@ -1854,7 +2007,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
1854
2007
  throw this.logger.Error().Err(bytes.Err()).Msg("error get").AsError();
1855
2008
  }
1856
2009
  try {
1857
- return bytes && parse(this.sthis.txt.decode(bytes.Ok()));
2010
+ return bytes && parse2(this.sthis.txt.decode(bytes.Ok()));
1858
2011
  } catch (e) {
1859
2012
  throw this.logger.Error().Err(e).Msg("error parse").AsError();
1860
2013
  }
@@ -1866,7 +2019,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
1866
2019
  }
1867
2020
  let encoded;
1868
2021
  try {
1869
- encoded = format(state);
2022
+ encoded = format2(state);
1870
2023
  } catch (e) {
1871
2024
  throw this.logger.Error().Err(e).Any("state", state).Msg("error format").AsError();
1872
2025
  }
@@ -1878,7 +2031,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
1878
2031
  async close() {
1879
2032
  await this.gateway.close(this.url());
1880
2033
  this._onClosed.forEach((fn) => fn());
1881
- return Result3.Ok(void 0);
2034
+ return Result5.Ok(void 0);
1882
2035
  }
1883
2036
  destroy() {
1884
2037
  return this.gateway.destroy(this.url());
@@ -1904,10 +2057,10 @@ function buildURL(optURL, loader) {
1904
2057
  const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
1905
2058
  let obuUrl;
1906
2059
  if (obuItem && obuItem.overrideBaseURL) {
1907
- obuUrl = URI3.from(obuItem.overrideBaseURL);
2060
+ obuUrl = URI5.from(obuItem.overrideBaseURL);
1908
2061
  }
1909
2062
  const ret = ensureIsIndex(
1910
- URI3.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
2063
+ URI5.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
1911
2064
  storeOpts.isIndex
1912
2065
  );
1913
2066
  return ret;
@@ -1954,52 +2107,61 @@ function registerStoreProtocol(item) {
1954
2107
  storeFactory.delete(protocol);
1955
2108
  };
1956
2109
  }
2110
+ var onceDataStoreFactory = new KeyedResolvOnce2();
1957
2111
  async function dataStoreFactory(loader) {
1958
2112
  const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
1959
2113
  const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
1960
- const gateway = await getGatewayFromURL(url, sthis);
1961
- if (!gateway) {
1962
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
1963
- }
1964
- const store = new DataStoreImpl(sthis, loader.name, url, {
1965
- gateway: gateway.gateway,
1966
- keybag: () => getKeyBag(loader.sthis, {
1967
- ...loader.ebOpts.keyBag
1968
- })
2114
+ return onceDataStoreFactory.get(url.toString()).once(async () => {
2115
+ const gateway = await getGatewayFromURL(url, sthis);
2116
+ if (!gateway) {
2117
+ throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2118
+ }
2119
+ const store = new DataStoreImpl(sthis, loader.name, url, {
2120
+ gateway: gateway.gateway,
2121
+ keybag: () => getKeyBag(loader.sthis, {
2122
+ ...loader.ebOpts.keyBag
2123
+ })
2124
+ });
2125
+ return store;
1969
2126
  });
1970
- return store;
1971
2127
  }
2128
+ var onceMetaStoreFactory = new KeyedResolvOnce2();
1972
2129
  async function metaStoreFactory(loader) {
1973
2130
  const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
1974
2131
  const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
1975
- sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
1976
- const gateway = await getGatewayFromURL(url, sthis);
1977
- if (!gateway) {
1978
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
1979
- }
1980
- const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
1981
- gateway: gateway.gateway,
1982
- keybag: () => getKeyBag(loader.sthis, {
1983
- ...loader.ebOpts.keyBag
1984
- })
2132
+ return onceMetaStoreFactory.get(url.toString()).once(async () => {
2133
+ sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
2134
+ const gateway = await getGatewayFromURL(url, sthis);
2135
+ if (!gateway) {
2136
+ throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2137
+ }
2138
+ const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
2139
+ gateway: gateway.gateway,
2140
+ keybag: () => getKeyBag(loader.sthis, {
2141
+ ...loader.ebOpts.keyBag
2142
+ })
2143
+ });
2144
+ return store;
1985
2145
  });
1986
- return store;
1987
2146
  }
2147
+ var onceRemoteWalFactory = new KeyedResolvOnce2();
1988
2148
  async function remoteWalFactory(loader) {
1989
2149
  const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
1990
2150
  const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
1991
- const gateway = await getGatewayFromURL(url, sthis);
1992
- if (!gateway) {
1993
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
1994
- }
1995
- sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
1996
- const store = new WALStoreImpl(loader, url, {
1997
- gateway: gateway.gateway,
1998
- keybag: () => getKeyBag(loader.sthis, {
1999
- ...loader.ebOpts.keyBag
2000
- })
2151
+ return onceRemoteWalFactory.get(url.toString()).once(async () => {
2152
+ const gateway = await getGatewayFromURL(url, sthis);
2153
+ if (!gateway) {
2154
+ throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2155
+ }
2156
+ sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
2157
+ const store = new WALStoreImpl(loader, url, {
2158
+ gateway: gateway.gateway,
2159
+ keybag: () => getKeyBag(loader.sthis, {
2160
+ ...loader.ebOpts.keyBag
2161
+ })
2162
+ });
2163
+ return store;
2001
2164
  });
2002
- return store;
2003
2165
  }
2004
2166
  async function testStoreFactory(url, sthis) {
2005
2167
  sthis = ensureSuperLog(sthis, "testStoreFactory");
@@ -2038,78 +2200,27 @@ function toStoreRuntime(opts, sthis) {
2038
2200
  }
2039
2201
  registerStoreProtocol({
2040
2202
  protocol: "file:",
2041
- gateway: async (logger) => {
2042
- const { FileGateway } = await import("./gateway-YSNUK2L3.js");
2043
- return new FileGateway(logger);
2203
+ gateway: async (sthis) => {
2204
+ const { FileGateway } = await import("./gateway-5FCWPX5W.js");
2205
+ return new FileGateway(sthis);
2044
2206
  },
2045
- test: async (logger) => {
2046
- const { FileTestStore } = await import("./gateway-YSNUK2L3.js");
2047
- return new FileTestStore(logger);
2207
+ test: async (sthis) => {
2208
+ const { FileTestStore } = await import("./gateway-5FCWPX5W.js");
2209
+ return new FileTestStore(sthis);
2048
2210
  }
2049
2211
  });
2050
2212
  registerStoreProtocol({
2051
2213
  protocol: "indexdb:",
2052
- gateway: async (logger) => {
2053
- const { IndexDBGateway } = await import("./gateway-IZRHJWPE.js");
2054
- return new IndexDBGateway(logger);
2214
+ gateway: async (sthis) => {
2215
+ const { IndexDBGateway } = await import("./gateway-H7UD6TNB.js");
2216
+ return new IndexDBGateway(sthis);
2055
2217
  },
2056
- test: async (logger) => {
2057
- const { IndexDBTestStore } = await import("./gateway-IZRHJWPE.js");
2058
- return new IndexDBTestStore(logger);
2218
+ test: async (sthis) => {
2219
+ const { IndexDBTestStore } = await import("./gateway-H7UD6TNB.js");
2220
+ return new IndexDBTestStore(sthis);
2059
2221
  }
2060
2222
  });
2061
2223
 
2062
- // src/blockstore/connection-base.ts
2063
- import { EventBlock, decodeEventBlock } from "@web3-storage/pail/clock";
2064
- import { MemoryBlockstore as MemoryBlockstore2 } from "@web3-storage/pail/block";
2065
-
2066
- // src/blockstore/task-manager.ts
2067
- var TaskManager = class {
2068
- constructor(loader) {
2069
- this.eventsWeHandled = /* @__PURE__ */ new Set();
2070
- this.queue = [];
2071
- this.isProcessing = false;
2072
- this.loader = loader;
2073
- this.logger = ensureLogger(loader.sthis, "TaskManager");
2074
- }
2075
- async handleEvent(eventBlock) {
2076
- const cid = eventBlock.cid.toString();
2077
- const parents = eventBlock.value.parents.map((cid2) => cid2.toString());
2078
- for (const parent of parents) {
2079
- this.eventsWeHandled.add(parent);
2080
- }
2081
- this.queue.push({ cid, eventBlock, retries: 0 });
2082
- this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
2083
- void this.processQueue();
2084
- }
2085
- async processQueue() {
2086
- if (this.isProcessing) return;
2087
- this.isProcessing = true;
2088
- const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
2089
- const first = filteredQueue[0];
2090
- if (!first) {
2091
- return;
2092
- }
2093
- try {
2094
- this.loader?.remoteMetaStore?.handleByteHeads([first.eventBlock.value.data.dbMeta]);
2095
- this.eventsWeHandled.add(first.cid);
2096
- this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
2097
- } catch (err) {
2098
- if (first.retries++ > 3) {
2099
- this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
2100
- this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
2101
- }
2102
- await new Promise((resolve) => setTimeout(resolve, 50));
2103
- throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
2104
- } finally {
2105
- this.isProcessing = false;
2106
- if (this.queue.length > 0) {
2107
- void this.processQueue();
2108
- }
2109
- }
2110
- }
2111
- };
2112
-
2113
2224
  // src/blockstore/store-remote.ts
2114
2225
  async function RemoteDataStore(sthis, name, url, opts) {
2115
2226
  const ds = new DataStoreImpl(sthis, name, url, opts);
@@ -2117,7 +2228,13 @@ async function RemoteDataStore(sthis, name, url, opts) {
2117
2228
  return ds;
2118
2229
  }
2119
2230
  async function RemoteMetaStore(sthis, name, url, opts) {
2120
- const ms = new MetaStoreImpl(sthis, name, url, opts);
2231
+ const ms = new MetaStoreImpl(
2232
+ sthis,
2233
+ name,
2234
+ url,
2235
+ opts
2236
+ /* , true*/
2237
+ );
2121
2238
  await ms.start();
2122
2239
  return ms;
2123
2240
  }
@@ -2125,16 +2242,12 @@ async function RemoteMetaStore(sthis, name, url, opts) {
2125
2242
  // src/blockstore/connection-base.ts
2126
2243
  var ConnectionBase = class {
2127
2244
  constructor(url, logger) {
2128
- // readonly ready: Promise<unknown>;
2129
- // todo move to LRU blockstore https://github.com/web3-storage/w3clock/blob/main/src/worker/block.js
2130
- this.eventBlocks = new MemoryBlockstore2();
2131
- this.parents = [];
2132
2245
  this.loaded = Promise.resolve();
2133
2246
  this.logger = logger;
2134
2247
  this.url = url;
2135
2248
  }
2136
2249
  async refresh() {
2137
- await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load("main");
2250
+ await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
2138
2251
  await (await throwFalsy(this.loader).WALStore()).process();
2139
2252
  }
2140
2253
  async connect_X({ loader }) {
@@ -2145,26 +2258,20 @@ var ConnectionBase = class {
2145
2258
  async connectMeta_X({ loader }) {
2146
2259
  if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
2147
2260
  this.loader = loader;
2148
- this.taskManager = new TaskManager(loader);
2149
2261
  await this.onConnect();
2150
2262
  const metaUrl = this.url.build().defParam("store", "meta").URI();
2151
2263
  const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
2152
2264
  if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
2153
- const name = metaUrl.toString();
2154
- const remote = await RemoteMetaStore(loader.sthis, name, metaUrl, {
2265
+ const dbName = metaUrl.getParam("name");
2266
+ if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: name is required").AsError();
2267
+ const remote = await RemoteMetaStore(loader.sthis, dbName, metaUrl, {
2155
2268
  gateway: gateway.gateway,
2156
- keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag)
2157
- });
2158
- remote.onLoad("main", async (metas) => {
2159
- if (metas) {
2160
- this.logger.Debug().Any("metas", metas).Bool("loader", this.loader).Msg("connectMeta_X: handleDbMetasFromStore pre");
2161
- await throwFalsy(this.loader).handleDbMetasFromStore(metas);
2162
- this.logger.Debug().Any("metas", metas).Msg("connectMeta_X: handleDbMetasFromStore post");
2163
- }
2269
+ keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag),
2270
+ loader
2164
2271
  });
2165
2272
  this.loader.remoteMetaStore = remote;
2166
2273
  this.loaded = this.loader.ready().then(async () => {
2167
- remote.load("main").then(async () => {
2274
+ remote.load().then(async () => {
2168
2275
  (await throwFalsy(this.loader).WALStore()).process();
2169
2276
  });
2170
2277
  });
@@ -2175,28 +2282,14 @@ var ConnectionBase = class {
2175
2282
  const dataUrl = this.url.build().defParam("store", "data").URI();
2176
2283
  const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
2177
2284
  if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
2178
- const name = dataUrl.toString();
2285
+ const name = dataUrl.getParam("name");
2286
+ if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: name is required").AsError;
2179
2287
  loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
2180
2288
  gateway: gateway.gateway,
2181
2289
  keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
2182
2290
  });
2183
2291
  loader.remoteFileStore = loader.remoteCarStore;
2184
2292
  }
2185
- async createEventBlock(bytes) {
2186
- const data = {
2187
- dbMeta: bytes
2188
- };
2189
- const event = await EventBlock.create(
2190
- data,
2191
- this.parents
2192
- );
2193
- await this.eventBlocks.put(event.cid, event.bytes);
2194
- return event;
2195
- }
2196
- async decodeEventBlock(bytes) {
2197
- const event = await decodeEventBlock(bytes);
2198
- return event;
2199
- }
2200
2293
  // move this stuff to connect
2201
2294
  // async getDashboardURL(compact = true) {
2202
2295
  // const baseUrl = 'https://dashboard.fireproof.storage/'
@@ -2490,7 +2583,7 @@ async function doCompact(blockLog, head, logger) {
2490
2583
  isCompacting = false;
2491
2584
  }
2492
2585
  async function getBlock(blocks, cidString) {
2493
- const block = await blocks.get(parse2(cidString));
2586
+ const block = await blocks.get(parse3(cidString));
2494
2587
  if (!block) throw new Error(`Missing block ${cidString}`);
2495
2588
  const { cid, value } = await decode({ bytes: block.bytes, codec, hasher: hasher5 });
2496
2589
  return new Block({ cid, value, bytes: block.bytes });
@@ -2826,7 +2919,7 @@ var Index = class {
2826
2919
  // src/crdt-clock.ts
2827
2920
  import { advance } from "@web3-storage/pail/clock";
2828
2921
  import { root as root2 } from "@web3-storage/pail/crdt";
2829
- import { ResolveOnce as ResolveOnce3 } from "@adviser/cement";
2922
+ import { ResolveOnce as ResolveOnce4 } from "@adviser/cement";
2830
2923
 
2831
2924
  // src/apply-head-queue.ts
2832
2925
  function applyHeadQueue(worker, logger) {
@@ -2841,7 +2934,7 @@ function applyHeadQueue(worker, logger) {
2841
2934
  queue.sort((a, b) => b.updates ? 1 : -1);
2842
2935
  const task = queue.shift();
2843
2936
  if (!task) continue;
2844
- await worker(task.newHead, task.prevHead, task.updates !== null).catch((e) => {
2937
+ await worker(task.newHead, task.prevHead, task.updates !== void 0).catch((e) => {
2845
2938
  throw logger.Error().Err(e).Msg("int_applyHead worker error").AsError();
2846
2939
  });
2847
2940
  if (task.updates) {
@@ -2883,7 +2976,7 @@ var CRDTClock = class {
2883
2976
  this.zoomers = /* @__PURE__ */ new Set();
2884
2977
  this.watchers = /* @__PURE__ */ new Set();
2885
2978
  this.emptyWatchers = /* @__PURE__ */ new Set();
2886
- this._ready = new ResolveOnce3();
2979
+ this._ready = new ResolveOnce4();
2887
2980
  this.blockstore = blockstore;
2888
2981
  this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
2889
2982
  this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
@@ -2931,6 +3024,7 @@ var CRDTClock = class {
2931
3024
  this.zoomers.add(fn);
2932
3025
  }
2933
3026
  async int_applyHead(newHead, prevHead, localUpdates) {
3027
+ const noLoader = !localUpdates;
2934
3028
  const ogHead = sortClockHead(this.head);
2935
3029
  newHead = sortClockHead(newHead);
2936
3030
  if (compareClockHeads(ogHead, newHead)) {
@@ -2941,7 +3035,6 @@ var CRDTClock = class {
2941
3035
  this.setHead(newHead);
2942
3036
  return;
2943
3037
  }
2944
- const noLoader = !localUpdates;
2945
3038
  if (!this.blockstore) {
2946
3039
  throw this.logger.Error().Msg("missing blockstore").AsError();
2947
3040
  }
@@ -2994,7 +3087,7 @@ async function advanceBlocks(logger, newHead, tblocks, head) {
2994
3087
  var CRDT = class {
2995
3088
  constructor(sthis, name, opts = {}) {
2996
3089
  this.indexers = /* @__PURE__ */ new Map();
2997
- this.onceReady = new ResolveOnce4();
3090
+ this.onceReady = new ResolveOnce5();
2998
3091
  this.sthis = sthis;
2999
3092
  this.name = name;
3000
3093
  this.logger = ensureLogger(sthis, "CRDT");
@@ -3060,7 +3153,7 @@ var CRDT = class {
3060
3153
  try {
3061
3154
  await Promise.all([this.blockstore.ready(), this.indexBlockstore.ready(), this.clock.ready()]);
3062
3155
  } catch (e) {
3063
- throw this.logger.Error().Err(e).Msg("CRDT not ready").AsError();
3156
+ throw this.logger.Error().Err(e).Msg(`CRDT is not ready`).AsError();
3064
3157
  }
3065
3158
  });
3066
3159
  }
@@ -3114,7 +3207,7 @@ var Database = class {
3114
3207
  this._listening = false;
3115
3208
  this._listeners = /* @__PURE__ */ new Set();
3116
3209
  this._noupdate_listeners = /* @__PURE__ */ new Set();
3117
- this._ready = new ResolveOnce5();
3210
+ this._ready = new ResolveOnce6();
3118
3211
  this.name = name;
3119
3212
  this.opts = opts || this.opts;
3120
3213
  this.sthis = ensureSuperThis(this.opts);
@@ -3163,7 +3256,7 @@ var Database = class {
3163
3256
  await this.ready();
3164
3257
  this.logger.Debug().Str("id", doc._id).Msg("put");
3165
3258
  const { _id, ...value } = doc;
3166
- const docId = _id || this.sthis.nextId().str;
3259
+ const docId = _id || this.sthis.timeOrderedNextId().str;
3167
3260
  const result = await this._writeQueue.push({
3168
3261
  id: docId,
3169
3262
  value: {
@@ -3304,6 +3397,7 @@ __export(runtime_exports, {
3304
3397
  kb: () => key_bag_exports,
3305
3398
  kc: () => keyed_crypto_exports,
3306
3399
  mf: () => wait_pr_multiformats_exports,
3400
+ runtimeFn: () => runtimeFn2,
3307
3401
  toArrayBuffer: () => toArrayBuffer
3308
3402
  });
3309
3403
 
@@ -3317,9 +3411,12 @@ __export(wait_pr_multiformats_exports, {
3317
3411
  // src/runtime/wait-pr-multiformats/codec-interface.ts
3318
3412
  var codec_interface_exports = {};
3319
3413
 
3414
+ // src/runtime/index.ts
3415
+ import { runtimeFn as runtimeFn2 } from "@adviser/cement";
3416
+
3320
3417
  // src/version.ts
3321
3418
  var PACKAGE_VERSION = Object.keys({
3322
- "0.19.9-dev-frag": "xxxx"
3419
+ "0.19.11-dev-dryrun2": "xxxx"
3323
3420
  })[0];
3324
3421
  export {
3325
3422
  CRDT,
@@ -3335,7 +3432,6 @@ export {
3335
3432
  ensureLogger,
3336
3433
  ensureSuperLog,
3337
3434
  ensureSuperThis,
3338
- exception2Result,
3339
3435
  exceptionWrapper,
3340
3436
  falsyToUndef,
3341
3437
  fireproof,