@fireproof/core 0.19.121-dev → 0.20.0-dev-preview-05

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 (103) hide show
  1. package/README.md +13 -12
  2. package/deno/index.d.ts +7 -0
  3. package/deno/index.js +66 -0
  4. package/deno/index.js.map +1 -0
  5. package/deno/metafile-esm.json +1 -0
  6. package/deno.json +3 -4
  7. package/index.cjs +1797 -1431
  8. package/index.cjs.map +1 -1
  9. package/index.d.cts +760 -381
  10. package/index.d.ts +760 -381
  11. package/index.js +1976 -913
  12. package/index.js.map +1 -1
  13. package/metafile-cjs.json +1 -1
  14. package/metafile-esm.json +1 -1
  15. package/node/{node-filesystem.cjs → index.cjs} +17 -6
  16. package/node/index.cjs.map +1 -0
  17. package/node/index.d.cts +7 -0
  18. package/node/index.d.ts +7 -0
  19. package/node/{node-filesystem.js → index.js} +25 -5
  20. package/node/index.js.map +1 -0
  21. package/node/metafile-cjs.json +1 -1
  22. package/node/metafile-esm.json +1 -1
  23. package/package.json +27 -17
  24. package/react/index.cjs +22 -22
  25. package/react/index.cjs.map +1 -1
  26. package/react/index.d.cts +7 -7
  27. package/react/index.d.ts +7 -7
  28. package/react/index.js +22 -22
  29. package/react/index.js.map +1 -1
  30. package/react/metafile-cjs.json +1 -1
  31. package/react/metafile-esm.json +1 -1
  32. package/tests/blockstore/fp-envelope.test.ts-off +65 -0
  33. package/tests/blockstore/interceptor-gateway.test.ts +122 -0
  34. package/tests/blockstore/keyed-crypto-indexdb-file.test.ts +130 -0
  35. package/tests/blockstore/keyed-crypto.test.ts +75 -118
  36. package/tests/blockstore/loader.test.ts +18 -9
  37. package/tests/blockstore/store.test.ts +40 -31
  38. package/tests/blockstore/transaction.test.ts +14 -13
  39. package/tests/fireproof/all-gateway.test.ts +286 -216
  40. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.ts +324 -316
  41. package/tests/fireproof/crdt.test.ts +78 -19
  42. package/tests/fireproof/fireproof.test.ts +111 -92
  43. package/tests/fireproof/hello.test.ts +21 -17
  44. package/tests/fireproof/indexer.test.ts +74 -50
  45. package/tests/fireproof/{database.test.ts → ledger.test.ts} +241 -45
  46. package/tests/fireproof/multiple-ledger.test.ts +2 -2
  47. package/tests/fireproof/utils.test.ts +47 -6
  48. package/tests/gateway/file/loader-config.test.ts +307 -0
  49. package/tests/gateway/fp-envelope-serialize.test.ts +256 -0
  50. package/tests/gateway/indexdb/loader-config.test.ts +79 -0
  51. package/tests/helpers.ts +44 -17
  52. package/tests/react/useFireproof.test.tsx +2 -2
  53. package/tests/www/gallery.html +2 -2
  54. package/tests/www/todo-aws.html +1 -1
  55. package/tests/www/todo-ipfs.html +1 -1
  56. package/tests/www/todo-local.html +1 -1
  57. package/tests/www/todo.html +25 -4
  58. package/web/index.cjs +218 -0
  59. package/web/index.cjs.map +1 -0
  60. package/web/index.d.cts +30 -0
  61. package/web/index.d.ts +30 -0
  62. package/web/index.js +195 -0
  63. package/web/index.js.map +1 -0
  64. package/web/metafile-cjs.json +1 -1
  65. package/web/metafile-esm.json +1 -1
  66. package/chunk-7EWIAXTM.js +0 -7
  67. package/chunk-7EWIAXTM.js.map +0 -1
  68. package/chunk-F4FC6B2T.js +0 -63
  69. package/chunk-F4FC6B2T.js.map +0 -1
  70. package/chunk-PZ5AY32C.js +0 -10
  71. package/chunk-PZ5AY32C.js.map +0 -1
  72. package/chunk-RXC4JGJT.js +0 -301
  73. package/chunk-RXC4JGJT.js.map +0 -1
  74. package/gateway-C62S56GY.js +0 -66
  75. package/gateway-C62S56GY.js.map +0 -1
  76. package/gateway-VVS4QWDA.js +0 -145
  77. package/gateway-VVS4QWDA.js.map +0 -1
  78. package/key-bag-file-PWZ3QE7B.js +0 -55
  79. package/key-bag-file-PWZ3QE7B.js.map +0 -1
  80. package/key-bag-indexdb-SYG3YD4D.js +0 -51
  81. package/key-bag-indexdb-SYG3YD4D.js.map +0 -1
  82. package/node/chunk-4A4RAVNS.js +0 -17
  83. package/node/chunk-4A4RAVNS.js.map +0 -1
  84. package/node/mem-filesystem.cjs +0 -72
  85. package/node/mem-filesystem.cjs.map +0 -1
  86. package/node/mem-filesystem.d.cts +0 -25
  87. package/node/mem-filesystem.d.ts +0 -25
  88. package/node/mem-filesystem.js +0 -40
  89. package/node/mem-filesystem.js.map +0 -1
  90. package/node/node-filesystem.cjs.map +0 -1
  91. package/node/node-filesystem.d.cts +0 -35
  92. package/node/node-filesystem.d.ts +0 -35
  93. package/node/node-filesystem.js.map +0 -1
  94. package/tests/fireproof/config.test.ts +0 -172
  95. package/utils-ZVVGAXFE.js +0 -13
  96. package/utils-ZVVGAXFE.js.map +0 -1
  97. package/web/gateway-impl.cjs +0 -183
  98. package/web/gateway-impl.cjs.map +0 -1
  99. package/web/gateway-impl.d.cts +0 -31
  100. package/web/gateway-impl.d.ts +0 -31
  101. package/web/gateway-impl.js +0 -162
  102. package/web/gateway-impl.js.map +0 -1
  103. /package/tests/blockstore/{fragment-gateway.test.ts → fragment-gateway.test.ts-off} +0 -0
package/index.cjs CHANGED
@@ -5,9 +5,6 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res) => function __init() {
9
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
10
- };
11
8
  var __export = (target, all) => {
12
9
  for (var name in all)
13
10
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -30,10 +27,136 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
27
  ));
31
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
29
 
30
+ // src/index.ts
31
+ var index_exports = {};
32
+ __export(index_exports, {
33
+ CRDT: () => CRDT,
34
+ Index: () => Index,
35
+ LedgerFactory: () => LedgerFactory,
36
+ LedgerShell: () => LedgerShell,
37
+ NotFoundError: () => NotFoundError,
38
+ PACKAGE_VERSION: () => PACKAGE_VERSION,
39
+ PARAM: () => PARAM,
40
+ UInt8ArrayEqual: () => UInt8ArrayEqual,
41
+ blockstore: () => blockstore_exports,
42
+ bs: () => blockstore_exports,
43
+ coerceIntoUint8: () => coerceIntoUint8,
44
+ coercePromiseIntoUint8: () => coercePromiseIntoUint8,
45
+ defaultWriteQueueOpts: () => defaultWriteQueueOpts,
46
+ ensureLogger: () => ensureLogger,
47
+ ensureSuperLog: () => ensureSuperLog,
48
+ ensureSuperThis: () => ensureSuperThis,
49
+ exceptionWrapper: () => exceptionWrapper,
50
+ falsyToUndef: () => falsyToUndef,
51
+ fireproof: () => fireproof,
52
+ getKey: () => getKey,
53
+ getName: () => getName,
54
+ getStore: () => getStore,
55
+ index: () => index,
56
+ inplaceFilter: () => inplaceFilter,
57
+ isFalsy: () => isFalsy,
58
+ isLedger: () => isLedger,
59
+ isNotFoundError: () => isNotFoundError,
60
+ keyConfigOpts: () => keyConfigOpts,
61
+ onSuperThis: () => onSuperThis,
62
+ rt: () => runtime_exports,
63
+ runtime: () => runtime_exports,
64
+ throwFalsy: () => throwFalsy,
65
+ toSortedArray: () => toSortedArray,
66
+ toStoreURIRuntime: () => toStoreURIRuntime
67
+ });
68
+ module.exports = __toCommonJS(index_exports);
69
+
70
+ // src/ledger.ts
71
+ var import_cement20 = require("@adviser/cement");
72
+
33
73
  // src/utils.ts
74
+ var import_cement = require("@adviser/cement");
75
+
76
+ // src/types.ts
77
+ function isFalsy(value) {
78
+ return value === false && value === null && value === void 0;
79
+ }
80
+ var PARAM = /* @__PURE__ */ ((PARAM2) => {
81
+ PARAM2["SUFFIX"] = "suffix";
82
+ PARAM2["URL_GEN"] = "urlGen";
83
+ PARAM2["STORE_KEY"] = "storekey";
84
+ PARAM2["STORE"] = "store";
85
+ PARAM2["KEY"] = "key";
86
+ PARAM2["INDEX"] = "index";
87
+ PARAM2["NAME"] = "name";
88
+ PARAM2["VERSION"] = "version";
89
+ PARAM2["RUNTIME"] = "runtime";
90
+ PARAM2["FRAG_SIZE"] = "fragSize";
91
+ PARAM2["IV_VERIFY"] = "ivVerify";
92
+ PARAM2["IV_HASH"] = "ivHash";
93
+ PARAM2["FRAG_FID"] = "fid";
94
+ PARAM2["FRAG_OFS"] = "ofs";
95
+ PARAM2["FRAG_LEN"] = "len";
96
+ PARAM2["FRAG_HEAD"] = "headerSize";
97
+ PARAM2["EXTRACTKEY"] = "extractKey";
98
+ return PARAM2;
99
+ })(PARAM || {});
100
+ function throwFalsy(value) {
101
+ if (isFalsy(value)) {
102
+ throw new Error("value is Falsy");
103
+ }
104
+ return value;
105
+ }
106
+ function falsyToUndef(value) {
107
+ if (isFalsy(value)) {
108
+ return void 0;
109
+ }
110
+ return value;
111
+ }
112
+
113
+ // src/utils.ts
114
+ var import_base58 = require("multiformats/bases/base58");
115
+ var _globalLogger = new import_cement.ResolveOnce();
34
116
  function globalLogger() {
35
117
  return _globalLogger.once(() => new import_cement.LoggerImpl());
36
118
  }
119
+ var registerFP_DEBUG = new import_cement.ResolveOnce();
120
+ var SuperThisImpl = class _SuperThisImpl {
121
+ constructor(opts) {
122
+ this.logger = opts.logger;
123
+ this.env = opts.env;
124
+ this.crypto = opts.crypto;
125
+ this.pathOps = opts.pathOps;
126
+ this.txt = opts.txt;
127
+ this.ctx = { ...opts.ctx };
128
+ }
129
+ nextId(bytes = 6) {
130
+ const bin = this.crypto.randomBytes(bytes);
131
+ return {
132
+ str: import_base58.base58btc.encode(bin),
133
+ bin
134
+ };
135
+ }
136
+ timeOrderedNextId(now) {
137
+ now = typeof now === "number" ? now : (/* @__PURE__ */ new Date()).getTime();
138
+ const t = (281474976710656 + now).toString(16).replace(/^1/, "");
139
+ const bin = this.crypto.randomBytes(10);
140
+ bin[1] = bin[1] & 240 | (bin[1] | 8 && 11);
141
+ const hex = Array.from(bin).map((i) => i.toString(16).padStart(2, "0")).join("");
142
+ return {
143
+ str: `${t.slice(0, 8)}-${t.slice(8)}-7${hex.slice(0, 3)}-${hex.slice(3, 7)}-${hex.slice(7, 19)}`
144
+ };
145
+ }
146
+ start() {
147
+ return Promise.resolve();
148
+ }
149
+ clone(override) {
150
+ return new _SuperThisImpl({
151
+ logger: override.logger || this.logger,
152
+ env: (0, import_cement.envFactory)(override.env) || this.env,
153
+ crypto: override.crypto || this.crypto,
154
+ pathOps: override.pathOps || this.pathOps,
155
+ txt: override.txt || this.txt,
156
+ ctx: { ...this.ctx, ...override.ctx }
157
+ });
158
+ }
159
+ };
37
160
  function presetEnv() {
38
161
  const penv = new Map([
39
162
  // ["FP_DEBUG", "xxx"],
@@ -48,6 +171,27 @@ function presetEnv() {
48
171
  ]);
49
172
  return penv;
50
173
  }
174
+ var pathOpsImpl = class {
175
+ join(...paths) {
176
+ return paths.map((i) => i.replace(/\/+$/, "")).join("/");
177
+ }
178
+ dirname(path) {
179
+ return path.split("/").slice(0, -1).join("/");
180
+ }
181
+ basename(path) {
182
+ return path.split("/").pop() || "";
183
+ }
184
+ // homedir() {
185
+ // throw new Error("SysContainer:homedir is not available in seeded state");
186
+ // }
187
+ };
188
+ var pathOps = new pathOpsImpl();
189
+ var txtOps = /* @__PURE__ */ ((txtEncoder, txtDecoder) => ({
190
+ encode: (input) => txtEncoder.encode(input),
191
+ decode: (input) => txtDecoder.decode(coerceIntoUint8(input).Ok())
192
+ // eslint-disable-next-line no-restricted-globals
193
+ }))(new TextEncoder(), new TextDecoder());
194
+ var _onSuperThis = /* @__PURE__ */ new Map();
51
195
  function onSuperThis(fn) {
52
196
  const key = `onSuperThis-${Math.random().toString(36).slice(2)}`;
53
197
  _onSuperThis.set(key, fn);
@@ -78,9 +222,7 @@ function ensureSuperLog(sthis, componentName, ctx) {
78
222
  }
79
223
  function ensureLogger(sthis, componentName, ctx) {
80
224
  let logger;
81
- if ((0, import_cement.IsLogger)(sthis)) {
82
- logger = sthis;
83
- } else if (sthis && (0, import_cement.IsLogger)(sthis.logger)) {
225
+ if (sthis && (0, import_cement.IsLogger)(sthis.logger)) {
84
226
  logger = sthis.logger;
85
227
  } else {
86
228
  logger = globalLogger();
@@ -101,6 +243,10 @@ function ensureLogger(sthis, componentName, ctx) {
101
243
  exposeStack = true;
102
244
  delete ctx.exposeStack;
103
245
  }
246
+ if ("exposeStack" in ctx) {
247
+ exposeStack = true;
248
+ delete ctx.exposeStack;
249
+ }
104
250
  if ("this" in ctx) {
105
251
  cLogger.Str("this", sthis.nextId(4).str);
106
252
  delete ctx.this;
@@ -167,10 +313,13 @@ function ensureLogger(sthis, componentName, ctx) {
167
313
  logger.SetExposeStack(true);
168
314
  }
169
315
  const out = cLogger.Logger();
316
+ if (sthis.env.get("FP_CONSTRUCTOR_DEBUG")) {
317
+ out.Debug().Msg("constructor");
318
+ }
170
319
  return out;
171
320
  }
172
321
  function getStore(url, sthis, joiner) {
173
- const store = url.getParam("store");
322
+ const store = url.getParam("store" /* STORE */);
174
323
  switch (store) {
175
324
  case "data":
176
325
  case "wal":
@@ -178,20 +327,21 @@ function getStore(url, sthis, joiner) {
178
327
  break;
179
328
  default:
180
329
  throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
330
+ throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
181
331
  }
182
332
  let name = store;
183
333
  if (url.hasParam("index")) {
184
- name = joiner(url.getParam("index") || "idx", name);
334
+ name = joiner(url.getParam("index" /* INDEX */) || "idx", name);
185
335
  }
186
336
  return { store, name };
187
337
  }
188
338
  function getKey(url, logger) {
189
- const result = url.getParam("key");
339
+ const result = url.getParam("key" /* KEY */);
190
340
  if (!result) throw logger.Error().Str("url", url.toString()).Msg(`key not found`).AsError();
191
341
  return result;
192
342
  }
193
343
  function getName(sthis, url) {
194
- let result = url.getParam("name");
344
+ let result = url.getParam("name" /* NAME */);
195
345
  if (!result) {
196
346
  result = sthis.pathOps.dirname(url.pathname);
197
347
  if (result.length === 0) {
@@ -203,6 +353,12 @@ function getName(sthis, url) {
203
353
  async function exceptionWrapper(fn) {
204
354
  return fn().catch((e) => import_cement.Result.Err(e));
205
355
  }
356
+ var NotFoundError = class extends Error {
357
+ constructor() {
358
+ super(...arguments);
359
+ this.code = "ENOENT";
360
+ }
361
+ };
206
362
  function isNotFoundError(e) {
207
363
  if (import_cement.Result.Is(e)) {
208
364
  if (e.isOk()) return false;
@@ -211,17 +367,6 @@ function isNotFoundError(e) {
211
367
  if (e.code === "ENOENT") return true;
212
368
  return false;
213
369
  }
214
- function dataDir(sthis, name, base) {
215
- if (!base) {
216
- if (!(0, import_cement.runtimeFn)().isBrowser) {
217
- const home = sthis.env.get("HOME") || "./";
218
- base = sthis.env.get("FP_STORAGE_URL") || `file://${sthis.pathOps.join(home, ".fireproof")}`;
219
- } else {
220
- base = sthis.env.get("FP_STORAGE_URL") || `indexdb://fp`;
221
- }
222
- }
223
- return import_cement.URI.from(base.toString()).build().setParam("name", name || "").URI();
224
- }
225
370
  function UInt8ArrayEqual(a, b) {
226
371
  if (a.length !== b.length) {
227
372
  return false;
@@ -233,663 +378,142 @@ function UInt8ArrayEqual(a, b) {
233
378
  }
234
379
  return true;
235
380
  }
236
- var import_cement, import_base58, _globalLogger, registerFP_DEBUG, SuperThisImpl, pathOpsImpl, pathOps, txtOps, _onSuperThis, NotFoundError;
237
- var init_utils = __esm({
238
- "src/utils.ts"() {
239
- "use strict";
240
- import_cement = require("@adviser/cement");
241
- import_base58 = require("multiformats/bases/base58");
242
- _globalLogger = new import_cement.ResolveOnce();
243
- registerFP_DEBUG = new import_cement.ResolveOnce();
244
- SuperThisImpl = class _SuperThisImpl {
245
- constructor(opts) {
246
- this.logger = opts.logger;
247
- this.env = opts.env;
248
- this.crypto = opts.crypto;
249
- this.pathOps = opts.pathOps;
250
- this.txt = opts.txt;
251
- this.ctx = { ...opts.ctx };
252
- }
253
- nextId(bytes = 6) {
254
- const bin = this.crypto.randomBytes(bytes);
255
- return {
256
- str: import_base58.base58btc.encode(bin),
257
- bin
258
- };
259
- }
260
- timeOrderedNextId(now) {
261
- now = typeof now === "number" ? now : (/* @__PURE__ */ new Date()).getTime();
262
- const t = (281474976710656 + now).toString(16).replace(/^1/, "");
263
- const bin = this.crypto.randomBytes(10);
264
- bin[1] = bin[1] & 240 | (bin[1] | 8 && 11);
265
- const hex = Array.from(bin).map((i) => i.toString(16).padStart(2, "0")).join("");
266
- return {
267
- str: `${t.slice(0, 8)}-${t.slice(8)}-7${hex.slice(0, 3)}-${hex.slice(3, 7)}-${hex.slice(7, 19)}`
268
- };
269
- }
270
- start() {
271
- return Promise.resolve();
272
- }
273
- clone(override) {
274
- return new _SuperThisImpl({
275
- logger: override.logger || this.logger,
276
- env: (0, import_cement.envFactory)(override.env) || this.env,
277
- crypto: override.crypto || this.crypto,
278
- pathOps: override.pathOps || this.pathOps,
279
- txt: override.txt || this.txt,
280
- ctx: { ...this.ctx, ...override.ctx }
281
- });
282
- }
283
- };
284
- pathOpsImpl = class {
285
- join(...paths) {
286
- return paths.map((i) => i.replace(/\/+$/, "")).join("/");
287
- }
288
- dirname(path) {
289
- return path.split("/").slice(0, -1).join("/");
290
- }
291
- // homedir() {
292
- // throw new Error("SysContainer:homedir is not available in seeded state");
293
- // }
294
- };
295
- pathOps = new pathOpsImpl();
296
- txtOps = {
297
- // eslint-disable-next-line no-restricted-globals
298
- encode: (input) => new TextEncoder().encode(input),
299
- // eslint-disable-next-line no-restricted-globals
300
- decode: (input) => new TextDecoder().decode(input)
301
- };
302
- _onSuperThis = /* @__PURE__ */ new Map();
303
- NotFoundError = class extends Error {
304
- constructor() {
305
- super(...arguments);
306
- this.code = "ENOENT";
307
- }
308
- };
309
- }
310
- });
311
-
312
- // src/runtime/gateways/file/get-file-system-static.ts
313
- async function getFileSystem(url) {
314
- const name = url.getParam("fs", "node");
315
- let fs;
316
- switch (name) {
317
- case "mem":
318
- fs = await externalLoaders.get(name).once(async () => {
319
- const { MemFileSystem } = await import("@fireproof/core/mem");
320
- return new MemFileSystem();
321
- });
322
- break;
323
- // case 'deno': {
324
- // const { DenoFileSystem } = await import("./deno-filesystem.js");
325
- // fs = new DenoFileSystem();
326
- // break;
327
- // }
328
- default:
329
- fs = await externalLoaders.get(name).once(async () => {
330
- const { NodeFileSystem } = await import("@fireproof/core/node");
331
- return new NodeFileSystem();
332
- });
333
- }
334
- return fs.start();
335
- }
336
- var import_cement4, externalLoaders;
337
- var init_get_file_system_static = __esm({
338
- "src/runtime/gateways/file/get-file-system-static.ts"() {
339
- "use strict";
340
- import_cement4 = require("@adviser/cement");
341
- externalLoaders = new import_cement4.KeyedResolvOnce();
342
- }
343
- });
344
-
345
- // src/runtime/gateways/file/utils.ts
346
- var utils_exports = {};
347
- __export(utils_exports, {
348
- getFileName: () => getFileName,
349
- getFileSystem: () => getFileSystem,
350
- getPath: () => getPath
351
- });
352
- function getPath(url, sthis) {
353
- const basePath = url.pathname;
354
- const name = url.getParam("name");
355
- if (name) {
356
- const version = url.getParam("version");
357
- if (!version) throw sthis.logger.Error().Url(url).Msg(`version not found`).AsError();
358
- return sthis.pathOps.join(basePath, version, name);
359
- }
360
- return sthis.pathOps.join(basePath);
361
- }
362
- function getFileName(url, sthis) {
363
- const key = url.getParam("key");
364
- if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
365
- const res = getStore(url, sthis, (...a) => a.join("-"));
366
- switch (res.store) {
367
- case "data":
368
- return sthis.pathOps.join(res.name, key + ".car");
369
- case "wal":
370
- case "meta":
371
- return sthis.pathOps.join(res.name, key + ".json");
372
- default:
373
- throw sthis.logger.Error().Url(url).Msg(`unsupported store type`).AsError();
374
- }
375
- }
376
- var init_utils2 = __esm({
377
- "src/runtime/gateways/file/utils.ts"() {
378
- "use strict";
379
- init_utils();
380
- init_get_file_system_static();
381
- }
382
- });
383
-
384
- // src/runtime/key-bag-file.ts
385
- var key_bag_file_exports = {};
386
- __export(key_bag_file_exports, {
387
- KeyBagProviderFile: () => KeyBagProviderFile
388
- });
389
- var KeyBagProviderFile;
390
- var init_key_bag_file = __esm({
391
- "src/runtime/key-bag-file.ts"() {
392
- "use strict";
393
- init_utils();
394
- KeyBagProviderFile = class {
395
- async _prepare(id) {
396
- await this.sthis.start();
397
- let sysFS;
398
- switch (this.url.protocol) {
399
- case "file:": {
400
- const { getFileSystem: getFileSystem2 } = await Promise.resolve().then(() => (init_utils2(), utils_exports));
401
- sysFS = await getFileSystem2(this.url);
402
- break;
403
- }
404
- default:
405
- throw this.logger.Error().Url(this.url).Msg("unsupported protocol").AsError();
406
- }
407
- const dirName = this.url.pathname;
408
- await sysFS.mkdir(dirName, { recursive: true });
409
- return {
410
- dirName,
411
- sysFS,
412
- fName: this.sthis.pathOps.join(dirName, `${id.replace(/[^a-zA-Z0-9]/g, "_")}.json`)
413
- };
414
- }
415
- constructor(url, sthis) {
416
- this.url = url;
417
- this.sthis = sthis;
418
- this.logger = sthis.logger;
419
- }
420
- async get(id) {
421
- const ctx = await this._prepare(id);
422
- try {
423
- const p = await ctx.sysFS.readfile(ctx.fName);
424
- const ki = JSON.parse(this.sthis.txt.decode(p));
425
- return ki;
426
- } catch (e) {
427
- if (isNotFoundError(e)) {
428
- return void 0;
429
- }
430
- throw this.logger.Error().Err(e).Str("file", ctx.dirName).Msg("read bag failed").AsError();
431
- }
432
- }
433
- async set(id, item) {
434
- const ctx = await this._prepare(id);
435
- const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
436
- await ctx.sysFS.writefile(ctx.fName, p);
437
- }
438
- };
439
- }
440
- });
441
-
442
- // src/runtime/key-bag-indexdb.ts
443
- var key_bag_indexdb_exports = {};
444
- __export(key_bag_indexdb_exports, {
445
- KeyBagProviderIndexDB: () => KeyBagProviderIndexDB
446
- });
447
- var import_idb, import_cement5, KeyBagProviderIndexDB;
448
- var init_key_bag_indexdb = __esm({
449
- "src/runtime/key-bag-indexdb.ts"() {
450
- "use strict";
451
- import_idb = require("idb");
452
- init_utils2();
453
- import_cement5 = require("@adviser/cement");
454
- KeyBagProviderIndexDB = class {
455
- constructor(url, sthis) {
456
- this._db = new import_cement5.ResolveOnce();
457
- this.sthis = sthis;
458
- this.logger = sthis.logger;
459
- this.url = url;
460
- this.dbName = getPath(this.url, this.sthis);
461
- }
462
- async _prepare() {
463
- return this._db.once(async () => {
464
- return await (0, import_idb.openDB)(this.dbName, 1, {
465
- upgrade(db) {
466
- ["bag"].map((store) => {
467
- db.createObjectStore(store, {
468
- autoIncrement: false
469
- });
470
- });
471
- }
472
- });
473
- });
474
- }
475
- async get(id) {
476
- const db = await this._prepare();
477
- const tx = db.transaction(["bag"], "readonly");
478
- const keyItem = await tx.objectStore("bag").get(id);
479
- await tx.done;
480
- if (!keyItem) {
481
- return void 0;
482
- }
483
- return keyItem;
484
- }
485
- async set(id, item) {
486
- const db = await this._prepare();
487
- const tx = db.transaction(["bag"], "readwrite");
488
- await tx.objectStore("bag").put(item, id);
489
- await tx.done;
490
- }
491
- };
492
- }
493
- });
494
-
495
- // src/runtime/gateways/file/version.ts
496
- var FILESTORE_VERSION;
497
- var init_version = __esm({
498
- "src/runtime/gateways/file/version.ts"() {
499
- "use strict";
500
- FILESTORE_VERSION = "v0.19-file";
501
- }
502
- });
503
-
504
- // src/runtime/gateways/file/gateway.ts
505
- var gateway_exports = {};
506
- __export(gateway_exports, {
507
- FileGateway: () => FileGateway,
508
- FileTestStore: () => FileTestStore
509
- });
510
- var import_cement11, versionFiles, FileGateway, FileTestStore;
511
- var init_gateway = __esm({
512
- "src/runtime/gateways/file/gateway.ts"() {
513
- "use strict";
514
- init_version();
515
- import_cement11 = require("@adviser/cement");
516
- init_utils();
517
- init_utils2();
518
- init_get_file_system_static();
519
- versionFiles = new import_cement11.KeyedResolvOnce();
520
- FileGateway = class {
521
- get fs() {
522
- if (!this._fs) throw this.logger.Error().Msg("fs not initialized").AsError();
523
- return this._fs;
524
- }
525
- constructor(sthis) {
526
- this.sthis = sthis;
527
- this.logger = sthis.logger;
528
- }
529
- async getVersionFromFile(path, logger) {
530
- return versionFiles.get(path).once(async () => {
531
- await this.fs.mkdir(path, { recursive: true });
532
- const vFile = this.sthis.pathOps.join(path, "version");
533
- const vFileStat = await this.fs.stat(vFile).catch(() => void 0);
534
- if (!vFileStat) {
535
- await this.fs.writefile(this.sthis.pathOps.join(path, "version"), FILESTORE_VERSION);
536
- return FILESTORE_VERSION;
537
- } else if (!vFileStat.isFile()) {
538
- throw logger.Error().Str("file", vFile).Msg(`version file is a directory`).AsError();
539
- }
540
- const v = await this.fs.readfile(vFile);
541
- const vStr = this.sthis.txt.decode(v);
542
- if (vStr !== FILESTORE_VERSION) {
543
- logger.Warn().Str("file", vFile).Str("from", vStr).Str("expected", FILESTORE_VERSION).Msg(`version mismatch`);
544
- }
545
- return vStr;
546
- });
547
- }
548
- start(baseURL) {
549
- return (0, import_cement11.exception2Result)(async () => {
550
- this._fs = await getFileSystem(baseURL);
551
- await this.fs.start();
552
- const url = baseURL.build();
553
- url.defParam("version", FILESTORE_VERSION);
554
- const dbUrl = await this.buildUrl(url.URI(), "dummy");
555
- const dbdirFile = this.getFilePath(dbUrl.Ok());
556
- await this.fs.mkdir(this.sthis.pathOps.dirname(dbdirFile), { recursive: true });
557
- const dbroot = this.sthis.pathOps.dirname(dbdirFile);
558
- this.logger.Debug().Url(url.URI()).Str("dbroot", dbroot).Msg("start");
559
- url.setParam("version", await this.getVersionFromFile(dbroot, this.logger));
560
- return url.URI();
561
- });
562
- }
563
- async buildUrl(baseUrl, key) {
564
- return import_cement11.Result.Ok(baseUrl.build().setParam("key", key).URI());
565
- }
566
- async close() {
567
- return import_cement11.Result.Ok(void 0);
568
- }
569
- // abstract buildUrl(baseUrl: URL, key: string): Promise<Result<URL>>;
570
- getFilePath(url) {
571
- const key = url.getParam("key");
572
- if (!key) throw this.logger.Error().Url(url).Msg(`key not found`).AsError();
573
- return this.sthis.pathOps.join(getPath(url, this.sthis), getFileName(url, this.sthis));
574
- }
575
- async put(url, body) {
576
- return (0, import_cement11.exception2Result)(async () => {
577
- const file = await this.getFilePath(url);
578
- this.logger.Debug().Str("url", url.toString()).Str("file", file).Msg("put");
579
- await this.fs.writefile(file, body);
580
- });
581
- }
582
- async get(url) {
583
- return exceptionWrapper(async () => {
584
- const file = this.getFilePath(url);
585
- try {
586
- const res = await this.fs.readfile(file);
587
- this.logger.Debug().Url(url.asURL()).Str("file", file).Msg("get");
588
- return import_cement11.Result.Ok(new Uint8Array(res));
589
- } catch (e) {
590
- if (isNotFoundError(e)) {
591
- return import_cement11.Result.Err(new NotFoundError(`file not found: ${file}`));
592
- }
593
- return import_cement11.Result.Err(e);
594
- }
595
- });
596
- }
597
- async delete(url) {
598
- return (0, import_cement11.exception2Result)(async () => {
599
- await this.fs.unlink(this.getFilePath(url));
600
- });
601
- }
602
- async destroy(baseURL) {
603
- const url = await this.buildUrl(baseURL, "x");
604
- if (url.isErr()) return url;
605
- const filepath = this.sthis.pathOps.dirname(this.getFilePath(url.Ok()));
606
- let files = [];
607
- try {
608
- files = await this.fs.readdir(filepath);
609
- } catch (e) {
610
- if (!isNotFoundError(e)) {
611
- throw this.logger.Error().Err(e).Str("dir", filepath).Msg("destroy:readdir").AsError();
612
- }
613
- }
614
- for (const file of files) {
615
- const pathed = this.sthis.pathOps.join(filepath, file);
616
- try {
617
- await this.fs.unlink(pathed);
618
- } catch (e) {
619
- if (!isNotFoundError(e)) {
620
- throw this.logger.Error().Err(e).Str("file", pathed).Msg("destroy:unlink").AsError();
621
- }
622
- }
623
- }
624
- return import_cement11.Result.Ok(void 0);
625
- }
626
- };
627
- FileTestStore = class {
628
- constructor(sthis) {
629
- this.logger = ensureLogger(sthis, "FileTestStore");
630
- this.sthis = sthis;
631
- }
632
- async get(iurl, key) {
633
- const url = iurl.build().setParam("key", key).URI();
634
- const dbFile = this.sthis.pathOps.join(getPath(url, this.sthis), getFileName(url, this.sthis));
635
- this.logger.Debug().Url(url).Str("dbFile", dbFile).Msg("get");
636
- const buffer = await (await getFileSystem(url)).readfile(dbFile);
637
- this.logger.Debug().Url(url).Str("dbFile", dbFile).Len(buffer).Msg("got");
638
- return buffer;
639
- }
640
- };
641
- }
642
- });
643
-
644
- // src/runtime/gateways/indexdb/gateway-import-static.ts
645
- function gatewayImport() {
646
- return import("@fireproof/core/web");
647
- }
648
- var init_gateway_import_static = __esm({
649
- "src/runtime/gateways/indexdb/gateway-import-static.ts"() {
650
- "use strict";
651
- }
652
- });
653
-
654
- // src/runtime/gateways/indexdb/gateway.ts
655
- var gateway_exports2 = {};
656
- __export(gateway_exports2, {
657
- IndexDBGateway: () => IndexDBGateway,
658
- IndexDBTestStore: () => IndexDBTestStore
659
- });
660
- var import_cement12, loadExternal, IndexDBGateway, IndexDBTestStore;
661
- var init_gateway2 = __esm({
662
- "src/runtime/gateways/indexdb/gateway.ts"() {
663
- "use strict";
664
- import_cement12 = require("@adviser/cement");
665
- init_gateway_import_static();
666
- loadExternal = new import_cement12.ResolveOnce();
667
- IndexDBGateway = class {
668
- constructor(sthis) {
669
- this.sthis = sthis;
670
- }
671
- getGateway() {
672
- return loadExternal.once(() => {
673
- return gatewayImport().then(({ IndexDBGatewayImpl }) => new IndexDBGatewayImpl(this.sthis));
674
- });
675
- }
676
- buildUrl(baseUrl, key) {
677
- return this.getGateway().then((gw) => gw.buildUrl(baseUrl, key));
678
- }
679
- start(baseUrl) {
680
- return this.getGateway().then((gw) => gw.start(baseUrl));
681
- }
682
- close(baseUrl) {
683
- return this.getGateway().then((gw) => gw.close(baseUrl));
684
- }
685
- destroy(baseUrl) {
686
- return this.getGateway().then((gw) => gw.destroy(baseUrl));
687
- }
688
- put(url, body) {
689
- return this.getGateway().then((gw) => gw.put(url, body));
690
- }
691
- get(url) {
692
- return this.getGateway().then((gw) => gw.get(url));
693
- }
694
- delete(url) {
695
- return this.getGateway().then((gw) => gw.delete(url));
696
- }
697
- // subscribe?(url: URI, callback: (meta: Uint8Array) => void): Promise<UnsubscribeResult> {
698
- // // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
699
- // return this.getGateway().then(gw => gw.subscribe!(url, callback));
700
- // }
701
- };
702
- IndexDBTestStore = class {
703
- constructor(sthis) {
704
- this.loadExternal = new import_cement12.ResolveOnce();
705
- this.sthis = sthis;
706
- }
707
- getGateway() {
708
- return this.loadExternal.once(() => {
709
- return gatewayImport().then(({ IndexDBTestStore: IndexDBTestStore2 }) => new IndexDBTestStore2(this.sthis));
710
- });
711
- }
712
- get(url, key) {
713
- return this.getGateway().then((gw) => gw.get(url, key));
714
- }
715
- };
716
- }
717
- });
718
-
719
- // src/index.ts
720
- var index_exports = {};
721
- __export(index_exports, {
722
- CRDT: () => CRDT,
723
- Database: () => Database,
724
- Index: () => Index,
725
- NotFoundError: () => NotFoundError,
726
- PACKAGE_VERSION: () => PACKAGE_VERSION,
727
- Result: () => import_cement.Result,
728
- UInt8ArrayEqual: () => UInt8ArrayEqual,
729
- blockstore: () => blockstore_exports,
730
- bs: () => blockstore_exports,
731
- dataDir: () => dataDir,
732
- ensureLogger: () => ensureLogger,
733
- ensureSuperLog: () => ensureSuperLog,
734
- ensureSuperThis: () => ensureSuperThis,
735
- exceptionWrapper: () => exceptionWrapper,
736
- falsyToUndef: () => falsyToUndef,
737
- fireproof: () => fireproof,
738
- getKey: () => getKey,
739
- getName: () => getName,
740
- getStore: () => getStore,
741
- index: () => index,
742
- isFalsy: () => isFalsy,
743
- isNotFoundError: () => isNotFoundError,
744
- onSuperThis: () => onSuperThis,
745
- rt: () => runtime_exports,
746
- runtime: () => runtime_exports,
747
- throwFalsy: () => throwFalsy
748
- });
749
- module.exports = __toCommonJS(index_exports);
750
-
751
- // src/database.ts
752
- var import_cement16 = require("@adviser/cement");
753
-
754
- // src/write-queue.ts
755
- function writeQueue(worker, payload = Infinity, unbounded = false) {
756
- const queue = [];
757
- let isProcessing = false;
758
- async function process() {
759
- if (isProcessing || queue.length === 0) return;
760
- isProcessing = true;
761
- const tasksToProcess = queue.splice(0, payload);
762
- const updates = tasksToProcess.map((item) => item.task);
763
- if (unbounded) {
764
- const promises = updates.map(async (update, index2) => {
765
- try {
766
- const result = await worker([update]);
767
- tasksToProcess[index2].resolve(result);
768
- } catch (error) {
769
- tasksToProcess[index2].reject(error);
770
- }
771
- });
772
- await Promise.all(promises);
773
- } else {
774
- try {
775
- const result = await worker(updates);
776
- tasksToProcess.forEach((task) => task.resolve(result));
777
- } catch (error) {
778
- tasksToProcess.forEach((task) => task.reject(error));
779
- }
381
+ function inplaceFilter(i, pred) {
382
+ const founds = [];
383
+ for (let j = 0; j < i.length; j++) {
384
+ if (!pred(i[j], j)) {
385
+ founds.push(j);
780
386
  }
781
- isProcessing = false;
782
- void process();
783
387
  }
784
- return {
785
- push(task) {
786
- return new Promise((resolve, reject) => {
787
- queue.push({ task, resolve, reject });
788
- void process();
789
- });
790
- }
791
- };
792
- }
793
-
794
- // src/crdt.ts
795
- var import_cement15 = require("@adviser/cement");
796
-
797
- // src/runtime/wait-pr-multiformats/block.ts
798
- var block_exports = {};
799
- __export(block_exports, {
800
- Block: () => Block,
801
- create: () => create,
802
- createUnsafe: () => createUnsafe,
803
- decode: () => decode,
804
- encode: () => encode
805
- });
806
- var import_multiformats = require("multiformats");
807
- var import_block = require("multiformats/block");
808
- var Block = import_block.Block;
809
- async function decode({
810
- bytes,
811
- codec: codec3,
812
- hasher: hasher7
813
- }) {
814
- if (bytes == null) throw new Error('Missing required argument "bytes"');
815
- if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
816
- const value = await Promise.resolve(codec3.decode(bytes));
817
- const hash = await hasher7.digest(bytes);
818
- const cid = import_multiformats.CID.create(1, codec3.code, hash);
819
- return new import_block.Block({ value, bytes, cid });
388
+ for (let j = founds.length - 1; j >= 0; j--) {
389
+ i.splice(founds[j], 1);
390
+ }
391
+ return i;
820
392
  }
821
- async function encode({
822
- value,
823
- codec: codec3,
824
- hasher: hasher7
825
- }) {
826
- if (typeof value === "undefined") throw new Error('Missing required argument "value"');
827
- if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
828
- const bytes = await Promise.resolve(codec3.encode(value));
829
- const hash = await hasher7.digest(bytes);
830
- const cid = import_multiformats.CID.create(1, codec3.code, hash);
831
- return new import_block.Block({ value, bytes, cid });
393
+ function toSortedArray(set) {
394
+ if (!set) return [];
395
+ return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
832
396
  }
833
- async function create({
834
- bytes,
835
- cid,
836
- hasher: hasher7,
837
- codec: codec3
838
- }) {
839
- if (bytes == null) throw new Error('Missing required argument "bytes"');
840
- if (hasher7 == null) throw new Error('Missing required argument "hasher"');
841
- const value = await Promise.resolve(codec3.decode(bytes));
842
- const hash = await hasher7.digest(bytes);
843
- if (!import_multiformats.bytes.equals(cid.multihash.bytes, hash.bytes)) {
844
- throw new Error("CID hash does not match bytes");
397
+ function coerceIntoUint8(raw2) {
398
+ if (raw2 instanceof Uint8Array) {
399
+ return import_cement.Result.Ok(raw2);
845
400
  }
846
- return createUnsafe({
847
- bytes,
848
- cid,
849
- value,
850
- codec: codec3
851
- });
401
+ if (import_cement.Result.Is(raw2)) {
402
+ return raw2;
403
+ }
404
+ return import_cement.Result.Err("Not a Uint8Array");
852
405
  }
853
- async function createUnsafe({
854
- bytes,
855
- cid,
856
- value: maybeValue,
857
- codec: codec3
858
- }) {
859
- const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
860
- if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
861
- return new Block({
862
- cid,
863
- bytes,
864
- value
865
- });
406
+ async function coercePromiseIntoUint8(raw2) {
407
+ if (raw2 instanceof Uint8Array) {
408
+ return import_cement.Result.Ok(raw2);
409
+ }
410
+ if (import_cement.Result.Is(raw2)) {
411
+ return raw2;
412
+ }
413
+ if (typeof raw2.then === "function") {
414
+ try {
415
+ return coercePromiseIntoUint8(await raw2);
416
+ } catch (e) {
417
+ return import_cement.Result.Err(e);
418
+ }
419
+ }
420
+ return import_cement.Result.Err("Not a Uint8Array");
866
421
  }
867
422
 
868
- // src/crdt-helpers.ts
869
- var import_link = require("multiformats/link");
870
- var import_sha25 = require("multiformats/hashes/sha2");
871
- var codec = __toESM(require("@fireproof/vendor/@ipld/dag-cbor"), 1);
872
- var import_crdt = require("@fireproof/vendor/@web3-storage/pail/crdt");
873
- var import_clock2 = require("@fireproof/vendor/@web3-storage/pail/clock");
874
- var Batch = __toESM(require("@fireproof/vendor/@web3-storage/pail/crdt/batch"), 1);
423
+ // src/write-queue.ts
424
+ var import_cement2 = require("@adviser/cement");
425
+ function defaultWriteQueueOpts(opts = {}) {
426
+ return {
427
+ ...opts,
428
+ chunkSize: opts.chunkSize && opts.chunkSize > 0 ? opts.chunkSize : 32
429
+ };
430
+ }
431
+ var WriteQueueImpl = class {
432
+ constructor(sthis, worker, opts) {
433
+ this.queue = [];
434
+ this.isProcessing = false;
435
+ this.logger = ensureLogger(sthis, "WriteQueueImpl");
436
+ this.worker = worker;
437
+ this.opts = defaultWriteQueueOpts(opts);
438
+ }
439
+ testEmptyQueue() {
440
+ if (this.waitForEmptyQueue && this.queue.length === 0) {
441
+ this.waitForEmptyQueue.resolve();
442
+ }
443
+ }
444
+ async process() {
445
+ if (this.isProcessing || this.queue.length === 0) {
446
+ this.testEmptyQueue();
447
+ return;
448
+ }
449
+ this.isProcessing = true;
450
+ try {
451
+ this.logger.Debug().Any("opts", this.opts).Len(this.queue).Msg("Processing tasks");
452
+ const tasksToProcess = this.queue.splice(0, this.opts.chunkSize);
453
+ const updates = tasksToProcess.map((item) => item.tasks).filter((item) => item);
454
+ const promises = updates.map(async (update, index2) => {
455
+ try {
456
+ const result = await this.worker(update);
457
+ tasksToProcess[index2].resolve(result);
458
+ } catch (error) {
459
+ tasksToProcess[index2].reject(this.logger.Error().Err(error).Msg("Error processing task").AsError());
460
+ }
461
+ });
462
+ await Promise.allSettled(promises);
463
+ this.logger.Debug().Any("opts", this.opts).Len(this.queue).Msg("Processed tasks");
464
+ } catch (error) {
465
+ this.logger.Error().Err(error).Msg("Error processing tasks");
466
+ } finally {
467
+ this.isProcessing = false;
468
+ setTimeout(() => this.process(), 0);
469
+ }
470
+ }
471
+ bulk(tasks) {
472
+ return new Promise((resolve, reject) => {
473
+ this.queue.push({ tasks, resolve, reject });
474
+ this.process();
475
+ });
476
+ }
477
+ push(task) {
478
+ return this.bulk([task]);
479
+ }
480
+ close() {
481
+ this.waitForEmptyQueue = new import_cement2.Future();
482
+ this.testEmptyQueue();
483
+ return this.waitForEmptyQueue.asPromise();
484
+ }
485
+ };
486
+ function writeQueue(sthis, worker, opts) {
487
+ return new WriteQueueImpl(sthis, worker, opts);
488
+ }
489
+
490
+ // src/crdt.ts
491
+ var import_cement19 = require("@adviser/cement");
875
492
 
876
493
  // src/blockstore/index.ts
877
494
  var blockstore_exports = {};
878
495
  __export(blockstore_exports, {
879
496
  BaseBlockstore: () => BaseBlockstore,
497
+ Car2FPMsg: () => Car2FPMsg,
880
498
  CarTransaction: () => CarTransaction,
881
499
  CompactionFetcher: () => CompactionFetcher,
882
500
  ConnectionBase: () => ConnectionBase,
501
+ DbMetaEventEqual: () => DbMetaEventEqual,
502
+ DbMetaEventsEqual: () => DbMetaEventsEqual,
883
503
  EncryptedBlockstore: () => EncryptedBlockstore,
884
- FragmentGateway: () => FragmentGateway,
504
+ FPEnvelopeType: () => FPEnvelopeType,
505
+ File2FPMsg: () => File2FPMsg,
506
+ InterceptorGateway: () => InterceptorGateway,
885
507
  Loader: () => Loader,
886
- addCryptoKeyToGatewayMetaPayload: () => addCryptoKeyToGatewayMetaPayload,
887
- ensureStart: () => ensureStart,
888
- getGatewayFromURL: () => getGatewayFromURL,
508
+ PassThroughGateway: () => PassThroughGateway,
509
+ createDbMetaEvent: () => createDbMetaEvent,
510
+ defaultGatewayFactoryItem: () => defaultGatewayFactoryItem,
511
+ ensureStoreEnDeFile: () => ensureStoreEnDeFile,
512
+ getDefaultURI: () => getDefaultURI,
513
+ getGatewayFactoryItem: () => getGatewayFactoryItem,
514
+ getStartedGateway: () => getStartedGateway,
889
515
  parseCarFile: () => parseCarFile,
890
516
  registerStoreProtocol: () => registerStoreProtocol,
891
- setCryptoKeyFromGatewayMetaPayload: () => setCryptoKeyFromGatewayMetaPayload,
892
- testStoreFactory: () => testStoreFactory,
893
517
  toCIDBlock: () => toCIDBlock,
894
518
  toStoreRuntime: () => toStoreRuntime
895
519
  });
@@ -898,9 +522,15 @@ __export(blockstore_exports, {
898
522
  function toCIDBlock(block) {
899
523
  return block;
900
524
  }
525
+ function DbMetaEventEqual(a, b) {
526
+ return a.eventCid.equals(b.eventCid) && a.parents.length === b.parents.length && a.parents.every((p, i) => p.equals(b.parents[i])) && a.dbMeta.cars.length === b.dbMeta.cars.length && a.dbMeta.cars.every((c, i) => c.equals(b.dbMeta.cars[i]));
527
+ }
528
+ function DbMetaEventsEqual(a, b) {
529
+ return a.length === b.length && a.every((e, i) => DbMetaEventEqual(e, b[i]));
530
+ }
901
531
 
902
532
  // src/blockstore/store-factory.ts
903
- var import_cement13 = require("@adviser/cement");
533
+ var import_cement17 = require("@adviser/cement");
904
534
 
905
535
  // src/runtime/files.ts
906
536
  var files_exports = {};
@@ -974,34 +604,84 @@ var UnixFSFileBuilder = class {
974
604
  };
975
605
 
976
606
  // src/blockstore/store.ts
977
- var import_dag_json2 = require("@fireproof/vendor/@ipld/dag-json");
978
607
  var import_cement10 = require("@adviser/cement");
979
608
 
980
- // src/types.ts
981
- function isFalsy(value) {
982
- return value === false && value === null && value === void 0;
983
- }
984
- function throwFalsy(value) {
985
- if (isFalsy(value)) {
986
- throw new Error("value is Falsy");
987
- }
988
- return value;
989
- }
990
- function falsyToUndef(value) {
991
- if (isFalsy(value)) {
992
- return void 0;
993
- }
994
- return value;
995
- }
996
-
997
- // src/blockstore/store.ts
998
- init_utils();
999
-
1000
609
  // src/blockstore/loader.ts
1001
610
  var import_p_limit = __toESM(require("p-limit"), 1);
1002
611
  var import_reader = require("@fireproof/vendor/@ipld/car/reader");
1003
612
  var import_cement7 = require("@adviser/cement");
1004
613
 
614
+ // src/runtime/wait-pr-multiformats/block.ts
615
+ var block_exports = {};
616
+ __export(block_exports, {
617
+ Block: () => Block,
618
+ create: () => create,
619
+ createUnsafe: () => createUnsafe,
620
+ decode: () => decode,
621
+ encode: () => encode
622
+ });
623
+ var import_multiformats = require("multiformats");
624
+ var import_block = require("multiformats/block");
625
+ var Block = import_block.Block;
626
+ async function decode({
627
+ bytes,
628
+ codec: codec3,
629
+ hasher: hasher7
630
+ }) {
631
+ if (bytes == null) throw new Error('Missing required argument "bytes"');
632
+ if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
633
+ const value = await Promise.resolve(codec3.decode(bytes));
634
+ const hash = await hasher7.digest(bytes);
635
+ const cid = import_multiformats.CID.create(1, codec3.code, hash);
636
+ return new import_block.Block({ value, bytes, cid });
637
+ }
638
+ async function encode({
639
+ value,
640
+ codec: codec3,
641
+ hasher: hasher7
642
+ }) {
643
+ if (typeof value === "undefined") throw new Error('Missing required argument "value"');
644
+ if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
645
+ const bytes = await Promise.resolve(codec3.encode(value));
646
+ const hash = await hasher7.digest(bytes);
647
+ const cid = import_multiformats.CID.create(1, codec3.code, hash);
648
+ return new import_block.Block({ value, bytes, cid });
649
+ }
650
+ async function create({
651
+ bytes,
652
+ cid,
653
+ hasher: hasher7,
654
+ codec: codec3
655
+ }) {
656
+ if (bytes == null) throw new Error('Missing required argument "bytes"');
657
+ if (hasher7 == null) throw new Error('Missing required argument "hasher"');
658
+ const value = await Promise.resolve(codec3.decode(bytes));
659
+ const hash = await hasher7.digest(bytes);
660
+ if (!import_multiformats.bytes.equals(cid.multihash.bytes, hash.bytes)) {
661
+ throw new Error("CID hash does not match bytes");
662
+ }
663
+ return createUnsafe({
664
+ bytes,
665
+ cid,
666
+ value,
667
+ codec: codec3
668
+ });
669
+ }
670
+ async function createUnsafe({
671
+ bytes,
672
+ cid,
673
+ value: maybeValue,
674
+ codec: codec3
675
+ }) {
676
+ const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
677
+ if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
678
+ return new Block({
679
+ cid,
680
+ bytes,
681
+ value
682
+ });
683
+ }
684
+
1005
685
  // src/blockstore/loader-helpers.ts
1006
686
  var import_sha2 = require("multiformats/hashes/sha2");
1007
687
  var dagCodec = __toESM(require("@fireproof/vendor/@ipld/dag-cbor"), 1);
@@ -1019,8 +699,7 @@ async function parseCarFile(reader, logger) {
1019
699
 
1020
700
  // src/blockstore/transaction.ts
1021
701
  var import_block3 = require("@fireproof/vendor/@web3-storage/pail/block");
1022
- var import_cement2 = require("@adviser/cement");
1023
- init_utils();
702
+ var import_cement3 = require("@adviser/cement");
1024
703
  var CarTransaction = class extends import_block3.MemoryBlockstore {
1025
704
  constructor(parent, opts = { add: true, noLoader: false }) {
1026
705
  super();
@@ -1038,7 +717,6 @@ var CarTransaction = class extends import_block3.MemoryBlockstore {
1038
717
  };
1039
718
  function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
1040
719
  const logger = ensureLogger(sthis, component, ctx);
1041
- const store = opts.store || {};
1042
720
  return {
1043
721
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1044
722
  applyMeta: (meta, snap) => {
@@ -1050,30 +728,27 @@ function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
1050
728
  },
1051
729
  autoCompact: 100,
1052
730
  public: false,
1053
- name: void 0,
731
+ // name: undefined,
1054
732
  threshold: 1e3 * 1e3,
1055
733
  ...opts,
1056
734
  logger,
1057
735
  keyBag: opts.keyBag || {},
1058
- crypto: (0, import_cement2.toCryptoRuntime)(opts.crypto),
1059
- store,
1060
- storeRuntime: toStoreRuntime(store, sthis)
736
+ crypto: (0, import_cement3.toCryptoRuntime)(opts.crypto),
737
+ storeUrls: opts.storeUrls,
738
+ // storeEnDeFile: ensureStoreEnDeFile(opts.storeEnDeFile),
739
+ // store,
740
+ storeRuntime: toStoreRuntime(sthis, ensureStoreEnDeFile(opts.storeEnDeFile))
1061
741
  };
1062
742
  }
1063
- function blockstoreFactory(sthis, opts) {
1064
- if (opts.name) {
1065
- return new EncryptedBlockstore(sthis, opts);
1066
- } else {
1067
- return new BaseBlockstore(opts);
1068
- }
1069
- }
1070
743
  var BaseBlockstore = class {
1071
- constructor(ebOpts = {}) {
744
+ constructor(ebOpts) {
1072
745
  this.transactions = /* @__PURE__ */ new Set();
1073
746
  this.sthis = ensureSuperThis(ebOpts);
1074
747
  this.ebOpts = defaultedBlockstoreRuntime(this.sthis, ebOpts, "BaseBlockstore");
1075
748
  this.logger = this.ebOpts.logger;
749
+ this.loader = new Loader(this.sthis, ebOpts);
1076
750
  }
751
+ // readonly name?: string;
1077
752
  // ready: Promise<void>;
1078
753
  ready() {
1079
754
  return Promise.resolve();
@@ -1097,8 +772,11 @@ var BaseBlockstore = class {
1097
772
  }
1098
773
  // TransactionMeta
1099
774
  async transaction(fn, _opts) {
775
+ this.logger.Debug().Msg("enter transaction");
1100
776
  const t = new CarTransaction(this, _opts);
777
+ this.logger.Debug().Msg("post CarTransaction");
1101
778
  const done = await fn(t);
779
+ this.logger.Debug().Msg("post fn");
1102
780
  this.lastTxMeta = done;
1103
781
  return { t, meta: done };
1104
782
  }
@@ -1107,7 +785,7 @@ var BaseBlockstore = class {
1107
785
  }
1108
786
  async commitTransaction(t, done, opts) {
1109
787
  if (!this.loader) throw this.logger.Error().Msg("loader required to commit").AsError();
1110
- const cars = await this.loader?.commit(t, done, opts);
788
+ const cars = await this.loader.commit(t, done, opts);
1111
789
  if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
1112
790
  setTimeout(() => void this.compact(), 10);
1113
791
  }
@@ -1132,14 +810,11 @@ var EncryptedBlockstore = class extends BaseBlockstore {
1132
810
  constructor(sthis, ebOpts) {
1133
811
  super(ebOpts);
1134
812
  this.compacting = false;
1135
- this.logger = ensureLogger(this.sthis, "EncryptedBlockstore");
1136
- const { name } = ebOpts;
1137
- if (!name) {
1138
- throw this.logger.Error().Msg("name required").AsError();
1139
- }
1140
- this.name = name;
1141
- this.loader = new Loader(this.name, ebOpts, sthis);
813
+ this.logger = ensureLogger(this.sthis, "EncryptedBlockstore", {
814
+ this: 1
815
+ });
1142
816
  }
817
+ // readonly name: string;
1143
818
  ready() {
1144
819
  return this.loader.ready();
1145
820
  }
@@ -1158,8 +833,11 @@ var EncryptedBlockstore = class extends BaseBlockstore {
1158
833
  return falsyToUndef(await this.loader.getBlock(cid));
1159
834
  }
1160
835
  async transaction(fn, opts = { noLoader: false }) {
836
+ this.logger.Debug().Msg("enter transaction");
1161
837
  const { t, meta: done } = await super.transaction(fn);
838
+ this.logger.Debug().Msg("post super.transaction");
1162
839
  const cars = await this.loader.commit(t, done, opts);
840
+ this.logger.Debug().Msg("post this.loader.commit");
1163
841
  if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
1164
842
  setTimeout(() => void this.compact(), 10);
1165
843
  }
@@ -1171,7 +849,7 @@ var EncryptedBlockstore = class extends BaseBlockstore {
1171
849
  }
1172
850
  async getFile(car, cid) {
1173
851
  await this.ready();
1174
- if (!this.loader) throw this.logger.Error().Msg("loader required to get file, database must be named").AsError();
852
+ if (!this.loader) throw this.logger.Error().Msg("loader required to get file, ledger must be named").AsError();
1175
853
  const reader = await this.loader.loadFileCar(
1176
854
  car
1177
855
  /*, isPublic */
@@ -1189,7 +867,7 @@ var EncryptedBlockstore = class extends BaseBlockstore {
1189
867
  const blockLog = new CompactionFetcher(this);
1190
868
  this.compacting = true;
1191
869
  const meta = await compactFn(blockLog);
1192
- await this.loader?.commit(blockLog.loggedBlocks, meta, {
870
+ await this.loader.commit(blockLog.loggedBlocks, meta, {
1193
871
  compact: true,
1194
872
  noLoader: true
1195
873
  });
@@ -1231,7 +909,7 @@ var CompactionFetcher = class {
1231
909
  };
1232
910
 
1233
911
  // src/blockstore/commit-queue.ts
1234
- var import_cement3 = require("@adviser/cement");
912
+ var import_cement4 = require("@adviser/cement");
1235
913
  var CommitQueue = class {
1236
914
  constructor() {
1237
915
  this.queue = [];
@@ -1242,7 +920,7 @@ var CommitQueue = class {
1242
920
  if (this.queue.length === 0 && !this.processing) {
1243
921
  return Promise.resolve();
1244
922
  }
1245
- const fn = new import_cement3.Future();
923
+ const fn = new import_cement4.Future();
1246
924
  this._waitIdleItems.add(fn);
1247
925
  return fn.asPromise();
1248
926
  }
@@ -1285,23 +963,103 @@ var CommitQueue = class {
1285
963
  var key_bag_exports = {};
1286
964
  __export(key_bag_exports, {
1287
965
  KeyBag: () => KeyBag,
966
+ defaultKeyBagOpts: () => defaultKeyBagOpts,
1288
967
  defaultKeyBagUrl: () => defaultKeyBagUrl,
1289
968
  getKeyBag: () => getKeyBag,
1290
969
  registerKeyBagProviderFactory: () => registerKeyBagProviderFactory
1291
970
  });
1292
971
  var import_cement6 = require("@adviser/cement");
1293
- init_utils();
1294
972
  var import_base582 = require("multiformats/bases/base58");
973
+
974
+ // src/runtime/gateways/file/sys-file-system-factory.ts
975
+ var import_cement5 = require("@adviser/cement");
976
+ function sysFileSystemFactory(uri) {
977
+ const rt = (0, import_cement5.runtimeFn)();
978
+ switch (true) {
979
+ case rt.isNodeIsh:
980
+ return import("@fireproof/core/node").then((m) => m.getSysFileSystem(uri));
981
+ case rt.isDeno:
982
+ return import("@fireproof/core/deno").then((m) => m.getSysFileSystem(uri));
983
+ default:
984
+ throw new Error(`unsupported runtime:${rt}`);
985
+ }
986
+ }
987
+
988
+ // src/runtime/gateways/file/key-bag-file.ts
989
+ var KeyBagProviderFile = class {
990
+ async _prepare(id) {
991
+ await this.sthis.start();
992
+ const sysFS = await sysFileSystemFactory(this.url);
993
+ const dirName = this.url.pathname;
994
+ await sysFS.mkdir(dirName, { recursive: true });
995
+ return {
996
+ dirName,
997
+ sysFS,
998
+ fName: this.sthis.pathOps.join(dirName, `${id.replace(/[^a-zA-Z0-9]/g, "_")}.json`)
999
+ };
1000
+ }
1001
+ constructor(url, sthis) {
1002
+ this.url = url;
1003
+ this.sthis = sthis;
1004
+ this.logger = sthis.logger;
1005
+ }
1006
+ async get(id) {
1007
+ const ctx = await this._prepare(id);
1008
+ try {
1009
+ const p = await ctx.sysFS.readfile(ctx.fName);
1010
+ const ki = JSON.parse(this.sthis.txt.decode(p));
1011
+ return ki;
1012
+ } catch (e) {
1013
+ if (isNotFoundError(e)) {
1014
+ return void 0;
1015
+ }
1016
+ throw this.logger.Error().Err(e).Str("file", ctx.dirName).Msg("read bag failed").AsError();
1017
+ }
1018
+ }
1019
+ async set(id, item) {
1020
+ const ctx = await this._prepare(id);
1021
+ const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
1022
+ await ctx.sysFS.writefile(ctx.fName, p);
1023
+ }
1024
+ };
1025
+
1026
+ // src/runtime/key-bag-memory.ts
1027
+ var memoryKeyBag = /* @__PURE__ */ new Map();
1028
+ var KeyBagProviderMemory = class {
1029
+ constructor(url, sthis) {
1030
+ this.url = url;
1031
+ this.sthis = sthis;
1032
+ }
1033
+ key(id) {
1034
+ return `${this.url.pathname}/${id}`;
1035
+ }
1036
+ async get(id) {
1037
+ const binKeyItem = memoryKeyBag.get(this.key(id));
1038
+ if (binKeyItem) {
1039
+ const ki = JSON.parse(this.sthis.txt.decode(binKeyItem));
1040
+ return ki;
1041
+ }
1042
+ return void 0;
1043
+ }
1044
+ async set(id, item) {
1045
+ const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
1046
+ memoryKeyBag.set(this.key(id), p);
1047
+ }
1048
+ };
1049
+
1050
+ // src/runtime/key-bag.ts
1295
1051
  var KeyBag = class {
1296
1052
  constructor(rt) {
1297
1053
  this.rt = rt;
1298
1054
  this._warnOnce = new import_cement6.ResolveOnce();
1299
1055
  this._seq = new import_cement6.ResolveSeq();
1300
- this.logger = ensureLogger(rt.sthis, "KeyBag");
1056
+ this.logger = ensureLogger(rt.sthis, "KeyBag", {
1057
+ // id: rt.id(),
1058
+ });
1301
1059
  this.logger.Debug().Msg("KeyBag created");
1302
1060
  }
1303
1061
  async subtleKey(key) {
1304
- const extractable = this.rt.url.getParam("extractKey") === "_deprecated_internal_api";
1062
+ const extractable = this.rt.url.getParam("extractKey" /* EXTRACTKEY */) === "_deprecated_internal_api";
1305
1063
  if (extractable) {
1306
1064
  this._warnOnce.once(
1307
1065
  () => this.logger.Warn().Msg("extractKey is enabled via _deprecated_internal_api --- handle keys safely!!!")
@@ -1318,7 +1076,7 @@ var KeyBag = class {
1318
1076
  );
1319
1077
  }
1320
1078
  async ensureKeyFromUrl(url, keyFactory) {
1321
- const storeKey = url.getParam("storekey");
1079
+ const storeKey = url.getParam("storekey" /* STORE_KEY */);
1322
1080
  if (storeKey === "insecure") {
1323
1081
  return import_cement6.Result.Ok(url);
1324
1082
  }
@@ -1328,7 +1086,7 @@ var KeyBag = class {
1328
1086
  if (ret.isErr()) {
1329
1087
  return ret;
1330
1088
  }
1331
- const urb = url.build().setParam("storekey", keyName);
1089
+ const urb = url.build().setParam("storekey" /* STORE_KEY */, keyName);
1332
1090
  return import_cement6.Result.Ok(urb.URI());
1333
1091
  }
1334
1092
  if (storeKey.startsWith("@") && storeKey.endsWith("@")) {
@@ -1404,15 +1162,20 @@ var keyBagProviderFactories = new Map(
1404
1162
  {
1405
1163
  protocol: "file:",
1406
1164
  factory: async (url, sthis) => {
1407
- const { KeyBagProviderFile: KeyBagProviderFile2 } = await Promise.resolve().then(() => (init_key_bag_file(), key_bag_file_exports));
1408
- return new KeyBagProviderFile2(url, sthis);
1165
+ return new KeyBagProviderFile(url, sthis);
1409
1166
  }
1410
1167
  },
1411
1168
  {
1412
1169
  protocol: "indexdb:",
1413
1170
  factory: async (url, sthis) => {
1414
- const { KeyBagProviderIndexDB: KeyBagProviderIndexDB2 } = await Promise.resolve().then(() => (init_key_bag_indexdb(), key_bag_indexdb_exports));
1415
- return new KeyBagProviderIndexDB2(url, sthis);
1171
+ const { KeyBagProviderImpl } = await import("@fireproof/core/web");
1172
+ return new KeyBagProviderImpl(url, sthis);
1173
+ }
1174
+ },
1175
+ {
1176
+ protocol: "memory:",
1177
+ factory: async (url, sthis) => {
1178
+ return new KeyBagProviderMemory(url, sthis);
1416
1179
  }
1417
1180
  }
1418
1181
  ].map((i) => [i.protocol, i])
@@ -1443,6 +1206,7 @@ function defaultKeyBagUrl(sthis) {
1443
1206
  return url;
1444
1207
  }
1445
1208
  function defaultKeyBagOpts(sthis, kbo) {
1209
+ kbo = kbo || {};
1446
1210
  if (kbo.keyRuntime) {
1447
1211
  return kbo.keyRuntime;
1448
1212
  }
@@ -1452,13 +1216,24 @@ function defaultKeyBagOpts(sthis, kbo) {
1452
1216
  url = import_cement6.URI.from(kbo.url);
1453
1217
  logger.Debug().Url(url).Msg("from opts");
1454
1218
  } else {
1455
- url = defaultKeyBagUrl(sthis);
1219
+ let bagFnameOrUrl = sthis.env.get("FP_KEYBAG_URL");
1220
+ if ((0, import_cement6.runtimeFn)().isBrowser) {
1221
+ url = import_cement6.URI.from(bagFnameOrUrl || "indexdb://fp-keybag");
1222
+ } else {
1223
+ if (!bagFnameOrUrl) {
1224
+ const home = sthis.env.get("HOME");
1225
+ bagFnameOrUrl = `${home}/.fireproof/keybag`;
1226
+ url = import_cement6.URI.from(`file://${bagFnameOrUrl}`);
1227
+ } else {
1228
+ url = import_cement6.URI.from(bagFnameOrUrl);
1229
+ }
1230
+ }
1231
+ logger.Debug().Url(url).Msg("from env");
1456
1232
  }
1457
1233
  const kitem = keyBagProviderFactories.get(url.protocol);
1458
1234
  if (!kitem) {
1459
1235
  throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
1460
1236
  }
1461
- const getBag = async () => kitem.factory(url, sthis);
1462
1237
  if (url.hasParam("masterkey")) {
1463
1238
  throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
1464
1239
  }
@@ -1468,7 +1243,7 @@ function defaultKeyBagOpts(sthis, kbo) {
1468
1243
  sthis,
1469
1244
  logger,
1470
1245
  keyLength: kbo.keyLength || 16,
1471
- getBag,
1246
+ getBag: () => kitem.factory(url, sthis),
1472
1247
  id: () => {
1473
1248
  return url.toString();
1474
1249
  }
@@ -1493,7 +1268,7 @@ async function encodeCarFile(roots, t, codec3) {
1493
1268
  size += CBW.blockLength({ cid, bytes });
1494
1269
  }
1495
1270
  const buffer = new Uint8Array(size);
1496
- const writer = CBW.createWriter(buffer, { headerSize });
1271
+ const writer = CBW.createWriter(buffer.buffer, { headerSize });
1497
1272
  for (const r of roots) {
1498
1273
  writer.addRoot(r);
1499
1274
  }
@@ -1587,7 +1362,6 @@ async function prepareCarFiles(encoder, threshold, rootBlock, t) {
1587
1362
  var import_sha23 = require("multiformats/hashes/sha2");
1588
1363
 
1589
1364
  // src/blockstore/task-manager.ts
1590
- init_utils();
1591
1365
  var TaskManager = class {
1592
1366
  constructor(sthis, callback) {
1593
1367
  // we need to remove the events after some time
@@ -1649,7 +1423,7 @@ function uniqueCids(list, remove = /* @__PURE__ */ new Set()) {
1649
1423
  return [...byString.values()];
1650
1424
  }
1651
1425
  var Loader = class {
1652
- constructor(name, ebOpts, sthis) {
1426
+ constructor(sthis, ebOpts) {
1653
1427
  this.commitQueue = new CommitQueue();
1654
1428
  this.isCompacting = false;
1655
1429
  this.carReaders = /* @__PURE__ */ new Map();
@@ -1659,14 +1433,17 @@ var Loader = class {
1659
1433
  this.getBlockCache = /* @__PURE__ */ new Map();
1660
1434
  this.seenMeta = /* @__PURE__ */ new Set();
1661
1435
  this.writeLimit = (0, import_p_limit.default)(1);
1436
+ this._carStore = new import_cement7.ResolveOnce();
1437
+ this._fileStore = new import_cement7.ResolveOnce();
1438
+ this._WALStore = new import_cement7.ResolveOnce();
1439
+ this._metaStore = new import_cement7.ResolveOnce();
1662
1440
  this.onceReady = new import_cement7.ResolveOnce();
1663
- this.name = name;
1664
1441
  this.sthis = sthis;
1665
1442
  this.ebOpts = defaultedBlockstoreRuntime(
1666
1443
  sthis,
1667
1444
  {
1668
- ...ebOpts,
1669
- name
1445
+ ...ebOpts
1446
+ // name,
1670
1447
  },
1671
1448
  "Loader"
1672
1449
  );
@@ -1675,21 +1452,52 @@ var Loader = class {
1675
1452
  await this.handleDbMetasFromStore([dbMeta]);
1676
1453
  });
1677
1454
  }
1678
- // readonly id = uuidv4();
1679
- async keyBag() {
1680
- return getKeyBag(this.sthis, this.ebOpts.keyBag);
1681
- }
1682
1455
  async carStore() {
1683
- return this.ebOpts.storeRuntime.makeDataStore(this);
1456
+ return this._carStore.once(
1457
+ async () => this.ebOpts.storeRuntime.makeDataStore({
1458
+ sthis: this.sthis,
1459
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1460
+ url: this.ebOpts.storeUrls.data,
1461
+ // keybag: await this.keyBag(),
1462
+ loader: this
1463
+ })
1464
+ );
1684
1465
  }
1685
1466
  async fileStore() {
1686
- return this.ebOpts.storeRuntime.makeDataStore(this);
1467
+ return this._fileStore.once(
1468
+ async () => this.ebOpts.storeRuntime.makeDataStore({
1469
+ sthis: this.sthis,
1470
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1471
+ url: this.ebOpts.storeUrls.file,
1472
+ // keybag: await this.keyBag(),
1473
+ loader: this
1474
+ })
1475
+ );
1687
1476
  }
1688
1477
  async WALStore() {
1689
- return this.ebOpts.storeRuntime.makeWALStore(this);
1478
+ return this._WALStore.once(
1479
+ async () => this.ebOpts.storeRuntime.makeWALStore({
1480
+ sthis: this.sthis,
1481
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1482
+ url: this.ebOpts.storeUrls.wal,
1483
+ // keybag: await this.keyBag(),
1484
+ loader: this
1485
+ })
1486
+ );
1690
1487
  }
1691
1488
  async metaStore() {
1692
- return this.ebOpts.storeRuntime.makeMetaStore(this);
1489
+ return this._metaStore.once(
1490
+ async () => this.ebOpts.storeRuntime.makeMetaStore({
1491
+ sthis: this.sthis,
1492
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1493
+ url: this.ebOpts.storeUrls.meta,
1494
+ // keybag: await this.keyBag(),
1495
+ loader: this
1496
+ })
1497
+ );
1498
+ }
1499
+ keyBag() {
1500
+ return getKeyBag(this.sthis, this.ebOpts.keyBag);
1693
1501
  }
1694
1502
  async ready() {
1695
1503
  return this.onceReady.once(async () => {
@@ -1702,6 +1510,7 @@ var Loader = class {
1702
1510
  });
1703
1511
  }
1704
1512
  async close() {
1513
+ await this.commitQueue.waitIdle();
1705
1514
  const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
1706
1515
  await Promise.all(toClose.map((store) => store.close()));
1707
1516
  }
@@ -1771,11 +1580,11 @@ var Loader = class {
1771
1580
  }
1772
1581
  async commit(t, done, opts = { noLoader: false, compact: false }) {
1773
1582
  await this.ready();
1774
- const fstore = await this.fileStore();
1583
+ const carStore = await this.carStore();
1775
1584
  const params = {
1776
- encoder: (await fstore.keyedCrypto()).codec(),
1585
+ encoder: (await carStore.keyedCrypto()).codec(),
1777
1586
  carLog: this.carLog,
1778
- carStore: fstore,
1587
+ carStore,
1779
1588
  WALStore: await this.WALStore(),
1780
1589
  metaStore: await this.metaStore(),
1781
1590
  threshold: this.ebOpts.threshold
@@ -1984,7 +1793,6 @@ __export(keyed_crypto_exports, {
1984
1793
  BlockIvKeyIdCodec: () => BlockIvKeyIdCodec,
1985
1794
  keyedCryptoFactory: () => keyedCryptoFactory
1986
1795
  });
1987
- init_utils();
1988
1796
  var import_base583 = require("multiformats/bases/base58");
1989
1797
  var import_sha24 = require("multiformats/hashes/sha2");
1990
1798
  var CBOR = __toESM(require("@fireproof/vendor/cborg"), 1);
@@ -2010,12 +1818,12 @@ var generateIV = {
2010
1818
  return hashArray;
2011
1819
  },
2012
1820
  verify: async function(ko, crypto, iv, data) {
2013
- return ko.url.getParam("ivverify") !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
1821
+ return ko.url.getParam("ivVerify" /* IV_VERIFY */) !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
2014
1822
  }
2015
1823
  }
2016
1824
  };
2017
1825
  function getGenerateIVFn(url, opts) {
2018
- const ivhash = opts.ivCalc || url.getParam("ivhash") || "hash";
1826
+ const ivhash = opts.ivCalc || url.getParam("ivHash" /* IV_HASH */) || "hash";
2019
1827
  return generateIV[ivhash] || generateIV["hash"];
2020
1828
  }
2021
1829
  var BlockIvKeyIdCodec = class {
@@ -2136,7 +1944,7 @@ var noCrypto = class {
2136
1944
  }
2137
1945
  };
2138
1946
  async function keyedCryptoFactory(url, kb, sthis) {
2139
- const storekey = url.getParam("storekey");
1947
+ const storekey = url.getParam("storekey" /* STORE_KEY */);
2140
1948
  if (storekey && storekey !== "insecure") {
2141
1949
  let rkey = await kb.getNamedKey(storekey, true);
2142
1950
  if (rkey.isErr()) {
@@ -2151,279 +1959,167 @@ async function keyedCryptoFactory(url, kb, sthis) {
2151
1959
  return new noCrypto(url, kb.rt.crypto, sthis);
2152
1960
  }
2153
1961
 
2154
- // src/blockstore/fragment-gateway.ts
1962
+ // src/blockstore/fp-envelope.ts
2155
1963
  var import_cement8 = require("@adviser/cement");
2156
- var import_base584 = require("multiformats/bases/base58");
2157
- var import_cborg = require("@fireproof/vendor/cborg");
2158
- init_utils();
2159
- function getFragSize(url) {
2160
- const fragSize = url.getParam("fragSize");
2161
- let ret = 0;
2162
- if (fragSize) {
2163
- ret = parseInt(fragSize);
2164
- }
2165
- if (isNaN(ret) || ret <= 0) {
2166
- ret = 0;
2167
- }
2168
- return ret;
1964
+ var FPEnvelopeType = /* @__PURE__ */ ((FPEnvelopeType2) => {
1965
+ FPEnvelopeType2["CAR"] = "car";
1966
+ FPEnvelopeType2["FILE"] = "file";
1967
+ FPEnvelopeType2["META"] = "meta";
1968
+ FPEnvelopeType2["WAL"] = "wal";
1969
+ return FPEnvelopeType2;
1970
+ })(FPEnvelopeType || {});
1971
+ function Car2FPMsg(fpcar) {
1972
+ return import_cement8.Result.Ok({ type: "car" /* CAR */, payload: fpcar });
2169
1973
  }
2170
- async function getFrags(url, innerGW, headerSize, logger) {
2171
- const fragSize = getFragSize(url);
2172
- if (!fragSize) {
2173
- const res = await innerGW.get(url);
2174
- if (res.isErr()) {
2175
- return [res];
2176
- }
2177
- const data = res.unwrap();
2178
- return [
2179
- import_cement8.Result.Ok({
2180
- fid: new Uint8Array(0),
2181
- ofs: 0,
2182
- len: data.length,
2183
- data
2184
- })
2185
- ];
2186
- }
2187
- const firstRaw = await innerGW.get(url.build().setParam("ofs", "0").URI());
2188
- if (firstRaw.isErr()) {
2189
- return [firstRaw];
2190
- }
2191
- const firstFragment = (0, import_cborg.decode)(firstRaw.unwrap());
2192
- const blockSize = firstFragment.data.length;
2193
- const ops = [Promise.resolve(import_cement8.Result.Ok(firstFragment))];
2194
- const fidStr = import_base584.base58btc.encode(firstFragment.fid);
2195
- const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
2196
- for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
2197
- ops.push(
2198
- (async (furl, ofs2) => {
2199
- const raw2 = await innerGW.get(furl);
2200
- if (raw2.isErr()) {
2201
- return raw2;
2202
- }
2203
- const fragment = (0, import_cborg.decode)(raw2.unwrap());
2204
- if (import_base584.base58btc.encode(fragment.fid) !== fidStr) {
2205
- return import_cement8.Result.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
2206
- }
2207
- if (fragment.ofs !== ofs2) {
2208
- return import_cement8.Result.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
2209
- }
2210
- return import_cement8.Result.Ok(fragment);
2211
- })(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
2212
- );
1974
+ function File2FPMsg(fpfile) {
1975
+ return import_cement8.Result.Ok({ type: "file" /* FILE */, payload: fpfile });
1976
+ }
1977
+
1978
+ // src/blockstore/store.ts
1979
+ var import_clock = require("@fireproof/vendor/@web3-storage/pail/clock");
1980
+ var import_dag_json = require("@fireproof/vendor/@ipld/dag-json");
1981
+ var import_p_retry = __toESM(require("p-retry"), 1);
1982
+ var import_p_map = __toESM(require("p-map"), 1);
1983
+
1984
+ // src/blockstore/interceptor-gateway.ts
1985
+ var import_cement9 = require("@adviser/cement");
1986
+ var PassThroughGateway = class {
1987
+ async buildUrl(sthis, url, key) {
1988
+ const op = { url, key };
1989
+ return import_cement9.Result.Ok({ op });
1990
+ }
1991
+ async start(sthis, url) {
1992
+ const op = { url };
1993
+ return import_cement9.Result.Ok({ op });
1994
+ }
1995
+ async close(sthis, url) {
1996
+ const op = { url };
1997
+ return import_cement9.Result.Ok({ op });
1998
+ }
1999
+ async delete(sthis, url) {
2000
+ const op = { url };
2001
+ return import_cement9.Result.Ok({ op });
2002
+ }
2003
+ async destroy(sthis, url) {
2004
+ const op = { url };
2005
+ return import_cement9.Result.Ok({ op });
2006
+ }
2007
+ async put(sthis, url, body) {
2008
+ const op = { url, body };
2009
+ return import_cement9.Result.Ok({ op });
2010
+ }
2011
+ async get(sthis, url) {
2012
+ const op = { url };
2013
+ return import_cement9.Result.Ok({ op });
2213
2014
  }
2214
- return Promise.all(ops);
2215
- }
2216
- var FragmentGateway = class {
2217
- constructor(sthis, innerGW) {
2218
- this.fidLength = 4;
2219
- this.headerSize = 32;
2220
- this.sthis = ensureSuperLog(sthis, "FragmentGateway");
2221
- this.logger = this.sthis.logger;
2015
+ async subscribe(sthis, url, callback) {
2016
+ const op = { url, callback };
2017
+ return import_cement9.Result.Ok({ op });
2018
+ }
2019
+ };
2020
+ var passThrougthGateway = new PassThroughGateway();
2021
+ var InterceptorGateway = class {
2022
+ constructor(sthis, innerGW, interceptor) {
2222
2023
  this.innerGW = innerGW;
2024
+ this.interceptor = interceptor || passThrougthGateway;
2223
2025
  }
2224
- slicer(url, body) {
2225
- const fragSize = getFragSize(url);
2226
- if (!fragSize) {
2227
- return [this.innerGW.put(url, body)];
2228
- }
2229
- const blocksize = fragSize - this.headerSize;
2230
- if (blocksize <= 0) {
2231
- throw this.logger.Error().Uint64("fragSize", fragSize).Uint64("headerSize", this.headerSize).Msg("Fragment size is too small").AsError();
2232
- }
2233
- const ops = [];
2234
- const fid = this.sthis.nextId(this.fidLength);
2235
- const fragUrl = url.build().setParam("fid", fid.str).setParam("len", body.length.toString()).setParam("headerSize", this.headerSize.toString());
2236
- for (let ofs = 0; ofs < body.length; ofs += blocksize) {
2237
- const block = (0, import_cborg.encode)({
2238
- fid: fid.bin,
2239
- ofs,
2240
- len: body.length,
2241
- data: body.slice(ofs, ofs + blocksize)
2242
- });
2243
- if (block.length > fragSize) {
2244
- throw this.logger.Error().Uint64("block", block.length).Uint64("fragSize", fragSize).Msg("Block size to big").AsError();
2245
- }
2246
- ops.push(this.innerGW.put(fragUrl.setParam("ofs", ofs.toString()).URI(), block));
2026
+ async buildUrl(sthis, baseUrl, key, loader) {
2027
+ const rret = await this.interceptor.buildUrl(sthis, baseUrl, key, loader);
2028
+ if (rret.isErr()) {
2029
+ return import_cement9.Result.Err(rret.Err());
2030
+ }
2031
+ const ret = rret.unwrap();
2032
+ if (ret.stop && ret.value) {
2033
+ return ret.value;
2247
2034
  }
2248
- return ops;
2035
+ return this.innerGW.buildUrl(sthis, ret.op.url, ret.op.key, loader);
2249
2036
  }
2250
- buildUrl(baseUrl, key) {
2251
- return this.innerGW.buildUrl(baseUrl, key);
2252
- }
2253
- async destroy(iurl) {
2254
- return this.innerGW.destroy(iurl);
2255
- }
2256
- async start(url) {
2257
- this.headerSize = (0, import_cborg.encode)({
2258
- fid: this.sthis.nextId(this.fidLength).bin,
2259
- ofs: 1024 * 1024,
2260
- // 32bit
2261
- len: 16 * 1024 * 1024,
2262
- // 32bit
2263
- data: new Uint8Array(1024)
2264
- }).length - 1024;
2265
- return this.innerGW.start(url);
2266
- }
2267
- async close(url) {
2268
- return this.innerGW.close(url);
2269
- }
2270
- async put(url, body) {
2271
- await Promise.all(this.slicer(url, body));
2272
- return import_cement8.Result.Ok(void 0);
2273
- }
2274
- async get(url) {
2275
- const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
2276
- let buffer = void 0;
2277
- for (const rfrag of rfrags) {
2278
- if (rfrag.isErr()) {
2279
- return import_cement8.Result.Err(rfrag.Err());
2280
- }
2281
- const frag = rfrag.Ok();
2282
- buffer = buffer || new Uint8Array(frag.len);
2283
- buffer.set(frag.data, frag.ofs);
2037
+ async destroy(sthis, iurl, loader) {
2038
+ const rret = await this.interceptor.destroy(sthis, iurl, loader);
2039
+ if (rret.isErr()) {
2040
+ return import_cement9.Result.Err(rret.Err());
2284
2041
  }
2285
- return import_cement8.Result.Ok(buffer || new Uint8Array(0));
2042
+ const ret = rret.unwrap();
2043
+ if (ret.stop && ret.value) {
2044
+ return ret.value;
2045
+ }
2046
+ return this.innerGW.destroy(sthis, ret.op.url, loader);
2286
2047
  }
2287
- async subscribe(url, callback) {
2288
- if (this.innerGW.subscribe) {
2289
- return this.innerGW.subscribe(url, callback);
2290
- } else {
2291
- return import_cement8.Result.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
2048
+ async start(sthis, url, loader) {
2049
+ const rret = await this.interceptor.start(sthis, url, loader);
2050
+ if (rret.isErr()) {
2051
+ return import_cement9.Result.Err(rret.Err());
2292
2052
  }
2053
+ const ret = rret.unwrap();
2054
+ if (ret.stop && ret.value) {
2055
+ return ret.value;
2056
+ }
2057
+ return await this.innerGW.start(sthis, ret.op.url, loader);
2293
2058
  }
2294
- async delete(url) {
2295
- const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
2296
- for (const rfrag of rfrags) {
2297
- if (rfrag.isErr()) {
2298
- return import_cement8.Result.Err(rfrag.Err());
2299
- }
2300
- const frag = rfrag.Ok();
2301
- const fidStr = import_base584.base58btc.encode(frag.fid);
2302
- const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
2303
- await this.innerGW.delete(fragUrl);
2059
+ async close(sthis, url, loader) {
2060
+ const rret = await this.interceptor.close(sthis, url, loader);
2061
+ if (rret.isErr()) {
2062
+ return import_cement9.Result.Err(rret.Err());
2304
2063
  }
2305
- return import_cement8.Result.Ok(void 0);
2064
+ const ret = rret.unwrap();
2065
+ if (ret.stop && ret.value) {
2066
+ return ret.value;
2067
+ }
2068
+ return await this.innerGW.close(sthis, ret.op.url, loader);
2306
2069
  }
2307
- };
2308
-
2309
- // src/blockstore/meta-key-helper.ts
2310
- var import_dag_json = require("@fireproof/vendor/@ipld/dag-json");
2311
- var import_clock = require("@fireproof/vendor/@web3-storage/pail/clock");
2312
- var import_multiformats2 = require("multiformats");
2313
- var import_base64 = require("multiformats/bases/base64");
2314
- var import_cement9 = require("@adviser/cement");
2315
- init_utils();
2316
- async function decodeGatewayMetaBytesToDbMeta(sthis, byteHeads) {
2317
- const crdtEntries = JSON.parse(sthis.txt.decode(byteHeads));
2318
- if (!Array.isArray(crdtEntries)) {
2319
- sthis.logger.Debug().Str("crdtEntries", JSON.stringify(crdtEntries)).Msg("No data in CRDT entries");
2320
- return [];
2321
- }
2322
- if (!crdtEntries.length) {
2323
- sthis.logger.Debug().Any("byteHeads", byteHeads).Msg("No CRDT entries found");
2324
- return [];
2325
- }
2326
- const logger = ensureLogger(sthis, "decodeGatewayMetaBytesToDbMeta");
2327
- return Promise.all(
2328
- crdtEntries.map(async (crdtEntry) => {
2329
- const eventBlock = await (0, import_clock.decodeEventBlock)(import_base64.base64pad.decode(crdtEntry.data));
2330
- const dbMeta = (0, import_dag_json.parse)(sthis.txt.decode(eventBlock.value.data.dbMeta));
2331
- logger.Debug().Any("crdtEntry", {
2332
- crdtEntry,
2333
- eventBlock,
2334
- dbMeta,
2335
- dbMetaStrings: dbMeta.cars.map((car) => car.toString())
2336
- }).Msg("CRDT entry");
2337
- return {
2338
- eventCid: eventBlock.cid,
2339
- parents: crdtEntry.parents,
2340
- dbMeta
2341
- };
2342
- })
2343
- );
2344
- }
2345
- async function setCryptoKeyFromGatewayMetaPayload(uri, sthis, data) {
2346
- try {
2347
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Setting crypto key from gateway meta payload");
2348
- const keyInfo = await decodeGatewayMetaBytesToDbMeta(sthis, data);
2349
- if (keyInfo.length) {
2350
- const dbMeta = keyInfo[0].dbMeta;
2351
- if (dbMeta.key) {
2352
- const kb = await getKeyBag(sthis);
2353
- const keyName = getStoreKeyName(uri);
2354
- const res = await kb.setNamedKey(keyName, dbMeta.key);
2355
- if (res.isErr()) {
2356
- sthis.logger.Debug().Str("keyName", keyName).Str("dbMeta.key", dbMeta.key).Msg("Failed to set named key");
2357
- throw res.Err();
2358
- }
2359
- }
2360
- sthis.logger.Debug().Str("dbMeta.key", dbMeta.key).Str("uri", uri.toString()).Msg("Set crypto key from gateway meta payload");
2361
- return import_cement9.Result.Ok(dbMeta);
2070
+ async put(sthis, url, fpEnv, loader) {
2071
+ const rret = await this.interceptor.put(sthis, url, fpEnv, loader);
2072
+ if (rret.isErr()) {
2073
+ return import_cement9.Result.Err(rret.Err());
2074
+ }
2075
+ const ret = rret.unwrap();
2076
+ if (ret.stop && ret.value) {
2077
+ return ret.value;
2362
2078
  }
2363
- sthis.logger.Debug().Any("data", data).Msg("No crypto in gateway meta payload");
2364
- return import_cement9.Result.Ok(void 0);
2365
- } catch (error) {
2366
- sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
2367
- return import_cement9.Result.Err(error);
2079
+ return this.innerGW.put(sthis, ret.op.url, ret.op.body, loader);
2368
2080
  }
2369
- }
2370
- async function addCryptoKeyToGatewayMetaPayload(uri, sthis, body) {
2371
- try {
2372
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Adding crypto key to gateway meta payload");
2373
- const keyName = getStoreKeyName(uri);
2374
- const kb = await getKeyBag(sthis);
2375
- const res = await kb.getNamedExtractableKey(keyName, true);
2376
- if (res.isErr()) {
2377
- sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
2378
- throw res.Err();
2081
+ async get(sthis, url, loader) {
2082
+ const rret = await this.interceptor.get(sthis, url, loader);
2083
+ if (rret.isErr()) {
2084
+ return import_cement9.Result.Err(rret.Err());
2085
+ }
2086
+ const ret = rret.unwrap();
2087
+ if (ret.stop && ret.value) {
2088
+ return ret.value;
2379
2089
  }
2380
- const keyData = await res.Ok().extract();
2381
- const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
2382
- const { dbMeta, parents } = dbMetas[0];
2383
- const parentLinks = parents.map((p) => import_multiformats2.CID.parse(p));
2384
- dbMeta.key = keyData.keyStr;
2385
- const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
2386
- const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
2387
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
2388
- return import_cement9.Result.Ok(encoded);
2389
- } catch (error) {
2390
- sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
2391
- return import_cement9.Result.Err(error);
2090
+ return this.innerGW.get(sthis, ret.op.url, loader);
2392
2091
  }
2393
- }
2394
- function getStoreKeyName(url) {
2395
- const storeKeyName = [url.getParam("localName") || url.getParam("name")];
2396
- const idx = url.getParam("index");
2397
- if (idx) {
2398
- storeKeyName.push(idx);
2399
- }
2400
- storeKeyName.push("data");
2401
- return `@${storeKeyName.join(":")}@`;
2402
- }
2403
- async function createDbMetaEventBlock(sthis, dbMeta, parents) {
2404
- const event = await import_clock.EventBlock.create(
2405
- {
2406
- dbMeta: sthis.txt.encode((0, import_dag_json.format)(dbMeta))
2407
- },
2408
- parents
2409
- );
2410
- return event;
2411
- }
2412
- async function encodeEventsWithParents(sthis, events, parents) {
2413
- const crdtEntries = events.map((event) => {
2414
- const base64String = import_base64.base64pad.encode(event.bytes);
2415
- return {
2416
- cid: event.cid.toString(),
2417
- data: base64String,
2418
- parents: parents.map((p) => p.toString())
2419
- };
2420
- });
2421
- return sthis.txt.encode(JSON.stringify(crdtEntries));
2422
- }
2092
+ async subscribe(sthis, url, callback, loader) {
2093
+ if (!this.innerGW.subscribe) {
2094
+ return import_cement9.Result.Err(sthis.logger.Error().Url(url).Msg("subscribe not supported").AsError());
2095
+ }
2096
+ const rret = await this.interceptor.subscribe(sthis, url, callback, loader);
2097
+ if (rret.isErr()) {
2098
+ return import_cement9.Result.Err(rret.Err());
2099
+ }
2100
+ const ret = rret.unwrap();
2101
+ if (ret.stop && ret.value) {
2102
+ return ret.value;
2103
+ }
2104
+ return this.innerGW.subscribe(sthis, ret.op.url, ret.op.callback, loader);
2105
+ }
2106
+ async delete(sthis, url, loader) {
2107
+ const rret = await this.interceptor.delete(sthis, url, loader);
2108
+ if (rret.isErr()) {
2109
+ return import_cement9.Result.Err(rret.Err());
2110
+ }
2111
+ const ret = rret.unwrap();
2112
+ if (ret.stop && ret.value) {
2113
+ return ret.value;
2114
+ }
2115
+ return this.innerGW.delete(sthis, url, loader);
2116
+ }
2117
+ async getPlain(sthis, url, key, loader) {
2118
+ return this.innerGW.getPlain(sthis, url, key, loader);
2119
+ }
2120
+ };
2423
2121
 
2424
2122
  // src/blockstore/store.ts
2425
- var import_p_retry = __toESM(require("p-retry"), 1);
2426
- var import_p_map = __toESM(require("p-map"), 1);
2427
2123
  function guardVersion(url) {
2428
2124
  if (!url.hasParam("version")) {
2429
2125
  return import_cement10.Result.Err(`missing version: ${url.toString()}`);
@@ -2431,16 +2127,21 @@ function guardVersion(url) {
2431
2127
  return import_cement10.Result.Ok(url);
2432
2128
  }
2433
2129
  var BaseStoreImpl = class {
2434
- constructor(name, url, opts, sthis, logger) {
2130
+ // readonly loader: Loadable;
2131
+ constructor(sthis, url, opts, logger) {
2435
2132
  this._onStarted = [];
2436
2133
  this._onClosed = [];
2437
- this.name = name;
2438
2134
  this._url = url;
2439
- this.keybag = opts.keybag;
2440
- this.sthis = sthis;
2441
- this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
2442
- this.gateway = new FragmentGateway(this.sthis, opts.gateway);
2135
+ this.opts = opts;
2443
2136
  this.loader = opts.loader;
2137
+ this.sthis = sthis;
2138
+ const name = this._url.getParam("name" /* NAME */);
2139
+ if (!name) {
2140
+ throw logger.Error().Url(this._url).Msg("missing name").AsError();
2141
+ }
2142
+ this.logger = logger.With().Str("this", this.sthis.nextId().str).Ref("url", () => this._url.toString()).Logger();
2143
+ this.realGateway = opts.gateway;
2144
+ this.gateway = new InterceptorGateway(this.sthis, opts.gateway, opts.gatewayInterceptor);
2444
2145
  }
2445
2146
  url() {
2446
2147
  return this._url;
@@ -2455,21 +2156,21 @@ var BaseStoreImpl = class {
2455
2156
  return;
2456
2157
  }
2457
2158
  async keyedCrypto() {
2458
- return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
2159
+ return keyedCryptoFactory(this._url, await this.loader.keyBag(), this.sthis);
2459
2160
  }
2460
2161
  async start() {
2461
2162
  this.logger.Debug().Str("storeType", this.storeType).Msg("starting-gateway-pre");
2462
- this._url = this._url.build().setParam("store", this.storeType).URI();
2463
- const res = await this.gateway.start(this._url);
2163
+ this._url = this._url.build().setParam("store" /* STORE */, this.storeType).URI();
2164
+ const res = await this.gateway.start(this.sthis, this._url, this.loader);
2464
2165
  if (res.isErr()) {
2465
2166
  this.logger.Error().Result("gw-start", res).Msg("started-gateway");
2466
2167
  return res;
2467
2168
  }
2468
2169
  this._url = res.Ok();
2469
- const kb = await this.keybag();
2170
+ const kb = await this.loader.keyBag();
2470
2171
  const skRes = await kb.ensureKeyFromUrl(this._url, () => {
2471
- const idx = this._url.getParam("index");
2472
- const storeKeyName = [this.name];
2172
+ const idx = this._url.getParam("index" /* INDEX */);
2173
+ const storeKeyName = [this.url().getParam("name" /* NAME */)];
2473
2174
  if (idx) {
2474
2175
  storeKeyName.push(idx);
2475
2176
  }
@@ -2499,10 +2200,23 @@ var BaseStoreImpl = class {
2499
2200
  return version;
2500
2201
  }
2501
2202
  };
2203
+ async function createDbMetaEvent(sthis, dbMeta, parents) {
2204
+ const event = await import_clock.EventBlock.create(
2205
+ {
2206
+ dbMeta: sthis.txt.encode((0, import_dag_json.format)(dbMeta))
2207
+ },
2208
+ parents
2209
+ );
2210
+ return {
2211
+ eventCid: event.cid,
2212
+ dbMeta,
2213
+ parents
2214
+ };
2215
+ }
2502
2216
  var MetaStoreImpl = class extends BaseStoreImpl {
2503
2217
  // remote: boolean;
2504
- constructor(sthis, name, url, opts) {
2505
- super(name, url, { ...opts }, sthis, ensureLogger(sthis, "MetaStoreImpl"));
2218
+ constructor(sthis, url, opts) {
2219
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "MetaStoreImpl"));
2506
2220
  this.storeType = "meta";
2507
2221
  this.subscribers = /* @__PURE__ */ new Map();
2508
2222
  this.parents = [];
@@ -2512,14 +2226,18 @@ var MetaStoreImpl = class extends BaseStoreImpl {
2512
2226
  ) {
2513
2227
  this.onStarted(async () => {
2514
2228
  this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
2515
- opts.gateway.subscribe?.(this.url(), async (message) => {
2516
- this.logger.Debug().Msg("Received message from gateway");
2517
- const dbMetas = await decodeGatewayMetaBytesToDbMeta(this.sthis, message);
2518
- await Promise.all(
2519
- dbMetas.map((dbMeta) => this.loader?.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
2520
- );
2521
- this.updateParentsFromDbMetas(dbMetas);
2522
- });
2229
+ opts.gateway.subscribe?.(
2230
+ this.sthis,
2231
+ this.url(),
2232
+ async ({ payload: dbMetas }) => {
2233
+ this.logger.Debug().Msg("Received message from gateway");
2234
+ await Promise.all(
2235
+ dbMetas.map((dbMeta) => this.loader.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
2236
+ );
2237
+ this.updateParentsFromDbMetas(dbMetas);
2238
+ },
2239
+ this.loader
2240
+ );
2523
2241
  });
2524
2242
  }
2525
2243
  }
@@ -2530,129 +2248,165 @@ var MetaStoreImpl = class extends BaseStoreImpl {
2530
2248
  const dbMetaParentsSet = new Set(dbMetaParents.map((p) => p.toString()));
2531
2249
  this.parents = Array.from(uniqueParentsMap.values()).filter((p) => !dbMetaParentsSet.has(p.toString()));
2532
2250
  }
2533
- async handleByteHeads(byteHeads) {
2534
- return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
2535
- }
2251
+ // async handleByteHeads(byteHeads: Uint8Array) {
2252
+ // // return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
2253
+ // const rDbMeta = await fpDeserialize(this.sthis, byteHeads, this.url());
2254
+ // if (rDbMeta.isErr()) {
2255
+ // throw this.logger.Error().Err(rDbMeta).Msg("error deserializing").AsError();
2256
+ // }
2257
+ // return (rDbMeta.Ok() as FPEnvelopeMeta).payload;
2258
+ // }
2536
2259
  async load() {
2537
2260
  const branch = "main";
2538
- const url = await this.gateway.buildUrl(this.url(), branch);
2261
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), branch, this.loader);
2539
2262
  if (url.isErr()) {
2540
2263
  throw this.logger.Error().Result("buildUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
2541
2264
  }
2542
- const bytes = await this.gateway.get(url.Ok());
2543
- if (bytes.isErr()) {
2544
- if (isNotFoundError(bytes)) {
2265
+ const rfpEnv = await this.gateway.get(this.sthis, url.Ok(), this.loader);
2266
+ if (rfpEnv.isErr()) {
2267
+ if (isNotFoundError(rfpEnv)) {
2545
2268
  return void 0;
2546
2269
  }
2547
- throw this.logger.Error().Url(url.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
2270
+ throw this.logger.Error().Url(url.Ok()).Err(rfpEnv).Msg("gateway get").AsError();
2548
2271
  }
2549
- const dbMetas = await this.handleByteHeads(bytes.Ok());
2550
- await this.loader?.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
2272
+ const dbMetas = rfpEnv.Ok().payload;
2273
+ await this.loader.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
2551
2274
  this.updateParentsFromDbMetas(dbMetas);
2552
2275
  return dbMetas.map((m) => m.dbMeta);
2553
2276
  }
2554
2277
  async save(meta, branch) {
2555
2278
  branch = branch || "main";
2556
2279
  this.logger.Debug().Str("branch", branch).Any("meta", meta).Msg("saving meta");
2557
- const event = await createDbMetaEventBlock(this.sthis, meta, this.parents);
2558
- const bytes = await encodeEventsWithParents(this.sthis, [event], this.parents);
2559
- const url = await this.gateway.buildUrl(this.url(), branch);
2280
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), branch, this.loader);
2560
2281
  if (url.isErr()) {
2561
2282
  throw this.logger.Error().Err(url.Err()).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
2562
2283
  }
2563
- this.parents = [event.cid];
2564
- const res = await this.gateway.put(url.Ok(), bytes);
2284
+ const dbMetaEvent = await createDbMetaEvent(this.sthis, meta, this.parents);
2285
+ const res = await this.gateway.put(
2286
+ this.sthis,
2287
+ url.Ok(),
2288
+ {
2289
+ type: "meta",
2290
+ payload: [dbMetaEvent]
2291
+ },
2292
+ this.loader
2293
+ );
2565
2294
  if (res.isErr()) {
2566
2295
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
2567
2296
  }
2568
2297
  return res;
2569
2298
  }
2570
2299
  async close() {
2571
- await this.gateway.close(this.url());
2300
+ await this.gateway.close(this.sthis, this.url(), this.loader);
2572
2301
  this._onClosed.forEach((fn) => fn());
2573
2302
  return import_cement10.Result.Ok(void 0);
2574
2303
  }
2575
2304
  async destroy() {
2576
- return this.gateway.destroy(this.url());
2305
+ this.logger.Debug().Msg("destroy");
2306
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
2577
2307
  }
2578
2308
  };
2579
2309
  var DataStoreImpl = class extends BaseStoreImpl {
2580
- // readonly tag: string = "car-base";
2581
- constructor(sthis, name, url, opts) {
2582
- super(name, url, { ...opts }, sthis, ensureLogger(sthis, "DataStoreImpl"));
2310
+ constructor(sthis, url, opts) {
2311
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "DataStoreImpl"));
2583
2312
  this.storeType = "data";
2584
2313
  }
2585
2314
  async load(cid) {
2586
2315
  this.logger.Debug().Any("cid", cid).Msg("loading");
2587
- const url = await this.gateway.buildUrl(this.url(), cid.toString());
2316
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), cid.toString(), this.loader);
2588
2317
  if (url.isErr()) {
2589
2318
  throw this.logger.Error().Err(url.Err()).Str("cid", cid.toString()).Msg("got error from gateway.buildUrl").AsError();
2590
2319
  }
2591
- const res = await this.gateway.get(url.Ok());
2320
+ const res = await this.gateway.get(this.sthis, url.Ok(), this.loader);
2592
2321
  if (res.isErr()) {
2593
2322
  throw res.Err();
2594
2323
  }
2595
- return { cid, bytes: res.Ok() };
2324
+ const fpenv = res.Ok();
2325
+ switch (fpenv.type) {
2326
+ case "car":
2327
+ return { cid, bytes: fpenv.payload };
2328
+ case "file":
2329
+ return { cid, bytes: fpenv.payload };
2330
+ default:
2331
+ throw this.logger.Error().Msg("unexpected type").AsError();
2332
+ }
2596
2333
  }
2597
2334
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2598
2335
  async save(car, opts) {
2599
2336
  this.logger.Debug().Any("cid", car.cid.toString()).Msg("saving");
2600
- const url = await this.gateway.buildUrl(this.url(), car.cid.toString());
2337
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), car.cid.toString(), this.loader);
2601
2338
  if (url.isErr()) {
2602
2339
  throw this.logger.Error().Err(url.Err()).Ref("cid", car.cid).Msg("got error from gateway.buildUrl").AsError();
2603
2340
  }
2604
- const res = await this.gateway.put(url.Ok(), car.bytes);
2341
+ let fpMsg;
2342
+ switch (url.Ok().getParam("store" /* STORE */)) {
2343
+ case "data":
2344
+ if (url.Ok().getParam("suffix" /* SUFFIX */)) {
2345
+ fpMsg = Car2FPMsg(car.bytes);
2346
+ } else {
2347
+ fpMsg = File2FPMsg(car.bytes);
2348
+ }
2349
+ break;
2350
+ default:
2351
+ throw this.logger.Error().Str("store", url.Ok().getParam("store" /* STORE */)).Msg("unexpected store").AsError();
2352
+ }
2353
+ if (fpMsg.isErr()) {
2354
+ throw this.logger.Error().Err(fpMsg).Msg("got error from FPMsg2Car").AsError();
2355
+ }
2356
+ const res = await this.gateway.put(this.sthis, url.Ok(), fpMsg.Ok(), this.loader);
2605
2357
  if (res.isErr()) {
2606
2358
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
2607
2359
  }
2608
2360
  return res.Ok();
2609
2361
  }
2610
2362
  async remove(cid) {
2611
- const url = await this.gateway.buildUrl(this.url(), cid.toString());
2363
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), cid.toString(), this.loader);
2612
2364
  if (url.isErr()) {
2613
2365
  return url;
2614
2366
  }
2615
- return this.gateway.delete(url.Ok());
2367
+ return this.gateway.delete(this.sthis, url.Ok(), this.loader);
2616
2368
  }
2617
2369
  async close() {
2618
- await this.gateway.close(this.url());
2370
+ await this.gateway.close(this.sthis, this.url(), this.loader);
2619
2371
  this._onClosed.forEach((fn) => fn());
2620
2372
  return import_cement10.Result.Ok(void 0);
2621
2373
  }
2622
2374
  destroy() {
2623
- return this.gateway.destroy(this.url());
2375
+ this.logger.Debug().Msg("destroy");
2376
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
2624
2377
  }
2625
2378
  };
2626
2379
  var WALStoreImpl = class extends BaseStoreImpl {
2627
- constructor(loader, url, opts) {
2628
- super(loader.name, url, { ...opts }, loader.sthis, ensureLogger(loader.sthis, "WALStoreImpl"));
2380
+ constructor(sthis, url, opts) {
2381
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "WALStoreImpl"));
2629
2382
  this.storeType = "wal";
2383
+ // readonly tag: string = "rwal-base";
2384
+ // readonly loader: Loadable;
2630
2385
  this._ready = new import_cement10.ResolveOnce();
2631
2386
  this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
2632
2387
  this.processing = void 0;
2633
2388
  this.processQueue = new CommitQueue();
2634
- this.loader = loader;
2635
2389
  }
2636
2390
  async ready() {
2637
2391
  return this._ready.once(async () => {
2638
2392
  const walState = await this.load().catch((e) => {
2639
- this.logger.Error().Any("error", e).Msg("error loading wal");
2393
+ this.logger.Error().Err(e).Msg("error loading wal");
2640
2394
  return void 0;
2641
2395
  });
2642
- if (!walState) {
2643
- this.walState.operations = [];
2644
- this.walState.fileOperations = [];
2645
- } else {
2646
- this.walState.operations = walState.operations || [];
2647
- this.walState.fileOperations = walState.fileOperations || [];
2396
+ this.walState.operations.splice(0, this.walState.operations.length);
2397
+ this.walState.fileOperations.splice(0, this.walState.fileOperations.length);
2398
+ if (walState) {
2399
+ this.walState.operations.push(...walState.operations);
2400
+ this.walState.fileOperations.push(...walState.fileOperations);
2648
2401
  }
2649
2402
  });
2650
2403
  }
2651
2404
  async enqueue(dbMeta, opts) {
2652
2405
  await this.ready();
2653
2406
  if (opts.compact) {
2654
- this.walState.operations = [];
2655
- this.walState.noLoaderOps = [dbMeta];
2407
+ this.walState.operations.splice(0, this.walState.operations.length);
2408
+ this.walState.noLoaderOps.splice(0, this.walState.noLoaderOps.length);
2409
+ this.walState.noLoaderOps.push(dbMeta);
2656
2410
  } else if (opts.noLoader) {
2657
2411
  this.walState.noLoaderOps.push(dbMeta);
2658
2412
  } else {
@@ -2682,6 +2436,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
2682
2436
  });
2683
2437
  }
2684
2438
  async _doProcess() {
2439
+ if (!this.loader) return;
2685
2440
  if (!this.loader.remoteCarStore) return;
2686
2441
  const operations = [...this.walState.operations];
2687
2442
  const noLoaderOps = [...this.walState.noLoaderOps];
@@ -2699,6 +2454,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
2699
2454
  noLoaderOps,
2700
2455
  async (dbMeta) => {
2701
2456
  await retryableUpload(async () => {
2457
+ if (!this.loader) {
2458
+ return;
2459
+ }
2702
2460
  for (const cid of dbMeta.cars) {
2703
2461
  const car = await (await this.loader.carStore()).load(cid);
2704
2462
  if (!car) {
@@ -2709,7 +2467,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
2709
2467
  await throwFalsy(this.loader.remoteCarStore).save(car);
2710
2468
  }
2711
2469
  }
2712
- this.walState.noLoaderOps = this.walState.noLoaderOps.filter((op) => op !== dbMeta);
2470
+ inplaceFilter(this.walState.noLoaderOps, (op) => op !== dbMeta);
2713
2471
  }, `noLoaderOp with dbMeta.cars=${dbMeta.cars.toString()}`);
2714
2472
  },
2715
2473
  { concurrency: concurrencyLimit }
@@ -2718,6 +2476,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
2718
2476
  operations,
2719
2477
  async (dbMeta) => {
2720
2478
  await retryableUpload(async () => {
2479
+ if (!this.loader) {
2480
+ return;
2481
+ }
2721
2482
  for (const cid of dbMeta.cars) {
2722
2483
  const car = await (await this.loader.carStore()).load(cid);
2723
2484
  if (!car) {
@@ -2728,7 +2489,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
2728
2489
  await throwFalsy(this.loader.remoteCarStore).save(car);
2729
2490
  }
2730
2491
  }
2731
- this.walState.operations = this.walState.operations.filter((op) => op !== dbMeta);
2492
+ inplaceFilter(this.walState.operations, (op) => op !== dbMeta);
2732
2493
  }, `operation with dbMeta.cars=${dbMeta.cars.toString()}`);
2733
2494
  },
2734
2495
  { concurrency: concurrencyLimit }
@@ -2737,12 +2498,15 @@ var WALStoreImpl = class extends BaseStoreImpl {
2737
2498
  fileOperations,
2738
2499
  async ({ cid: fileCid, public: publicFile }) => {
2739
2500
  await retryableUpload(async () => {
2501
+ if (!this.loader) {
2502
+ return;
2503
+ }
2740
2504
  const fileBlock = await (await this.loader.fileStore()).load(fileCid);
2741
2505
  if (!fileBlock) {
2742
2506
  throw this.logger.Error().Ref("cid", fileCid).Msg("missing file block").AsError();
2743
2507
  }
2744
2508
  await this.loader.remoteFileStore?.save(fileBlock, { public: publicFile });
2745
- this.walState.fileOperations = this.walState.fileOperations.filter((op) => op.cid !== fileCid);
2509
+ inplaceFilter(this.walState.fileOperations, (op) => op.cid !== fileCid);
2746
2510
  }, `fileOperation with cid=${fileCid.toString()}`);
2747
2511
  },
2748
2512
  { concurrency: concurrencyLimit }
@@ -2750,6 +2514,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
2750
2514
  if (operations.length) {
2751
2515
  const lastOp = operations[operations.length - 1];
2752
2516
  await retryableUpload(async () => {
2517
+ if (!this.loader) {
2518
+ return;
2519
+ }
2753
2520
  await this.loader.remoteMetaStore?.save(lastOp);
2754
2521
  }, `remoteMetaStore save with dbMeta.cars=${lastOp.cars.toString()}`);
2755
2522
  }
@@ -2762,252 +2529,715 @@ var WALStoreImpl = class extends BaseStoreImpl {
2762
2529
  }
2763
2530
  async load() {
2764
2531
  this.logger.Debug().Msg("loading");
2765
- const filepath = await this.gateway.buildUrl(this.url(), "main");
2532
+ const filepath = await this.gateway.buildUrl(this.sthis, this.url(), "main", this.loader);
2766
2533
  if (filepath.isErr()) {
2767
2534
  throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2768
2535
  }
2769
- const bytes = await this.gateway.get(filepath.Ok());
2536
+ const bytes = await this.gateway.get(this.sthis, filepath.Ok(), this.loader);
2770
2537
  if (bytes.isErr()) {
2771
2538
  if (isNotFoundError(bytes)) {
2772
2539
  return void 0;
2773
2540
  }
2774
2541
  throw this.logger.Error().Err(bytes.Err()).Msg("error get").AsError();
2775
2542
  }
2776
- try {
2777
- return bytes && (0, import_dag_json2.parse)(this.sthis.txt.decode(bytes.Ok()));
2778
- } catch (e) {
2779
- throw this.logger.Error().Err(e).Msg("error parse").AsError();
2543
+ if (bytes.Ok().type !== "wal") {
2544
+ throw this.logger.Error().Str("type", bytes.Ok().type).Msg("unexpected type").AsError();
2545
+ }
2546
+ return bytes.Ok().payload;
2547
+ }
2548
+ async save(state) {
2549
+ const filepath = await this.gateway.buildUrl(this.sthis, this.url(), "main", this.loader);
2550
+ if (filepath.isErr()) {
2551
+ throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2552
+ }
2553
+ const res = await this.gateway.put(
2554
+ this.sthis,
2555
+ filepath.Ok(),
2556
+ {
2557
+ type: "wal",
2558
+ payload: state
2559
+ },
2560
+ this.loader
2561
+ );
2562
+ if (res.isErr()) {
2563
+ throw this.logger.Error().Err(res.Err()).Str("filePath", filepath.Ok().toString()).Msg("error saving").AsError();
2564
+ }
2565
+ }
2566
+ async close() {
2567
+ await this.gateway.close(this.sthis, this.url(), this.loader);
2568
+ this._onClosed.forEach((fn) => fn());
2569
+ return import_cement10.Result.Ok(void 0);
2570
+ }
2571
+ destroy() {
2572
+ this.logger.Debug().Msg("destroy");
2573
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
2574
+ }
2575
+ };
2576
+
2577
+ // src/blockstore/register-store-protocol.ts
2578
+ var import_cement16 = require("@adviser/cement");
2579
+
2580
+ // src/runtime/gateways/file/version.ts
2581
+ var FILESTORE_VERSION = "v0.19-file";
2582
+
2583
+ // src/runtime/gateways/memory/gateway.ts
2584
+ var import_cement11 = require("@adviser/cement");
2585
+
2586
+ // src/runtime/gateways/memory/version.ts
2587
+ var MEMORY_VERSION = "v0.19-memory";
2588
+
2589
+ // src/runtime/gateways/memory/gateway.ts
2590
+ var MemoryGateway = class {
2591
+ constructor(sthis, memorys) {
2592
+ this.memorys = memorys;
2593
+ this.sthis = sthis;
2594
+ }
2595
+ buildUrl(baseUrl, key) {
2596
+ return Promise.resolve(import_cement11.Result.Ok(baseUrl.build().setParam("key" /* KEY */, key).URI()));
2597
+ }
2598
+ start(baseUrl) {
2599
+ return Promise.resolve(import_cement11.Result.Ok(baseUrl.build().setParam("version" /* VERSION */, MEMORY_VERSION).URI()));
2600
+ }
2601
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2602
+ close(baseUrl) {
2603
+ return Promise.resolve(import_cement11.Result.Ok(void 0));
2604
+ }
2605
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2606
+ destroy(baseUrl) {
2607
+ this.memorys.clear();
2608
+ return Promise.resolve(import_cement11.Result.Ok(void 0));
2609
+ }
2610
+ async put(url, bytes) {
2611
+ this.memorys.set(url.toString(), bytes);
2612
+ return import_cement11.Result.Ok(void 0);
2613
+ }
2614
+ // get could return a NotFoundError if the key is not found
2615
+ get(url) {
2616
+ const x = this.memorys.get(url.toString());
2617
+ if (!x) {
2618
+ return Promise.resolve(import_cement11.Result.Err(new NotFoundError("not found")));
2619
+ }
2620
+ return Promise.resolve(import_cement11.Result.Ok(x));
2621
+ }
2622
+ delete(url) {
2623
+ this.memorys.delete(url.toString());
2624
+ return Promise.resolve(import_cement11.Result.Ok(void 0));
2625
+ }
2626
+ async getPlain(url, key) {
2627
+ const x = this.memorys.get(url.build().setParam("key" /* KEY */, key).toString());
2628
+ if (!x) {
2629
+ return import_cement11.Result.Err(new NotFoundError("not found"));
2780
2630
  }
2631
+ return import_cement11.Result.Ok(x);
2632
+ }
2633
+ };
2634
+
2635
+ // src/runtime/index.ts
2636
+ var runtime_exports = {};
2637
+ __export(runtime_exports, {
2638
+ FILESTORE_VERSION: () => FILESTORE_VERSION,
2639
+ INDEXDB_VERSION: () => INDEXDB_VERSION,
2640
+ KeyBag: () => KeyBag,
2641
+ defaultKeyBagOpts: () => defaultKeyBagOpts,
2642
+ defaultKeyBagUrl: () => defaultKeyBagUrl,
2643
+ files: () => files_exports,
2644
+ getFileName: () => getFileName,
2645
+ getKeyBag: () => getKeyBag,
2646
+ getPath: () => getPath,
2647
+ gw: () => gateways_exports,
2648
+ kb: () => key_bag_exports,
2649
+ kc: () => keyed_crypto_exports,
2650
+ mf: () => wait_pr_multiformats_exports,
2651
+ registerKeyBagProviderFactory: () => registerKeyBagProviderFactory,
2652
+ runtimeFn: () => import_cement13.runtimeFn
2653
+ });
2654
+
2655
+ // src/runtime/gateways/file/utils.ts
2656
+ var import_core = require("@fireproof/core");
2657
+ function getPath(url, sthis) {
2658
+ const basePath = url.pathname;
2659
+ const name = url.getParam("name");
2660
+ if (name) {
2661
+ return sthis.pathOps.join(basePath, name);
2662
+ }
2663
+ return sthis.pathOps.join(basePath);
2664
+ }
2665
+ function getFileName(url, sthis) {
2666
+ const key = url.getParam("key");
2667
+ if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
2668
+ const res = (0, import_core.getStore)(url, sthis, (...a) => a.join("-"));
2669
+ switch (res.store) {
2670
+ case "data":
2671
+ return sthis.pathOps.join(res.name, key + ".car");
2672
+ case "wal":
2673
+ case "meta":
2674
+ return sthis.pathOps.join(res.name, key + ".json");
2675
+ default:
2676
+ throw sthis.logger.Error().Url(url).Msg(`unsupported store type`).AsError();
2677
+ }
2678
+ }
2679
+
2680
+ // src/runtime/wait-pr-multiformats/index.ts
2681
+ var wait_pr_multiformats_exports = {};
2682
+ __export(wait_pr_multiformats_exports, {
2683
+ block: () => block_exports,
2684
+ codec: () => codec_interface_exports
2685
+ });
2686
+
2687
+ // src/runtime/wait-pr-multiformats/codec-interface.ts
2688
+ var codec_interface_exports = {};
2689
+
2690
+ // src/runtime/index.ts
2691
+ var import_cement13 = require("@adviser/cement");
2692
+
2693
+ // src/runtime/gateways/index.ts
2694
+ var gateways_exports = {};
2695
+ __export(gateways_exports, {
2696
+ file: () => file_exports,
2697
+ fpDeserialize: () => fpDeserialize,
2698
+ fpSerialize: () => fpSerialize
2699
+ });
2700
+
2701
+ // src/runtime/gateways/fp-envelope-serialize.ts
2702
+ var import_cement12 = require("@adviser/cement");
2703
+ var import_clock2 = require("@fireproof/vendor/@web3-storage/pail/clock");
2704
+ var import_base64 = require("multiformats/bases/base64");
2705
+ var import_multiformats2 = require("multiformats");
2706
+ var import_link = require("multiformats/link");
2707
+ var import_dag_json2 = require("@fireproof/vendor/@ipld/dag-json");
2708
+ async function dbMetaEvent2Serialized(sthis, dbEvents) {
2709
+ return await Promise.all(
2710
+ dbEvents.map(async (dbEvent) => {
2711
+ const event = await import_clock2.EventBlock.create(
2712
+ {
2713
+ dbMeta: sthis.txt.encode((0, import_dag_json2.format)(dbEvent.dbMeta))
2714
+ },
2715
+ dbEvent.parents
2716
+ );
2717
+ return {
2718
+ cid: event.cid.toString(),
2719
+ parents: dbEvent.parents.map((i) => i.toString()),
2720
+ data: import_base64.base64pad.encode(event.bytes)
2721
+ };
2722
+ })
2723
+ );
2724
+ }
2725
+ function WALState2Serialized(sthis, wal) {
2726
+ const serializedWAL = {
2727
+ fileOperations: wal.fileOperations.map((fop) => ({
2728
+ cid: fop.cid.toString(),
2729
+ public: fop.public
2730
+ })),
2731
+ noLoaderOps: wal.noLoaderOps.map((nop) => ({
2732
+ cars: nop.cars.map((i) => i.toString())
2733
+ })),
2734
+ operations: wal.operations.map((op) => ({
2735
+ cars: op.cars.map((i) => i.toString())
2736
+ }))
2737
+ };
2738
+ return serializedWAL;
2739
+ }
2740
+ var defaultEncoder = {
2741
+ car: async (sthis, payload) => import_cement12.Result.Ok(payload),
2742
+ file: async (sthis, payload) => import_cement12.Result.Ok(payload),
2743
+ meta: async (sthis, payload) => import_cement12.Result.Ok(sthis.txt.encode(JSON.stringify(payload))),
2744
+ wal: async (sthis, payload) => import_cement12.Result.Ok(sthis.txt.encode(JSON.stringify(payload)))
2745
+ };
2746
+ async function fpSerialize(sthis, env, pencoder) {
2747
+ const encoder = {
2748
+ ...defaultEncoder,
2749
+ ...pencoder
2750
+ };
2751
+ switch (env.type) {
2752
+ case "file" /* FILE */:
2753
+ return encoder.file(sthis, env.payload);
2754
+ case "car" /* CAR */:
2755
+ return encoder.car(sthis, env.payload);
2756
+ case "wal" /* WAL */:
2757
+ return encoder.wal(sthis, WALState2Serialized(sthis, env.payload));
2758
+ case "meta" /* META */:
2759
+ return encoder.meta(sthis, await dbMetaEvent2Serialized(sthis, env.payload));
2760
+ default:
2761
+ throw sthis.logger.Error().Str("type", env.type).Msg("unsupported store").AsError();
2762
+ }
2763
+ }
2764
+ async function decode2DbMetaEvents(sthis, rserializedMeta) {
2765
+ if (rserializedMeta.isErr()) {
2766
+ return import_cement12.Result.Err(rserializedMeta.Err());
2767
+ }
2768
+ const serializedMeta = rserializedMeta.unwrap();
2769
+ if (!Array.isArray(serializedMeta)) {
2770
+ return sthis.logger.Debug().Any("metaEntries", serializedMeta).Msg("No data in MetaEntries").ResultError();
2771
+ }
2772
+ if (!serializedMeta.length) {
2773
+ return sthis.logger.Debug().Msg("No MetaEntries found").ResultError();
2774
+ }
2775
+ return import_cement12.Result.Ok(
2776
+ await Promise.all(
2777
+ serializedMeta.map(async (metaEntry) => {
2778
+ const eventBlock = await (0, import_clock2.decodeEventBlock)(import_base64.base64pad.decode(metaEntry.data));
2779
+ const dbMeta = (0, import_dag_json2.parse)(sthis.txt.decode(eventBlock.value.data.dbMeta));
2780
+ return {
2781
+ eventCid: eventBlock.cid,
2782
+ parents: metaEntry.parents.map((i) => import_multiformats2.CID.parse(i)),
2783
+ dbMeta
2784
+ };
2785
+ })
2786
+ )
2787
+ );
2788
+ }
2789
+ function toCid(sthis, link) {
2790
+ if (typeof link === "string") {
2791
+ return import_multiformats2.CID.parse(link);
2792
+ }
2793
+ return (0, import_link.fromJSON)(link);
2794
+ }
2795
+ async function decode2WalState(sthis, rserializedWAL) {
2796
+ if (rserializedWAL.isErr()) {
2797
+ return import_cement12.Result.Err(rserializedWAL.Err());
2798
+ }
2799
+ const serializedWAL = rserializedWAL.unwrap();
2800
+ return import_cement12.Result.Ok({
2801
+ fileOperations: (serializedWAL.fileOperations || []).map((fop) => ({
2802
+ cid: toCid(sthis, fop.cid),
2803
+ public: !!fop.public
2804
+ })),
2805
+ noLoaderOps: (serializedWAL.noLoaderOps || []).map((nop) => ({
2806
+ cars: (nop.cars || []).map((i) => toCid(sthis, i))
2807
+ })),
2808
+ operations: (serializedWAL.operations || []).map((op) => ({
2809
+ cars: (op.cars || []).map((i) => toCid(sthis, i))
2810
+ }))
2811
+ });
2812
+ }
2813
+ var defaultDecoder = {
2814
+ car: async (sthis, payload) => import_cement12.Result.Ok(payload),
2815
+ file: async (sthis, payload) => import_cement12.Result.Ok(payload),
2816
+ meta: async (sthis, payload) => (0, import_cement12.exception2Result)(() => JSON.parse(sthis.txt.decode(payload))),
2817
+ wal: async (sthis, payload) => (0, import_cement12.exception2Result)(() => JSON.parse(sthis.txt.decode(payload)))
2818
+ };
2819
+ function makeFPEnvelope(type, payload) {
2820
+ if (payload.isErr()) {
2821
+ return import_cement12.Result.Err(payload.Err());
2822
+ }
2823
+ return import_cement12.Result.Ok({
2824
+ type,
2825
+ payload: payload.unwrap()
2826
+ });
2827
+ }
2828
+ async function fpDeserialize(sthis, url, intoRaw, pdecoder) {
2829
+ const rraw = await coercePromiseIntoUint8(intoRaw);
2830
+ if (rraw.isErr()) {
2831
+ return import_cement12.Result.Err(rraw.Err());
2832
+ }
2833
+ const raw2 = rraw.unwrap();
2834
+ const decoder = {
2835
+ ...defaultDecoder,
2836
+ ...pdecoder
2837
+ };
2838
+ switch (url.getParam("store" /* STORE */)) {
2839
+ case "data":
2840
+ if (url.getParam("suffix" /* SUFFIX */) === ".car") {
2841
+ return makeFPEnvelope("car" /* CAR */, await decoder.car(sthis, raw2));
2842
+ }
2843
+ return makeFPEnvelope("file" /* FILE */, await decoder.file(sthis, raw2));
2844
+ case "wal":
2845
+ return makeFPEnvelope("wal" /* WAL */, await decode2WalState(sthis, await decoder.wal(sthis, raw2)));
2846
+ case "meta":
2847
+ return makeFPEnvelope("meta" /* META */, await decode2DbMetaEvents(sthis, await decoder.meta(sthis, raw2)));
2848
+ default:
2849
+ return sthis.logger.Error().Str("store", url.getParam("store" /* STORE */)).Msg("unsupported store").ResultError();
2850
+ }
2851
+ }
2852
+
2853
+ // src/runtime/gateways/file/index.ts
2854
+ var file_exports = {};
2855
+ __export(file_exports, {
2856
+ KeyBagProviderFile: () => KeyBagProviderFile,
2857
+ sysFileSystemFactory: () => sysFileSystemFactory
2858
+ });
2859
+
2860
+ // src/runtime/gateways/indexdb/version.ts
2861
+ var INDEXDB_VERSION = "v0.19-indexdb";
2862
+
2863
+ // src/runtime/gateways/file/gateway-impl.ts
2864
+ var import_cement14 = require("@adviser/cement");
2865
+ var versionFiles = new import_cement14.KeyedResolvOnce();
2866
+ var FileGateway = class {
2867
+ constructor(sthis, fs) {
2868
+ this.fs = fs;
2869
+ }
2870
+ async getVersionFromFile(path, sthis) {
2871
+ return versionFiles.get(path).once(async () => {
2872
+ await this.fs.mkdir(path, { recursive: true });
2873
+ const vFile = sthis.pathOps.join(path, "version");
2874
+ const vFileStat = await this.fs.stat(vFile).catch(() => void 0);
2875
+ if (!vFileStat) {
2876
+ await this.fs.writefile(sthis.pathOps.join(path, "version"), FILESTORE_VERSION);
2877
+ return FILESTORE_VERSION;
2878
+ } else if (!vFileStat.isFile()) {
2879
+ throw sthis.logger.Error().Str("file", vFile).Msg(`version file is a directory`).AsError();
2880
+ }
2881
+ const v = await this.fs.readfile(vFile);
2882
+ const vStr = sthis.txt.decode(v);
2883
+ if (vStr !== FILESTORE_VERSION) {
2884
+ sthis.logger.Warn().Str("file", vFile).Str("from", vStr).Str("expected", FILESTORE_VERSION).Msg(`version mismatch`);
2885
+ }
2886
+ return vStr;
2887
+ });
2888
+ }
2889
+ start(baseURL, sthis) {
2890
+ return (0, import_cement14.exception2Result)(async () => {
2891
+ await this.fs.start();
2892
+ const url = baseURL.build();
2893
+ url.defParam("version" /* VERSION */, FILESTORE_VERSION);
2894
+ const dbUrl = await this.buildUrl(url.URI(), "dummy");
2895
+ const dbdirFile = this.getFilePath(dbUrl.Ok(), sthis);
2896
+ await this.fs.mkdir(sthis.pathOps.dirname(dbdirFile), { recursive: true });
2897
+ const dbroot = sthis.pathOps.dirname(dbdirFile);
2898
+ sthis.logger.Debug().Url(url.URI()).Str("dbroot", dbroot).Msg("start");
2899
+ url.setParam("version" /* VERSION */, await this.getVersionFromFile(dbroot, sthis));
2900
+ return url.URI();
2901
+ });
2902
+ }
2903
+ async buildUrl(baseUrl, key) {
2904
+ return import_cement14.Result.Ok(baseUrl.build().setParam("key" /* KEY */, key).URI());
2905
+ }
2906
+ async close() {
2907
+ return import_cement14.Result.Ok(void 0);
2908
+ }
2909
+ getFilePath(url, sthis) {
2910
+ const key = url.getParam("key" /* KEY */);
2911
+ if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
2912
+ return sthis.pathOps.join(getPath(url, sthis), getFileName(url, sthis));
2913
+ }
2914
+ async put(url, bytes, sthis) {
2915
+ return (0, import_cement14.exception2Result)(async () => {
2916
+ const file = await this.getFilePath(url, sthis);
2917
+ sthis.logger.Debug().Str("url", url.toString()).Str("file", file).Msg("put");
2918
+ await this.fs.writefile(file, bytes);
2919
+ });
2920
+ }
2921
+ async get(url, sthis) {
2922
+ return exceptionWrapper(async () => {
2923
+ const file = this.getFilePath(url, sthis);
2924
+ try {
2925
+ sthis.logger.Debug().Url(url).Str("file", file).Msg("get");
2926
+ const res = await this.fs.readfile(file);
2927
+ return import_cement14.Result.Ok(res);
2928
+ } catch (e) {
2929
+ if (isNotFoundError(e)) {
2930
+ return import_cement14.Result.Err(new NotFoundError(`file not found: ${file}`));
2931
+ }
2932
+ return import_cement14.Result.Err(e);
2933
+ }
2934
+ });
2781
2935
  }
2782
- async save(state) {
2783
- const filepath = await this.gateway.buildUrl(this.url(), "main");
2784
- if (filepath.isErr()) {
2785
- throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2786
- }
2787
- let encoded;
2936
+ async delete(url, sthis) {
2937
+ return (0, import_cement14.exception2Result)(async () => {
2938
+ await this.fs.unlink(this.getFilePath(url, sthis));
2939
+ });
2940
+ }
2941
+ async destroy(baseURL, sthis) {
2942
+ const url = await this.buildUrl(baseURL, "x");
2943
+ if (url.isErr()) return url;
2944
+ const filepath = sthis.pathOps.dirname(this.getFilePath(url.Ok(), sthis));
2945
+ let files = [];
2788
2946
  try {
2789
- encoded = (0, import_dag_json2.format)(state);
2947
+ files = await this.fs.readdir(filepath);
2790
2948
  } catch (e) {
2791
- throw this.logger.Error().Err(e).Any("state", state).Msg("error format").AsError();
2949
+ if (!isNotFoundError(e)) {
2950
+ throw sthis.logger.Error().Err(e).Str("dir", filepath).Msg("destroy:readdir").AsError();
2951
+ }
2792
2952
  }
2793
- const res = await this.gateway.put(filepath.Ok(), this.sthis.txt.encode(encoded));
2794
- if (res.isErr()) {
2795
- throw this.logger.Error().Err(res.Err()).Str("filePath", filepath.Ok().toString()).Msg("error saving").AsError();
2953
+ for (const file of files) {
2954
+ const pathed = sthis.pathOps.join(filepath, file);
2955
+ try {
2956
+ await this.fs.unlink(pathed);
2957
+ } catch (e) {
2958
+ if (!isNotFoundError(e)) {
2959
+ throw sthis.logger.Error().Err(e).Str("file", pathed).Msg("destroy:unlink").AsError();
2960
+ }
2961
+ }
2796
2962
  }
2963
+ return import_cement14.Result.Ok(void 0);
2797
2964
  }
2798
- async close() {
2799
- await this.gateway.close(this.url());
2800
- this._onClosed.forEach((fn) => fn());
2801
- return import_cement10.Result.Ok(void 0);
2802
- }
2803
- destroy() {
2804
- return this.gateway.destroy(this.url());
2965
+ async getPlain(iurl, key, sthis) {
2966
+ const url = iurl.build().setParam("key" /* KEY */, key).URI();
2967
+ const dbFile = sthis.pathOps.join(getPath(url, sthis), getFileName(url, sthis));
2968
+ sthis.logger.Debug().Url(url).Str("dbFile", dbFile).Msg("get");
2969
+ const buffer = await this.fs.readfile(dbFile);
2970
+ sthis.logger.Debug().Url(url).Str("dbFile", dbFile).Len(buffer).Msg("got");
2971
+ return import_cement14.Result.Ok(buffer);
2805
2972
  }
2806
2973
  };
2807
2974
 
2808
- // src/blockstore/store-factory.ts
2809
- init_utils();
2810
- function ensureIsIndex(url, isIndex) {
2811
- if (isIndex) {
2812
- return url.build().setParam("index", isIndex).URI();
2975
+ // src/runtime/gateways/def-serde-gateway.ts
2976
+ var import_cement15 = require("@adviser/cement");
2977
+ var DefSerdeGateway = class {
2978
+ constructor(gw) {
2979
+ this.gw = gw;
2813
2980
  }
2814
- return url.build().delParam("index").URI();
2815
- }
2816
- function ensureName(name, url) {
2817
- if (!url.hasParam("name")) {
2818
- return url.build().setParam("name", name).URI();
2981
+ start(sthis, baseURL) {
2982
+ return this.gw.start(baseURL, sthis);
2819
2983
  }
2820
- return url;
2821
- }
2984
+ async buildUrl(sthis, baseUrl, key) {
2985
+ return this.gw.buildUrl(baseUrl, key, sthis);
2986
+ }
2987
+ async close(sthis, uri) {
2988
+ return this.gw.close(uri, sthis);
2989
+ }
2990
+ async put(sthis, url, env) {
2991
+ const rUint8 = await fpSerialize(sthis, env);
2992
+ if (rUint8.isErr()) return rUint8;
2993
+ return this.gw.put(url, rUint8.Ok(), sthis);
2994
+ }
2995
+ async get(sthis, url) {
2996
+ const res = await this.gw.get(url, sthis);
2997
+ if (res.isErr()) return import_cement15.Result.Err(res.Err());
2998
+ return fpDeserialize(sthis, url, res);
2999
+ }
3000
+ async delete(sthis, url) {
3001
+ return this.gw.delete(url, sthis);
3002
+ }
3003
+ async destroy(sthis, baseURL) {
3004
+ return this.gw.destroy(baseURL, sthis);
3005
+ }
3006
+ async getPlain(sthis, iurl, key) {
3007
+ return this.gw.getPlain(iurl, key, sthis);
3008
+ }
3009
+ };
3010
+
3011
+ // src/blockstore/register-store-protocol.ts
2822
3012
  var storeFactory = /* @__PURE__ */ new Map();
2823
- function buildURL(optURL, loader) {
2824
- const storeOpts = loader.ebOpts.store;
2825
- const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
2826
- let obuUrl;
2827
- if (obuItem && obuItem.overrideBaseURL) {
2828
- obuUrl = import_cement13.URI.from(obuItem.overrideBaseURL);
2829
- }
2830
- const ret = ensureIsIndex(
2831
- import_cement13.URI.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
2832
- storeOpts.isIndex
2833
- );
2834
- return ret;
2835
- }
2836
- var onceGateway = new import_cement13.KeyedResolvOnce();
2837
- async function getGatewayFromURL(url, sthis) {
2838
- return onceGateway.get(url.toString()).once(async () => {
2839
- const item = storeFactory.get(url.protocol);
2840
- if (item) {
2841
- const ret = {
2842
- gateway: await item.gateway(sthis),
2843
- test: await item.test(sthis)
2844
- };
2845
- const res = await ret.gateway.start(url);
2846
- if (res.isErr()) {
2847
- sthis.logger.Error().Result("start", res).Msg("start failed");
2848
- return void 0;
2849
- }
2850
- return ret;
3013
+ function getDefaultURI(sthis, protocol) {
3014
+ if (protocol) {
3015
+ if (!protocol.endsWith(":")) {
3016
+ protocol += ":";
2851
3017
  }
2852
- sthis.logger.Warn().Url(url).Msg("unsupported protocol");
2853
- return void 0;
2854
- });
3018
+ const gfi = storeFactory.get(protocol);
3019
+ if (gfi) {
3020
+ return gfi.defaultURI(sthis);
3021
+ }
3022
+ }
3023
+ const found = Array.from(storeFactory.values()).find((item) => item.isDefault);
3024
+ if (!found) {
3025
+ throw sthis.logger.Error().Msg("no default found").AsError();
3026
+ }
3027
+ return found.defaultURI(sthis);
2855
3028
  }
2856
3029
  function registerStoreProtocol(item) {
2857
3030
  let protocol = item.protocol;
2858
3031
  if (!protocol.endsWith(":")) {
2859
3032
  protocol += ":";
2860
3033
  }
2861
- if (storeFactory.has(protocol)) {
2862
- if (!item.overrideBaseURL && storeFactory.get(protocol) !== item) {
2863
- throw new Error(`we need a logger here`);
2864
- return () => {
2865
- };
2866
- }
3034
+ if (!item.serdegateway && !item.gateway) {
3035
+ throw new Error(`registerStoreProtocol needs a gateway or serdegateway`);
2867
3036
  }
2868
- if (item.overrideBaseURL) {
3037
+ let serdegateway;
3038
+ if (item.gateway) {
3039
+ serdegateway = async (sthis) => {
3040
+ const m = await item.gateway(sthis);
3041
+ return new DefSerdeGateway(m);
3042
+ };
3043
+ } else {
3044
+ serdegateway = item.serdegateway;
3045
+ }
3046
+ if (item.isDefault) {
2869
3047
  Array.from(storeFactory.values()).forEach((items) => {
2870
- items.overrideBaseURL = void 0;
3048
+ items.isDefault = false;
2871
3049
  });
2872
3050
  }
2873
- storeFactory.set(protocol, item);
3051
+ storeFactory.set(protocol, {
3052
+ ...item,
3053
+ serdegateway
3054
+ });
2874
3055
  return () => {
2875
3056
  storeFactory.delete(protocol);
2876
3057
  };
2877
3058
  }
2878
- var onceDataStoreFactory = new import_cement13.KeyedResolvOnce();
2879
- async function dataStoreFactory(loader) {
2880
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
2881
- const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
2882
- return onceDataStoreFactory.get(url.toString()).once(async () => {
2883
- const gateway = await getGatewayFromURL(url, sthis);
2884
- if (!gateway) {
2885
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2886
- }
2887
- const store = new DataStoreImpl(sthis, loader.name, url, {
2888
- gateway: gateway.gateway,
2889
- keybag: () => getKeyBag(loader.sthis, {
2890
- ...loader.ebOpts.keyBag
2891
- })
2892
- });
2893
- return store;
2894
- });
3059
+ function getGatewayFactoryItem(protocol) {
3060
+ return storeFactory.get(protocol);
2895
3061
  }
2896
- var onceMetaStoreFactory = new import_cement13.KeyedResolvOnce();
2897
- async function metaStoreFactory(loader) {
2898
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
2899
- const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
2900
- return onceMetaStoreFactory.get(url.toString()).once(async () => {
2901
- sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
2902
- const gateway = await getGatewayFromURL(url, sthis);
2903
- if (!gateway) {
2904
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2905
- }
2906
- const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
2907
- gateway: gateway.gateway,
2908
- keybag: () => getKeyBag(loader.sthis, {
2909
- ...loader.ebOpts.keyBag
2910
- })
2911
- });
2912
- return store;
3062
+ function defaultGatewayFactoryItem() {
3063
+ const found = Array.from(storeFactory.values()).find((item) => item.isDefault);
3064
+ if (!found) {
3065
+ throw new Error("no default found");
3066
+ }
3067
+ return found;
3068
+ }
3069
+ function defaultURI(sthis) {
3070
+ const rt = (0, import_cement16.runtimeFn)();
3071
+ return import_cement16.BuildURI.from("file://").pathname(`${sthis.env.get("HOME")}/.fireproof/${FILESTORE_VERSION.replace(/-.*$/, "")}`).setParam("version" /* VERSION */, FILESTORE_VERSION).setParam("urlGen" /* URL_GEN */, "default").setParam("runtime" /* RUNTIME */, rt.isNodeIsh ? "node" : rt.isDeno ? "deno" : "unknown").URI();
3072
+ }
3073
+ if ((0, import_cement16.runtimeFn)().isNodeIsh || (0, import_cement16.runtimeFn)().isDeno) {
3074
+ registerStoreProtocol({
3075
+ protocol: "file:",
3076
+ isDefault: true,
3077
+ defaultURI,
3078
+ gateway: async (sthis) => {
3079
+ return new FileGateway(sthis, await sysFileSystemFactory(defaultURI(sthis)));
3080
+ }
2913
3081
  });
2914
3082
  }
2915
- var onceRemoteWalFactory = new import_cement13.KeyedResolvOnce();
2916
- async function remoteWalFactory(loader) {
2917
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
2918
- const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
2919
- return onceRemoteWalFactory.get(url.toString()).once(async () => {
2920
- const gateway = await getGatewayFromURL(url, sthis);
2921
- if (!gateway) {
2922
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2923
- }
2924
- sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
2925
- const store = new WALStoreImpl(loader, url, {
2926
- gateway: gateway.gateway,
2927
- keybag: () => getKeyBag(loader.sthis, {
2928
- ...loader.ebOpts.keyBag
2929
- })
2930
- });
2931
- return store;
3083
+ if ((0, import_cement16.runtimeFn)().isBrowser) {
3084
+ registerStoreProtocol({
3085
+ protocol: "indexdb:",
3086
+ isDefault: true,
3087
+ defaultURI: () => {
3088
+ return import_cement16.BuildURI.from("indexdb://").pathname("fp").setParam("version" /* VERSION */, INDEXDB_VERSION).setParam("runtime" /* RUNTIME */, "browser").URI();
3089
+ },
3090
+ gateway: async () => {
3091
+ const { GatewayImpl } = await import("@fireproof/core/web");
3092
+ return new GatewayImpl();
3093
+ }
2932
3094
  });
2933
3095
  }
2934
- async function testStoreFactory(url, sthis) {
2935
- sthis = ensureSuperLog(sthis, "testStoreFactory");
2936
- const gateway = await getGatewayFromURL(url, sthis);
2937
- if (!gateway) {
2938
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
3096
+ var memory = /* @__PURE__ */ new Map();
3097
+ registerStoreProtocol({
3098
+ protocol: "memory:",
3099
+ isDefault: false,
3100
+ defaultURI: () => {
3101
+ return import_cement16.BuildURI.from("memory://").pathname("ram").URI();
3102
+ },
3103
+ gateway: async (sthis) => {
3104
+ return new MemoryGateway(sthis, memory);
2939
3105
  }
2940
- return gateway.test;
3106
+ });
3107
+
3108
+ // src/blockstore/store-factory.ts
3109
+ var onceGateway = new import_cement17.KeyedResolvOnce();
3110
+ var gatewayInstances = new import_cement17.KeyedResolvOnce();
3111
+ async function getStartedGateway(sthis, url) {
3112
+ return onceGateway.get(url.toString()).once(async () => {
3113
+ const item = getGatewayFactoryItem(url.protocol);
3114
+ if (item) {
3115
+ const ret = {
3116
+ url,
3117
+ ...await gatewayInstances.get(url.protocol).once(async () => ({})),
3118
+ gateway: await item.serdegateway(sthis)
3119
+ };
3120
+ const res = await ret.gateway.start(sthis, url);
3121
+ if (res.isErr()) {
3122
+ return import_cement17.Result.Err(sthis.logger.Error().Result("start", res).Msg("start failed").AsError());
3123
+ }
3124
+ ret.url = res.Ok();
3125
+ return import_cement17.Result.Ok(ret);
3126
+ }
3127
+ return import_cement17.Result.Err(sthis.logger.Warn().Url(url).Msg("unsupported protocol").AsError());
3128
+ });
3129
+ }
3130
+ async function dataStoreFactory(sfi) {
3131
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "data").URI();
3132
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3133
+ if (rgateway.isErr()) {
3134
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3135
+ }
3136
+ const gateway = rgateway.Ok();
3137
+ const store = new DataStoreImpl(sfi.sthis, gateway.url, {
3138
+ gateway: gateway.gateway,
3139
+ gatewayInterceptor: sfi.gatewayInterceptor,
3140
+ loader: sfi.loader
3141
+ });
3142
+ return store;
3143
+ }
3144
+ async function metaStoreFactory(sfi) {
3145
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "meta").URI();
3146
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3147
+ if (rgateway.isErr()) {
3148
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3149
+ }
3150
+ const gateway = rgateway.Ok();
3151
+ const store = new MetaStoreImpl(sfi.sthis, gateway.url, {
3152
+ gateway: gateway.gateway,
3153
+ gatewayInterceptor: sfi.gatewayInterceptor,
3154
+ loader: sfi.loader
3155
+ });
3156
+ return store;
3157
+ }
3158
+ async function WALStoreFactory(sfi) {
3159
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "wal").URI();
3160
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3161
+ if (rgateway.isErr()) {
3162
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3163
+ }
3164
+ const gateway = rgateway.Ok();
3165
+ const store = new WALStoreImpl(sfi.sthis, gateway.url, {
3166
+ gateway: gateway.gateway,
3167
+ gatewayInterceptor: sfi.gatewayInterceptor,
3168
+ loader: sfi.loader
3169
+ });
3170
+ return store;
2941
3171
  }
2942
- async function ensureStart(store, logger) {
3172
+ async function ensureStart(store) {
2943
3173
  const ret = await store.start();
2944
3174
  if (ret.isErr()) {
2945
- throw logger.Error().Result("start", ret).Msg("start failed").AsError();
3175
+ throw store.logger.Error().Result("start", ret).Msg("start failed").AsError();
2946
3176
  }
2947
- logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
3177
+ store.logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
2948
3178
  return store;
2949
3179
  }
2950
- function toStoreRuntime(opts, sthis) {
2951
- const logger = ensureLogger(sthis, "toStoreRuntime", {});
3180
+ function ensureStoreEnDeFile(ende) {
3181
+ ende = ende || {};
2952
3182
  return {
2953
- makeMetaStore: async (loader) => {
2954
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeMetaStore).Msg("makeMetaStore");
2955
- return ensureStart(await (loader.ebOpts.store.makeMetaStore || metaStoreFactory)(loader), logger);
2956
- },
2957
- makeDataStore: async (loader) => {
2958
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeDataStore).Msg("makeDataStore");
2959
- return ensureStart(await (loader.ebOpts.store.makeDataStore || dataStoreFactory)(loader), logger);
2960
- },
2961
- makeWALStore: async (loader) => {
2962
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeWALStore).Msg("makeRemoteWAL");
2963
- return ensureStart(await (loader.ebOpts.store.makeWALStore || remoteWalFactory)(loader), logger);
2964
- },
2965
- encodeFile: opts.encodeFile || encodeFile,
2966
- decodeFile: opts.decodeFile || decodeFile
3183
+ encodeFile: ende.encodeFile || encodeFile,
3184
+ decodeFile: ende.decodeFile || decodeFile
3185
+ };
3186
+ }
3187
+ function toStoreRuntime(sthis, endeOpts = {}) {
3188
+ return {
3189
+ makeMetaStore: async (sfi) => ensureStart(await metaStoreFactory(sfi)),
3190
+ // async (loader: Loadable) => {
3191
+ // logger
3192
+ // .Debug()
3193
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeMetaStore)
3194
+ // .Msg("makeMetaStore");
3195
+ // return ensureStart(await (endeOpts.func?.makeMetaStore || metaStoreFactory)(loader), logger);
3196
+ // },
3197
+ makeDataStore: async (sfi) => ensureStart(await dataStoreFactory(sfi)),
3198
+ // async (loader: Loadable) => {
3199
+ // logger
3200
+ // .Debug()
3201
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeDataStore)
3202
+ // .Msg("makeDataStore");
3203
+ // return ensureStart(await (endeOpts.func?.makeDataStore || dataStoreFactory)(loader), logger);
3204
+ // },
3205
+ makeWALStore: async (sfi) => ensureStart(await WALStoreFactory(sfi)),
3206
+ // async (loader: Loadable) => {
3207
+ // logger
3208
+ // .Debug()
3209
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeWALStore)
3210
+ // .Msg("makeRemoteWAL");
3211
+ // return ensureStart(await (endeOpts.func?.makeWALStore || remoteWalFactory)(loader), logger);
3212
+ // },
3213
+ ...ensureStoreEnDeFile(endeOpts)
2967
3214
  };
2968
3215
  }
2969
- registerStoreProtocol({
2970
- protocol: "file:",
2971
- gateway: async (sthis) => {
2972
- const { FileGateway: FileGateway2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
2973
- return new FileGateway2(sthis);
2974
- },
2975
- test: async (sthis) => {
2976
- const { FileTestStore: FileTestStore2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
2977
- return new FileTestStore2(sthis);
2978
- }
2979
- });
2980
- registerStoreProtocol({
2981
- protocol: "indexdb:",
2982
- gateway: async (sthis) => {
2983
- const { IndexDBGateway: IndexDBGateway2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
2984
- return new IndexDBGateway2(sthis);
2985
- },
2986
- test: async (sthis) => {
2987
- const { IndexDBTestStore: IndexDBTestStore2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
2988
- return new IndexDBTestStore2(sthis);
2989
- }
2990
- });
2991
3216
 
2992
3217
  // src/blockstore/store-remote.ts
2993
- async function RemoteDataStore(sthis, name, url, opts) {
2994
- const ds = new DataStoreImpl(sthis, name, url, opts);
3218
+ async function RemoteDataStore(sthis, url, opts) {
3219
+ const ds = new DataStoreImpl(sthis, url, opts);
2995
3220
  await ds.start();
2996
3221
  return ds;
2997
3222
  }
2998
- async function RemoteMetaStore(sthis, name, url, opts) {
2999
- const ms = new MetaStoreImpl(
3000
- sthis,
3001
- name,
3002
- url,
3003
- opts
3004
- /* , true*/
3005
- );
3223
+ async function RemoteMetaStore(sthis, url, opts) {
3224
+ const ms = new MetaStoreImpl(sthis, url, opts);
3006
3225
  await ms.start();
3007
3226
  return ms;
3008
3227
  }
3009
3228
 
3010
3229
  // src/blockstore/connection-base.ts
3230
+ function coerceLoader(ref) {
3231
+ const refl = ref;
3232
+ if (refl.loader) {
3233
+ return refl.loader;
3234
+ }
3235
+ const refb = ref;
3236
+ if (refb.blockstore) {
3237
+ return coerceLoader(refb.blockstore);
3238
+ }
3239
+ return void 0;
3240
+ }
3011
3241
  var ConnectionBase = class {
3012
3242
  constructor(url, logger) {
3013
3243
  this.loaded = Promise.resolve();
@@ -3018,23 +3248,26 @@ var ConnectionBase = class {
3018
3248
  await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
3019
3249
  await (await throwFalsy(this.loader).WALStore()).process();
3020
3250
  }
3021
- async connect_X({ loader }) {
3022
- if (!loader) throw this.logger.Error().Msg("loader is required").AsError();
3023
- await this.connectMeta_X({ loader });
3024
- await this.connectStorage_X({ loader });
3251
+ async connect(refl) {
3252
+ await this.connectMeta(refl);
3253
+ await this.connectStorage(refl);
3025
3254
  }
3026
- async connectMeta_X({ loader }) {
3027
- if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
3255
+ async connectMeta(refl) {
3256
+ const loader = coerceLoader(refl);
3257
+ if (!loader) throw this.logger.Error().Msg("connectMeta: loader is required").AsError();
3028
3258
  this.loader = loader;
3029
3259
  await this.onConnect();
3030
- const metaUrl = this.url.build().defParam("store", "meta").URI();
3031
- const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
3032
- if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
3033
- const dbName = metaUrl.getParam("name");
3034
- if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: name is required").AsError();
3035
- const remote = await RemoteMetaStore(loader.sthis, dbName, metaUrl, {
3260
+ const metaUrl = this.url.build().defParam("store" /* STORE */, "meta").URI();
3261
+ const rgateway = await getStartedGateway(loader.sthis, metaUrl);
3262
+ if (rgateway.isErr())
3263
+ throw this.logger.Error().Result("err", rgateway).Url(metaUrl).Msg("connectMeta: gateway is required").AsError();
3264
+ const dbName = metaUrl.getParam("name" /* NAME */);
3265
+ if (!dbName) {
3266
+ throw this.logger.Error().Url(metaUrl).Msg("connectMeta: dbName is required").AsError();
3267
+ }
3268
+ const gateway = rgateway.Ok();
3269
+ const remote = await RemoteMetaStore(loader.sthis, metaUrl, {
3036
3270
  gateway: gateway.gateway,
3037
- keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag),
3038
3271
  loader
3039
3272
  });
3040
3273
  this.loader.remoteMetaStore = remote;
@@ -3044,17 +3277,19 @@ var ConnectionBase = class {
3044
3277
  });
3045
3278
  });
3046
3279
  }
3047
- async connectStorage_X({ loader }) {
3280
+ async connectStorage(refl) {
3281
+ const loader = coerceLoader(refl);
3048
3282
  if (!loader) throw this.logger.Error().Msg("connectStorage_X: loader is required").AsError();
3049
3283
  this.loader = loader;
3050
- const dataUrl = this.url.build().defParam("store", "data").URI();
3051
- const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
3052
- if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
3053
- const name = dataUrl.getParam("name");
3284
+ const dataUrl = this.url.build().defParam("store" /* STORE */, "data").URI();
3285
+ const rgateway = await getStartedGateway(loader.sthis, dataUrl);
3286
+ if (rgateway.isErr())
3287
+ throw this.logger.Error().Result("err", rgateway).Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
3288
+ const name = dataUrl.getParam("name" /* NAME */);
3054
3289
  if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: name is required").AsError;
3055
- loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
3056
- gateway: gateway.gateway,
3057
- keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
3290
+ loader.remoteCarStore = await RemoteDataStore(loader.sthis, this.url, {
3291
+ gateway: rgateway.Ok().gateway,
3292
+ loader
3058
3293
  });
3059
3294
  loader.remoteFileStore = loader.remoteCarStore;
3060
3295
  }
@@ -3066,9 +3301,9 @@ var ConnectionBase = class {
3066
3301
  // // await this.compact()
3067
3302
  // // }
3068
3303
  // const currents = await this.loader?.metaStore?.load()
3069
- // if (!currents) throw new Error("Can't sync empty database: save data first")
3304
+ // if (!currents) throw new Error("Can't sync empty ledger: save data first")
3070
3305
  // if (currents.length > 1)
3071
- // throw new Error("Can't sync database with split heads: make an update first")
3306
+ // throw new Error("Can't sync ledger with split heads: make an update first")
3072
3307
  // const current = currents[0]
3073
3308
  // const params = {
3074
3309
  // car: current.car.toString()
@@ -3094,6 +3329,12 @@ var ConnectionBase = class {
3094
3329
  };
3095
3330
 
3096
3331
  // src/crdt-helpers.ts
3332
+ var import_link2 = require("multiformats/link");
3333
+ var import_sha25 = require("multiformats/hashes/sha2");
3334
+ var codec = __toESM(require("@fireproof/vendor/@ipld/dag-cbor"), 1);
3335
+ var import_crdt = require("@fireproof/vendor/@web3-storage/pail/crdt");
3336
+ var import_clock3 = require("@fireproof/vendor/@web3-storage/pail/clock");
3337
+ var Batch = __toESM(require("@fireproof/vendor/@web3-storage/pail/crdt/batch"), 1);
3097
3338
  function time(tag) {
3098
3339
  }
3099
3340
  function timeEnd(tag) {
@@ -3161,7 +3402,7 @@ async function processFiles(store, blocks, doc, logger) {
3161
3402
  }
3162
3403
  async function processFileset(logger, store, blocks, files) {
3163
3404
  const dbBlockstore = blocks.parent;
3164
- if (!dbBlockstore.loader) throw logger.Error().Msg("Missing loader, database name is required").AsError();
3405
+ if (!dbBlockstore.loader) throw logger.Error().Msg("Missing loader, ledger name is required").AsError();
3165
3406
  const t = new CarTransaction(dbBlockstore);
3166
3407
  const didPut = [];
3167
3408
  for (const filename in files) {
@@ -3193,7 +3434,7 @@ async function processFileset(logger, store, blocks, files) {
3193
3434
  }
3194
3435
  }
3195
3436
  async function getValueFromCrdt(blocks, head, key, logger) {
3196
- if (!head.length) throw logger.Debug().Msg("Getting from an empty database").AsError();
3437
+ if (!head.length) throw logger.Debug().Msg("Getting from an empty ledger").AsError();
3197
3438
  const link = await (0, import_crdt.get)(blocks, head, key);
3198
3439
  if (!link) throw logger.Error().Str("key", key).Msg(`Missing key`).AsError();
3199
3440
  return await getValueFromLink(blocks, link, logger);
@@ -3240,7 +3481,7 @@ async function getValueFromLink(blocks, link, logger) {
3240
3481
  readFiles(blocks, cvalue);
3241
3482
  return cvalue;
3242
3483
  }
3243
- var DirtyEventFetcher = class extends import_clock2.EventFetcher {
3484
+ var DirtyEventFetcher = class extends import_clock3.EventFetcher {
3244
3485
  constructor(logger, blocks) {
3245
3486
  super(blocks);
3246
3487
  this.logger = logger;
@@ -3255,7 +3496,7 @@ var DirtyEventFetcher = class extends import_clock2.EventFetcher {
3255
3496
  }
3256
3497
  };
3257
3498
  async function clockChangesSince(blocks, head, since, opts, logger) {
3258
- const eventsFetcher = opts.dirty ? new DirtyEventFetcher(logger, blocks) : new import_clock2.EventFetcher(blocks);
3499
+ const eventsFetcher = opts.dirty ? new DirtyEventFetcher(logger, blocks) : new import_clock3.EventFetcher(blocks);
3259
3500
  const keys = /* @__PURE__ */ new Set();
3260
3501
  const updates = await gatherUpdates(
3261
3502
  blocks,
@@ -3312,7 +3553,7 @@ async function* getAllEntries(blocks, head, logger) {
3312
3553
  }
3313
3554
  }
3314
3555
  async function* clockVis(blocks, head) {
3315
- for await (const line of (0, import_clock2.vis)(blocks, head)) {
3556
+ for await (const line of (0, import_clock3.vis)(blocks, head)) {
3316
3557
  yield line;
3317
3558
  }
3318
3559
  }
@@ -3334,7 +3575,7 @@ async function doCompact(blockLog, head, logger) {
3334
3575
  }
3335
3576
  timeEnd("compact all entries");
3336
3577
  time("compact clock vis");
3337
- for await (const _line of (0, import_clock2.vis)(blockLog, head)) {
3578
+ for await (const _line of (0, import_clock3.vis)(blockLog, head)) {
3338
3579
  }
3339
3580
  timeEnd("compact clock vis");
3340
3581
  time("compact root");
@@ -3351,7 +3592,7 @@ async function doCompact(blockLog, head, logger) {
3351
3592
  isCompacting = false;
3352
3593
  }
3353
3594
  async function getBlock(blocks, cidString) {
3354
- const block = await blocks.get((0, import_link.parse)(cidString));
3595
+ const block = await blocks.get((0, import_link2.parse)(cidString));
3355
3596
  if (!block) throw new Error(`Missing block ${cidString}`);
3356
3597
  const { cid, value } = await decode({ bytes: block.bytes, codec, hasher: import_sha25.sha256 });
3357
3598
  return new Block({ cid, value, bytes: block.bytes });
@@ -3362,7 +3603,7 @@ var import_sha26 = require("multiformats/hashes/sha2");
3362
3603
  var codec2 = __toESM(require("@fireproof/vendor/@ipld/dag-cbor"), 1);
3363
3604
  var import_charwise = __toESM(require("charwise"), 1);
3364
3605
  var DbIndex = __toESM(require("prolly-trees/db-index"), 1);
3365
- var import_utils14 = require("prolly-trees/utils");
3606
+ var import_utils12 = require("prolly-trees/utils");
3366
3607
  var import_cache = require("prolly-trees/cache");
3367
3608
  var IndexTree = class {
3368
3609
  };
@@ -3370,17 +3611,17 @@ function refCompare(aRef, bRef) {
3370
3611
  if (Number.isNaN(aRef)) return -1;
3371
3612
  if (Number.isNaN(bRef)) throw new Error("ref may not be Infinity or NaN");
3372
3613
  if (aRef === Infinity) return 1;
3373
- return (0, import_utils14.simpleCompare)(aRef, bRef);
3614
+ return (0, import_utils12.simpleCompare)(aRef, bRef);
3374
3615
  }
3375
3616
  function compare(a, b) {
3376
3617
  const [aKey, aRef] = a;
3377
3618
  const [bKey, bRef] = b;
3378
- const comp = (0, import_utils14.simpleCompare)(aKey, bKey);
3619
+ const comp = (0, import_utils12.simpleCompare)(aKey, bKey);
3379
3620
  if (comp !== 0) return comp;
3380
3621
  return refCompare(aRef, bRef);
3381
3622
  }
3382
- var byKeyOpts = { cache: import_cache.nocache, chunker: (0, import_utils14.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare };
3383
- var byIdOpts = { cache: import_cache.nocache, chunker: (0, import_utils14.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare: import_utils14.simpleCompare };
3623
+ var byKeyOpts = { cache: import_cache.nocache, chunker: (0, import_utils12.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare };
3624
+ var byIdOpts = { cache: import_cache.nocache, chunker: (0, import_utils12.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare: import_utils12.simpleCompare };
3384
3625
  function indexEntriesForChanges(changes, mapFn) {
3385
3626
  const indexEntries = [];
3386
3627
  changes.forEach(({ id: key, value, del }) => {
@@ -3411,7 +3652,8 @@ function makeProllyGetBlock(blocks) {
3411
3652
  return create({ cid, bytes, hasher: import_sha26.sha256, codec: codec2 });
3412
3653
  };
3413
3654
  }
3414
- async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
3655
+ async function bulkIndex(logger, tblocks, inIndex, indexEntries, opts) {
3656
+ logger.Debug().Msg("enter bulkIndex");
3415
3657
  if (!indexEntries.length) return inIndex;
3416
3658
  if (!inIndex.root) {
3417
3659
  if (!inIndex.cid) {
@@ -3428,18 +3670,22 @@ async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
3428
3670
  returnNode = node;
3429
3671
  }
3430
3672
  if (!returnNode || !returnRootBlock) throw new Error("failed to create index");
3673
+ logger.Debug().Msg("exit !root bulkIndex");
3431
3674
  return { root: returnNode, cid: returnRootBlock.cid };
3432
3675
  } else {
3433
3676
  inIndex.root = await DbIndex.load({ cid: inIndex.cid, get: makeProllyGetBlock(tblocks), ...opts });
3434
3677
  }
3435
3678
  }
3679
+ logger.Debug().Msg("pre bulk bulkIndex");
3436
3680
  const { root: root3, blocks: newBlocks } = await inIndex.root.bulk(indexEntries);
3437
3681
  if (root3) {
3682
+ logger.Debug().Msg("pre root put bulkIndex");
3438
3683
  for await (const block of newBlocks) {
3439
3684
  await tblocks.put(block.cid, block.bytes);
3440
3685
  }
3441
3686
  return { root: root3, cid: (await root3.block).cid };
3442
3687
  } else {
3688
+ logger.Debug().Msg("pre !root bulkIndex");
3443
3689
  return { root: void 0, cid: void 0 };
3444
3690
  }
3445
3691
  }
@@ -3479,18 +3725,17 @@ function encodeKey(key) {
3479
3725
  }
3480
3726
 
3481
3727
  // src/indexer.ts
3482
- init_utils();
3483
- function index(sthis, { _crdt }, name, mapFn, meta) {
3484
- if (mapFn && meta) throw _crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
3485
- if (mapFn && mapFn.constructor.name !== "Function") throw _crdt.logger.Error().Msg("mapFn must be a function").AsError();
3486
- if (_crdt.indexers.has(name)) {
3487
- const idx = _crdt.indexers.get(name);
3728
+ function index(refDb, name, mapFn, meta) {
3729
+ if (mapFn && meta) throw refDb.crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
3730
+ if (mapFn && mapFn.constructor.name !== "Function") throw refDb.crdt.logger.Error().Msg("mapFn must be a function").AsError();
3731
+ if (refDb.crdt.indexers.has(name)) {
3732
+ const idx = refDb.crdt.indexers.get(name);
3488
3733
  idx.applyMapFn(name, mapFn, meta);
3489
3734
  } else {
3490
- const idx = new Index(sthis, _crdt, name, mapFn, meta);
3491
- _crdt.indexers.set(name, idx);
3735
+ const idx = new Index(refDb.crdt.sthis, refDb.crdt, name, mapFn, meta);
3736
+ refDb.crdt.indexers.set(name, idx);
3492
3737
  }
3493
- return _crdt.indexers.get(name);
3738
+ return refDb.crdt.indexers.get(name);
3494
3739
  }
3495
3740
  var Index = class {
3496
3741
  constructor(sthis, crdt, name, mapFn, meta) {
@@ -3509,18 +3754,9 @@ var Index = class {
3509
3754
  return Promise.all([this.blockstore.ready(), this.crdt.ready()]).then(() => {
3510
3755
  });
3511
3756
  }
3512
- close() {
3513
- return Promise.all([this.blockstore.close(), this.crdt.close()]).then(() => {
3514
- });
3515
- }
3516
- destroy() {
3517
- return Promise.all([this.blockstore.destroy(), this.crdt.destroy()]).then(() => {
3518
- });
3519
- }
3520
3757
  applyMapFn(name, mapFn, meta) {
3521
3758
  if (mapFn && meta) throw this.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
3522
3759
  if (this.name && this.name !== name) throw this.logger.Error().Msg("cannot change name").AsError();
3523
- this.name = name;
3524
3760
  try {
3525
3761
  if (meta) {
3526
3762
  if (this.indexHead && this.indexHead.map((c) => c.toString()).join() !== meta.head.map((c) => c.toString()).join()) {
@@ -3568,9 +3804,13 @@ var Index = class {
3568
3804
  }
3569
3805
  }
3570
3806
  async query(opts = {}) {
3807
+ this.logger.Debug().Msg("enter query");
3571
3808
  await this.ready();
3809
+ this.logger.Debug().Msg("post ready query");
3572
3810
  await this._updateIndex();
3811
+ this.logger.Debug().Msg("post _updateIndex query");
3573
3812
  await this._hydrateIndex();
3813
+ this.logger.Debug().Msg("post _hydrateIndex query");
3574
3814
  if (!this.byKey.root) {
3575
3815
  return await applyQuery(this.crdt, { result: [] }, opts);
3576
3816
  }
@@ -3626,13 +3866,16 @@ var Index = class {
3626
3866
  }
3627
3867
  async _updateIndex() {
3628
3868
  await this.ready();
3869
+ this.logger.Debug().Msg("enter _updateIndex");
3629
3870
  if (this.initError) throw this.initError;
3630
3871
  if (!this.mapFn) throw this.logger.Error().Msg("No map function defined").AsError();
3631
3872
  let result, head;
3632
3873
  if (!this.indexHead || this.indexHead.length === 0) {
3633
3874
  ({ result, head } = await this.crdt.allDocs());
3875
+ this.logger.Debug().Msg("enter crdt.allDocs");
3634
3876
  } else {
3635
3877
  ({ result, head } = await this.crdt.changes(this.indexHead));
3878
+ this.logger.Debug().Msg("enter crdt.changes");
3636
3879
  }
3637
3880
  if (result.length === 0) {
3638
3881
  this.indexHead = head;
@@ -3665,9 +3908,22 @@ var Index = class {
3665
3908
  if (result.length === 0) {
3666
3909
  return indexerMeta;
3667
3910
  }
3911
+ this.logger.Debug().Msg("pre this.blockstore.transaction");
3668
3912
  const { meta } = await this.blockstore.transaction(async (tblocks) => {
3669
- this.byId = await bulkIndex(tblocks, this.byId, removeIdIndexEntries.concat(byIdIndexEntries), byIdOpts);
3670
- this.byKey = await bulkIndex(tblocks, this.byKey, staleKeyIndexEntries.concat(indexEntries), byKeyOpts);
3913
+ this.byId = await bulkIndex(
3914
+ this.logger,
3915
+ tblocks,
3916
+ this.byId,
3917
+ removeIdIndexEntries.concat(byIdIndexEntries),
3918
+ byIdOpts
3919
+ );
3920
+ this.byKey = await bulkIndex(
3921
+ this.logger,
3922
+ tblocks,
3923
+ this.byKey,
3924
+ staleKeyIndexEntries.concat(indexEntries),
3925
+ byKeyOpts
3926
+ );
3671
3927
  this.indexHead = head;
3672
3928
  if (this.byId.cid && this.byKey.cid) {
3673
3929
  const idxMeta = {
@@ -3679,16 +3935,18 @@ var Index = class {
3679
3935
  };
3680
3936
  indexerMeta.indexes?.set(this.name, idxMeta);
3681
3937
  }
3938
+ this.logger.Debug().Any("indexerMeta", new Array(indexerMeta.indexes?.entries())).Msg("exit this.blockstore.transaction fn");
3682
3939
  return indexerMeta;
3683
3940
  });
3941
+ this.logger.Debug().Msg("post this.blockstore.transaction");
3684
3942
  return meta;
3685
3943
  }
3686
3944
  };
3687
3945
 
3688
3946
  // src/crdt-clock.ts
3689
- var import_clock3 = require("@fireproof/vendor/@web3-storage/pail/clock");
3947
+ var import_clock4 = require("@fireproof/vendor/@web3-storage/pail/clock");
3690
3948
  var import_crdt2 = require("@fireproof/vendor/@web3-storage/pail/crdt");
3691
- var import_cement14 = require("@adviser/cement");
3949
+ var import_cement18 = require("@adviser/cement");
3692
3950
 
3693
3951
  // src/apply-head-queue.ts
3694
3952
  function applyHeadQueue(worker, logger) {
@@ -3736,7 +3994,6 @@ function applyHeadQueue(worker, logger) {
3736
3994
  }
3737
3995
 
3738
3996
  // src/crdt-clock.ts
3739
- init_utils();
3740
3997
  var CRDTClock = class {
3741
3998
  constructor(blockstore) {
3742
3999
  // todo: track local and remote clocks independently, merge on read
@@ -3746,7 +4003,7 @@ var CRDTClock = class {
3746
4003
  this.zoomers = /* @__PURE__ */ new Set();
3747
4004
  this.watchers = /* @__PURE__ */ new Set();
3748
4005
  this.emptyWatchers = /* @__PURE__ */ new Set();
3749
- this._ready = new import_cement14.ResolveOnce();
4006
+ this._ready = new import_cement18.ResolveOnce();
3750
4007
  this.blockstore = blockstore;
3751
4008
  this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
3752
4009
  this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
@@ -3846,7 +4103,7 @@ function compareClockHeads(head1, head2) {
3846
4103
  async function advanceBlocks(logger, newHead, tblocks, head) {
3847
4104
  for (const cid of newHead) {
3848
4105
  try {
3849
- head = await (0, import_clock3.advance)(tblocks, head, cid);
4106
+ head = await (0, import_clock4.advance)(tblocks, head, cid);
3850
4107
  } catch (e) {
3851
4108
  logger.Debug().Err(e).Msg("failed to advance head");
3852
4109
  continue;
@@ -3856,17 +4113,14 @@ async function advanceBlocks(logger, newHead, tblocks, head) {
3856
4113
  }
3857
4114
 
3858
4115
  // src/crdt.ts
3859
- init_utils();
3860
4116
  var CRDT = class {
3861
- constructor(sthis, name, opts = {}) {
4117
+ constructor(sthis, opts) {
3862
4118
  this.indexers = /* @__PURE__ */ new Map();
3863
- this.onceReady = new import_cement15.ResolveOnce();
4119
+ this.onceReady = new import_cement19.ResolveOnce();
3864
4120
  this.sthis = sthis;
3865
- this.name = name;
3866
4121
  this.logger = ensureLogger(sthis, "CRDT");
3867
4122
  this.opts = opts;
3868
- this.blockstore = blockstoreFactory(sthis, {
3869
- name,
4123
+ this.blockstore = new EncryptedBlockstore(sthis, {
3870
4124
  applyMeta: async (meta) => {
3871
4125
  const crdtMeta = meta;
3872
4126
  if (!crdtMeta.head) throw this.logger.Error().Msg("missing head").AsError();
@@ -3876,23 +4130,29 @@ var CRDT = class {
3876
4130
  await doCompact(blocks, this.clock.head, this.logger);
3877
4131
  return { head: this.clock.head };
3878
4132
  },
3879
- autoCompact: this.opts.autoCompact || 100,
3880
- store: { ...this.opts.store, isIndex: void 0 },
3881
- public: this.opts.public,
3882
- meta: this.opts.meta,
3883
- threshold: this.opts.threshold
4133
+ gatewayInterceptor: opts.gatewayInterceptor,
4134
+ // autoCompact: this.opts.autoCompact || 100,
4135
+ storeRuntime: toStoreRuntime(this.sthis, this.opts.storeEnDe),
4136
+ storeUrls: this.opts.storeUrls.data,
4137
+ keyBag: this.opts.keyBag,
4138
+ // public: this.opts.public,
4139
+ meta: this.opts.meta
4140
+ // threshold: this.opts.threshold,
3884
4141
  });
3885
- this.indexBlockstore = blockstoreFactory(sthis, {
3886
- name,
4142
+ this.indexBlockstore = new EncryptedBlockstore(sthis, {
4143
+ // name: opts.name,
3887
4144
  applyMeta: async (meta) => {
3888
4145
  const idxCarMeta = meta;
3889
4146
  if (!idxCarMeta.indexes) throw this.logger.Error().Msg("missing indexes").AsError();
3890
- for (const [name2, idx] of Object.entries(idxCarMeta.indexes)) {
3891
- index(this.sthis, { _crdt: this }, name2, void 0, idx);
4147
+ for (const [name, idx] of Object.entries(idxCarMeta.indexes)) {
4148
+ index({ crdt: this }, name, void 0, idx);
3892
4149
  }
3893
4150
  },
3894
- store: { ...this.opts.store, isIndex: this.opts.store?.isIndex || "idx" },
3895
- public: this.opts.public
4151
+ gatewayInterceptor: opts.gatewayInterceptor,
4152
+ storeRuntime: toStoreRuntime(this.sthis, this.opts.storeEnDe),
4153
+ storeUrls: this.opts.storeUrls.idx,
4154
+ keyBag: this.opts.keyBag
4155
+ // public: this.opts.public,
3896
4156
  });
3897
4157
  this.clock = new CRDTClock(this.blockstore);
3898
4158
  this.clock.onZoom(() => {
@@ -3973,76 +4233,169 @@ var CRDT = class {
3973
4233
  }
3974
4234
  };
3975
4235
 
3976
- // src/database.ts
3977
- init_utils();
3978
- var Database = class {
3979
- constructor(name, opts) {
3980
- this.opts = {};
4236
+ // src/ledger.ts
4237
+ var ledgers = new import_cement20.KeyedResolvOnce();
4238
+ function keyConfigOpts(sthis, name, opts) {
4239
+ return JSON.stringify(
4240
+ toSortedArray({
4241
+ name,
4242
+ stores: toSortedArray(JSON.parse(JSON.stringify(toStoreURIRuntime(sthis, name, opts?.storeUrls))))
4243
+ })
4244
+ );
4245
+ }
4246
+ function isLedger(db) {
4247
+ return db instanceof LedgerImpl || db instanceof LedgerShell;
4248
+ }
4249
+ function LedgerFactory(name, opts) {
4250
+ const sthis = ensureSuperThis(opts);
4251
+ return new LedgerShell(
4252
+ ledgers.get(keyConfigOpts(sthis, name, opts)).once((key) => {
4253
+ const db = new LedgerImpl(sthis, {
4254
+ name,
4255
+ meta: opts?.meta,
4256
+ keyBag: defaultKeyBagOpts(sthis, opts?.keyBag),
4257
+ storeUrls: toStoreURIRuntime(sthis, name, opts?.storeUrls),
4258
+ gatewayInterceptor: opts?.gatewayInterceptor,
4259
+ writeQueue: defaultWriteQueueOpts(opts?.writeQueue),
4260
+ storeEnDe: {
4261
+ encodeFile,
4262
+ decodeFile,
4263
+ ...opts?.storeEnDe
4264
+ }
4265
+ });
4266
+ db.onClosed(() => {
4267
+ ledgers.unget(key);
4268
+ });
4269
+ return db;
4270
+ })
4271
+ );
4272
+ }
4273
+ var LedgerShell = class {
4274
+ constructor(ref) {
4275
+ this.ref = ref;
4276
+ ref.addShell(this);
4277
+ }
4278
+ get id() {
4279
+ return this.ref.id;
4280
+ }
4281
+ get logger() {
4282
+ return this.ref.logger;
4283
+ }
4284
+ get sthis() {
4285
+ return this.ref.sthis;
4286
+ }
4287
+ get crdt() {
4288
+ return this.ref.crdt;
4289
+ }
4290
+ get name() {
4291
+ return this.ref.name;
4292
+ }
4293
+ onClosed(fn) {
4294
+ return this.ref.onClosed(fn);
4295
+ }
4296
+ close() {
4297
+ return this.ref.shellClose(this);
4298
+ }
4299
+ destroy() {
4300
+ return this.ref.destroy();
4301
+ }
4302
+ ready() {
4303
+ return this.ref.ready();
4304
+ }
4305
+ get(id) {
4306
+ return this.ref.get(id);
4307
+ }
4308
+ put(doc) {
4309
+ return this.ref.put(doc);
4310
+ }
4311
+ bulk(docs) {
4312
+ return this.ref.bulk(docs);
4313
+ }
4314
+ del(id) {
4315
+ return this.ref.del(id);
4316
+ }
4317
+ changes(since, opts) {
4318
+ return this.ref.changes(since, opts);
4319
+ }
4320
+ allDocs(opts) {
4321
+ return this.ref.allDocs(opts);
4322
+ }
4323
+ allDocuments() {
4324
+ return this.ref.allDocuments();
4325
+ }
4326
+ subscribe(listener, updates) {
4327
+ return this.ref.subscribe(listener, updates);
4328
+ }
4329
+ query(field, opts) {
4330
+ return this.ref.query(field, opts);
4331
+ }
4332
+ compact() {
4333
+ return this.ref.compact();
4334
+ }
4335
+ };
4336
+ var LedgerImpl = class {
4337
+ constructor(sthis, opts) {
3981
4338
  this._listening = false;
3982
4339
  this._listeners = /* @__PURE__ */ new Set();
3983
4340
  this._noupdate_listeners = /* @__PURE__ */ new Set();
3984
- this._ready = new import_cement16.ResolveOnce();
3985
- this.name = name;
3986
- this.opts = opts || this.opts;
3987
- this.sthis = ensureSuperThis(this.opts);
3988
- this.logger = ensureLogger(this.sthis, "Database");
3989
- this._crdt = new CRDT(this.sthis, name, this.opts);
3990
- this.blockstore = this._crdt.blockstore;
3991
- this._writeQueue = writeQueue(async (updates) => {
3992
- return await this._crdt.bulk(updates);
3993
- });
3994
- this._crdt.clock.onTock(() => {
3995
- this._no_update_notify();
3996
- });
4341
+ // readonly blockstore: BaseBlockstore;
4342
+ this.shells = /* @__PURE__ */ new Set();
4343
+ this._onClosedFns = /* @__PURE__ */ new Set();
4344
+ this._ready = new import_cement20.ResolveOnce();
4345
+ this.opts = opts;
4346
+ this.sthis = sthis;
4347
+ this.id = sthis.timeOrderedNextId().str;
4348
+ this.logger = ensureLogger(this.sthis, "Ledger");
4349
+ this.crdt = new CRDT(this.sthis, this.opts);
4350
+ this._writeQueue = writeQueue(this.sthis, async (updates) => this.crdt.bulk(updates), this.opts.writeQueue);
4351
+ this.crdt.clock.onTock(() => this._no_update_notify());
4352
+ }
4353
+ addShell(shell) {
4354
+ this.shells.add(shell);
3997
4355
  }
3998
- static {
3999
- this.databases = /* @__PURE__ */ new Map();
4356
+ onClosed(fn) {
4357
+ this._onClosedFns.add(fn);
4000
4358
  }
4001
- /**
4002
- * Close the database and release resources
4003
- */
4004
4359
  async close() {
4005
- await this.ready();
4006
- await this._crdt.close();
4007
- await this.blockstore.close();
4360
+ throw this.logger.Error().Str("db", this.name).Msg(`use shellClose`).AsError();
4361
+ }
4362
+ async shellClose(db) {
4363
+ if (!this.shells.has(db)) {
4364
+ throw this.logger.Error().Str("db", this.name).Msg(`LedgerShell mismatch`).AsError();
4365
+ }
4366
+ this.shells.delete(db);
4367
+ if (this.shells.size === 0) {
4368
+ await this.ready();
4369
+ await this.crdt.close();
4370
+ await this._writeQueue.close();
4371
+ this._onClosedFns.forEach((fn) => fn());
4372
+ }
4008
4373
  }
4009
- /**
4010
- * Destroy the database and release all resources
4011
- */
4012
4374
  async destroy() {
4013
4375
  await this.ready();
4014
- await this._crdt.destroy();
4015
- await this.blockstore.destroy();
4376
+ await this.crdt.destroy();
4016
4377
  }
4017
4378
  async ready() {
4018
- return this._ready.once(async () => {
4379
+ const ret = await this._ready.once(async () => {
4019
4380
  await this.sthis.start();
4020
- await this._crdt.ready();
4021
- await this.blockstore.ready();
4381
+ await this.crdt.ready();
4022
4382
  });
4383
+ return ret;
4384
+ }
4385
+ get name() {
4386
+ return this.opts.storeUrls.data.data.getParam("name" /* NAME */) || "default";
4023
4387
  }
4024
- /**
4025
- * Get a document from the database
4026
- * @param id - the document id
4027
- * @returns the document with the _id
4028
- * @throws NotFoundError if the document is not found
4029
- */
4030
4388
  async get(id) {
4031
4389
  if (!id) throw this.logger.Error().Str("db", this.name).Msg(`Doc id is required`).AsError();
4032
4390
  await this.ready();
4033
4391
  this.logger.Debug().Str("id", id).Msg("get");
4034
- const got = await this._crdt.get(id).catch((e) => {
4392
+ const got = await this.crdt.get(id).catch((e) => {
4035
4393
  throw new NotFoundError(`Not found: ${id} - ${e.message}`);
4036
4394
  });
4037
4395
  if (!got) throw new NotFoundError(`Not found: ${id}`);
4038
4396
  const { doc } = got;
4039
4397
  return { ...doc, _id: id };
4040
4398
  }
4041
- /**
4042
- * Put a document from the database
4043
- * @param doc - the document to put
4044
- * @returns add DocResponse with the id and clock
4045
- */
4046
4399
  async put(doc) {
4047
4400
  await this.ready();
4048
4401
  this.logger.Debug().Str("id", doc._id).Msg("put");
@@ -4057,11 +4410,21 @@ var Database = class {
4057
4410
  });
4058
4411
  return { id: docId, clock: result?.head, name: this.name };
4059
4412
  }
4060
- /**
4061
- * delete a document from the database
4062
- * @param id Document id
4063
- * @returns DocResponse with the id and clock
4064
- */
4413
+ async bulk(docs) {
4414
+ await this.ready();
4415
+ const updates = docs.map((doc) => {
4416
+ const id = doc._id || this.sthis.timeOrderedNextId().str;
4417
+ return {
4418
+ id,
4419
+ value: {
4420
+ ...doc,
4421
+ _id: id
4422
+ }
4423
+ };
4424
+ });
4425
+ const result = await this._writeQueue.bulk(updates);
4426
+ return { ids: updates.map((u) => u.id), clock: result.head, name: this.name };
4427
+ }
4065
4428
  async del(id) {
4066
4429
  await this.ready();
4067
4430
  this.logger.Debug().Str("id", id).Msg("del");
@@ -4071,7 +4434,7 @@ var Database = class {
4071
4434
  async changes(since = [], opts = {}) {
4072
4435
  await this.ready();
4073
4436
  this.logger.Debug().Any("since", since).Any("opts", opts).Msg("changes");
4074
- const { result, head } = await this._crdt.changes(since, opts);
4437
+ const { result, head } = await this.crdt.changes(since, opts);
4075
4438
  const rows = result.map(({ id: key, value, del, clock }) => ({
4076
4439
  key,
4077
4440
  value: del ? { _id: key, _deleted: true } : { _id: key, ...value },
@@ -4082,7 +4445,7 @@ var Database = class {
4082
4445
  async allDocs(opts = {}) {
4083
4446
  await this.ready();
4084
4447
  this.logger.Debug().Msg("allDocs");
4085
- const { result, head } = await this._crdt.allDocs();
4448
+ const { result, head } = await this.crdt.allDocs();
4086
4449
  const rows = result.map(({ id: key, value, del }) => ({
4087
4450
  key,
4088
4451
  value: del ? { _id: key, _deleted: true } : { _id: key, ...value }
@@ -4097,7 +4460,7 @@ var Database = class {
4097
4460
  if (updates) {
4098
4461
  if (!this._listening) {
4099
4462
  this._listening = true;
4100
- this._crdt.clock.onTick((updates2) => {
4463
+ this.crdt.clock.onTick((updates2) => {
4101
4464
  void this._notify(updates2);
4102
4465
  });
4103
4466
  }
@@ -4116,13 +4479,13 @@ var Database = class {
4116
4479
  async query(field, opts = {}) {
4117
4480
  await this.ready();
4118
4481
  this.logger.Debug().Any("field", field).Any("opts", opts).Msg("query");
4119
- const _crdt = this._crdt;
4120
- const idx = typeof field === "string" ? index(this.sthis, { _crdt }, field) : index(this.sthis, { _crdt }, makeName(field.toString()), field);
4482
+ const _crdt = this.crdt;
4483
+ const idx = typeof field === "string" ? index({ crdt: _crdt }, field) : index({ crdt: _crdt }, makeName(field.toString()), field);
4121
4484
  return await idx.query(opts);
4122
4485
  }
4123
4486
  async compact() {
4124
4487
  await this.ready();
4125
- await this._crdt.compact();
4488
+ await this.crdt.compact();
4126
4489
  }
4127
4490
  async _notify(updates) {
4128
4491
  await this.ready();
@@ -4146,23 +4509,62 @@ var Database = class {
4146
4509
  }
4147
4510
  }
4148
4511
  };
4149
- function toSortedArray(set) {
4150
- if (!set) return [];
4151
- return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
4512
+ function defaultURI2(sthis, curi, uri, store, ctx) {
4513
+ ctx = ctx || {};
4514
+ const ret = (curi ? import_cement20.URI.from(curi) : uri).build().setParam("store" /* STORE */, store);
4515
+ if (!ret.hasParam("name" /* NAME */)) {
4516
+ const name = sthis.pathOps.basename(ret.URI().pathname);
4517
+ if (!name) {
4518
+ throw sthis.logger.Error().Url(ret).Any("ctx", ctx).Msg("Ledger name is required").AsError();
4519
+ }
4520
+ ret.setParam("name" /* NAME */, name);
4521
+ }
4522
+ if (ctx.idx) {
4523
+ ret.defParam("index" /* INDEX */, "idx");
4524
+ ret.defParam("storekey" /* STORE_KEY */, `@${ret.getParam("name" /* NAME */)}-${store}-idx@`);
4525
+ } else {
4526
+ ret.defParam("storekey" /* STORE_KEY */, `@${ret.getParam("name" /* NAME */)}-${store}@`);
4527
+ }
4528
+ if (store === "data") {
4529
+ if (ctx.file) {
4530
+ } else {
4531
+ ret.defParam("suffix" /* SUFFIX */, ".car");
4532
+ }
4533
+ }
4534
+ return ret.URI();
4152
4535
  }
4153
- function fireproof(name, opts) {
4154
- const key = JSON.stringify(
4155
- toSortedArray({
4156
- name,
4157
- stores: toSortedArray(opts?.store?.stores)
4158
- })
4159
- );
4160
- let db = Database.databases.get(key);
4161
- if (!db) {
4162
- db = new Database(name, opts);
4163
- Database.databases.set(key, db);
4536
+ function toStoreURIRuntime(sthis, name, sopts) {
4537
+ sopts = sopts || {};
4538
+ if (!sopts.base) {
4539
+ const fp_env = sthis.env.get("FP_STORAGE_URL");
4540
+ if (fp_env) {
4541
+ sopts = { ...sopts, base: import_cement20.BuildURI.from(fp_env).setParam("urlGen" /* URL_GEN */, "fromEnv") };
4542
+ } else {
4543
+ sopts = { ...sopts, base: getDefaultURI(sthis).build().setParam("urlGen" /* URL_GEN */, "default") };
4544
+ }
4545
+ }
4546
+ const bbase = import_cement20.BuildURI.from(sopts.base);
4547
+ if (name) {
4548
+ bbase.setParam("name" /* NAME */, name);
4164
4549
  }
4165
- return db;
4550
+ const base = bbase.URI();
4551
+ return {
4552
+ idx: {
4553
+ data: defaultURI2(sthis, sopts.idx?.data, base, "data", { idx: true }),
4554
+ file: defaultURI2(sthis, sopts.idx?.data, base, "data", { file: true, idx: true }),
4555
+ meta: defaultURI2(sthis, sopts.idx?.meta, base, "meta", { idx: true }),
4556
+ wal: defaultURI2(sthis, sopts.idx?.wal, base, "wal", { idx: true })
4557
+ },
4558
+ data: {
4559
+ data: defaultURI2(sthis, sopts.data?.data, base, "data"),
4560
+ file: defaultURI2(sthis, sopts.data?.data, base, "data", { file: true }),
4561
+ meta: defaultURI2(sthis, sopts.data?.meta, base, "meta"),
4562
+ wal: defaultURI2(sthis, sopts.data?.wal, base, "wal")
4563
+ }
4564
+ };
4565
+ }
4566
+ function fireproof(name, opts) {
4567
+ return LedgerFactory(name, opts);
4166
4568
  }
4167
4569
  function makeName(fnString) {
4168
4570
  const regex = /\(([^,()]+,\s*[^,()]+|\[[^\]]+\],\s*[^,()]+)\)/g;
@@ -4181,44 +4583,8 @@ function makeName(fnString) {
4181
4583
  }
4182
4584
  }
4183
4585
 
4184
- // src/runtime/index.ts
4185
- var runtime_exports = {};
4186
- __export(runtime_exports, {
4187
- FILESTORE_VERSION: () => FILESTORE_VERSION,
4188
- INDEXDB_VERSION: () => INDEXDB_VERSION,
4189
- files: () => files_exports,
4190
- getFileName: () => getFileName,
4191
- getFileSystem: () => getFileSystem,
4192
- getPath: () => getPath,
4193
- kb: () => key_bag_exports,
4194
- kc: () => keyed_crypto_exports,
4195
- mf: () => wait_pr_multiformats_exports,
4196
- runtimeFn: () => import_cement17.runtimeFn
4197
- });
4198
- init_utils2();
4199
-
4200
- // src/runtime/wait-pr-multiformats/index.ts
4201
- var wait_pr_multiformats_exports = {};
4202
- __export(wait_pr_multiformats_exports, {
4203
- block: () => block_exports,
4204
- codec: () => codec_interface_exports
4205
- });
4206
-
4207
- // src/runtime/wait-pr-multiformats/codec-interface.ts
4208
- var codec_interface_exports = {};
4209
-
4210
- // src/runtime/index.ts
4211
- var import_cement17 = require("@adviser/cement");
4212
- init_version();
4213
-
4214
- // src/runtime/gateways/indexdb/version.ts
4215
- var INDEXDB_VERSION = "v0.19-indexdb";
4216
-
4217
- // src/index.ts
4218
- init_utils();
4219
-
4220
4586
  // src/version.ts
4221
4587
  var PACKAGE_VERSION = Object.keys({
4222
- "0.19.121-dev": "xxxx"
4588
+ "0.20.0-dev-preview-05": "xxxx"
4223
4589
  })[0];
4224
4590
  //# sourceMappingURL=index.cjs.map