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

Sign up to get free protection for your applications and to get access to all the features.
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,