@fireproof/core 0.20.0-dev-preview-39 → 0.20.0-dev-preview-41

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 (38) hide show
  1. package/README.md +6 -4
  2. package/deno/index.js +2 -2
  3. package/deno/index.js.map +1 -1
  4. package/index.cjs +499 -370
  5. package/index.cjs.map +1 -1
  6. package/index.d.cts +162 -64
  7. package/index.d.ts +162 -64
  8. package/index.js +473 -344
  9. package/index.js.map +1 -1
  10. package/metafile-cjs.json +1 -1
  11. package/metafile-esm.json +1 -1
  12. package/package.json +3 -3
  13. package/react/index.cjs +28 -11
  14. package/react/index.cjs.map +1 -1
  15. package/react/index.d.cts +2 -1
  16. package/react/index.d.ts +2 -1
  17. package/react/index.js +29 -12
  18. package/react/index.js.map +1 -1
  19. package/react/metafile-cjs.json +1 -1
  20. package/react/metafile-esm.json +1 -1
  21. package/tests/blockstore/interceptor-gateway.test.ts +5 -1
  22. package/tests/blockstore/keyed-crypto-indexeddb-file.test.ts +8 -18
  23. package/tests/blockstore/keyed-crypto.test.ts +7 -30
  24. package/tests/blockstore/loader.test.ts +19 -17
  25. package/tests/blockstore/store.test.ts +48 -51
  26. package/tests/blockstore/transaction.test.ts +13 -11
  27. package/tests/fireproof/all-gateway.test.ts +49 -46
  28. package/tests/fireproof/attachable.test.ts +82 -0
  29. package/tests/fireproof/crdt.test.ts +49 -48
  30. package/tests/fireproof/database.test.ts +40 -40
  31. package/tests/fireproof/fireproof.test.ts +43 -42
  32. package/tests/fireproof/hello.test.ts +4 -4
  33. package/tests/fireproof/indexer.test.ts +44 -44
  34. package/tests/fireproof/utils.test.ts +4 -3
  35. package/tests/gateway/file/loader-config.test.ts +17 -17
  36. package/tests/gateway/indexeddb/loader-config.test.ts +4 -4
  37. package/tests/helpers.ts +80 -2
  38. package/tests/react/useFireproof.test.tsx +79 -4
package/index.js CHANGED
@@ -5,7 +5,7 @@ var __export = (target, all) => {
5
5
  };
6
6
 
7
7
  // src/ledger.ts
8
- import { BuildURI as BuildURI2, KeyedResolvOnce as KeyedResolvOnce4, ResolveOnce as ResolveOnce7, URI as URI13 } from "@adviser/cement";
8
+ import { BuildURI as BuildURI3, KeyedResolvOnce as KeyedResolvOnce5, ResolveOnce as ResolveOnce7, URI as URI12 } from "@adviser/cement";
9
9
 
10
10
  // src/utils.ts
11
11
  import {
@@ -60,6 +60,18 @@ function falsyToUndef(value) {
60
60
  }
61
61
  return value;
62
62
  }
63
+ var DataAndMetaAndWalAndBaseStore = class {
64
+ constructor(dam) {
65
+ this.wal = dam.wal;
66
+ this.file = dam.file;
67
+ this.car = dam.car;
68
+ this.meta = dam.meta;
69
+ this.baseStores = [this.file, this.car, this.meta];
70
+ if (this.wal) {
71
+ this.baseStores.push(this.wal);
72
+ }
73
+ }
74
+ };
63
75
 
64
76
  // src/utils.ts
65
77
  import { base58btc } from "multiformats/bases/base58";
@@ -1237,7 +1249,7 @@ var MemoryGateway = class {
1237
1249
  get(url) {
1238
1250
  const x = this.memorys.get(url.toString());
1239
1251
  if (!x) {
1240
- return Promise.resolve(Result4.Err(new NotFoundError("not found")));
1252
+ return Promise.resolve(Result4.Err(new NotFoundError(`not found: ${url.getParam(PARAM.STORE)}`)));
1241
1253
  }
1242
1254
  return Promise.resolve(Result4.Ok(x));
1243
1255
  }
@@ -1343,9 +1355,6 @@ async function decode2DbMetaEvents(sthis, rserializedMeta) {
1343
1355
  if (!Array.isArray(serializedMeta)) {
1344
1356
  return sthis.logger.Debug().Any("metaEntries", serializedMeta).Msg("No data in MetaEntries").ResultError();
1345
1357
  }
1346
- if (!serializedMeta.length) {
1347
- return sthis.logger.Debug().Msg("No MetaEntries found").ResultError();
1348
- }
1349
1358
  return Result6.Ok(
1350
1359
  await Promise.all(
1351
1360
  serializedMeta.map(async (metaEntry) => {
@@ -2032,6 +2041,9 @@ var DatabaseImpl = class {
2032
2041
  this.id = ledger.id;
2033
2042
  this.logger = ensureLogger(this.sthis, "Database");
2034
2043
  }
2044
+ attach(a) {
2045
+ return this.ledger.attach(a);
2046
+ }
2035
2047
  get name() {
2036
2048
  return this.ledger.name;
2037
2049
  }
@@ -2127,11 +2139,11 @@ import { ResolveOnce as ResolveOnce6 } from "@adviser/cement";
2127
2139
  // src/blockstore/index.ts
2128
2140
  var blockstore_exports = {};
2129
2141
  __export(blockstore_exports, {
2142
+ AttachedRemotesImpl: () => AttachedRemotesImpl,
2130
2143
  BaseBlockstoreImpl: () => BaseBlockstoreImpl,
2131
2144
  Car2FPMsg: () => Car2FPMsg,
2132
2145
  CarTransactionImpl: () => CarTransactionImpl,
2133
2146
  CompactionFetcher: () => CompactionFetcher,
2134
- ConnectionBase: () => ConnectionBase,
2135
2147
  DbMetaEventEqual: () => DbMetaEventEqual,
2136
2148
  DbMetaEventsEqual: () => DbMetaEventsEqual,
2137
2149
  EncryptedBlockstore: () => EncryptedBlockstore,
@@ -2140,6 +2152,7 @@ __export(blockstore_exports, {
2140
2152
  InterceptorGateway: () => InterceptorGateway,
2141
2153
  Loader: () => Loader,
2142
2154
  PassThroughGateway: () => PassThroughGateway,
2155
+ createAttachedStores: () => createAttachedStores,
2143
2156
  createDbMetaEvent: () => createDbMetaEvent,
2144
2157
  defaultGatewayFactoryItem: () => defaultGatewayFactoryItem,
2145
2158
  ensureStoreEnDeFile: () => ensureStoreEnDeFile,
@@ -2164,7 +2177,7 @@ function DbMetaEventsEqual(a, b) {
2164
2177
  }
2165
2178
 
2166
2179
  // src/blockstore/store-factory.ts
2167
- import { KeyedResolvOnce as KeyedResolvOnce3, Result as Result10 } from "@adviser/cement";
2180
+ import { KeyedResolvOnce as KeyedResolvOnce4, Result as Result10 } from "@adviser/cement";
2168
2181
 
2169
2182
  // src/blockstore/store.ts
2170
2183
  import { exception2Result as exception2Result3, ResolveOnce as ResolveOnce4, Result as Result9 } from "@adviser/cement";
@@ -2333,7 +2346,7 @@ var EncryptedBlockstore = class extends BaseBlockstoreImpl {
2333
2346
  if (!this.loader) {
2334
2347
  return;
2335
2348
  }
2336
- return falsyToUndef(await this.loader.getBlock(cid));
2349
+ return falsyToUndef(await this.loader.getBlock(cid, this.loader.attachedStores.local()));
2337
2350
  }
2338
2351
  async transaction(fn, opts = { noLoader: false }) {
2339
2352
  this.logger.Debug().Msg("enter transaction");
@@ -2353,10 +2366,7 @@ var EncryptedBlockstore = class extends BaseBlockstoreImpl {
2353
2366
  async getFile(car, cid) {
2354
2367
  await this.ready();
2355
2368
  if (!this.loader) throw this.logger.Error().Msg("loader required to get file, ledger must be named").AsError();
2356
- const reader = await this.loader.loadFileCar(
2357
- car
2358
- /*, isPublic */
2359
- );
2369
+ const reader = await this.loader.loadFileCar(car, this.loader.attachedStores.local());
2360
2370
  const block = await reader.get(cid);
2361
2371
  if (!block) throw this.logger.Error().Str("cid", cid.toString()).Msg(`Missing block`).AsError();
2362
2372
  return block.bytes;
@@ -2577,11 +2587,11 @@ var TaskManager = class {
2577
2587
  this.logger = ensureLogger(sthis, "TaskManager");
2578
2588
  this.callback = callback;
2579
2589
  }
2580
- async handleEvent(cid, parents, dbMeta) {
2590
+ async handleEvent(cid, parents, dbMeta, store) {
2581
2591
  for (const parent of parents) {
2582
2592
  this.eventsWeHandled.add(parent.toString());
2583
2593
  }
2584
- this.queue.push({ cid: cid.toString(), dbMeta, retries: 0 });
2594
+ this.queue.push({ cid: cid.toString(), dbMeta, retries: 0, store });
2585
2595
  this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
2586
2596
  void this.processQueue();
2587
2597
  }
@@ -2595,7 +2605,7 @@ var TaskManager = class {
2595
2605
  return;
2596
2606
  }
2597
2607
  try {
2598
- await this.callback(first.dbMeta);
2608
+ await this.callback(first.dbMeta, first.store);
2599
2609
  this.eventsWeHandled.add(first.cid);
2600
2610
  this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
2601
2611
  } catch (err) {
@@ -2614,6 +2624,237 @@ var TaskManager = class {
2614
2624
  }
2615
2625
  };
2616
2626
 
2627
+ // src/blockstore/attachable-store.ts
2628
+ import { KeyedResolvOnce as KeyedResolvOnce3, BuildURI as BuildURI2, isCoerceURI } from "@adviser/cement";
2629
+ var AttachedImpl = class {
2630
+ constructor(gws, stores, unreg) {
2631
+ this.gatewayUrls = gws;
2632
+ this.stores = new DataAndMetaAndWalAndBaseStore(stores);
2633
+ this.unreg = unreg;
2634
+ }
2635
+ async detach() {
2636
+ const toClose = [this.stores.car.close(), this.stores.file.close(), this.stores.meta.close()];
2637
+ if (this.stores.wal) {
2638
+ toClose.push(this.stores.wal.close());
2639
+ }
2640
+ await Promise.all(toClose);
2641
+ this.unreg();
2642
+ }
2643
+ status() {
2644
+ return "attached";
2645
+ }
2646
+ };
2647
+ var DataActiveStoreImpl = class {
2648
+ constructor(ref, active, attached) {
2649
+ this.ref = ref;
2650
+ this.active = active;
2651
+ this.attached = attached;
2652
+ }
2653
+ };
2654
+ var CarAttachedStoresImpl = class {
2655
+ constructor(attached) {
2656
+ this.attached = attached;
2657
+ }
2658
+ local() {
2659
+ return this.attached.local().active.car;
2660
+ }
2661
+ remotes() {
2662
+ return this.attached.remotes().map(({ active }) => active.car);
2663
+ }
2664
+ };
2665
+ var FileAttachedStoresImpl = class {
2666
+ constructor(attached) {
2667
+ this.attached = attached;
2668
+ }
2669
+ local() {
2670
+ return this.attached.local().active.file;
2671
+ }
2672
+ remotes() {
2673
+ return this.attached.remotes().map(({ active }) => active.file);
2674
+ }
2675
+ };
2676
+ var MetaActiveStoreImpl = class {
2677
+ constructor(ref, active, attached) {
2678
+ this.ref = ref;
2679
+ this.active = active;
2680
+ this.attached = attached;
2681
+ }
2682
+ };
2683
+ var MetaAttachedStoresImpl = class {
2684
+ constructor(attached) {
2685
+ this.attached = attached;
2686
+ }
2687
+ local() {
2688
+ return this.attached.local().active.meta;
2689
+ }
2690
+ remotes() {
2691
+ return this.attached.remotes().map(({ active }) => active.meta);
2692
+ }
2693
+ };
2694
+ var WALActiveStoreImpl = class {
2695
+ constructor(ref, active, attached) {
2696
+ this.ref = ref;
2697
+ this.active = active;
2698
+ this.attached = attached;
2699
+ }
2700
+ };
2701
+ var WALAttachedStoresImpl = class {
2702
+ constructor(attached) {
2703
+ this.attached = attached;
2704
+ }
2705
+ local() {
2706
+ return this.attached.local().active.wal;
2707
+ }
2708
+ remotes() {
2709
+ return this.attached.remotes().filter(({ active }) => active.wal).map(({ active }) => active.wal);
2710
+ }
2711
+ };
2712
+ var ActiveStoreImpl = class {
2713
+ constructor(active, attached) {
2714
+ this.active = active;
2715
+ this.attached = attached;
2716
+ }
2717
+ baseStores() {
2718
+ const bs = [this.active.car, this.active.file, this.active.meta];
2719
+ if (this.active.wal) {
2720
+ bs.push(this.active.wal);
2721
+ }
2722
+ return bs;
2723
+ }
2724
+ carStore() {
2725
+ return new DataActiveStoreImpl(this, this.active.car, new CarAttachedStoresImpl(this.attached));
2726
+ }
2727
+ fileStore() {
2728
+ return new DataActiveStoreImpl(this, this.active.file, new FileAttachedStoresImpl(this.attached));
2729
+ }
2730
+ metaStore() {
2731
+ return new MetaActiveStoreImpl(this, this.active.meta, new MetaAttachedStoresImpl(this.attached));
2732
+ }
2733
+ walStore() {
2734
+ if (!this.active.wal) {
2735
+ throw this.attached.loadable.sthis.logger.Error().Msg("wal store not set").AsError();
2736
+ }
2737
+ return new WALActiveStoreImpl(this, this.active.wal, new WALAttachedStoresImpl(this.attached));
2738
+ }
2739
+ };
2740
+ function isLoadable(unknown) {
2741
+ return !!unknown.sthis && !!unknown.attachedStores;
2742
+ }
2743
+ async function createAttachedStores(urlOrGup, arOrLoadable, name = "local") {
2744
+ let ar;
2745
+ if (!isLoadable(arOrLoadable)) {
2746
+ ar = arOrLoadable;
2747
+ } else {
2748
+ ar = arOrLoadable.attachedStores;
2749
+ }
2750
+ let gup;
2751
+ if (!urlOrGup) {
2752
+ throw new Error("urlOrGup is required");
2753
+ }
2754
+ if (isCoerceURI(urlOrGup)) {
2755
+ const url = urlOrGup;
2756
+ gup = {
2757
+ car: { url },
2758
+ file: { url },
2759
+ meta: { url },
2760
+ wal: { url }
2761
+ };
2762
+ } else {
2763
+ gup = urlOrGup;
2764
+ }
2765
+ return await ar.attach({
2766
+ name,
2767
+ prepare: async () => gup
2768
+ });
2769
+ }
2770
+ var AttachedRemotesImpl = class {
2771
+ constructor(loadable) {
2772
+ this._remotes = new KeyedResolvOnce3();
2773
+ this.loadable = loadable;
2774
+ }
2775
+ forRemotes(action) {
2776
+ return Promise.all(this.remotes().map((i) => action(i))).then(() => void 0);
2777
+ }
2778
+ remotes() {
2779
+ return this._remotes.values().filter(({ value }) => value.isOk() && !value.Ok().stores.wal).map(({ value }) => value.Ok().stores).map((i) => this.activate(i));
2780
+ }
2781
+ local() {
2782
+ if (!this._local) {
2783
+ throw this.loadable.sthis.logger.Error().Msg("local store not set").AsError();
2784
+ }
2785
+ return new ActiveStoreImpl(this._local.stores, this);
2786
+ }
2787
+ activate(store) {
2788
+ if (isCoerceURI(store)) {
2789
+ throw this.loadable.sthis.logger.Error().Msg("store must be an object").AsError();
2790
+ }
2791
+ return new ActiveStoreImpl(store, this);
2792
+ }
2793
+ async detach() {
2794
+ await Promise.all(
2795
+ this._remotes.values().map(async ({ value: rvalue }) => {
2796
+ if (rvalue.isOk()) {
2797
+ await rvalue.Ok().detach();
2798
+ }
2799
+ })
2800
+ );
2801
+ }
2802
+ async attach(attached) {
2803
+ const gwp = await attached.prepare();
2804
+ const gws = {
2805
+ car: {
2806
+ ...gwp.car,
2807
+ url: BuildURI2.from(gwp.car.url).defParam("name", attached.name).URI()
2808
+ },
2809
+ file: {
2810
+ ...gwp.file,
2811
+ url: BuildURI2.from(gwp.file.url).defParam("name", attached.name).URI()
2812
+ },
2813
+ meta: {
2814
+ ...gwp.meta,
2815
+ url: BuildURI2.from(gwp.meta.url).defParam("name", attached.name).URI()
2816
+ },
2817
+ wal: gwp.wal ? {
2818
+ ...gwp.wal,
2819
+ url: BuildURI2.from(gwp.wal.url).defParam("name", attached.name).URI()
2820
+ } : void 0
2821
+ };
2822
+ const key = JSON.stringify(
2823
+ toSortedArray({
2824
+ carUrl: gws.car.url.toString(),
2825
+ filesUrl: gws.file.url.toString(),
2826
+ metaUrl: gws.meta.url.toString(),
2827
+ walUrl: gws.wal?.url.toString()
2828
+ })
2829
+ );
2830
+ return this._remotes.get(key).once(async () => {
2831
+ const rt = toStoreRuntime(this.loadable.sthis);
2832
+ const result = new AttachedImpl(
2833
+ gws,
2834
+ await rt.makeStores({
2835
+ byStore: gws,
2836
+ loader: this.loadable
2837
+ }),
2838
+ // {
2839
+ // car: await rt.makeDataStore({ url: gws.carUrl, loader: this.loadable }),
2840
+ // file: await rt.makeDataStore({ url: gws.filesUrl, loader: this.loadable }),
2841
+ // meta: await rt.makeMetaStore({ url: gws.metaUrl, loader: this.loadable }),
2842
+ // },
2843
+ () => {
2844
+ this._remotes.unget(key);
2845
+ }
2846
+ );
2847
+ if (result.stores.wal) {
2848
+ if (this._local) {
2849
+ throw this.loadable.sthis.logger.Error().Msg("local store could only set once").AsError();
2850
+ }
2851
+ this._local = result;
2852
+ }
2853
+ return result;
2854
+ });
2855
+ }
2856
+ };
2857
+
2617
2858
  // src/blockstore/loader.ts
2618
2859
  function carLogIncludesGroup(list, cids) {
2619
2860
  return list.some((arr) => {
@@ -2639,10 +2880,6 @@ var Loader = class {
2639
2880
  this.getBlockCache = /* @__PURE__ */ new Map();
2640
2881
  this.seenMeta = /* @__PURE__ */ new Set();
2641
2882
  this.writeLimit = pLimit(1);
2642
- this._carStore = new ResolveOnce3();
2643
- this._fileStore = new ResolveOnce3();
2644
- this._WALStore = new ResolveOnce3();
2645
- this._metaStore = new ResolveOnce3();
2646
2883
  this.onceReady = new ResolveOnce3();
2647
2884
  this.sthis = sthis;
2648
2885
  this.ebOpts = defaultedBlockstoreRuntime(
@@ -2654,75 +2891,93 @@ var Loader = class {
2654
2891
  "Loader"
2655
2892
  );
2656
2893
  this.logger = this.ebOpts.logger;
2657
- this.taskManager = new TaskManager(sthis, async (dbMeta) => {
2658
- await this.handleDbMetasFromStore([dbMeta]);
2894
+ this.taskManager = new TaskManager(sthis, async (dbMeta, activeStore) => {
2895
+ await this.handleDbMetasFromStore([dbMeta], activeStore);
2659
2896
  });
2660
- }
2661
- async carStore() {
2662
- return this._carStore.once(
2663
- async () => this.ebOpts.storeRuntime.makeDataStore({
2664
- // sthis: this.sthis,
2665
- gatewayInterceptor: this.ebOpts.gatewayInterceptor,
2666
- url: this.ebOpts.storeUrls.data,
2667
- // keybag: await this.keyBag(),
2668
- loader: this
2669
- })
2670
- );
2671
- }
2672
- async fileStore() {
2673
- return this._fileStore.once(
2674
- async () => this.ebOpts.storeRuntime.makeDataStore({
2675
- // sthis: this.sthis,
2676
- gatewayInterceptor: this.ebOpts.gatewayInterceptor,
2677
- url: this.ebOpts.storeUrls.file,
2678
- // keybag: await this.keyBag(),
2679
- loader: this
2680
- })
2681
- );
2682
- }
2683
- async WALStore() {
2684
- return this._WALStore.once(
2685
- async () => this.ebOpts.storeRuntime.makeWALStore({
2686
- // sthis: this.sthis,
2687
- gatewayInterceptor: this.ebOpts.gatewayInterceptor,
2688
- url: this.ebOpts.storeUrls.wal,
2689
- // keybag: await this.keyBag(),
2690
- loader: this
2691
- })
2692
- );
2693
- }
2694
- async metaStore() {
2695
- return this._metaStore.once(
2696
- async () => this.ebOpts.storeRuntime.makeMetaStore({
2697
- // sthis: this.sthis,
2698
- gatewayInterceptor: this.ebOpts.gatewayInterceptor,
2699
- url: this.ebOpts.storeUrls.meta,
2700
- // keybag: await this.keyBag(),
2701
- loader: this
2702
- })
2703
- );
2704
- }
2897
+ this.attachedStores = new AttachedRemotesImpl(this);
2898
+ }
2899
+ attach(attached) {
2900
+ return this.attachedStores.attach(attached);
2901
+ }
2902
+ // private readonly _carStore = new ResolveOnce<DataStore>();
2903
+ // async carStore(): Promise<DataStore> {
2904
+ // return this._carStore.once(async () =>
2905
+ // this.ebOpts.storeRuntime.makeDataStore({
2906
+ // // sthis: this.sthis,
2907
+ // gatewayInterceptor: this.ebOpts.gatewayInterceptor,
2908
+ // url: this.ebOpts.storeUrls.data,
2909
+ // // keybag: await this.keyBag(),
2910
+ // loader: this,
2911
+ // }),
2912
+ // );
2913
+ // }
2914
+ // private readonly _fileStore = new ResolveOnce<DataStore>();
2915
+ // async fileStore(): Promise<DataStore> {
2916
+ // return this._fileStore.once(async () =>
2917
+ // this.ebOpts.storeRuntime.makeDataStore({
2918
+ // // sthis: this.sthis,
2919
+ // gatewayInterceptor: this.ebOpts.gatewayInterceptor,
2920
+ // url: this.ebOpts.storeUrls.file,
2921
+ // // keybag: await this.keyBag(),
2922
+ // loader: this,
2923
+ // }),
2924
+ // );
2925
+ // }
2926
+ // private readonly _WALStore = new ResolveOnce<WALStore>();
2927
+ // async WALStore(): Promise<WALStore> {
2928
+ // return this._WALStore.once(async () =>
2929
+ // this.ebOpts.storeRuntime.makeWALStore({
2930
+ // // sthis: this.sthis,
2931
+ // gatewayInterceptor: this.ebOpts.gatewayInterceptor,
2932
+ // url: this.ebOpts.storeUrls.wal,
2933
+ // // keybag: await this.keyBag(),
2934
+ // loader: this,
2935
+ // }),
2936
+ // );
2937
+ // }
2938
+ // private readonly _metaStore = new ResolveOnce<MetaStore>();
2939
+ // async metaStore(): Promise<MetaStore> {
2940
+ // return this._metaStore.once(async () =>
2941
+ // this.ebOpts.storeRuntime.makeMetaStore({
2942
+ // // sthis: this.sthis,
2943
+ // gatewayInterceptor: this.ebOpts.gatewayInterceptor,
2944
+ // url: this.ebOpts.storeUrls.meta,
2945
+ // // keybag: await this.keyBag(),
2946
+ // loader: this,
2947
+ // }),
2948
+ // );
2949
+ // }
2705
2950
  keyBag() {
2706
2951
  return getKeyBag(this.sthis, this.ebOpts.keyBag);
2707
2952
  }
2708
2953
  async ready() {
2709
2954
  return this.onceReady.once(async () => {
2710
- const metas = await (await this.metaStore()).load();
2955
+ await createAttachedStores(
2956
+ {
2957
+ car: { url: this.ebOpts.storeUrls.car, gatewayInterceptor: this.ebOpts.gatewayInterceptor },
2958
+ file: { url: this.ebOpts.storeUrls.file, gatewayInterceptor: this.ebOpts.gatewayInterceptor },
2959
+ meta: { url: this.ebOpts.storeUrls.meta, gatewayInterceptor: this.ebOpts.gatewayInterceptor },
2960
+ wal: { url: this.ebOpts.storeUrls.wal, gatewayInterceptor: this.ebOpts.gatewayInterceptor }
2961
+ },
2962
+ this.attachedStores
2963
+ );
2964
+ const local = this.attachedStores.local();
2965
+ const metas = await local.active.meta.load();
2711
2966
  if (this.ebOpts.meta) {
2712
- await this.handleDbMetasFromStore([this.ebOpts.meta]);
2967
+ await this.handleDbMetasFromStore([this.ebOpts.meta, ...metas || []], local);
2713
2968
  } else if (metas) {
2714
- await this.handleDbMetasFromStore(metas);
2969
+ await this.handleDbMetasFromStore(metas, local);
2715
2970
  }
2716
2971
  });
2717
2972
  }
2718
2973
  async close() {
2719
2974
  await this.commitQueue.waitIdle();
2720
- const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
2721
- await Promise.all(toClose.map((store) => store.close()));
2975
+ await this.attachedStores.detach();
2722
2976
  }
2723
2977
  async destroy() {
2724
- const toDestroy = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
2725
- await Promise.all(toDestroy.map((store) => store.destroy()));
2978
+ await Promise.all(
2979
+ this.attachedStores.local().baseStores().map((store) => store.destroy())
2980
+ );
2726
2981
  }
2727
2982
  // async snapToCar(carCid: AnyLink | string) {
2728
2983
  // await this.ready
@@ -2734,15 +2989,15 @@ var Loader = class {
2734
2989
  // await this.getMoreReaders(carHeader.cars)
2735
2990
  // await this._applyCarHeader(carHeader, true)
2736
2991
  // }
2737
- async handleDbMetasFromStore(metas) {
2992
+ async handleDbMetasFromStore(metas, activeStore) {
2738
2993
  this.logger.Debug().Any("metas", metas).Msg("handleDbMetasFromStore");
2739
2994
  for (const meta of metas) {
2740
2995
  await this.writeLimit(async () => {
2741
- await this.mergeDbMetaIntoClock(meta);
2996
+ await this.mergeDbMetaIntoClock(meta, activeStore);
2742
2997
  });
2743
2998
  }
2744
2999
  }
2745
- async mergeDbMetaIntoClock(meta) {
3000
+ async mergeDbMetaIntoClock(meta, activeStore) {
2746
3001
  if (this.isCompacting) {
2747
3002
  throw this.logger.Error().Msg("cannot merge while compacting").AsError();
2748
3003
  }
@@ -2751,9 +3006,9 @@ var Loader = class {
2751
3006
  if (carLogIncludesGroup(this.carLog, meta.cars)) {
2752
3007
  return;
2753
3008
  }
2754
- const carHeader = await this.loadCarHeaderFromMeta(meta);
3009
+ const carHeader = await this.loadCarHeaderFromMeta(meta, activeStore);
2755
3010
  carHeader.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
2756
- await this.getMoreReaders(carHeader.cars.flat());
3011
+ await this.getMoreReaders(carHeader.cars.flat(), activeStore);
2757
3012
  this.carLog = [...uniqueCids([meta.cars, ...this.carLog, ...carHeader.cars], this.seenCompacted)];
2758
3013
  await this.ebOpts.applyMeta?.(carHeader.meta);
2759
3014
  }
@@ -2763,8 +3018,8 @@ var Loader = class {
2763
3018
  // await this.setKey(key);
2764
3019
  // }
2765
3020
  // }
2766
- async loadCarHeaderFromMeta({ cars: cids }) {
2767
- const reader = await this.loadCar(cids[0]);
3021
+ async loadCarHeaderFromMeta(dbm, astore) {
3022
+ const reader = await this.loadCar(dbm.cars[0], astore);
2768
3023
  return await parseCarFile(reader, this.logger);
2769
3024
  }
2770
3025
  // async _getKey(): Promise<string | undefined> {
@@ -2777,22 +3032,22 @@ var Loader = class {
2777
3032
  // }
2778
3033
  async commitFiles(t, done) {
2779
3034
  await this.ready();
2780
- const fstore = await this.fileStore();
2781
- const wstore = await this.WALStore();
3035
+ const fstore = this.attachedStores.local().active.file;
3036
+ const wstore = this.attachedStores.local().active.wal;
2782
3037
  return this.commitQueue.enqueue(() => commitFiles(fstore, wstore, t, done));
2783
3038
  }
2784
- async loadFileCar(cid) {
2785
- return await this.storesLoadCar(cid, await this.fileStore(), this.remoteFileStore);
3039
+ async loadFileCar(cid, store) {
3040
+ return await this.storesLoadCar(cid, store.fileStore());
2786
3041
  }
2787
3042
  async commit(t, done, opts = { noLoader: false, compact: false }) {
2788
3043
  await this.ready();
2789
- const carStore = await this.carStore();
3044
+ const carStore = await this.attachedStores.local().active.car;
2790
3045
  const params = {
2791
3046
  encoder: (await carStore.keyedCrypto()).codec(),
2792
3047
  carLog: this.carLog,
2793
3048
  carStore,
2794
- WALStore: await this.WALStore(),
2795
- metaStore: await this.metaStore(),
3049
+ WALStore: await this.attachedStores.local().active.wal,
3050
+ metaStore: await this.attachedStores.local().active.meta,
2796
3051
  threshold: this.ebOpts.threshold
2797
3052
  };
2798
3053
  return this.commitQueue.enqueue(async () => {
@@ -2807,7 +3062,7 @@ var Loader = class {
2807
3062
  const previousCompactCid = fp.compact[fp.compact.length - 1];
2808
3063
  fp.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
2809
3064
  this.carLog = [...uniqueCids([...this.carLog, ...fp.cars, cids], this.seenCompacted)];
2810
- await this.removeCidsForCompact(previousCompactCid[0]).catch((e) => e);
3065
+ await this.removeCidsForCompact(previousCompactCid[0], this.attachedStores.local()).catch((e) => e);
2811
3066
  } else {
2812
3067
  this.carLog.unshift(cids);
2813
3068
  }
@@ -2830,13 +3085,16 @@ var Loader = class {
2830
3085
  }
2831
3086
  }
2832
3087
  }
2833
- async removeCidsForCompact(cid) {
2834
- const carHeader = await this.loadCarHeaderFromMeta({
2835
- cars: [cid]
2836
- });
3088
+ async removeCidsForCompact(cid, store) {
3089
+ const carHeader = await this.loadCarHeaderFromMeta(
3090
+ {
3091
+ cars: [cid]
3092
+ },
3093
+ store
3094
+ );
2837
3095
  for (const cids of carHeader.compact) {
2838
3096
  for (const cid2 of cids) {
2839
- await (await this.carStore()).remove(cid2);
3097
+ await this.attachedStores.local().active.car.remove(cid2);
2840
3098
  }
2841
3099
  }
2842
3100
  }
@@ -2860,7 +3118,7 @@ var Loader = class {
2860
3118
  }
2861
3119
  for (const cids of this.carLog) {
2862
3120
  for (const cid of cids) {
2863
- const reader = await this.loadCar(cid);
3121
+ const reader = await this.loadCar(cid, this.attachedStores.local());
2864
3122
  if (!reader) throw this.logger.Error().Ref("cid", cid).Msg("missing car reader").AsError();
2865
3123
  for await (const block of reader.blocks()) {
2866
3124
  const sCid = block.cid.toString();
@@ -2872,13 +3130,13 @@ var Loader = class {
2872
3130
  }
2873
3131
  }
2874
3132
  }
2875
- async getBlock(cid) {
3133
+ async getBlock(cid, store) {
2876
3134
  await this.ready();
2877
3135
  const sCid = cid.toString();
2878
3136
  if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
2879
3137
  const getCarCid = async (carCid) => {
2880
3138
  if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
2881
- const reader = await this.loadCar(carCid);
3139
+ const reader = await this.loadCar(carCid, store);
2882
3140
  if (!reader) {
2883
3141
  throw this.logger.Error().Ref("cid", carCid).Msg("missing car reader").AsError();
2884
3142
  }
@@ -2889,7 +3147,7 @@ var Loader = class {
2889
3147
  throw this.logger.Error().Str("cid", sCid).Msg("block not in reader").AsError();
2890
3148
  };
2891
3149
  const getCompactCarCids = async (carCid) => {
2892
- const reader = await this.loadCar(carCid);
3150
+ const reader = await this.loadCar(carCid, store);
2893
3151
  if (!reader) {
2894
3152
  throw this.logger.Error().Str("cid", carCid.toString()).Msg("missing car reader").AsError();
2895
3153
  }
@@ -2932,36 +3190,37 @@ var Loader = class {
2932
3190
  }
2933
3191
  return got;
2934
3192
  }
2935
- async loadCar(cid) {
2936
- if (!this.carStore) {
2937
- throw this.logger.Error().Msg("car store not initialized").AsError();
2938
- }
2939
- const loaded = await this.storesLoadCar(cid, await this.carStore(), this.remoteCarStore);
3193
+ async loadCar(cid, store) {
3194
+ const loaded = await this.storesLoadCar(cid, store.carStore());
2940
3195
  return loaded;
2941
3196
  }
2942
- async makeDecoderAndCarReader(cid, local, remote) {
3197
+ async makeDecoderAndCarReader(cid, store) {
2943
3198
  const cidsString = cid.toString();
2944
3199
  let loadedCar = void 0;
2945
- let activeStore = local;
3200
+ let activeStore = store.attached.local();
2946
3201
  try {
2947
3202
  this.logger.Debug().Any("cid", cidsString).Msg("loading car");
2948
- loadedCar = await local.load(cid);
3203
+ loadedCar = await store.attached.local().load(cid);
2949
3204
  this.logger.Debug().Bool("loadedCar", loadedCar).Msg("loaded");
2950
3205
  } catch (e) {
2951
- if (remote) {
3206
+ if (!isNotFoundError(e)) {
3207
+ throw this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
3208
+ }
3209
+ for (const remote of store.attached.remotes()) {
2952
3210
  const remoteCar = await remote.load(cid);
2953
3211
  if (remoteCar) {
2954
3212
  this.logger.Debug().Ref("cid", remoteCar.cid).Msg("saving remote car locally");
2955
- await local.save(remoteCar);
3213
+ await store.attached.local().save(remoteCar);
2956
3214
  loadedCar = remoteCar;
2957
3215
  activeStore = remote;
3216
+ break;
3217
+ } else {
3218
+ this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
2958
3219
  }
2959
- } else {
2960
- this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
2961
3220
  }
2962
3221
  }
2963
3222
  if (!loadedCar) {
2964
- throw this.logger.Error().Url(local.url()).Str("cid", cidsString).Msg("missing car files").AsError();
3223
+ throw this.logger.Error().Url(store.attached.local().url()).Str("cid", cidsString).Msg("missing car files").AsError();
2965
3224
  }
2966
3225
  const bytes = await decode({ bytes: loadedCar.bytes, hasher: hasher4, codec: (await activeStore.keyedCrypto()).codec() });
2967
3226
  const rawReader = await CarReader.fromBytes(bytes.value);
@@ -2977,19 +3236,19 @@ var Loader = class {
2977
3236
  return readerP;
2978
3237
  }
2979
3238
  //What if instead it returns an Array of CarHeader
2980
- async storesLoadCar(cid, local, remote) {
3239
+ async storesLoadCar(cid, store) {
2981
3240
  const cidsString = cid.toString();
2982
3241
  let dacr = this.carReaders.get(cidsString);
2983
3242
  if (!dacr) {
2984
- dacr = this.makeDecoderAndCarReader(cid, local, remote);
3243
+ dacr = this.makeDecoderAndCarReader(cid, store);
2985
3244
  this.carReaders.set(cidsString, dacr);
2986
3245
  }
2987
3246
  return dacr;
2988
3247
  }
2989
- async getMoreReaders(cids) {
3248
+ async getMoreReaders(cids, store) {
2990
3249
  const limit = pLimit(5);
2991
3250
  const missing = cids.filter((cid) => !this.carReaders.has(cid.toString()));
2992
- await Promise.all(missing.map((cid) => limit(() => this.loadCar(cid))));
3251
+ await Promise.all(missing.map((cid) => limit(() => this.loadCar(cid, store))));
2993
3252
  }
2994
3253
  };
2995
3254
 
@@ -3360,7 +3619,7 @@ var BaseStoreImpl = class {
3360
3619
  async keyedCrypto() {
3361
3620
  return keyedCryptoFactory(this._url, await this.loader.keyBag(), this.sthis);
3362
3621
  }
3363
- async start() {
3622
+ async start(dam) {
3364
3623
  this.logger.Debug().Str("storeType", this.storeType).Msg("starting-gateway-pre");
3365
3624
  this._url = this._url.build().setParam(PARAM.STORE, this.storeType).URI();
3366
3625
  const res = await this.gateway.start({ loader: this.loader }, this._url);
@@ -3397,7 +3656,7 @@ var BaseStoreImpl = class {
3397
3656
  return ready;
3398
3657
  }
3399
3658
  }
3400
- this._onStarted.forEach((fn) => fn());
3659
+ this._onStarted.forEach((fn) => fn(dam));
3401
3660
  this.logger.Debug().Msg("started");
3402
3661
  return version;
3403
3662
  }
@@ -3426,12 +3685,19 @@ var MetaStoreImpl = class extends BaseStoreImpl {
3426
3685
  /*this.remote && */
3427
3686
  opts.gateway.subscribe
3428
3687
  ) {
3429
- this.onStarted(async () => {
3688
+ this.onStarted(async (dam) => {
3430
3689
  this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
3431
3690
  opts.gateway.subscribe({ loader: this.loader }, this.url(), async ({ payload: dbMetas }) => {
3432
3691
  this.logger.Debug().Msg("Received message from gateway");
3433
3692
  await Promise.all(
3434
- dbMetas.map((dbMeta) => this.loader.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
3693
+ dbMetas.map(
3694
+ (dbMetaEv) => this.loader.taskManager?.handleEvent(
3695
+ dbMetaEv.eventCid,
3696
+ dbMetaEv.parents,
3697
+ dbMetaEv.dbMeta,
3698
+ this.loader.attachedStores.activate(dam)
3699
+ )
3700
+ )
3435
3701
  );
3436
3702
  this.updateParentsFromDbMetas(dbMetas);
3437
3703
  });
@@ -3466,10 +3732,11 @@ var MetaStoreImpl = class extends BaseStoreImpl {
3466
3732
  }
3467
3733
  throw this.logger.Error().Url(url.Ok()).Err(rfpEnv).Msg("gateway get").AsError();
3468
3734
  }
3469
- const dbMetas = rfpEnv.Ok().payload;
3470
- await this.loader.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
3471
- this.updateParentsFromDbMetas(dbMetas);
3472
- return dbMetas.map((m) => m.dbMeta);
3735
+ const fpMeta = rfpEnv.Ok().payload;
3736
+ const dbMetas = fpMeta.map((m) => m.dbMeta);
3737
+ await this.loader.handleDbMetasFromStore(dbMetas, this.loader.attachedStores.local());
3738
+ this.updateParentsFromDbMetas(fpMeta);
3739
+ return dbMetas;
3473
3740
  }
3474
3741
  async save(meta, branch) {
3475
3742
  branch = branch || "main";
@@ -3615,7 +3882,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
3615
3882
  }
3616
3883
  async process() {
3617
3884
  await this.ready();
3618
- if (!this.loader.remoteCarStore) return;
3619
3885
  await this.processQueue.enqueue(async () => {
3620
3886
  try {
3621
3887
  await this._doProcess();
@@ -3629,7 +3895,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
3629
3895
  }
3630
3896
  async _doProcess() {
3631
3897
  if (!this.loader) return;
3632
- if (!this.loader.remoteCarStore) return;
3633
3898
  const operations = [...this.walState.operations];
3634
3899
  const noLoaderOps = [...this.walState.noLoaderOps];
3635
3900
  const fileOperations = [...this.walState.fileOperations];
@@ -3650,13 +3915,13 @@ var WALStoreImpl = class extends BaseStoreImpl {
3650
3915
  return;
3651
3916
  }
3652
3917
  for (const cid of dbMeta.cars) {
3653
- const car = await (await this.loader.carStore()).load(cid);
3918
+ const car = await this.loader.attachedStores.local().active.car.load(cid);
3654
3919
  if (!car) {
3655
3920
  if (carLogIncludesGroup(this.loader.carLog, dbMeta.cars)) {
3656
3921
  throw this.logger.Error().Ref("cid", cid).Msg("missing local car").AsError();
3657
3922
  }
3658
3923
  } else {
3659
- await throwFalsy(this.loader.remoteCarStore).save(car);
3924
+ await this.loader.attachedStores.forRemotes((x) => x.active.car.save(car));
3660
3925
  }
3661
3926
  }
3662
3927
  inplaceFilter(this.walState.noLoaderOps, (op) => op !== dbMeta);
@@ -3672,13 +3937,13 @@ var WALStoreImpl = class extends BaseStoreImpl {
3672
3937
  return;
3673
3938
  }
3674
3939
  for (const cid of dbMeta.cars) {
3675
- const car = await (await this.loader.carStore()).load(cid);
3940
+ const car = await this.loader.attachedStores.local().active.car.load(cid);
3676
3941
  if (!car) {
3677
3942
  if (carLogIncludesGroup(this.loader.carLog, dbMeta.cars)) {
3678
3943
  throw this.logger.Error().Ref("cid", cid).Msg(`missing local car`).AsError();
3679
3944
  }
3680
3945
  } else {
3681
- await throwFalsy(this.loader.remoteCarStore).save(car);
3946
+ await this.loader.attachedStores.forRemotes((x) => x.active.car.save(car));
3682
3947
  }
3683
3948
  }
3684
3949
  inplaceFilter(this.walState.operations, (op) => op !== dbMeta);
@@ -3693,11 +3958,11 @@ var WALStoreImpl = class extends BaseStoreImpl {
3693
3958
  if (!this.loader) {
3694
3959
  return;
3695
3960
  }
3696
- const fileBlock = await (await this.loader.fileStore()).load(fileCid);
3961
+ const fileBlock = await this.loader.attachedStores.local().active.file.load(fileCid);
3697
3962
  if (!fileBlock) {
3698
3963
  throw this.logger.Error().Ref("cid", fileCid).Msg("missing file block").AsError();
3699
3964
  }
3700
- await this.loader.remoteFileStore?.save(fileBlock, { public: publicFile });
3965
+ await this.loader.attachedStores.forRemotes((x) => x.active.file.save(fileBlock, { public: publicFile }));
3701
3966
  inplaceFilter(this.walState.fileOperations, (op) => op.cid !== fileCid);
3702
3967
  }, `fileOperation with cid=${fileCid.toString()}`);
3703
3968
  },
@@ -3709,7 +3974,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
3709
3974
  if (!this.loader) {
3710
3975
  return;
3711
3976
  }
3712
- await this.loader.remoteMetaStore?.save(lastOp);
3977
+ await this.loader.attachedStores.forRemotes((x) => x.active.meta.save(lastOp));
3713
3978
  }, `remoteMetaStore save with dbMeta.cars=${lastOp.cars.toString()}`);
3714
3979
  }
3715
3980
  } catch (error) {
@@ -3762,8 +4027,8 @@ var WALStoreImpl = class extends BaseStoreImpl {
3762
4027
  };
3763
4028
 
3764
4029
  // src/blockstore/store-factory.ts
3765
- var onceGateway = new KeyedResolvOnce3();
3766
- var gatewayInstances = new KeyedResolvOnce3();
4030
+ var onceGateway = new KeyedResolvOnce4();
4031
+ var gatewayInstances = new KeyedResolvOnce4();
3767
4032
  async function getStartedGateway(ctx, url) {
3768
4033
  return onceGateway.get(url.toString()).once(async () => {
3769
4034
  const item = getGatewayFactoryItem(url.protocol);
@@ -3783,50 +4048,50 @@ async function getStartedGateway(ctx, url) {
3783
4048
  return Result10.Err(ctx.loader.sthis.logger.Warn().Url(url).Msg("unsupported protocol").AsError());
3784
4049
  });
3785
4050
  }
3786
- async function dataStoreFactory(sfi) {
3787
- const storeUrl = sfi.url.build().setParam(PARAM.STORE, "data").URI();
3788
- const rgateway = await getStartedGateway(sfi, storeUrl);
4051
+ async function dataStoreFactory(ctx, uai) {
4052
+ const storeUrl = uai.url.build().setParam(PARAM.STORE, "data").URI();
4053
+ const rgateway = await getStartedGateway(ctx, storeUrl);
3789
4054
  if (rgateway.isErr()) {
3790
- throw sfi.loader.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
4055
+ throw ctx.loader.sthis.logger.Error().Result("err", rgateway).Url(uai.url).Msg("notfound").AsError();
3791
4056
  }
3792
4057
  const gateway = rgateway.Ok();
3793
- const store = new DataStoreImpl(sfi.loader.sthis, gateway.url, {
4058
+ const store = new DataStoreImpl(ctx.loader.sthis, gateway.url, {
3794
4059
  gateway: gateway.gateway,
3795
- gatewayInterceptor: sfi.gatewayInterceptor,
3796
- loader: sfi.loader
4060
+ gatewayInterceptor: uai.gatewayInterceptor,
4061
+ loader: ctx.loader
3797
4062
  });
3798
4063
  return store;
3799
4064
  }
3800
- async function metaStoreFactory(sfi) {
3801
- const storeUrl = sfi.url.build().setParam(PARAM.STORE, "meta").URI();
3802
- const rgateway = await getStartedGateway(sfi, storeUrl);
4065
+ async function metaStoreFactory(ctx, uai) {
4066
+ const storeUrl = uai.url.build().setParam(PARAM.STORE, "meta").URI();
4067
+ const rgateway = await getStartedGateway(ctx, storeUrl);
3803
4068
  if (rgateway.isErr()) {
3804
- throw sfi.loader.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
4069
+ throw ctx.loader.sthis.logger.Error().Result("err", rgateway).Url(uai.url).Msg("notfound").AsError();
3805
4070
  }
3806
4071
  const gateway = rgateway.Ok();
3807
- const store = new MetaStoreImpl(sfi.loader.sthis, gateway.url, {
4072
+ const store = new MetaStoreImpl(ctx.loader.sthis, gateway.url, {
3808
4073
  gateway: gateway.gateway,
3809
- gatewayInterceptor: sfi.gatewayInterceptor,
3810
- loader: sfi.loader
4074
+ gatewayInterceptor: uai.gatewayInterceptor,
4075
+ loader: ctx.loader
3811
4076
  });
3812
4077
  return store;
3813
4078
  }
3814
- async function WALStoreFactory(sfi) {
3815
- const storeUrl = sfi.url.build().setParam(PARAM.STORE, "wal").URI();
3816
- const rgateway = await getStartedGateway(sfi, storeUrl);
4079
+ async function WALStoreFactory(ctx, uai) {
4080
+ const storeUrl = uai.url.build().setParam(PARAM.STORE, "wal").URI();
4081
+ const rgateway = await getStartedGateway(ctx, storeUrl);
3817
4082
  if (rgateway.isErr()) {
3818
- throw sfi.loader.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
4083
+ throw ctx.loader.sthis.logger.Error().Result("err", rgateway).Url(uai.url).Msg("notfound").AsError();
3819
4084
  }
3820
4085
  const gateway = rgateway.Ok();
3821
- const store = new WALStoreImpl(sfi.loader.sthis, gateway.url, {
4086
+ const store = new WALStoreImpl(ctx.loader.sthis, gateway.url, {
3822
4087
  gateway: gateway.gateway,
3823
- gatewayInterceptor: sfi.gatewayInterceptor,
3824
- loader: sfi.loader
4088
+ gatewayInterceptor: uai.gatewayInterceptor,
4089
+ loader: ctx.loader
3825
4090
  });
3826
4091
  return store;
3827
4092
  }
3828
- async function ensureStart(store) {
3829
- const ret = await store.start();
4093
+ async function ensureStart(store, damaw) {
4094
+ const ret = await store.start(damaw);
3830
4095
  if (ret.isErr()) {
3831
4096
  throw store.logger.Error().Result("start", ret).Msg("start failed").AsError();
3832
4097
  }
@@ -3842,191 +4107,32 @@ function ensureStoreEnDeFile(ende) {
3842
4107
  }
3843
4108
  function toStoreRuntime(sthis, endeOpts = {}) {
3844
4109
  return {
3845
- makeMetaStore: async (sfi) => ensureStart(await metaStoreFactory(sfi)),
3846
- // async (loader: Loadable) => {
3847
- // logger
3848
- // .Debug()
3849
- // .Str("fromOpts", "" + !!endeOpts.func?.makeMetaStore)
3850
- // .Msg("makeMetaStore");
3851
- // return ensureStart(await (endeOpts.func?.makeMetaStore || metaStoreFactory)(loader), logger);
3852
- // },
3853
- makeDataStore: async (sfi) => ensureStart(await dataStoreFactory(sfi)),
3854
- // async (loader: Loadable) => {
3855
- // logger
3856
- // .Debug()
3857
- // .Str("fromOpts", "" + !!endeOpts.func?.makeDataStore)
3858
- // .Msg("makeDataStore");
3859
- // return ensureStart(await (endeOpts.func?.makeDataStore || dataStoreFactory)(loader), logger);
3860
- // },
3861
- makeWALStore: async (sfi) => ensureStart(await WALStoreFactory(sfi)),
3862
- // async (loader: Loadable) => {
3863
- // logger
3864
- // .Debug()
3865
- // .Str("fromOpts", "" + !!endeOpts.func?.makeWALStore)
3866
- // .Msg("makeRemoteWAL");
3867
- // return ensureStart(await (endeOpts.func?.makeWALStore || remoteWalFactory)(loader), logger);
3868
- // },
4110
+ makeStores: async (sfi) => {
4111
+ const ctx = {
4112
+ loader: sfi.loader
4113
+ };
4114
+ const storeSet = {};
4115
+ storeSet.meta = await metaStoreFactory(ctx, sfi.byStore.meta);
4116
+ storeSet.car = await dataStoreFactory(ctx, sfi.byStore.car);
4117
+ storeSet.file = await dataStoreFactory(ctx, sfi.byStore.file);
4118
+ if (sfi.byStore.wal) {
4119
+ storeSet.wal = await WALStoreFactory(ctx, sfi.byStore.wal);
4120
+ }
4121
+ await ensureStart(storeSet.meta, storeSet);
4122
+ await ensureStart(storeSet.car, storeSet);
4123
+ await ensureStart(storeSet.file, storeSet);
4124
+ if (storeSet.wal) {
4125
+ await ensureStart(storeSet.wal, storeSet);
4126
+ }
4127
+ return storeSet;
4128
+ },
4129
+ // makeMetaStore: async (sfi: StoreFactoryItem) => ensureStart(await metaStoreFactory(sfi)),
4130
+ // makeDataStore: async (sfi: StoreFactoryItem) => ensureStart(await dataStoreFactory(sfi)),
4131
+ // makeWALStore: async (sfi: StoreFactoryItem) => ensureStart(await WALStoreFactory(sfi)),
3869
4132
  ...ensureStoreEnDeFile(endeOpts)
3870
4133
  };
3871
4134
  }
3872
4135
 
3873
- // src/blockstore/connection-base.ts
3874
- import { exception2Result as exception2Result4, Future as Future3 } from "@adviser/cement";
3875
-
3876
- // src/blockstore/store-remote.ts
3877
- async function RemoteDataStore(sthis, url, opts) {
3878
- const ds = new DataStoreImpl(sthis, url, opts);
3879
- await ds.start();
3880
- return ds;
3881
- }
3882
- async function RemoteMetaStore(sthis, url, opts) {
3883
- const ms = new MetaStoreImpl(sthis, url, opts);
3884
- await ms.start();
3885
- return ms;
3886
- }
3887
-
3888
- // src/context.ts
3889
- var Context = class {
3890
- constructor() {
3891
- this.ctx = /* @__PURE__ */ new Map();
3892
- }
3893
- set(key, value) {
3894
- this.ctx.set(key, value);
3895
- }
3896
- get(key) {
3897
- return this.ctx.get(key);
3898
- }
3899
- delete(key) {
3900
- this.ctx.delete(key);
3901
- }
3902
- };
3903
-
3904
- // src/blockstore/connection-base.ts
3905
- function coerceLoader(ref) {
3906
- const refl = ref;
3907
- if (refl.loader) {
3908
- return refl.loader;
3909
- }
3910
- const refb = ref;
3911
- if (refb.blockstore) {
3912
- return coerceLoader(refb.blockstore);
3913
- }
3914
- return void 0;
3915
- }
3916
- var ConnectionBase = class {
3917
- constructor(url, logger) {
3918
- // loaded: Promise<void> = Promise.resolve();
3919
- this.context = new Context();
3920
- this._loaded = /* @__PURE__ */ new Set();
3921
- this._metaIsLoading = false;
3922
- this.logger = logger;
3923
- this.url = url;
3924
- }
3925
- loaded() {
3926
- const f = new Future3();
3927
- if (!this._metaIsLoading) {
3928
- f.resolve();
3929
- } else {
3930
- this._loaded.add(f);
3931
- }
3932
- return f;
3933
- }
3934
- async refresh() {
3935
- await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
3936
- await (await throwFalsy(this.loader).WALStore()).process();
3937
- }
3938
- async connect(refl) {
3939
- await this.connectMeta(refl);
3940
- await this.connectStorage(refl);
3941
- }
3942
- async connectMeta(refl) {
3943
- const loader = coerceLoader(refl);
3944
- if (!loader) throw this.logger.Error().Msg("connectMeta: loader is required").AsError();
3945
- this.loader = loader;
3946
- await this.onConnect();
3947
- const metaUrl = this.url.build().defParam(PARAM.STORE, "meta").URI();
3948
- const rgateway = await getStartedGateway({ loader }, metaUrl);
3949
- if (rgateway.isErr())
3950
- throw this.logger.Error().Result("err", rgateway).Url(metaUrl).Msg("connectMeta: gateway is required").AsError();
3951
- const dbName = metaUrl.getParam(PARAM.NAME);
3952
- if (!dbName) {
3953
- throw this.logger.Error().Url(metaUrl).Msg("connectMeta: dbName is required").AsError();
3954
- }
3955
- const gateway = rgateway.Ok();
3956
- const remote = await RemoteMetaStore(loader.sthis, metaUrl, {
3957
- gateway: gateway.gateway,
3958
- loader
3959
- });
3960
- this.loader.remoteMetaStore = remote;
3961
- this._metaIsLoading = true;
3962
- this.loader.ready().then(async () => {
3963
- return remote.load().then(async () => {
3964
- const res = await exception2Result4(async () => {
3965
- return await (await throwFalsy(this.loader).WALStore()).process();
3966
- });
3967
- this._metaIsLoading = false;
3968
- for (const f of this._loaded) {
3969
- if (res.isErr()) {
3970
- f.reject(res.Err());
3971
- } else {
3972
- f.resolve();
3973
- }
3974
- }
3975
- this._loaded.clear();
3976
- });
3977
- });
3978
- }
3979
- async connectStorage(refl) {
3980
- const loader = coerceLoader(refl);
3981
- if (!loader) throw this.logger.Error().Msg("connectStorage: loader is required").AsError();
3982
- this.loader = loader;
3983
- const dataUrl = this.url.build().defParam(PARAM.STORE, "data").URI();
3984
- const rgateway = await getStartedGateway({ loader }, dataUrl);
3985
- if (rgateway.isErr())
3986
- throw this.logger.Error().Result("err", rgateway).Url(dataUrl).Msg("connectStorage: gateway is required").AsError();
3987
- const name = dataUrl.getParam(PARAM.NAME);
3988
- if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage: name is required").AsError;
3989
- loader.remoteCarStore = await RemoteDataStore(loader.sthis, this.url, {
3990
- gateway: rgateway.Ok().gateway,
3991
- loader
3992
- });
3993
- loader.remoteFileStore = loader.remoteCarStore;
3994
- }
3995
- // move this stuff to connect
3996
- // async getDashboardURL(compact = true) {
3997
- // const baseUrl = 'https://dashboard.fireproof.storage/'
3998
- // if (!this.loader?.remoteCarStore) return new URL('/howto', baseUrl)
3999
- // // if (compact) {
4000
- // // await this.compact()
4001
- // // }
4002
- // const currents = await this.loader?.metaStore?.load()
4003
- // if (!currents) throw new Error("Can't sync empty ledger: save data first")
4004
- // if (currents.length > 1)
4005
- // throw new Error("Can't sync ledger with split heads: make an update first")
4006
- // const current = currents[0]
4007
- // const params = {
4008
- // car: current.car.toString()
4009
- // }
4010
- // if (current.key) {
4011
- // // @ts-ignore
4012
- // params.key = current.key.toString()
4013
- // }
4014
- // // @ts-ignore
4015
- // if (this.name) {
4016
- // // @ts-ignore
4017
- // params.name = this.name
4018
- // }
4019
- // const url = new URL('/import#' + new URLSearchParams(params).toString(), baseUrl)
4020
- // console.log('Import to dashboard: ' + url.toString())
4021
- // return url
4022
- // }
4023
- // openDashboard() {
4024
- // void this.getDashboardURL().then(url => {
4025
- // if (url) window.open(url.toString(), '_blank')
4026
- // })
4027
- // }
4028
- };
4029
-
4030
4136
  // src/crdt-helpers.ts
4031
4137
  import { parse as parse2 } from "multiformats/link";
4032
4138
  import { sha256 as hasher6 } from "multiformats/hashes/sha2";
@@ -4601,8 +4707,24 @@ var CRDTImpl = class {
4601
4707
  }
4602
4708
  };
4603
4709
 
4710
+ // src/context.ts
4711
+ var Context = class {
4712
+ constructor() {
4713
+ this.ctx = /* @__PURE__ */ new Map();
4714
+ }
4715
+ set(key, value) {
4716
+ this.ctx.set(key, value);
4717
+ }
4718
+ get(key) {
4719
+ return this.ctx.get(key);
4720
+ }
4721
+ delete(key) {
4722
+ this.ctx.delete(key);
4723
+ }
4724
+ };
4725
+
4604
4726
  // src/ledger.ts
4605
- var ledgers = new KeyedResolvOnce4();
4727
+ var ledgers = new KeyedResolvOnce5();
4606
4728
  function keyConfigOpts(sthis, name, opts) {
4607
4729
  return JSON.stringify(
4608
4730
  toSortedArray({
@@ -4645,6 +4767,9 @@ var LedgerShell = class {
4645
4767
  this.name = ref.name;
4646
4768
  ref.addShell(this);
4647
4769
  }
4770
+ attach(a) {
4771
+ return this.ref.attach(a);
4772
+ }
4648
4773
  get opts() {
4649
4774
  return this.ref.opts;
4650
4775
  }
@@ -4743,6 +4868,9 @@ var LedgerImpl = class {
4743
4868
  });
4744
4869
  return ret;
4745
4870
  }
4871
+ attach(a) {
4872
+ return this.crdt.blockstore.loader.attach(a);
4873
+ }
4746
4874
  // readonly _asDb = new ResolveOnce<Database>();
4747
4875
  // asDB(): Database {
4748
4876
  // return this._asDb.once(() => new DatabaseImpl(this));
@@ -4791,7 +4919,7 @@ var LedgerImpl = class {
4791
4919
  };
4792
4920
  function defaultURI2(sthis, name, curi, uri, store, ctx) {
4793
4921
  ctx = ctx || {};
4794
- const ret = (curi ? URI13.from(curi) : uri).build().setParam(PARAM.STORE, store).defParam(PARAM.NAME, name);
4922
+ const ret = (curi ? URI12.from(curi) : uri).build().setParam(PARAM.STORE, store).defParam(PARAM.NAME, name);
4795
4923
  if (!ret.hasParam(PARAM.NAME)) {
4796
4924
  throw sthis.logger.Error().Url(ret).Any("ctx", ctx).Msg("Ledger name is required").AsError();
4797
4925
  }
@@ -4814,21 +4942,21 @@ function toStoreURIRuntime(sthis, name, sopts) {
4814
4942
  if (!sopts.base) {
4815
4943
  const fp_env = sthis.env.get("FP_STORAGE_URL");
4816
4944
  if (fp_env) {
4817
- sopts = { ...sopts, base: BuildURI2.from(fp_env).setParam(PARAM.URL_GEN, "fromEnv") };
4945
+ sopts = { ...sopts, base: BuildURI3.from(fp_env).setParam(PARAM.URL_GEN, "fromEnv") };
4818
4946
  } else {
4819
4947
  sopts = { ...sopts, base: getDefaultURI(sthis).build().setParam(PARAM.URL_GEN, "default") };
4820
4948
  }
4821
4949
  }
4822
- const base = URI13.from(sopts.base);
4950
+ const base = URI12.from(sopts.base);
4823
4951
  return {
4824
4952
  idx: {
4825
- data: defaultURI2(sthis, name, sopts.idx?.data, base, "data", { idx: true }),
4953
+ car: defaultURI2(sthis, name, sopts.idx?.data, base, "data", { idx: true }),
4826
4954
  file: defaultURI2(sthis, name, sopts.idx?.data, base, "data", { file: true, idx: true }),
4827
4955
  meta: defaultURI2(sthis, name, sopts.idx?.meta, base, "meta", { idx: true }),
4828
4956
  wal: defaultURI2(sthis, name, sopts.idx?.wal, base, "wal", { idx: true })
4829
4957
  },
4830
4958
  data: {
4831
- data: defaultURI2(sthis, name, sopts.data?.data, base, "data"),
4959
+ car: defaultURI2(sthis, name, sopts.data?.data, base, "data"),
4832
4960
  file: defaultURI2(sthis, name, sopts.data?.data, base, "data", { file: true }),
4833
4961
  meta: defaultURI2(sthis, name, sopts.data?.meta, base, "meta"),
4834
4962
  wal: defaultURI2(sthis, name, sopts.data?.wal, base, "wal")
@@ -4895,10 +5023,11 @@ __export(file_exports, {
4895
5023
 
4896
5024
  // src/version.ts
4897
5025
  var PACKAGE_VERSION = Object.keys({
4898
- "0.20.0-dev-preview-39": "xxxx"
5026
+ "0.20.0-dev-preview-41": "xxxx"
4899
5027
  })[0];
4900
5028
  export {
4901
5029
  CRDTImpl,
5030
+ DataAndMetaAndWalAndBaseStore,
4902
5031
  DatabaseImpl,
4903
5032
  Index,
4904
5033
  LedgerFactory,