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

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