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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. package/README.md +13 -12
  2. package/deno/index.d.ts +7 -0
  3. package/deno/index.js +66 -0
  4. package/deno/index.js.map +1 -0
  5. package/deno/metafile-esm.json +1 -0
  6. package/deno.json +3 -4
  7. package/index.cjs +1797 -1431
  8. package/index.cjs.map +1 -1
  9. package/index.d.cts +760 -381
  10. package/index.d.ts +760 -381
  11. package/index.js +1976 -913
  12. package/index.js.map +1 -1
  13. package/metafile-cjs.json +1 -1
  14. package/metafile-esm.json +1 -1
  15. package/node/{node-filesystem.cjs → index.cjs} +17 -6
  16. package/node/index.cjs.map +1 -0
  17. package/node/index.d.cts +7 -0
  18. package/node/index.d.ts +7 -0
  19. package/node/{node-filesystem.js → index.js} +25 -5
  20. package/node/index.js.map +1 -0
  21. package/node/metafile-cjs.json +1 -1
  22. package/node/metafile-esm.json +1 -1
  23. package/package.json +27 -17
  24. package/react/index.cjs +22 -22
  25. package/react/index.cjs.map +1 -1
  26. package/react/index.d.cts +7 -7
  27. package/react/index.d.ts +7 -7
  28. package/react/index.js +22 -22
  29. package/react/index.js.map +1 -1
  30. package/react/metafile-cjs.json +1 -1
  31. package/react/metafile-esm.json +1 -1
  32. package/tests/blockstore/fp-envelope.test.ts-off +65 -0
  33. package/tests/blockstore/interceptor-gateway.test.ts +122 -0
  34. package/tests/blockstore/keyed-crypto-indexdb-file.test.ts +130 -0
  35. package/tests/blockstore/keyed-crypto.test.ts +75 -118
  36. package/tests/blockstore/loader.test.ts +18 -9
  37. package/tests/blockstore/store.test.ts +40 -31
  38. package/tests/blockstore/transaction.test.ts +14 -13
  39. package/tests/fireproof/all-gateway.test.ts +286 -216
  40. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.ts +324 -316
  41. package/tests/fireproof/crdt.test.ts +78 -19
  42. package/tests/fireproof/fireproof.test.ts +111 -92
  43. package/tests/fireproof/hello.test.ts +21 -17
  44. package/tests/fireproof/indexer.test.ts +74 -50
  45. package/tests/fireproof/{database.test.ts → ledger.test.ts} +241 -45
  46. package/tests/fireproof/multiple-ledger.test.ts +2 -2
  47. package/tests/fireproof/utils.test.ts +47 -6
  48. package/tests/gateway/file/loader-config.test.ts +307 -0
  49. package/tests/gateway/fp-envelope-serialize.test.ts +256 -0
  50. package/tests/gateway/indexdb/loader-config.test.ts +79 -0
  51. package/tests/helpers.ts +44 -17
  52. package/tests/react/useFireproof.test.tsx +2 -2
  53. package/tests/www/gallery.html +2 -2
  54. package/tests/www/todo-aws.html +1 -1
  55. package/tests/www/todo-ipfs.html +1 -1
  56. package/tests/www/todo-local.html +1 -1
  57. package/tests/www/todo.html +25 -4
  58. package/web/index.cjs +218 -0
  59. package/web/index.cjs.map +1 -0
  60. package/web/index.d.cts +30 -0
  61. package/web/index.d.ts +30 -0
  62. package/web/index.js +195 -0
  63. package/web/index.js.map +1 -0
  64. package/web/metafile-cjs.json +1 -1
  65. package/web/metafile-esm.json +1 -1
  66. package/chunk-7EWIAXTM.js +0 -7
  67. package/chunk-7EWIAXTM.js.map +0 -1
  68. package/chunk-F4FC6B2T.js +0 -63
  69. package/chunk-F4FC6B2T.js.map +0 -1
  70. package/chunk-PZ5AY32C.js +0 -10
  71. package/chunk-PZ5AY32C.js.map +0 -1
  72. package/chunk-RXC4JGJT.js +0 -301
  73. package/chunk-RXC4JGJT.js.map +0 -1
  74. package/gateway-C62S56GY.js +0 -66
  75. package/gateway-C62S56GY.js.map +0 -1
  76. package/gateway-VVS4QWDA.js +0 -145
  77. package/gateway-VVS4QWDA.js.map +0 -1
  78. package/key-bag-file-PWZ3QE7B.js +0 -55
  79. package/key-bag-file-PWZ3QE7B.js.map +0 -1
  80. package/key-bag-indexdb-SYG3YD4D.js +0 -51
  81. package/key-bag-indexdb-SYG3YD4D.js.map +0 -1
  82. package/node/chunk-4A4RAVNS.js +0 -17
  83. package/node/chunk-4A4RAVNS.js.map +0 -1
  84. package/node/mem-filesystem.cjs +0 -72
  85. package/node/mem-filesystem.cjs.map +0 -1
  86. package/node/mem-filesystem.d.cts +0 -25
  87. package/node/mem-filesystem.d.ts +0 -25
  88. package/node/mem-filesystem.js +0 -40
  89. package/node/mem-filesystem.js.map +0 -1
  90. package/node/node-filesystem.cjs.map +0 -1
  91. package/node/node-filesystem.d.cts +0 -35
  92. package/node/node-filesystem.d.ts +0 -35
  93. package/node/node-filesystem.js.map +0 -1
  94. package/tests/fireproof/config.test.ts +0 -172
  95. package/utils-ZVVGAXFE.js +0 -13
  96. package/utils-ZVVGAXFE.js.map +0 -1
  97. package/web/gateway-impl.cjs +0 -183
  98. package/web/gateway-impl.cjs.map +0 -1
  99. package/web/gateway-impl.d.cts +0 -31
  100. package/web/gateway-impl.d.ts +0 -31
  101. package/web/gateway-impl.js +0 -162
  102. package/web/gateway-impl.js.map +0 -1
  103. /package/tests/blockstore/{fragment-gateway.test.ts → fragment-gateway.test.ts-off} +0 -0
package/index.js CHANGED
@@ -1,172 +1,466 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ // src/ledger.ts
8
+ import { BuildURI as BuildURI2, KeyedResolvOnce as KeyedResolvOnce4, ResolveOnce as ResolveOnce7, URI as URI12 } from "@adviser/cement";
9
+
10
+ // src/utils.ts
1
11
  import {
2
- FILESTORE_VERSION
3
- } from "./chunk-7EWIAXTM.js";
4
- import {
5
- getFileName,
6
- getFileSystem,
7
- getPath
8
- } from "./chunk-F4FC6B2T.js";
9
- import {
10
- NotFoundError,
12
+ LoggerImpl,
13
+ IsLogger,
11
14
  Result,
12
- UInt8ArrayEqual,
13
- dataDir,
14
- ensureLogger,
15
- ensureSuperLog,
16
- ensureSuperThis,
17
- exceptionWrapper,
18
- getKey,
19
- getName,
20
- getStore,
21
- isNotFoundError,
22
- onSuperThis
23
- } from "./chunk-RXC4JGJT.js";
24
- import {
25
- __export
26
- } from "./chunk-PZ5AY32C.js";
15
+ ResolveOnce,
16
+ isURL,
17
+ envFactory,
18
+ toCryptoRuntime,
19
+ JSONFormatter,
20
+ YAMLFormatter
21
+ } from "@adviser/cement";
27
22
 
28
- // src/database.ts
29
- import { ResolveOnce as ResolveOnce6 } from "@adviser/cement";
23
+ // src/types.ts
24
+ function isFalsy(value) {
25
+ return value === false && value === null && value === void 0;
26
+ }
27
+ var PARAM = /* @__PURE__ */ ((PARAM2) => {
28
+ PARAM2["SUFFIX"] = "suffix";
29
+ PARAM2["URL_GEN"] = "urlGen";
30
+ PARAM2["STORE_KEY"] = "storekey";
31
+ PARAM2["STORE"] = "store";
32
+ PARAM2["KEY"] = "key";
33
+ PARAM2["INDEX"] = "index";
34
+ PARAM2["NAME"] = "name";
35
+ PARAM2["VERSION"] = "version";
36
+ PARAM2["RUNTIME"] = "runtime";
37
+ PARAM2["FRAG_SIZE"] = "fragSize";
38
+ PARAM2["IV_VERIFY"] = "ivVerify";
39
+ PARAM2["IV_HASH"] = "ivHash";
40
+ PARAM2["FRAG_FID"] = "fid";
41
+ PARAM2["FRAG_OFS"] = "ofs";
42
+ PARAM2["FRAG_LEN"] = "len";
43
+ PARAM2["FRAG_HEAD"] = "headerSize";
44
+ PARAM2["EXTRACTKEY"] = "extractKey";
45
+ return PARAM2;
46
+ })(PARAM || {});
47
+ function throwFalsy(value) {
48
+ if (isFalsy(value)) {
49
+ throw new Error("value is Falsy");
50
+ }
51
+ return value;
52
+ }
53
+ function falsyToUndef(value) {
54
+ if (isFalsy(value)) {
55
+ return void 0;
56
+ }
57
+ return value;
58
+ }
59
+
60
+ // src/utils.ts
61
+ import { base58btc } from "multiformats/bases/base58";
62
+ var _globalLogger = new ResolveOnce();
63
+ function globalLogger() {
64
+ return _globalLogger.once(() => new LoggerImpl());
65
+ }
66
+ var registerFP_DEBUG = new ResolveOnce();
67
+ var SuperThisImpl = class _SuperThisImpl {
68
+ constructor(opts) {
69
+ this.logger = opts.logger;
70
+ this.env = opts.env;
71
+ this.crypto = opts.crypto;
72
+ this.pathOps = opts.pathOps;
73
+ this.txt = opts.txt;
74
+ this.ctx = { ...opts.ctx };
75
+ }
76
+ nextId(bytes = 6) {
77
+ const bin = this.crypto.randomBytes(bytes);
78
+ return {
79
+ str: base58btc.encode(bin),
80
+ bin
81
+ };
82
+ }
83
+ timeOrderedNextId(now) {
84
+ now = typeof now === "number" ? now : (/* @__PURE__ */ new Date()).getTime();
85
+ const t = (281474976710656 + now).toString(16).replace(/^1/, "");
86
+ const bin = this.crypto.randomBytes(10);
87
+ bin[1] = bin[1] & 240 | (bin[1] | 8 && 11);
88
+ const hex = Array.from(bin).map((i) => i.toString(16).padStart(2, "0")).join("");
89
+ return {
90
+ str: `${t.slice(0, 8)}-${t.slice(8)}-7${hex.slice(0, 3)}-${hex.slice(3, 7)}-${hex.slice(7, 19)}`
91
+ };
92
+ }
93
+ start() {
94
+ return Promise.resolve();
95
+ }
96
+ clone(override) {
97
+ return new _SuperThisImpl({
98
+ logger: override.logger || this.logger,
99
+ env: envFactory(override.env) || this.env,
100
+ crypto: override.crypto || this.crypto,
101
+ pathOps: override.pathOps || this.pathOps,
102
+ txt: override.txt || this.txt,
103
+ ctx: { ...this.ctx, ...override.ctx }
104
+ });
105
+ }
106
+ };
107
+ function presetEnv() {
108
+ const penv = new Map([
109
+ // ["FP_DEBUG", "xxx"],
110
+ // ["FP_ENV", "development"],
111
+ ...Array.from(
112
+ Object.entries(
113
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
114
+ globalThis[Symbol.for("FP_PRESET_ENV")] || {}
115
+ )
116
+ )
117
+ // .map(([k, v]) => [k, v as string])
118
+ ]);
119
+ return penv;
120
+ }
121
+ var pathOpsImpl = class {
122
+ join(...paths) {
123
+ return paths.map((i) => i.replace(/\/+$/, "")).join("/");
124
+ }
125
+ dirname(path) {
126
+ return path.split("/").slice(0, -1).join("/");
127
+ }
128
+ basename(path) {
129
+ return path.split("/").pop() || "";
130
+ }
131
+ // homedir() {
132
+ // throw new Error("SysContainer:homedir is not available in seeded state");
133
+ // }
134
+ };
135
+ var pathOps = new pathOpsImpl();
136
+ var txtOps = /* @__PURE__ */ ((txtEncoder, txtDecoder) => ({
137
+ encode: (input) => txtEncoder.encode(input),
138
+ decode: (input) => txtDecoder.decode(coerceIntoUint8(input).Ok())
139
+ // eslint-disable-next-line no-restricted-globals
140
+ }))(new TextEncoder(), new TextDecoder());
141
+ var _onSuperThis = /* @__PURE__ */ new Map();
142
+ function onSuperThis(fn) {
143
+ const key = `onSuperThis-${Math.random().toString(36).slice(2)}`;
144
+ _onSuperThis.set(key, fn);
145
+ return () => {
146
+ _onSuperThis.delete(key);
147
+ };
148
+ }
149
+ function ensureSuperThis(osthis) {
150
+ const env = envFactory({
151
+ symbol: osthis?.env?.symbol || "FP_ENV",
152
+ presetEnv: osthis?.env?.presetEnv || presetEnv()
153
+ });
154
+ const ret = new SuperThisImpl({
155
+ logger: osthis?.logger || globalLogger(),
156
+ env,
157
+ crypto: osthis?.crypto || toCryptoRuntime(),
158
+ ctx: osthis?.ctx || {},
159
+ pathOps,
160
+ txt: osthis?.txt || txtOps
161
+ });
162
+ _onSuperThis.forEach((fn) => fn(ret));
163
+ return ret;
164
+ }
165
+ function ensureSuperLog(sthis, componentName, ctx) {
166
+ return sthis.clone({
167
+ logger: ensureLogger(sthis, componentName, ctx)
168
+ });
169
+ }
170
+ function ensureLogger(sthis, componentName, ctx) {
171
+ let logger;
172
+ if (sthis && IsLogger(sthis.logger)) {
173
+ logger = sthis.logger;
174
+ } else {
175
+ logger = globalLogger();
176
+ }
177
+ const cLogger = logger.With().Module(componentName);
178
+ const debug = [];
179
+ let exposeStack = false;
180
+ if (ctx) {
181
+ if ("debug" in ctx) {
182
+ if (typeof ctx.debug === "string" && ctx.debug.length > 0) {
183
+ debug.push(ctx.debug);
184
+ } else {
185
+ debug.push(componentName);
186
+ }
187
+ delete ctx.debug;
188
+ }
189
+ if ("exposeStack" in ctx) {
190
+ exposeStack = true;
191
+ delete ctx.exposeStack;
192
+ }
193
+ if ("exposeStack" in ctx) {
194
+ exposeStack = true;
195
+ delete ctx.exposeStack;
196
+ }
197
+ if ("this" in ctx) {
198
+ cLogger.Str("this", sthis.nextId(4).str);
199
+ delete ctx.this;
200
+ }
201
+ for (const [key, value] of Object.entries(ctx)) {
202
+ switch (typeof value) {
203
+ case "string":
204
+ cLogger.Str(key, value);
205
+ break;
206
+ case "number":
207
+ cLogger.Uint64(key, value);
208
+ break;
209
+ default:
210
+ if (value instanceof Date) {
211
+ cLogger.Str(key, value.toISOString());
212
+ } else if (isURL(value)) {
213
+ cLogger.Str(key, value.toString());
214
+ } else if (typeof value === "function") {
215
+ cLogger.Ref(key, value);
216
+ } else {
217
+ cLogger.Any(key, value);
218
+ }
219
+ break;
220
+ }
221
+ }
222
+ }
223
+ registerFP_DEBUG.once(async () => {
224
+ sthis.env.onSet(
225
+ (key, value) => {
226
+ switch (key) {
227
+ case "FP_FORMAT": {
228
+ switch (value) {
229
+ case "jsonice":
230
+ logger.SetFormatter(new JSONFormatter(logger.TxtEnDe(), 2));
231
+ break;
232
+ case "yaml":
233
+ logger.SetFormatter(new YAMLFormatter(logger.TxtEnDe(), 2));
234
+ break;
235
+ case "json":
236
+ default:
237
+ logger.SetFormatter(new JSONFormatter(logger.TxtEnDe()));
238
+ break;
239
+ }
240
+ break;
241
+ }
242
+ case "FP_DEBUG":
243
+ logger.SetDebug(value || []);
244
+ break;
245
+ case "FP_STACK":
246
+ logger.SetExposeStack(!!value);
247
+ break;
248
+ }
249
+ },
250
+ "FP_FORMAT",
251
+ "FP_DEBUG",
252
+ "FP_STACK"
253
+ );
254
+ }).finally(() => {
255
+ });
256
+ if (debug.length > 0) {
257
+ logger.SetDebug(debug);
258
+ }
259
+ if (exposeStack) {
260
+ logger.SetExposeStack(true);
261
+ }
262
+ const out = cLogger.Logger();
263
+ if (sthis.env.get("FP_CONSTRUCTOR_DEBUG")) {
264
+ out.Debug().Msg("constructor");
265
+ }
266
+ return out;
267
+ }
268
+ function getStore(url, sthis, joiner) {
269
+ const store = url.getParam("store" /* STORE */);
270
+ switch (store) {
271
+ case "data":
272
+ case "wal":
273
+ case "meta":
274
+ break;
275
+ default:
276
+ throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
277
+ throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
278
+ }
279
+ let name = store;
280
+ if (url.hasParam("index")) {
281
+ name = joiner(url.getParam("index" /* INDEX */) || "idx", name);
282
+ }
283
+ return { store, name };
284
+ }
285
+ function getKey(url, logger) {
286
+ const result = url.getParam("key" /* KEY */);
287
+ if (!result) throw logger.Error().Str("url", url.toString()).Msg(`key not found`).AsError();
288
+ return result;
289
+ }
290
+ function getName(sthis, url) {
291
+ let result = url.getParam("name" /* NAME */);
292
+ if (!result) {
293
+ result = sthis.pathOps.dirname(url.pathname);
294
+ if (result.length === 0) {
295
+ throw sthis.logger.Error().Str("url", url.toString()).Msg(`name not found`).AsError();
296
+ }
297
+ }
298
+ return result;
299
+ }
300
+ async function exceptionWrapper(fn) {
301
+ return fn().catch((e) => Result.Err(e));
302
+ }
303
+ var NotFoundError = class extends Error {
304
+ constructor() {
305
+ super(...arguments);
306
+ this.code = "ENOENT";
307
+ }
308
+ };
309
+ function isNotFoundError(e) {
310
+ if (Result.Is(e)) {
311
+ if (e.isOk()) return false;
312
+ e = e.Err();
313
+ }
314
+ if (e.code === "ENOENT") return true;
315
+ return false;
316
+ }
317
+ function UInt8ArrayEqual(a, b) {
318
+ if (a.length !== b.length) {
319
+ return false;
320
+ }
321
+ for (let i = 0; i < a.length; i++) {
322
+ if (a[i] !== b[i]) {
323
+ return false;
324
+ }
325
+ }
326
+ return true;
327
+ }
328
+ function inplaceFilter(i, pred) {
329
+ const founds = [];
330
+ for (let j = 0; j < i.length; j++) {
331
+ if (!pred(i[j], j)) {
332
+ founds.push(j);
333
+ }
334
+ }
335
+ for (let j = founds.length - 1; j >= 0; j--) {
336
+ i.splice(founds[j], 1);
337
+ }
338
+ return i;
339
+ }
340
+ function toSortedArray(set) {
341
+ if (!set) return [];
342
+ return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
343
+ }
344
+ function coerceIntoUint8(raw2) {
345
+ if (raw2 instanceof Uint8Array) {
346
+ return Result.Ok(raw2);
347
+ }
348
+ if (Result.Is(raw2)) {
349
+ return raw2;
350
+ }
351
+ return Result.Err("Not a Uint8Array");
352
+ }
353
+ async function coercePromiseIntoUint8(raw2) {
354
+ if (raw2 instanceof Uint8Array) {
355
+ return Result.Ok(raw2);
356
+ }
357
+ if (Result.Is(raw2)) {
358
+ return raw2;
359
+ }
360
+ if (typeof raw2.then === "function") {
361
+ try {
362
+ return coercePromiseIntoUint8(await raw2);
363
+ } catch (e) {
364
+ return Result.Err(e);
365
+ }
366
+ }
367
+ return Result.Err("Not a Uint8Array");
368
+ }
30
369
 
31
370
  // src/write-queue.ts
32
- function writeQueue(worker, payload = Infinity, unbounded = false) {
33
- const queue = [];
34
- let isProcessing = false;
35
- async function process() {
36
- if (isProcessing || queue.length === 0) return;
37
- isProcessing = true;
38
- const tasksToProcess = queue.splice(0, payload);
39
- const updates = tasksToProcess.map((item) => item.task);
40
- if (unbounded) {
371
+ import { Future } from "@adviser/cement";
372
+ function defaultWriteQueueOpts(opts = {}) {
373
+ return {
374
+ ...opts,
375
+ chunkSize: opts.chunkSize && opts.chunkSize > 0 ? opts.chunkSize : 32
376
+ };
377
+ }
378
+ var WriteQueueImpl = class {
379
+ constructor(sthis, worker, opts) {
380
+ this.queue = [];
381
+ this.isProcessing = false;
382
+ this.logger = ensureLogger(sthis, "WriteQueueImpl");
383
+ this.worker = worker;
384
+ this.opts = defaultWriteQueueOpts(opts);
385
+ }
386
+ testEmptyQueue() {
387
+ if (this.waitForEmptyQueue && this.queue.length === 0) {
388
+ this.waitForEmptyQueue.resolve();
389
+ }
390
+ }
391
+ async process() {
392
+ if (this.isProcessing || this.queue.length === 0) {
393
+ this.testEmptyQueue();
394
+ return;
395
+ }
396
+ this.isProcessing = true;
397
+ try {
398
+ this.logger.Debug().Any("opts", this.opts).Len(this.queue).Msg("Processing tasks");
399
+ const tasksToProcess = this.queue.splice(0, this.opts.chunkSize);
400
+ const updates = tasksToProcess.map((item) => item.tasks).filter((item) => item);
41
401
  const promises = updates.map(async (update, index2) => {
42
402
  try {
43
- const result = await worker([update]);
403
+ const result = await this.worker(update);
44
404
  tasksToProcess[index2].resolve(result);
45
405
  } catch (error) {
46
- tasksToProcess[index2].reject(error);
406
+ tasksToProcess[index2].reject(this.logger.Error().Err(error).Msg("Error processing task").AsError());
47
407
  }
48
408
  });
49
- await Promise.all(promises);
50
- } else {
51
- try {
52
- const result = await worker(updates);
53
- tasksToProcess.forEach((task) => task.resolve(result));
54
- } catch (error) {
55
- tasksToProcess.forEach((task) => task.reject(error));
56
- }
409
+ await Promise.allSettled(promises);
410
+ this.logger.Debug().Any("opts", this.opts).Len(this.queue).Msg("Processed tasks");
411
+ } catch (error) {
412
+ this.logger.Error().Err(error).Msg("Error processing tasks");
413
+ } finally {
414
+ this.isProcessing = false;
415
+ setTimeout(() => this.process(), 0);
57
416
  }
58
- isProcessing = false;
59
- void process();
60
417
  }
61
- return {
62
- push(task) {
63
- return new Promise((resolve, reject) => {
64
- queue.push({ task, resolve, reject });
65
- void process();
66
- });
67
- }
68
- };
69
- }
70
-
71
- // src/crdt.ts
72
- import { ResolveOnce as ResolveOnce5 } from "@adviser/cement";
73
-
74
- // src/runtime/wait-pr-multiformats/block.ts
75
- var block_exports = {};
76
- __export(block_exports, {
77
- Block: () => Block,
78
- create: () => create,
79
- createUnsafe: () => createUnsafe,
80
- decode: () => decode,
81
- encode: () => encode
82
- });
83
- import { bytes as binary, CID } from "multiformats";
84
- import { Block as mfBlock } from "multiformats/block";
85
- var Block = mfBlock;
86
- async function decode({
87
- bytes,
88
- codec: codec3,
89
- hasher: hasher7
90
- }) {
91
- if (bytes == null) throw new Error('Missing required argument "bytes"');
92
- if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
93
- const value = await Promise.resolve(codec3.decode(bytes));
94
- const hash = await hasher7.digest(bytes);
95
- const cid = CID.create(1, codec3.code, hash);
96
- return new mfBlock({ value, bytes, cid });
97
- }
98
- async function encode({
99
- value,
100
- codec: codec3,
101
- hasher: hasher7
102
- }) {
103
- if (typeof value === "undefined") throw new Error('Missing required argument "value"');
104
- if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
105
- const bytes = await Promise.resolve(codec3.encode(value));
106
- const hash = await hasher7.digest(bytes);
107
- const cid = CID.create(1, codec3.code, hash);
108
- return new mfBlock({ value, bytes, cid });
109
- }
110
- async function create({
111
- bytes,
112
- cid,
113
- hasher: hasher7,
114
- codec: codec3
115
- }) {
116
- if (bytes == null) throw new Error('Missing required argument "bytes"');
117
- if (hasher7 == null) throw new Error('Missing required argument "hasher"');
118
- const value = await Promise.resolve(codec3.decode(bytes));
119
- const hash = await hasher7.digest(bytes);
120
- if (!binary.equals(cid.multihash.bytes, hash.bytes)) {
121
- throw new Error("CID hash does not match bytes");
418
+ bulk(tasks) {
419
+ return new Promise((resolve, reject) => {
420
+ this.queue.push({ tasks, resolve, reject });
421
+ this.process();
422
+ });
122
423
  }
123
- return createUnsafe({
124
- bytes,
125
- cid,
126
- value,
127
- codec: codec3
128
- });
129
- }
130
- async function createUnsafe({
131
- bytes,
132
- cid,
133
- value: maybeValue,
134
- codec: codec3
135
- }) {
136
- const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
137
- if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
138
- return new Block({
139
- cid,
140
- bytes,
141
- value
142
- });
424
+ push(task) {
425
+ return this.bulk([task]);
426
+ }
427
+ close() {
428
+ this.waitForEmptyQueue = new Future();
429
+ this.testEmptyQueue();
430
+ return this.waitForEmptyQueue.asPromise();
431
+ }
432
+ };
433
+ function writeQueue(sthis, worker, opts) {
434
+ return new WriteQueueImpl(sthis, worker, opts);
143
435
  }
144
436
 
145
- // src/crdt-helpers.ts
146
- import { parse as parse3 } from "multiformats/link";
147
- import { sha256 as hasher5 } from "multiformats/hashes/sha2";
148
- import * as codec from "@fireproof/vendor/@ipld/dag-cbor";
149
- import { put, get, entries, root } from "@fireproof/vendor/@web3-storage/pail/crdt";
150
- import { EventFetcher, vis } from "@fireproof/vendor/@web3-storage/pail/clock";
151
- import * as Batch from "@fireproof/vendor/@web3-storage/pail/crdt/batch";
437
+ // src/crdt.ts
438
+ import { ResolveOnce as ResolveOnce6 } from "@adviser/cement";
152
439
 
153
440
  // src/blockstore/index.ts
154
441
  var blockstore_exports = {};
155
442
  __export(blockstore_exports, {
156
443
  BaseBlockstore: () => BaseBlockstore,
444
+ Car2FPMsg: () => Car2FPMsg,
157
445
  CarTransaction: () => CarTransaction,
158
446
  CompactionFetcher: () => CompactionFetcher,
159
447
  ConnectionBase: () => ConnectionBase,
448
+ DbMetaEventEqual: () => DbMetaEventEqual,
449
+ DbMetaEventsEqual: () => DbMetaEventsEqual,
160
450
  EncryptedBlockstore: () => EncryptedBlockstore,
161
- FragmentGateway: () => FragmentGateway,
451
+ FPEnvelopeType: () => FPEnvelopeType,
452
+ File2FPMsg: () => File2FPMsg,
453
+ InterceptorGateway: () => InterceptorGateway,
162
454
  Loader: () => Loader,
163
- addCryptoKeyToGatewayMetaPayload: () => addCryptoKeyToGatewayMetaPayload,
164
- ensureStart: () => ensureStart,
165
- getGatewayFromURL: () => getGatewayFromURL,
455
+ PassThroughGateway: () => PassThroughGateway,
456
+ createDbMetaEvent: () => createDbMetaEvent,
457
+ defaultGatewayFactoryItem: () => defaultGatewayFactoryItem,
458
+ ensureStoreEnDeFile: () => ensureStoreEnDeFile,
459
+ getDefaultURI: () => getDefaultURI,
460
+ getGatewayFactoryItem: () => getGatewayFactoryItem,
461
+ getStartedGateway: () => getStartedGateway,
166
462
  parseCarFile: () => parseCarFile,
167
463
  registerStoreProtocol: () => registerStoreProtocol,
168
- setCryptoKeyFromGatewayMetaPayload: () => setCryptoKeyFromGatewayMetaPayload,
169
- testStoreFactory: () => testStoreFactory,
170
464
  toCIDBlock: () => toCIDBlock,
171
465
  toStoreRuntime: () => toStoreRuntime
172
466
  });
@@ -175,9 +469,15 @@ __export(blockstore_exports, {
175
469
  function toCIDBlock(block) {
176
470
  return block;
177
471
  }
472
+ function DbMetaEventEqual(a, b) {
473
+ 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]));
474
+ }
475
+ function DbMetaEventsEqual(a, b) {
476
+ return a.length === b.length && a.every((e, i) => DbMetaEventEqual(e, b[i]));
477
+ }
178
478
 
179
479
  // src/blockstore/store-factory.ts
180
- import { KeyedResolvOnce as KeyedResolvOnce2, URI as URI5 } from "@adviser/cement";
480
+ import { KeyedResolvOnce as KeyedResolvOnce3, Result as Result10 } from "@adviser/cement";
181
481
 
182
482
  // src/runtime/files.ts
183
483
  var files_exports = {};
@@ -251,30 +551,83 @@ var UnixFSFileBuilder = class {
251
551
  };
252
552
 
253
553
  // src/blockstore/store.ts
254
- import { format as format2, parse as parse2 } from "@fireproof/vendor/@ipld/dag-json";
255
- import { exception2Result, ResolveOnce as ResolveOnce3, Result as Result5 } from "@adviser/cement";
554
+ import { exception2Result, ResolveOnce as ResolveOnce4, Result as Result5 } from "@adviser/cement";
256
555
 
257
- // src/types.ts
258
- function isFalsy(value) {
259
- return value === false && value === null && value === void 0;
556
+ // src/blockstore/loader.ts
557
+ import pLimit from "p-limit";
558
+ import { CarReader } from "@fireproof/vendor/@ipld/car/reader";
559
+ import { ResolveOnce as ResolveOnce3 } from "@adviser/cement";
560
+
561
+ // src/runtime/wait-pr-multiformats/block.ts
562
+ var block_exports = {};
563
+ __export(block_exports, {
564
+ Block: () => Block,
565
+ create: () => create,
566
+ createUnsafe: () => createUnsafe,
567
+ decode: () => decode,
568
+ encode: () => encode
569
+ });
570
+ import { bytes as binary, CID } from "multiformats";
571
+ import { Block as mfBlock } from "multiformats/block";
572
+ var Block = mfBlock;
573
+ async function decode({
574
+ bytes,
575
+ codec: codec3,
576
+ hasher: hasher7
577
+ }) {
578
+ if (bytes == null) throw new Error('Missing required argument "bytes"');
579
+ if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
580
+ const value = await Promise.resolve(codec3.decode(bytes));
581
+ const hash = await hasher7.digest(bytes);
582
+ const cid = CID.create(1, codec3.code, hash);
583
+ return new mfBlock({ value, bytes, cid });
260
584
  }
261
- function throwFalsy(value) {
262
- if (isFalsy(value)) {
263
- throw new Error("value is Falsy");
264
- }
265
- return value;
585
+ async function encode({
586
+ value,
587
+ codec: codec3,
588
+ hasher: hasher7
589
+ }) {
590
+ if (typeof value === "undefined") throw new Error('Missing required argument "value"');
591
+ if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
592
+ const bytes = await Promise.resolve(codec3.encode(value));
593
+ const hash = await hasher7.digest(bytes);
594
+ const cid = CID.create(1, codec3.code, hash);
595
+ return new mfBlock({ value, bytes, cid });
266
596
  }
267
- function falsyToUndef(value) {
268
- if (isFalsy(value)) {
269
- return void 0;
597
+ async function create({
598
+ bytes,
599
+ cid,
600
+ hasher: hasher7,
601
+ codec: codec3
602
+ }) {
603
+ if (bytes == null) throw new Error('Missing required argument "bytes"');
604
+ if (hasher7 == null) throw new Error('Missing required argument "hasher"');
605
+ const value = await Promise.resolve(codec3.decode(bytes));
606
+ const hash = await hasher7.digest(bytes);
607
+ if (!binary.equals(cid.multihash.bytes, hash.bytes)) {
608
+ throw new Error("CID hash does not match bytes");
270
609
  }
271
- return value;
610
+ return createUnsafe({
611
+ bytes,
612
+ cid,
613
+ value,
614
+ codec: codec3
615
+ });
616
+ }
617
+ async function createUnsafe({
618
+ bytes,
619
+ cid,
620
+ value: maybeValue,
621
+ codec: codec3
622
+ }) {
623
+ const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
624
+ if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
625
+ return new Block({
626
+ cid,
627
+ bytes,
628
+ value
629
+ });
272
630
  }
273
-
274
- // src/blockstore/loader.ts
275
- import pLimit from "p-limit";
276
- import { CarReader } from "@fireproof/vendor/@ipld/car/reader";
277
- import { ResolveOnce as ResolveOnce2 } from "@adviser/cement";
278
631
 
279
632
  // src/blockstore/loader-helpers.ts
280
633
  import { sha256 as hasher } from "multiformats/hashes/sha2";
@@ -293,7 +646,7 @@ async function parseCarFile(reader, logger) {
293
646
 
294
647
  // src/blockstore/transaction.ts
295
648
  import { MemoryBlockstore } from "@fireproof/vendor/@web3-storage/pail/block";
296
- import { toCryptoRuntime } from "@adviser/cement";
649
+ import { toCryptoRuntime as toCryptoRuntime2 } from "@adviser/cement";
297
650
  var CarTransaction = class extends MemoryBlockstore {
298
651
  constructor(parent, opts = { add: true, noLoader: false }) {
299
652
  super();
@@ -311,7 +664,6 @@ var CarTransaction = class extends MemoryBlockstore {
311
664
  };
312
665
  function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
313
666
  const logger = ensureLogger(sthis, component, ctx);
314
- const store = opts.store || {};
315
667
  return {
316
668
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
317
669
  applyMeta: (meta, snap) => {
@@ -323,30 +675,27 @@ function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
323
675
  },
324
676
  autoCompact: 100,
325
677
  public: false,
326
- name: void 0,
678
+ // name: undefined,
327
679
  threshold: 1e3 * 1e3,
328
680
  ...opts,
329
681
  logger,
330
682
  keyBag: opts.keyBag || {},
331
- crypto: toCryptoRuntime(opts.crypto),
332
- store,
333
- storeRuntime: toStoreRuntime(store, sthis)
683
+ crypto: toCryptoRuntime2(opts.crypto),
684
+ storeUrls: opts.storeUrls,
685
+ // storeEnDeFile: ensureStoreEnDeFile(opts.storeEnDeFile),
686
+ // store,
687
+ storeRuntime: toStoreRuntime(sthis, ensureStoreEnDeFile(opts.storeEnDeFile))
334
688
  };
335
689
  }
336
- function blockstoreFactory(sthis, opts) {
337
- if (opts.name) {
338
- return new EncryptedBlockstore(sthis, opts);
339
- } else {
340
- return new BaseBlockstore(opts);
341
- }
342
- }
343
690
  var BaseBlockstore = class {
344
- constructor(ebOpts = {}) {
691
+ constructor(ebOpts) {
345
692
  this.transactions = /* @__PURE__ */ new Set();
346
693
  this.sthis = ensureSuperThis(ebOpts);
347
694
  this.ebOpts = defaultedBlockstoreRuntime(this.sthis, ebOpts, "BaseBlockstore");
348
695
  this.logger = this.ebOpts.logger;
696
+ this.loader = new Loader(this.sthis, ebOpts);
349
697
  }
698
+ // readonly name?: string;
350
699
  // ready: Promise<void>;
351
700
  ready() {
352
701
  return Promise.resolve();
@@ -370,8 +719,11 @@ var BaseBlockstore = class {
370
719
  }
371
720
  // TransactionMeta
372
721
  async transaction(fn, _opts) {
722
+ this.logger.Debug().Msg("enter transaction");
373
723
  const t = new CarTransaction(this, _opts);
724
+ this.logger.Debug().Msg("post CarTransaction");
374
725
  const done = await fn(t);
726
+ this.logger.Debug().Msg("post fn");
375
727
  this.lastTxMeta = done;
376
728
  return { t, meta: done };
377
729
  }
@@ -380,7 +732,7 @@ var BaseBlockstore = class {
380
732
  }
381
733
  async commitTransaction(t, done, opts) {
382
734
  if (!this.loader) throw this.logger.Error().Msg("loader required to commit").AsError();
383
- const cars = await this.loader?.commit(t, done, opts);
735
+ const cars = await this.loader.commit(t, done, opts);
384
736
  if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
385
737
  setTimeout(() => void this.compact(), 10);
386
738
  }
@@ -405,14 +757,11 @@ var EncryptedBlockstore = class extends BaseBlockstore {
405
757
  constructor(sthis, ebOpts) {
406
758
  super(ebOpts);
407
759
  this.compacting = false;
408
- this.logger = ensureLogger(this.sthis, "EncryptedBlockstore");
409
- const { name } = ebOpts;
410
- if (!name) {
411
- throw this.logger.Error().Msg("name required").AsError();
412
- }
413
- this.name = name;
414
- this.loader = new Loader(this.name, ebOpts, sthis);
760
+ this.logger = ensureLogger(this.sthis, "EncryptedBlockstore", {
761
+ this: 1
762
+ });
415
763
  }
764
+ // readonly name: string;
416
765
  ready() {
417
766
  return this.loader.ready();
418
767
  }
@@ -431,8 +780,11 @@ var EncryptedBlockstore = class extends BaseBlockstore {
431
780
  return falsyToUndef(await this.loader.getBlock(cid));
432
781
  }
433
782
  async transaction(fn, opts = { noLoader: false }) {
783
+ this.logger.Debug().Msg("enter transaction");
434
784
  const { t, meta: done } = await super.transaction(fn);
785
+ this.logger.Debug().Msg("post super.transaction");
435
786
  const cars = await this.loader.commit(t, done, opts);
787
+ this.logger.Debug().Msg("post this.loader.commit");
436
788
  if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
437
789
  setTimeout(() => void this.compact(), 10);
438
790
  }
@@ -444,7 +796,7 @@ var EncryptedBlockstore = class extends BaseBlockstore {
444
796
  }
445
797
  async getFile(car, cid) {
446
798
  await this.ready();
447
- if (!this.loader) throw this.logger.Error().Msg("loader required to get file, database must be named").AsError();
799
+ if (!this.loader) throw this.logger.Error().Msg("loader required to get file, ledger must be named").AsError();
448
800
  const reader = await this.loader.loadFileCar(
449
801
  car
450
802
  /*, isPublic */
@@ -462,7 +814,7 @@ var EncryptedBlockstore = class extends BaseBlockstore {
462
814
  const blockLog = new CompactionFetcher(this);
463
815
  this.compacting = true;
464
816
  const meta = await compactFn(blockLog);
465
- await this.loader?.commit(blockLog.loggedBlocks, meta, {
817
+ await this.loader.commit(blockLog.loggedBlocks, meta, {
466
818
  compact: true,
467
819
  noLoader: true
468
820
  });
@@ -504,7 +856,7 @@ var CompactionFetcher = class {
504
856
  };
505
857
 
506
858
  // src/blockstore/commit-queue.ts
507
- import { Future } from "@adviser/cement";
859
+ import { Future as Future2 } from "@adviser/cement";
508
860
  var CommitQueue = class {
509
861
  constructor() {
510
862
  this.queue = [];
@@ -515,7 +867,7 @@ var CommitQueue = class {
515
867
  if (this.queue.length === 0 && !this.processing) {
516
868
  return Promise.resolve();
517
869
  }
518
- const fn = new Future();
870
+ const fn = new Future2();
519
871
  this._waitIdleItems.add(fn);
520
872
  return fn.asPromise();
521
873
  }
@@ -558,30 +910,111 @@ var CommitQueue = class {
558
910
  var key_bag_exports = {};
559
911
  __export(key_bag_exports, {
560
912
  KeyBag: () => KeyBag,
913
+ defaultKeyBagOpts: () => defaultKeyBagOpts,
561
914
  defaultKeyBagUrl: () => defaultKeyBagUrl,
562
915
  getKeyBag: () => getKeyBag,
563
916
  registerKeyBagProviderFactory: () => registerKeyBagProviderFactory
564
917
  });
565
918
  import {
566
919
  KeyedResolvOnce,
567
- ResolveOnce,
920
+ ResolveOnce as ResolveOnce2,
568
921
  ResolveSeq,
569
922
  Result as Result2,
570
- runtimeFn,
571
- toCryptoRuntime as toCryptoRuntime2,
572
- URI
923
+ runtimeFn as runtimeFn2,
924
+ toCryptoRuntime as toCryptoRuntime3,
925
+ URI as URI3
573
926
  } from "@adviser/cement";
574
- import { base58btc } from "multiformats/bases/base58";
927
+ import { base58btc as base58btc2 } from "multiformats/bases/base58";
928
+
929
+ // src/runtime/gateways/file/sys-file-system-factory.ts
930
+ import { runtimeFn } from "@adviser/cement";
931
+ function sysFileSystemFactory(uri) {
932
+ const rt = runtimeFn();
933
+ switch (true) {
934
+ case rt.isNodeIsh:
935
+ return import("@fireproof/core/node").then((m) => m.getSysFileSystem(uri));
936
+ case rt.isDeno:
937
+ return import("@fireproof/core/deno").then((m) => m.getSysFileSystem(uri));
938
+ default:
939
+ throw new Error(`unsupported runtime:${rt}`);
940
+ }
941
+ }
942
+
943
+ // src/runtime/gateways/file/key-bag-file.ts
944
+ var KeyBagProviderFile = class {
945
+ async _prepare(id) {
946
+ await this.sthis.start();
947
+ const sysFS = await sysFileSystemFactory(this.url);
948
+ const dirName = this.url.pathname;
949
+ await sysFS.mkdir(dirName, { recursive: true });
950
+ return {
951
+ dirName,
952
+ sysFS,
953
+ fName: this.sthis.pathOps.join(dirName, `${id.replace(/[^a-zA-Z0-9]/g, "_")}.json`)
954
+ };
955
+ }
956
+ constructor(url, sthis) {
957
+ this.url = url;
958
+ this.sthis = sthis;
959
+ this.logger = sthis.logger;
960
+ }
961
+ async get(id) {
962
+ const ctx = await this._prepare(id);
963
+ try {
964
+ const p = await ctx.sysFS.readfile(ctx.fName);
965
+ const ki = JSON.parse(this.sthis.txt.decode(p));
966
+ return ki;
967
+ } catch (e) {
968
+ if (isNotFoundError(e)) {
969
+ return void 0;
970
+ }
971
+ throw this.logger.Error().Err(e).Str("file", ctx.dirName).Msg("read bag failed").AsError();
972
+ }
973
+ }
974
+ async set(id, item) {
975
+ const ctx = await this._prepare(id);
976
+ const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
977
+ await ctx.sysFS.writefile(ctx.fName, p);
978
+ }
979
+ };
980
+
981
+ // src/runtime/key-bag-memory.ts
982
+ var memoryKeyBag = /* @__PURE__ */ new Map();
983
+ var KeyBagProviderMemory = class {
984
+ constructor(url, sthis) {
985
+ this.url = url;
986
+ this.sthis = sthis;
987
+ }
988
+ key(id) {
989
+ return `${this.url.pathname}/${id}`;
990
+ }
991
+ async get(id) {
992
+ const binKeyItem = memoryKeyBag.get(this.key(id));
993
+ if (binKeyItem) {
994
+ const ki = JSON.parse(this.sthis.txt.decode(binKeyItem));
995
+ return ki;
996
+ }
997
+ return void 0;
998
+ }
999
+ async set(id, item) {
1000
+ const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
1001
+ memoryKeyBag.set(this.key(id), p);
1002
+ }
1003
+ };
1004
+
1005
+ // src/runtime/key-bag.ts
575
1006
  var KeyBag = class {
576
1007
  constructor(rt) {
577
1008
  this.rt = rt;
578
- this._warnOnce = new ResolveOnce();
1009
+ this._warnOnce = new ResolveOnce2();
579
1010
  this._seq = new ResolveSeq();
580
- this.logger = ensureLogger(rt.sthis, "KeyBag");
1011
+ this.logger = ensureLogger(rt.sthis, "KeyBag", {
1012
+ // id: rt.id(),
1013
+ });
581
1014
  this.logger.Debug().Msg("KeyBag created");
582
1015
  }
583
1016
  async subtleKey(key) {
584
- const extractable = this.rt.url.getParam("extractKey") === "_deprecated_internal_api";
1017
+ const extractable = this.rt.url.getParam("extractKey" /* EXTRACTKEY */) === "_deprecated_internal_api";
585
1018
  if (extractable) {
586
1019
  this._warnOnce.once(
587
1020
  () => this.logger.Warn().Msg("extractKey is enabled via _deprecated_internal_api --- handle keys safely!!!")
@@ -590,7 +1023,7 @@ var KeyBag = class {
590
1023
  return await this.rt.crypto.importKey(
591
1024
  "raw",
592
1025
  // raw or jwk
593
- base58btc.decode(key),
1026
+ base58btc2.decode(key),
594
1027
  // hexStringToUint8Array(key), // raw data
595
1028
  "AES-GCM",
596
1029
  extractable,
@@ -598,7 +1031,7 @@ var KeyBag = class {
598
1031
  );
599
1032
  }
600
1033
  async ensureKeyFromUrl(url, keyFactory) {
601
- const storeKey = url.getParam("storekey");
1034
+ const storeKey = url.getParam("storekey" /* STORE_KEY */);
602
1035
  if (storeKey === "insecure") {
603
1036
  return Result2.Ok(url);
604
1037
  }
@@ -608,7 +1041,7 @@ var KeyBag = class {
608
1041
  if (ret.isErr()) {
609
1042
  return ret;
610
1043
  }
611
- const urb = url.build().setParam("storekey", keyName);
1044
+ const urb = url.build().setParam("storekey" /* STORE_KEY */, keyName);
612
1045
  return Result2.Ok(urb.URI());
613
1046
  }
614
1047
  if (storeKey.startsWith("@") && storeKey.endsWith("@")) {
@@ -620,12 +1053,12 @@ var KeyBag = class {
620
1053
  return Result2.Ok(url);
621
1054
  }
622
1055
  async toKeyWithFingerPrint(keyStr) {
623
- const material = base58btc.decode(keyStr);
1056
+ const material = base58btc2.decode(keyStr);
624
1057
  const key = await this.subtleKey(keyStr);
625
1058
  const fpr = await this.rt.crypto.digestSHA256(material);
626
1059
  return Result2.Ok({
627
1060
  key,
628
- fingerPrint: base58btc.encode(new Uint8Array(fpr))
1061
+ fingerPrint: base58btc2.encode(new Uint8Array(fpr))
629
1062
  });
630
1063
  }
631
1064
  async setNamedKey(name, key) {
@@ -654,7 +1087,7 @@ var KeyBag = class {
654
1087
  const ext = new Uint8Array(await this.rt.crypto.exportKey("raw", named.key));
655
1088
  return {
656
1089
  key: ext,
657
- keyStr: base58btc.encode(ext)
1090
+ keyStr: base58btc2.encode(ext)
658
1091
  };
659
1092
  }
660
1093
  });
@@ -673,7 +1106,7 @@ var KeyBag = class {
673
1106
  this.logger.Debug().Str("id", id).Str("name", name).Msg("failIfNotFound getNamedKey");
674
1107
  return Result2.Err(new Error(`Key not found: ${name}`));
675
1108
  }
676
- const ret = await this._setNamedKey(name, base58btc.encode(this.rt.crypto.randomBytes(this.rt.keyLength)));
1109
+ const ret = await this._setNamedKey(name, base58btc2.encode(this.rt.crypto.randomBytes(this.rt.keyLength)));
677
1110
  this.logger.Debug().Str("id", id).Str("name", name).Result("fpr", ret).Msg("createKey getNamedKey-post");
678
1111
  return ret;
679
1112
  });
@@ -684,15 +1117,20 @@ var keyBagProviderFactories = new Map(
684
1117
  {
685
1118
  protocol: "file:",
686
1119
  factory: async (url, sthis) => {
687
- const { KeyBagProviderFile } = await import("./key-bag-file-PWZ3QE7B.js");
688
1120
  return new KeyBagProviderFile(url, sthis);
689
1121
  }
690
1122
  },
691
1123
  {
692
1124
  protocol: "indexdb:",
693
1125
  factory: async (url, sthis) => {
694
- const { KeyBagProviderIndexDB } = await import("./key-bag-indexdb-SYG3YD4D.js");
695
- return new KeyBagProviderIndexDB(url, sthis);
1126
+ const { KeyBagProviderImpl } = await import("@fireproof/core/web");
1127
+ return new KeyBagProviderImpl(url, sthis);
1128
+ }
1129
+ },
1130
+ {
1131
+ protocol: "memory:",
1132
+ factory: async (url, sthis) => {
1133
+ return new KeyBagProviderMemory(url, sthis);
696
1134
  }
697
1135
  }
698
1136
  ].map((i) => [i.protocol, i])
@@ -707,15 +1145,15 @@ function registerKeyBagProviderFactory(item) {
707
1145
  function defaultKeyBagUrl(sthis) {
708
1146
  let bagFnameOrUrl = sthis.env.get("FP_KEYBAG_URL");
709
1147
  let url;
710
- if (runtimeFn().isBrowser) {
711
- url = URI.from(bagFnameOrUrl || "indexdb://fp-keybag");
1148
+ if (runtimeFn2().isBrowser) {
1149
+ url = URI3.from(bagFnameOrUrl || "indexdb://fp-keybag");
712
1150
  } else {
713
1151
  if (!bagFnameOrUrl) {
714
1152
  const home = sthis.env.get("HOME");
715
1153
  bagFnameOrUrl = `${home}/.fireproof/keybag`;
716
- url = URI.from(`file://${bagFnameOrUrl}`);
1154
+ url = URI3.from(`file://${bagFnameOrUrl}`);
717
1155
  } else {
718
- url = URI.from(bagFnameOrUrl);
1156
+ url = URI3.from(bagFnameOrUrl);
719
1157
  }
720
1158
  }
721
1159
  const logger = ensureLogger(sthis, "defaultKeyBagUrl");
@@ -723,32 +1161,44 @@ function defaultKeyBagUrl(sthis) {
723
1161
  return url;
724
1162
  }
725
1163
  function defaultKeyBagOpts(sthis, kbo) {
1164
+ kbo = kbo || {};
726
1165
  if (kbo.keyRuntime) {
727
1166
  return kbo.keyRuntime;
728
1167
  }
729
1168
  const logger = ensureLogger(sthis, "KeyBag");
730
1169
  let url;
731
1170
  if (kbo.url) {
732
- url = URI.from(kbo.url);
1171
+ url = URI3.from(kbo.url);
733
1172
  logger.Debug().Url(url).Msg("from opts");
734
1173
  } else {
735
- url = defaultKeyBagUrl(sthis);
1174
+ let bagFnameOrUrl = sthis.env.get("FP_KEYBAG_URL");
1175
+ if (runtimeFn2().isBrowser) {
1176
+ url = URI3.from(bagFnameOrUrl || "indexdb://fp-keybag");
1177
+ } else {
1178
+ if (!bagFnameOrUrl) {
1179
+ const home = sthis.env.get("HOME");
1180
+ bagFnameOrUrl = `${home}/.fireproof/keybag`;
1181
+ url = URI3.from(`file://${bagFnameOrUrl}`);
1182
+ } else {
1183
+ url = URI3.from(bagFnameOrUrl);
1184
+ }
1185
+ }
1186
+ logger.Debug().Url(url).Msg("from env");
736
1187
  }
737
1188
  const kitem = keyBagProviderFactories.get(url.protocol);
738
1189
  if (!kitem) {
739
1190
  throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
740
1191
  }
741
- const getBag = async () => kitem.factory(url, sthis);
742
1192
  if (url.hasParam("masterkey")) {
743
1193
  throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
744
1194
  }
745
1195
  return {
746
1196
  url,
747
- crypto: kbo.crypto || toCryptoRuntime2({}),
1197
+ crypto: kbo.crypto || toCryptoRuntime3({}),
748
1198
  sthis,
749
1199
  logger,
750
1200
  keyLength: kbo.keyLength || 16,
751
- getBag,
1201
+ getBag: () => kitem.factory(url, sthis),
752
1202
  id: () => {
753
1203
  return url.toString();
754
1204
  }
@@ -773,7 +1223,7 @@ async function encodeCarFile(roots, t, codec3) {
773
1223
  size += CBW.blockLength({ cid, bytes });
774
1224
  }
775
1225
  const buffer = new Uint8Array(size);
776
- const writer = CBW.createWriter(buffer, { headerSize });
1226
+ const writer = CBW.createWriter(buffer.buffer, { headerSize });
777
1227
  for (const r of roots) {
778
1228
  writer.addRoot(r);
779
1229
  }
@@ -928,7 +1378,7 @@ function uniqueCids(list, remove = /* @__PURE__ */ new Set()) {
928
1378
  return [...byString.values()];
929
1379
  }
930
1380
  var Loader = class {
931
- constructor(name, ebOpts, sthis) {
1381
+ constructor(sthis, ebOpts) {
932
1382
  this.commitQueue = new CommitQueue();
933
1383
  this.isCompacting = false;
934
1384
  this.carReaders = /* @__PURE__ */ new Map();
@@ -938,14 +1388,17 @@ var Loader = class {
938
1388
  this.getBlockCache = /* @__PURE__ */ new Map();
939
1389
  this.seenMeta = /* @__PURE__ */ new Set();
940
1390
  this.writeLimit = pLimit(1);
941
- this.onceReady = new ResolveOnce2();
942
- this.name = name;
1391
+ this._carStore = new ResolveOnce3();
1392
+ this._fileStore = new ResolveOnce3();
1393
+ this._WALStore = new ResolveOnce3();
1394
+ this._metaStore = new ResolveOnce3();
1395
+ this.onceReady = new ResolveOnce3();
943
1396
  this.sthis = sthis;
944
1397
  this.ebOpts = defaultedBlockstoreRuntime(
945
1398
  sthis,
946
1399
  {
947
- ...ebOpts,
948
- name
1400
+ ...ebOpts
1401
+ // name,
949
1402
  },
950
1403
  "Loader"
951
1404
  );
@@ -954,21 +1407,52 @@ var Loader = class {
954
1407
  await this.handleDbMetasFromStore([dbMeta]);
955
1408
  });
956
1409
  }
957
- // readonly id = uuidv4();
958
- async keyBag() {
959
- return getKeyBag(this.sthis, this.ebOpts.keyBag);
960
- }
961
1410
  async carStore() {
962
- return this.ebOpts.storeRuntime.makeDataStore(this);
1411
+ return this._carStore.once(
1412
+ async () => this.ebOpts.storeRuntime.makeDataStore({
1413
+ sthis: this.sthis,
1414
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1415
+ url: this.ebOpts.storeUrls.data,
1416
+ // keybag: await this.keyBag(),
1417
+ loader: this
1418
+ })
1419
+ );
963
1420
  }
964
1421
  async fileStore() {
965
- return this.ebOpts.storeRuntime.makeDataStore(this);
1422
+ return this._fileStore.once(
1423
+ async () => this.ebOpts.storeRuntime.makeDataStore({
1424
+ sthis: this.sthis,
1425
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1426
+ url: this.ebOpts.storeUrls.file,
1427
+ // keybag: await this.keyBag(),
1428
+ loader: this
1429
+ })
1430
+ );
966
1431
  }
967
1432
  async WALStore() {
968
- return this.ebOpts.storeRuntime.makeWALStore(this);
1433
+ return this._WALStore.once(
1434
+ async () => this.ebOpts.storeRuntime.makeWALStore({
1435
+ sthis: this.sthis,
1436
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1437
+ url: this.ebOpts.storeUrls.wal,
1438
+ // keybag: await this.keyBag(),
1439
+ loader: this
1440
+ })
1441
+ );
969
1442
  }
970
1443
  async metaStore() {
971
- return this.ebOpts.storeRuntime.makeMetaStore(this);
1444
+ return this._metaStore.once(
1445
+ async () => this.ebOpts.storeRuntime.makeMetaStore({
1446
+ sthis: this.sthis,
1447
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1448
+ url: this.ebOpts.storeUrls.meta,
1449
+ // keybag: await this.keyBag(),
1450
+ loader: this
1451
+ })
1452
+ );
1453
+ }
1454
+ keyBag() {
1455
+ return getKeyBag(this.sthis, this.ebOpts.keyBag);
972
1456
  }
973
1457
  async ready() {
974
1458
  return this.onceReady.once(async () => {
@@ -981,6 +1465,7 @@ var Loader = class {
981
1465
  });
982
1466
  }
983
1467
  async close() {
1468
+ await this.commitQueue.waitIdle();
984
1469
  const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
985
1470
  await Promise.all(toClose.map((store) => store.close()));
986
1471
  }
@@ -1050,11 +1535,11 @@ var Loader = class {
1050
1535
  }
1051
1536
  async commit(t, done, opts = { noLoader: false, compact: false }) {
1052
1537
  await this.ready();
1053
- const fstore = await this.fileStore();
1538
+ const carStore = await this.carStore();
1054
1539
  const params = {
1055
- encoder: (await fstore.keyedCrypto()).codec(),
1540
+ encoder: (await carStore.keyedCrypto()).codec(),
1056
1541
  carLog: this.carLog,
1057
- carStore: fstore,
1542
+ carStore,
1058
1543
  WALStore: await this.WALStore(),
1059
1544
  metaStore: await this.metaStore(),
1060
1545
  threshold: this.ebOpts.threshold
@@ -1263,7 +1748,7 @@ __export(keyed_crypto_exports, {
1263
1748
  BlockIvKeyIdCodec: () => BlockIvKeyIdCodec,
1264
1749
  keyedCryptoFactory: () => keyedCryptoFactory
1265
1750
  });
1266
- import { base58btc as base58btc2 } from "multiformats/bases/base58";
1751
+ import { base58btc as base58btc3 } from "multiformats/bases/base58";
1267
1752
  import { sha256 as hasher4 } from "multiformats/hashes/sha2";
1268
1753
  import * as CBOR from "@fireproof/vendor/cborg";
1269
1754
  var generateIV = {
@@ -1288,12 +1773,12 @@ var generateIV = {
1288
1773
  return hashArray;
1289
1774
  },
1290
1775
  verify: async function(ko, crypto, iv, data) {
1291
- return ko.url.getParam("ivverify") !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
1776
+ return ko.url.getParam("ivVerify" /* IV_VERIFY */) !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
1292
1777
  }
1293
1778
  }
1294
1779
  };
1295
1780
  function getGenerateIVFn(url, opts) {
1296
- const ivhash = opts.ivCalc || url.getParam("ivhash") || "hash";
1781
+ const ivhash = opts.ivCalc || url.getParam("ivHash" /* IV_HASH */) || "hash";
1297
1782
  return generateIV[ivhash] || generateIV["hash"];
1298
1783
  }
1299
1784
  var BlockIvKeyIdCodec = class {
@@ -1308,7 +1793,7 @@ var BlockIvKeyIdCodec = class {
1308
1793
  const calcIv = this.iv || await getGenerateIVFn(this.ko.url, this.opts).calc(this.ko, this.ko.crypto, data);
1309
1794
  const { iv } = this.ko.algo(calcIv);
1310
1795
  const fprt = await this.ko.fingerPrint();
1311
- const keyId = base58btc2.decode(fprt);
1796
+ const keyId = base58btc3.decode(fprt);
1312
1797
  this.ko.logger.Debug().Str("fp", fprt).Msg("encode");
1313
1798
  return CBOR.encode({
1314
1799
  iv,
@@ -1325,9 +1810,9 @@ var BlockIvKeyIdCodec = class {
1325
1810
  }
1326
1811
  const { iv, keyId, data } = CBOR.decode(bytes);
1327
1812
  const fprt = await this.ko.fingerPrint();
1328
- this.ko.logger.Debug().Str("fp", base58btc2.encode(keyId)).Msg("decode");
1329
- if (base58btc2.encode(keyId) !== fprt) {
1330
- throw this.ko.logger.Error().Str("fp", fprt).Str("keyId", base58btc2.encode(keyId)).Msg("keyId mismatch").AsError();
1813
+ this.ko.logger.Debug().Str("fp", base58btc3.encode(keyId)).Msg("decode");
1814
+ if (base58btc3.encode(keyId) !== fprt) {
1815
+ throw this.ko.logger.Error().Str("fp", fprt).Str("keyId", base58btc3.encode(keyId)).Msg("keyId mismatch").AsError();
1331
1816
  }
1332
1817
  const result = await this.ko._decrypt({ iv, bytes: data });
1333
1818
  if (!this.opts?.noIVVerify && !await getGenerateIVFn(this.ko.url, this.opts).verify(this.ko, this.ko.crypto, iv, result)) {
@@ -1414,7 +1899,7 @@ var noCrypto = class {
1414
1899
  }
1415
1900
  };
1416
1901
  async function keyedCryptoFactory(url, kb, sthis) {
1417
- const storekey = url.getParam("storekey");
1902
+ const storekey = url.getParam("storekey" /* STORE_KEY */);
1418
1903
  if (storekey && storekey !== "insecure") {
1419
1904
  let rkey = await kb.getNamedKey(storekey, true);
1420
1905
  if (rkey.isErr()) {
@@ -1429,277 +1914,167 @@ async function keyedCryptoFactory(url, kb, sthis) {
1429
1914
  return new noCrypto(url, kb.rt.crypto, sthis);
1430
1915
  }
1431
1916
 
1432
- // src/blockstore/fragment-gateway.ts
1917
+ // src/blockstore/fp-envelope.ts
1433
1918
  import { Result as Result3 } from "@adviser/cement";
1434
- import { base58btc as base58btc3 } from "multiformats/bases/base58";
1435
- import { encode as encode3, decode as decode3 } from "@fireproof/vendor/cborg";
1436
- function getFragSize(url) {
1437
- const fragSize = url.getParam("fragSize");
1438
- let ret = 0;
1439
- if (fragSize) {
1440
- ret = parseInt(fragSize);
1919
+ var FPEnvelopeType = /* @__PURE__ */ ((FPEnvelopeType2) => {
1920
+ FPEnvelopeType2["CAR"] = "car";
1921
+ FPEnvelopeType2["FILE"] = "file";
1922
+ FPEnvelopeType2["META"] = "meta";
1923
+ FPEnvelopeType2["WAL"] = "wal";
1924
+ return FPEnvelopeType2;
1925
+ })(FPEnvelopeType || {});
1926
+ function Car2FPMsg(fpcar) {
1927
+ return Result3.Ok({ type: "car" /* CAR */, payload: fpcar });
1928
+ }
1929
+ function File2FPMsg(fpfile) {
1930
+ return Result3.Ok({ type: "file" /* FILE */, payload: fpfile });
1931
+ }
1932
+
1933
+ // src/blockstore/store.ts
1934
+ import { EventBlock } from "@fireproof/vendor/@web3-storage/pail/clock";
1935
+ import { format } from "@fireproof/vendor/@ipld/dag-json";
1936
+ import pRetry from "p-retry";
1937
+ import pMap from "p-map";
1938
+
1939
+ // src/blockstore/interceptor-gateway.ts
1940
+ import { Result as Result4 } from "@adviser/cement";
1941
+ var PassThroughGateway = class {
1942
+ async buildUrl(sthis, url, key) {
1943
+ const op = { url, key };
1944
+ return Result4.Ok({ op });
1441
1945
  }
1442
- if (isNaN(ret) || ret <= 0) {
1443
- ret = 0;
1946
+ async start(sthis, url) {
1947
+ const op = { url };
1948
+ return Result4.Ok({ op });
1444
1949
  }
1445
- return ret;
1446
- }
1447
- async function getFrags(url, innerGW, headerSize, logger) {
1448
- const fragSize = getFragSize(url);
1449
- if (!fragSize) {
1450
- const res = await innerGW.get(url);
1451
- if (res.isErr()) {
1452
- return [res];
1453
- }
1454
- const data = res.unwrap();
1455
- return [
1456
- Result3.Ok({
1457
- fid: new Uint8Array(0),
1458
- ofs: 0,
1459
- len: data.length,
1460
- data
1461
- })
1462
- ];
1463
- }
1464
- const firstRaw = await innerGW.get(url.build().setParam("ofs", "0").URI());
1465
- if (firstRaw.isErr()) {
1466
- return [firstRaw];
1467
- }
1468
- const firstFragment = decode3(firstRaw.unwrap());
1469
- const blockSize = firstFragment.data.length;
1470
- const ops = [Promise.resolve(Result3.Ok(firstFragment))];
1471
- const fidStr = base58btc3.encode(firstFragment.fid);
1472
- const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
1473
- for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
1474
- ops.push(
1475
- (async (furl, ofs2) => {
1476
- const raw2 = await innerGW.get(furl);
1477
- if (raw2.isErr()) {
1478
- return raw2;
1479
- }
1480
- const fragment = decode3(raw2.unwrap());
1481
- if (base58btc3.encode(fragment.fid) !== fidStr) {
1482
- return Result3.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
1483
- }
1484
- if (fragment.ofs !== ofs2) {
1485
- return Result3.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
1486
- }
1487
- return Result3.Ok(fragment);
1488
- })(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
1489
- );
1950
+ async close(sthis, url) {
1951
+ const op = { url };
1952
+ return Result4.Ok({ op });
1490
1953
  }
1491
- return Promise.all(ops);
1492
- }
1493
- var FragmentGateway = class {
1494
- constructor(sthis, innerGW) {
1495
- this.fidLength = 4;
1496
- this.headerSize = 32;
1497
- this.sthis = ensureSuperLog(sthis, "FragmentGateway");
1498
- this.logger = this.sthis.logger;
1954
+ async delete(sthis, url) {
1955
+ const op = { url };
1956
+ return Result4.Ok({ op });
1957
+ }
1958
+ async destroy(sthis, url) {
1959
+ const op = { url };
1960
+ return Result4.Ok({ op });
1961
+ }
1962
+ async put(sthis, url, body) {
1963
+ const op = { url, body };
1964
+ return Result4.Ok({ op });
1965
+ }
1966
+ async get(sthis, url) {
1967
+ const op = { url };
1968
+ return Result4.Ok({ op });
1969
+ }
1970
+ async subscribe(sthis, url, callback) {
1971
+ const op = { url, callback };
1972
+ return Result4.Ok({ op });
1973
+ }
1974
+ };
1975
+ var passThrougthGateway = new PassThroughGateway();
1976
+ var InterceptorGateway = class {
1977
+ constructor(sthis, innerGW, interceptor) {
1499
1978
  this.innerGW = innerGW;
1979
+ this.interceptor = interceptor || passThrougthGateway;
1500
1980
  }
1501
- slicer(url, body) {
1502
- const fragSize = getFragSize(url);
1503
- if (!fragSize) {
1504
- return [this.innerGW.put(url, body)];
1505
- }
1506
- const blocksize = fragSize - this.headerSize;
1507
- if (blocksize <= 0) {
1508
- throw this.logger.Error().Uint64("fragSize", fragSize).Uint64("headerSize", this.headerSize).Msg("Fragment size is too small").AsError();
1509
- }
1510
- const ops = [];
1511
- const fid = this.sthis.nextId(this.fidLength);
1512
- const fragUrl = url.build().setParam("fid", fid.str).setParam("len", body.length.toString()).setParam("headerSize", this.headerSize.toString());
1513
- for (let ofs = 0; ofs < body.length; ofs += blocksize) {
1514
- const block = encode3({
1515
- fid: fid.bin,
1516
- ofs,
1517
- len: body.length,
1518
- data: body.slice(ofs, ofs + blocksize)
1519
- });
1520
- if (block.length > fragSize) {
1521
- throw this.logger.Error().Uint64("block", block.length).Uint64("fragSize", fragSize).Msg("Block size to big").AsError();
1522
- }
1523
- ops.push(this.innerGW.put(fragUrl.setParam("ofs", ofs.toString()).URI(), block));
1981
+ async buildUrl(sthis, baseUrl, key, loader) {
1982
+ const rret = await this.interceptor.buildUrl(sthis, baseUrl, key, loader);
1983
+ if (rret.isErr()) {
1984
+ return Result4.Err(rret.Err());
1985
+ }
1986
+ const ret = rret.unwrap();
1987
+ if (ret.stop && ret.value) {
1988
+ return ret.value;
1524
1989
  }
1525
- return ops;
1990
+ return this.innerGW.buildUrl(sthis, ret.op.url, ret.op.key, loader);
1526
1991
  }
1527
- buildUrl(baseUrl, key) {
1528
- return this.innerGW.buildUrl(baseUrl, key);
1529
- }
1530
- async destroy(iurl) {
1531
- return this.innerGW.destroy(iurl);
1532
- }
1533
- async start(url) {
1534
- this.headerSize = encode3({
1535
- fid: this.sthis.nextId(this.fidLength).bin,
1536
- ofs: 1024 * 1024,
1537
- // 32bit
1538
- len: 16 * 1024 * 1024,
1539
- // 32bit
1540
- data: new Uint8Array(1024)
1541
- }).length - 1024;
1542
- return this.innerGW.start(url);
1543
- }
1544
- async close(url) {
1545
- return this.innerGW.close(url);
1546
- }
1547
- async put(url, body) {
1548
- await Promise.all(this.slicer(url, body));
1549
- return Result3.Ok(void 0);
1550
- }
1551
- async get(url) {
1552
- const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
1553
- let buffer = void 0;
1554
- for (const rfrag of rfrags) {
1555
- if (rfrag.isErr()) {
1556
- return Result3.Err(rfrag.Err());
1557
- }
1558
- const frag = rfrag.Ok();
1559
- buffer = buffer || new Uint8Array(frag.len);
1560
- buffer.set(frag.data, frag.ofs);
1561
- }
1562
- return Result3.Ok(buffer || new Uint8Array(0));
1563
- }
1564
- async subscribe(url, callback) {
1565
- if (this.innerGW.subscribe) {
1566
- return this.innerGW.subscribe(url, callback);
1567
- } else {
1568
- return Result3.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
1992
+ async destroy(sthis, iurl, loader) {
1993
+ const rret = await this.interceptor.destroy(sthis, iurl, loader);
1994
+ if (rret.isErr()) {
1995
+ return Result4.Err(rret.Err());
1569
1996
  }
1997
+ const ret = rret.unwrap();
1998
+ if (ret.stop && ret.value) {
1999
+ return ret.value;
2000
+ }
2001
+ return this.innerGW.destroy(sthis, ret.op.url, loader);
1570
2002
  }
1571
- async delete(url) {
1572
- const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
1573
- for (const rfrag of rfrags) {
1574
- if (rfrag.isErr()) {
1575
- return Result3.Err(rfrag.Err());
1576
- }
1577
- const frag = rfrag.Ok();
1578
- const fidStr = base58btc3.encode(frag.fid);
1579
- const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
1580
- await this.innerGW.delete(fragUrl);
2003
+ async start(sthis, url, loader) {
2004
+ const rret = await this.interceptor.start(sthis, url, loader);
2005
+ if (rret.isErr()) {
2006
+ return Result4.Err(rret.Err());
1581
2007
  }
1582
- return Result3.Ok(void 0);
2008
+ const ret = rret.unwrap();
2009
+ if (ret.stop && ret.value) {
2010
+ return ret.value;
2011
+ }
2012
+ return await this.innerGW.start(sthis, ret.op.url, loader);
1583
2013
  }
1584
- };
1585
-
1586
- // src/blockstore/meta-key-helper.ts
1587
- import { format, parse } from "@fireproof/vendor/@ipld/dag-json";
1588
- import { EventBlock, decodeEventBlock } from "@fireproof/vendor/@web3-storage/pail/clock";
1589
- import { CID as CID2 } from "multiformats";
1590
- import { base64pad } from "multiformats/bases/base64";
1591
- import { Result as Result4 } from "@adviser/cement";
1592
- async function decodeGatewayMetaBytesToDbMeta(sthis, byteHeads) {
1593
- const crdtEntries = JSON.parse(sthis.txt.decode(byteHeads));
1594
- if (!Array.isArray(crdtEntries)) {
1595
- sthis.logger.Debug().Str("crdtEntries", JSON.stringify(crdtEntries)).Msg("No data in CRDT entries");
1596
- return [];
1597
- }
1598
- if (!crdtEntries.length) {
1599
- sthis.logger.Debug().Any("byteHeads", byteHeads).Msg("No CRDT entries found");
1600
- return [];
1601
- }
1602
- const logger = ensureLogger(sthis, "decodeGatewayMetaBytesToDbMeta");
1603
- return Promise.all(
1604
- crdtEntries.map(async (crdtEntry) => {
1605
- const eventBlock = await decodeEventBlock(base64pad.decode(crdtEntry.data));
1606
- const dbMeta = parse(sthis.txt.decode(eventBlock.value.data.dbMeta));
1607
- logger.Debug().Any("crdtEntry", {
1608
- crdtEntry,
1609
- eventBlock,
1610
- dbMeta,
1611
- dbMetaStrings: dbMeta.cars.map((car) => car.toString())
1612
- }).Msg("CRDT entry");
1613
- return {
1614
- eventCid: eventBlock.cid,
1615
- parents: crdtEntry.parents,
1616
- dbMeta
1617
- };
1618
- })
1619
- );
1620
- }
1621
- async function setCryptoKeyFromGatewayMetaPayload(uri, sthis, data) {
1622
- try {
1623
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Setting crypto key from gateway meta payload");
1624
- const keyInfo = await decodeGatewayMetaBytesToDbMeta(sthis, data);
1625
- if (keyInfo.length) {
1626
- const dbMeta = keyInfo[0].dbMeta;
1627
- if (dbMeta.key) {
1628
- const kb = await getKeyBag(sthis);
1629
- const keyName = getStoreKeyName(uri);
1630
- const res = await kb.setNamedKey(keyName, dbMeta.key);
1631
- if (res.isErr()) {
1632
- sthis.logger.Debug().Str("keyName", keyName).Str("dbMeta.key", dbMeta.key).Msg("Failed to set named key");
1633
- throw res.Err();
1634
- }
1635
- }
1636
- sthis.logger.Debug().Str("dbMeta.key", dbMeta.key).Str("uri", uri.toString()).Msg("Set crypto key from gateway meta payload");
1637
- return Result4.Ok(dbMeta);
2014
+ async close(sthis, url, loader) {
2015
+ const rret = await this.interceptor.close(sthis, url, loader);
2016
+ if (rret.isErr()) {
2017
+ return Result4.Err(rret.Err());
2018
+ }
2019
+ const ret = rret.unwrap();
2020
+ if (ret.stop && ret.value) {
2021
+ return ret.value;
1638
2022
  }
1639
- sthis.logger.Debug().Any("data", data).Msg("No crypto in gateway meta payload");
1640
- return Result4.Ok(void 0);
1641
- } catch (error) {
1642
- sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
1643
- return Result4.Err(error);
2023
+ return await this.innerGW.close(sthis, ret.op.url, loader);
1644
2024
  }
1645
- }
1646
- async function addCryptoKeyToGatewayMetaPayload(uri, sthis, body) {
1647
- try {
1648
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Adding crypto key to gateway meta payload");
1649
- const keyName = getStoreKeyName(uri);
1650
- const kb = await getKeyBag(sthis);
1651
- const res = await kb.getNamedExtractableKey(keyName, true);
1652
- if (res.isErr()) {
1653
- sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
1654
- throw res.Err();
2025
+ async put(sthis, url, fpEnv, loader) {
2026
+ const rret = await this.interceptor.put(sthis, url, fpEnv, loader);
2027
+ if (rret.isErr()) {
2028
+ return Result4.Err(rret.Err());
1655
2029
  }
1656
- const keyData = await res.Ok().extract();
1657
- const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
1658
- const { dbMeta, parents } = dbMetas[0];
1659
- const parentLinks = parents.map((p) => CID2.parse(p));
1660
- dbMeta.key = keyData.keyStr;
1661
- const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
1662
- const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
1663
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
1664
- return Result4.Ok(encoded);
1665
- } catch (error) {
1666
- sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
1667
- return Result4.Err(error);
1668
- }
1669
- }
1670
- function getStoreKeyName(url) {
1671
- const storeKeyName = [url.getParam("localName") || url.getParam("name")];
1672
- const idx = url.getParam("index");
1673
- if (idx) {
1674
- storeKeyName.push(idx);
1675
- }
1676
- storeKeyName.push("data");
1677
- return `@${storeKeyName.join(":")}@`;
1678
- }
1679
- async function createDbMetaEventBlock(sthis, dbMeta, parents) {
1680
- const event = await EventBlock.create(
1681
- {
1682
- dbMeta: sthis.txt.encode(format(dbMeta))
1683
- },
1684
- parents
1685
- );
1686
- return event;
1687
- }
1688
- async function encodeEventsWithParents(sthis, events, parents) {
1689
- const crdtEntries = events.map((event) => {
1690
- const base64String = base64pad.encode(event.bytes);
1691
- return {
1692
- cid: event.cid.toString(),
1693
- data: base64String,
1694
- parents: parents.map((p) => p.toString())
1695
- };
1696
- });
1697
- return sthis.txt.encode(JSON.stringify(crdtEntries));
1698
- }
2030
+ const ret = rret.unwrap();
2031
+ if (ret.stop && ret.value) {
2032
+ return ret.value;
2033
+ }
2034
+ return this.innerGW.put(sthis, ret.op.url, ret.op.body, loader);
2035
+ }
2036
+ async get(sthis, url, loader) {
2037
+ const rret = await this.interceptor.get(sthis, url, loader);
2038
+ if (rret.isErr()) {
2039
+ return Result4.Err(rret.Err());
2040
+ }
2041
+ const ret = rret.unwrap();
2042
+ if (ret.stop && ret.value) {
2043
+ return ret.value;
2044
+ }
2045
+ return this.innerGW.get(sthis, ret.op.url, loader);
2046
+ }
2047
+ async subscribe(sthis, url, callback, loader) {
2048
+ if (!this.innerGW.subscribe) {
2049
+ return Result4.Err(sthis.logger.Error().Url(url).Msg("subscribe not supported").AsError());
2050
+ }
2051
+ const rret = await this.interceptor.subscribe(sthis, url, callback, loader);
2052
+ if (rret.isErr()) {
2053
+ return Result4.Err(rret.Err());
2054
+ }
2055
+ const ret = rret.unwrap();
2056
+ if (ret.stop && ret.value) {
2057
+ return ret.value;
2058
+ }
2059
+ return this.innerGW.subscribe(sthis, ret.op.url, ret.op.callback, loader);
2060
+ }
2061
+ async delete(sthis, url, loader) {
2062
+ const rret = await this.interceptor.delete(sthis, url, loader);
2063
+ if (rret.isErr()) {
2064
+ return Result4.Err(rret.Err());
2065
+ }
2066
+ const ret = rret.unwrap();
2067
+ if (ret.stop && ret.value) {
2068
+ return ret.value;
2069
+ }
2070
+ return this.innerGW.delete(sthis, url, loader);
2071
+ }
2072
+ async getPlain(sthis, url, key, loader) {
2073
+ return this.innerGW.getPlain(sthis, url, key, loader);
2074
+ }
2075
+ };
1699
2076
 
1700
2077
  // src/blockstore/store.ts
1701
- import pRetry from "p-retry";
1702
- import pMap from "p-map";
1703
2078
  function guardVersion(url) {
1704
2079
  if (!url.hasParam("version")) {
1705
2080
  return Result5.Err(`missing version: ${url.toString()}`);
@@ -1707,16 +2082,21 @@ function guardVersion(url) {
1707
2082
  return Result5.Ok(url);
1708
2083
  }
1709
2084
  var BaseStoreImpl = class {
1710
- constructor(name, url, opts, sthis, logger) {
2085
+ // readonly loader: Loadable;
2086
+ constructor(sthis, url, opts, logger) {
1711
2087
  this._onStarted = [];
1712
2088
  this._onClosed = [];
1713
- this.name = name;
1714
2089
  this._url = url;
1715
- this.keybag = opts.keybag;
1716
- this.sthis = sthis;
1717
- this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
1718
- this.gateway = new FragmentGateway(this.sthis, opts.gateway);
2090
+ this.opts = opts;
1719
2091
  this.loader = opts.loader;
2092
+ this.sthis = sthis;
2093
+ const name = this._url.getParam("name" /* NAME */);
2094
+ if (!name) {
2095
+ throw logger.Error().Url(this._url).Msg("missing name").AsError();
2096
+ }
2097
+ this.logger = logger.With().Str("this", this.sthis.nextId().str).Ref("url", () => this._url.toString()).Logger();
2098
+ this.realGateway = opts.gateway;
2099
+ this.gateway = new InterceptorGateway(this.sthis, opts.gateway, opts.gatewayInterceptor);
1720
2100
  }
1721
2101
  url() {
1722
2102
  return this._url;
@@ -1731,21 +2111,21 @@ var BaseStoreImpl = class {
1731
2111
  return;
1732
2112
  }
1733
2113
  async keyedCrypto() {
1734
- return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
2114
+ return keyedCryptoFactory(this._url, await this.loader.keyBag(), this.sthis);
1735
2115
  }
1736
2116
  async start() {
1737
2117
  this.logger.Debug().Str("storeType", this.storeType).Msg("starting-gateway-pre");
1738
- this._url = this._url.build().setParam("store", this.storeType).URI();
1739
- const res = await this.gateway.start(this._url);
2118
+ this._url = this._url.build().setParam("store" /* STORE */, this.storeType).URI();
2119
+ const res = await this.gateway.start(this.sthis, this._url, this.loader);
1740
2120
  if (res.isErr()) {
1741
2121
  this.logger.Error().Result("gw-start", res).Msg("started-gateway");
1742
2122
  return res;
1743
2123
  }
1744
2124
  this._url = res.Ok();
1745
- const kb = await this.keybag();
2125
+ const kb = await this.loader.keyBag();
1746
2126
  const skRes = await kb.ensureKeyFromUrl(this._url, () => {
1747
- const idx = this._url.getParam("index");
1748
- const storeKeyName = [this.name];
2127
+ const idx = this._url.getParam("index" /* INDEX */);
2128
+ const storeKeyName = [this.url().getParam("name" /* NAME */)];
1749
2129
  if (idx) {
1750
2130
  storeKeyName.push(idx);
1751
2131
  }
@@ -1775,10 +2155,23 @@ var BaseStoreImpl = class {
1775
2155
  return version;
1776
2156
  }
1777
2157
  };
2158
+ async function createDbMetaEvent(sthis, dbMeta, parents) {
2159
+ const event = await EventBlock.create(
2160
+ {
2161
+ dbMeta: sthis.txt.encode(format(dbMeta))
2162
+ },
2163
+ parents
2164
+ );
2165
+ return {
2166
+ eventCid: event.cid,
2167
+ dbMeta,
2168
+ parents
2169
+ };
2170
+ }
1778
2171
  var MetaStoreImpl = class extends BaseStoreImpl {
1779
2172
  // remote: boolean;
1780
- constructor(sthis, name, url, opts) {
1781
- super(name, url, { ...opts }, sthis, ensureLogger(sthis, "MetaStoreImpl"));
2173
+ constructor(sthis, url, opts) {
2174
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "MetaStoreImpl"));
1782
2175
  this.storeType = "meta";
1783
2176
  this.subscribers = /* @__PURE__ */ new Map();
1784
2177
  this.parents = [];
@@ -1788,14 +2181,18 @@ var MetaStoreImpl = class extends BaseStoreImpl {
1788
2181
  ) {
1789
2182
  this.onStarted(async () => {
1790
2183
  this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
1791
- opts.gateway.subscribe?.(this.url(), async (message) => {
1792
- this.logger.Debug().Msg("Received message from gateway");
1793
- const dbMetas = await decodeGatewayMetaBytesToDbMeta(this.sthis, message);
1794
- await Promise.all(
1795
- dbMetas.map((dbMeta) => this.loader?.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
1796
- );
1797
- this.updateParentsFromDbMetas(dbMetas);
1798
- });
2184
+ opts.gateway.subscribe?.(
2185
+ this.sthis,
2186
+ this.url(),
2187
+ async ({ payload: dbMetas }) => {
2188
+ this.logger.Debug().Msg("Received message from gateway");
2189
+ await Promise.all(
2190
+ dbMetas.map((dbMeta) => this.loader.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
2191
+ );
2192
+ this.updateParentsFromDbMetas(dbMetas);
2193
+ },
2194
+ this.loader
2195
+ );
1799
2196
  });
1800
2197
  }
1801
2198
  }
@@ -1806,129 +2203,165 @@ var MetaStoreImpl = class extends BaseStoreImpl {
1806
2203
  const dbMetaParentsSet = new Set(dbMetaParents.map((p) => p.toString()));
1807
2204
  this.parents = Array.from(uniqueParentsMap.values()).filter((p) => !dbMetaParentsSet.has(p.toString()));
1808
2205
  }
1809
- async handleByteHeads(byteHeads) {
1810
- return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
1811
- }
2206
+ // async handleByteHeads(byteHeads: Uint8Array) {
2207
+ // // return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
2208
+ // const rDbMeta = await fpDeserialize(this.sthis, byteHeads, this.url());
2209
+ // if (rDbMeta.isErr()) {
2210
+ // throw this.logger.Error().Err(rDbMeta).Msg("error deserializing").AsError();
2211
+ // }
2212
+ // return (rDbMeta.Ok() as FPEnvelopeMeta).payload;
2213
+ // }
1812
2214
  async load() {
1813
2215
  const branch = "main";
1814
- const url = await this.gateway.buildUrl(this.url(), branch);
2216
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), branch, this.loader);
1815
2217
  if (url.isErr()) {
1816
2218
  throw this.logger.Error().Result("buildUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
1817
2219
  }
1818
- const bytes = await this.gateway.get(url.Ok());
1819
- if (bytes.isErr()) {
1820
- if (isNotFoundError(bytes)) {
2220
+ const rfpEnv = await this.gateway.get(this.sthis, url.Ok(), this.loader);
2221
+ if (rfpEnv.isErr()) {
2222
+ if (isNotFoundError(rfpEnv)) {
1821
2223
  return void 0;
1822
2224
  }
1823
- throw this.logger.Error().Url(url.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
2225
+ throw this.logger.Error().Url(url.Ok()).Err(rfpEnv).Msg("gateway get").AsError();
1824
2226
  }
1825
- const dbMetas = await this.handleByteHeads(bytes.Ok());
1826
- await this.loader?.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
2227
+ const dbMetas = rfpEnv.Ok().payload;
2228
+ await this.loader.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
1827
2229
  this.updateParentsFromDbMetas(dbMetas);
1828
2230
  return dbMetas.map((m) => m.dbMeta);
1829
2231
  }
1830
2232
  async save(meta, branch) {
1831
2233
  branch = branch || "main";
1832
2234
  this.logger.Debug().Str("branch", branch).Any("meta", meta).Msg("saving meta");
1833
- const event = await createDbMetaEventBlock(this.sthis, meta, this.parents);
1834
- const bytes = await encodeEventsWithParents(this.sthis, [event], this.parents);
1835
- const url = await this.gateway.buildUrl(this.url(), branch);
2235
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), branch, this.loader);
1836
2236
  if (url.isErr()) {
1837
2237
  throw this.logger.Error().Err(url.Err()).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
1838
2238
  }
1839
- this.parents = [event.cid];
1840
- const res = await this.gateway.put(url.Ok(), bytes);
2239
+ const dbMetaEvent = await createDbMetaEvent(this.sthis, meta, this.parents);
2240
+ const res = await this.gateway.put(
2241
+ this.sthis,
2242
+ url.Ok(),
2243
+ {
2244
+ type: "meta",
2245
+ payload: [dbMetaEvent]
2246
+ },
2247
+ this.loader
2248
+ );
1841
2249
  if (res.isErr()) {
1842
2250
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
1843
2251
  }
1844
2252
  return res;
1845
2253
  }
1846
2254
  async close() {
1847
- await this.gateway.close(this.url());
2255
+ await this.gateway.close(this.sthis, this.url(), this.loader);
1848
2256
  this._onClosed.forEach((fn) => fn());
1849
2257
  return Result5.Ok(void 0);
1850
2258
  }
1851
2259
  async destroy() {
1852
- return this.gateway.destroy(this.url());
2260
+ this.logger.Debug().Msg("destroy");
2261
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
1853
2262
  }
1854
2263
  };
1855
2264
  var DataStoreImpl = class extends BaseStoreImpl {
1856
- // readonly tag: string = "car-base";
1857
- constructor(sthis, name, url, opts) {
1858
- super(name, url, { ...opts }, sthis, ensureLogger(sthis, "DataStoreImpl"));
2265
+ constructor(sthis, url, opts) {
2266
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "DataStoreImpl"));
1859
2267
  this.storeType = "data";
1860
2268
  }
1861
2269
  async load(cid) {
1862
2270
  this.logger.Debug().Any("cid", cid).Msg("loading");
1863
- const url = await this.gateway.buildUrl(this.url(), cid.toString());
2271
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), cid.toString(), this.loader);
1864
2272
  if (url.isErr()) {
1865
2273
  throw this.logger.Error().Err(url.Err()).Str("cid", cid.toString()).Msg("got error from gateway.buildUrl").AsError();
1866
2274
  }
1867
- const res = await this.gateway.get(url.Ok());
2275
+ const res = await this.gateway.get(this.sthis, url.Ok(), this.loader);
1868
2276
  if (res.isErr()) {
1869
2277
  throw res.Err();
1870
2278
  }
1871
- return { cid, bytes: res.Ok() };
2279
+ const fpenv = res.Ok();
2280
+ switch (fpenv.type) {
2281
+ case "car":
2282
+ return { cid, bytes: fpenv.payload };
2283
+ case "file":
2284
+ return { cid, bytes: fpenv.payload };
2285
+ default:
2286
+ throw this.logger.Error().Msg("unexpected type").AsError();
2287
+ }
1872
2288
  }
1873
2289
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
1874
2290
  async save(car, opts) {
1875
2291
  this.logger.Debug().Any("cid", car.cid.toString()).Msg("saving");
1876
- const url = await this.gateway.buildUrl(this.url(), car.cid.toString());
2292
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), car.cid.toString(), this.loader);
1877
2293
  if (url.isErr()) {
1878
2294
  throw this.logger.Error().Err(url.Err()).Ref("cid", car.cid).Msg("got error from gateway.buildUrl").AsError();
1879
2295
  }
1880
- const res = await this.gateway.put(url.Ok(), car.bytes);
2296
+ let fpMsg;
2297
+ switch (url.Ok().getParam("store" /* STORE */)) {
2298
+ case "data":
2299
+ if (url.Ok().getParam("suffix" /* SUFFIX */)) {
2300
+ fpMsg = Car2FPMsg(car.bytes);
2301
+ } else {
2302
+ fpMsg = File2FPMsg(car.bytes);
2303
+ }
2304
+ break;
2305
+ default:
2306
+ throw this.logger.Error().Str("store", url.Ok().getParam("store" /* STORE */)).Msg("unexpected store").AsError();
2307
+ }
2308
+ if (fpMsg.isErr()) {
2309
+ throw this.logger.Error().Err(fpMsg).Msg("got error from FPMsg2Car").AsError();
2310
+ }
2311
+ const res = await this.gateway.put(this.sthis, url.Ok(), fpMsg.Ok(), this.loader);
1881
2312
  if (res.isErr()) {
1882
2313
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
1883
2314
  }
1884
2315
  return res.Ok();
1885
2316
  }
1886
2317
  async remove(cid) {
1887
- const url = await this.gateway.buildUrl(this.url(), cid.toString());
2318
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), cid.toString(), this.loader);
1888
2319
  if (url.isErr()) {
1889
2320
  return url;
1890
2321
  }
1891
- return this.gateway.delete(url.Ok());
2322
+ return this.gateway.delete(this.sthis, url.Ok(), this.loader);
1892
2323
  }
1893
2324
  async close() {
1894
- await this.gateway.close(this.url());
2325
+ await this.gateway.close(this.sthis, this.url(), this.loader);
1895
2326
  this._onClosed.forEach((fn) => fn());
1896
2327
  return Result5.Ok(void 0);
1897
2328
  }
1898
2329
  destroy() {
1899
- return this.gateway.destroy(this.url());
2330
+ this.logger.Debug().Msg("destroy");
2331
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
1900
2332
  }
1901
2333
  };
1902
2334
  var WALStoreImpl = class extends BaseStoreImpl {
1903
- constructor(loader, url, opts) {
1904
- super(loader.name, url, { ...opts }, loader.sthis, ensureLogger(loader.sthis, "WALStoreImpl"));
2335
+ constructor(sthis, url, opts) {
2336
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "WALStoreImpl"));
1905
2337
  this.storeType = "wal";
1906
- this._ready = new ResolveOnce3();
2338
+ // readonly tag: string = "rwal-base";
2339
+ // readonly loader: Loadable;
2340
+ this._ready = new ResolveOnce4();
1907
2341
  this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
1908
2342
  this.processing = void 0;
1909
2343
  this.processQueue = new CommitQueue();
1910
- this.loader = loader;
1911
2344
  }
1912
2345
  async ready() {
1913
2346
  return this._ready.once(async () => {
1914
2347
  const walState = await this.load().catch((e) => {
1915
- this.logger.Error().Any("error", e).Msg("error loading wal");
2348
+ this.logger.Error().Err(e).Msg("error loading wal");
1916
2349
  return void 0;
1917
2350
  });
1918
- if (!walState) {
1919
- this.walState.operations = [];
1920
- this.walState.fileOperations = [];
1921
- } else {
1922
- this.walState.operations = walState.operations || [];
1923
- this.walState.fileOperations = walState.fileOperations || [];
2351
+ this.walState.operations.splice(0, this.walState.operations.length);
2352
+ this.walState.fileOperations.splice(0, this.walState.fileOperations.length);
2353
+ if (walState) {
2354
+ this.walState.operations.push(...walState.operations);
2355
+ this.walState.fileOperations.push(...walState.fileOperations);
1924
2356
  }
1925
2357
  });
1926
2358
  }
1927
2359
  async enqueue(dbMeta, opts) {
1928
2360
  await this.ready();
1929
2361
  if (opts.compact) {
1930
- this.walState.operations = [];
1931
- this.walState.noLoaderOps = [dbMeta];
2362
+ this.walState.operations.splice(0, this.walState.operations.length);
2363
+ this.walState.noLoaderOps.splice(0, this.walState.noLoaderOps.length);
2364
+ this.walState.noLoaderOps.push(dbMeta);
1932
2365
  } else if (opts.noLoader) {
1933
2366
  this.walState.noLoaderOps.push(dbMeta);
1934
2367
  } else {
@@ -1958,6 +2391,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
1958
2391
  });
1959
2392
  }
1960
2393
  async _doProcess() {
2394
+ if (!this.loader) return;
1961
2395
  if (!this.loader.remoteCarStore) return;
1962
2396
  const operations = [...this.walState.operations];
1963
2397
  const noLoaderOps = [...this.walState.noLoaderOps];
@@ -1975,6 +2409,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
1975
2409
  noLoaderOps,
1976
2410
  async (dbMeta) => {
1977
2411
  await retryableUpload(async () => {
2412
+ if (!this.loader) {
2413
+ return;
2414
+ }
1978
2415
  for (const cid of dbMeta.cars) {
1979
2416
  const car = await (await this.loader.carStore()).load(cid);
1980
2417
  if (!car) {
@@ -1985,7 +2422,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
1985
2422
  await throwFalsy(this.loader.remoteCarStore).save(car);
1986
2423
  }
1987
2424
  }
1988
- this.walState.noLoaderOps = this.walState.noLoaderOps.filter((op) => op !== dbMeta);
2425
+ inplaceFilter(this.walState.noLoaderOps, (op) => op !== dbMeta);
1989
2426
  }, `noLoaderOp with dbMeta.cars=${dbMeta.cars.toString()}`);
1990
2427
  },
1991
2428
  { concurrency: concurrencyLimit }
@@ -1994,6 +2431,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
1994
2431
  operations,
1995
2432
  async (dbMeta) => {
1996
2433
  await retryableUpload(async () => {
2434
+ if (!this.loader) {
2435
+ return;
2436
+ }
1997
2437
  for (const cid of dbMeta.cars) {
1998
2438
  const car = await (await this.loader.carStore()).load(cid);
1999
2439
  if (!car) {
@@ -2004,7 +2444,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
2004
2444
  await throwFalsy(this.loader.remoteCarStore).save(car);
2005
2445
  }
2006
2446
  }
2007
- this.walState.operations = this.walState.operations.filter((op) => op !== dbMeta);
2447
+ inplaceFilter(this.walState.operations, (op) => op !== dbMeta);
2008
2448
  }, `operation with dbMeta.cars=${dbMeta.cars.toString()}`);
2009
2449
  },
2010
2450
  { concurrency: concurrencyLimit }
@@ -2013,12 +2453,15 @@ var WALStoreImpl = class extends BaseStoreImpl {
2013
2453
  fileOperations,
2014
2454
  async ({ cid: fileCid, public: publicFile }) => {
2015
2455
  await retryableUpload(async () => {
2456
+ if (!this.loader) {
2457
+ return;
2458
+ }
2016
2459
  const fileBlock = await (await this.loader.fileStore()).load(fileCid);
2017
2460
  if (!fileBlock) {
2018
2461
  throw this.logger.Error().Ref("cid", fileCid).Msg("missing file block").AsError();
2019
2462
  }
2020
2463
  await this.loader.remoteFileStore?.save(fileBlock, { public: publicFile });
2021
- this.walState.fileOperations = this.walState.fileOperations.filter((op) => op.cid !== fileCid);
2464
+ inplaceFilter(this.walState.fileOperations, (op) => op.cid !== fileCid);
2022
2465
  }, `fileOperation with cid=${fileCid.toString()}`);
2023
2466
  },
2024
2467
  { concurrency: concurrencyLimit }
@@ -2026,6 +2469,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
2026
2469
  if (operations.length) {
2027
2470
  const lastOp = operations[operations.length - 1];
2028
2471
  await retryableUpload(async () => {
2472
+ if (!this.loader) {
2473
+ return;
2474
+ }
2029
2475
  await this.loader.remoteMetaStore?.save(lastOp);
2030
2476
  }, `remoteMetaStore save with dbMeta.cars=${lastOp.cars.toString()}`);
2031
2477
  }
@@ -2038,251 +2484,715 @@ var WALStoreImpl = class extends BaseStoreImpl {
2038
2484
  }
2039
2485
  async load() {
2040
2486
  this.logger.Debug().Msg("loading");
2041
- const filepath = await this.gateway.buildUrl(this.url(), "main");
2487
+ const filepath = await this.gateway.buildUrl(this.sthis, this.url(), "main", this.loader);
2042
2488
  if (filepath.isErr()) {
2043
2489
  throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2044
2490
  }
2045
- const bytes = await this.gateway.get(filepath.Ok());
2491
+ const bytes = await this.gateway.get(this.sthis, filepath.Ok(), this.loader);
2046
2492
  if (bytes.isErr()) {
2047
2493
  if (isNotFoundError(bytes)) {
2048
2494
  return void 0;
2049
2495
  }
2050
2496
  throw this.logger.Error().Err(bytes.Err()).Msg("error get").AsError();
2051
2497
  }
2052
- try {
2053
- return bytes && parse2(this.sthis.txt.decode(bytes.Ok()));
2054
- } catch (e) {
2055
- throw this.logger.Error().Err(e).Msg("error parse").AsError();
2498
+ if (bytes.Ok().type !== "wal") {
2499
+ throw this.logger.Error().Str("type", bytes.Ok().type).Msg("unexpected type").AsError();
2500
+ }
2501
+ return bytes.Ok().payload;
2502
+ }
2503
+ async save(state) {
2504
+ const filepath = await this.gateway.buildUrl(this.sthis, this.url(), "main", this.loader);
2505
+ if (filepath.isErr()) {
2506
+ throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2507
+ }
2508
+ const res = await this.gateway.put(
2509
+ this.sthis,
2510
+ filepath.Ok(),
2511
+ {
2512
+ type: "wal",
2513
+ payload: state
2514
+ },
2515
+ this.loader
2516
+ );
2517
+ if (res.isErr()) {
2518
+ throw this.logger.Error().Err(res.Err()).Str("filePath", filepath.Ok().toString()).Msg("error saving").AsError();
2519
+ }
2520
+ }
2521
+ async close() {
2522
+ await this.gateway.close(this.sthis, this.url(), this.loader);
2523
+ this._onClosed.forEach((fn) => fn());
2524
+ return Result5.Ok(void 0);
2525
+ }
2526
+ destroy() {
2527
+ this.logger.Debug().Msg("destroy");
2528
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
2529
+ }
2530
+ };
2531
+
2532
+ // src/blockstore/register-store-protocol.ts
2533
+ import { BuildURI, runtimeFn as runtimeFn4 } from "@adviser/cement";
2534
+
2535
+ // src/runtime/gateways/file/version.ts
2536
+ var FILESTORE_VERSION = "v0.19-file";
2537
+
2538
+ // src/runtime/gateways/memory/gateway.ts
2539
+ import { Result as Result6 } from "@adviser/cement";
2540
+
2541
+ // src/runtime/gateways/memory/version.ts
2542
+ var MEMORY_VERSION = "v0.19-memory";
2543
+
2544
+ // src/runtime/gateways/memory/gateway.ts
2545
+ var MemoryGateway = class {
2546
+ constructor(sthis, memorys) {
2547
+ this.memorys = memorys;
2548
+ this.sthis = sthis;
2549
+ }
2550
+ buildUrl(baseUrl, key) {
2551
+ return Promise.resolve(Result6.Ok(baseUrl.build().setParam("key" /* KEY */, key).URI()));
2552
+ }
2553
+ start(baseUrl) {
2554
+ return Promise.resolve(Result6.Ok(baseUrl.build().setParam("version" /* VERSION */, MEMORY_VERSION).URI()));
2555
+ }
2556
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2557
+ close(baseUrl) {
2558
+ return Promise.resolve(Result6.Ok(void 0));
2559
+ }
2560
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2561
+ destroy(baseUrl) {
2562
+ this.memorys.clear();
2563
+ return Promise.resolve(Result6.Ok(void 0));
2564
+ }
2565
+ async put(url, bytes) {
2566
+ this.memorys.set(url.toString(), bytes);
2567
+ return Result6.Ok(void 0);
2568
+ }
2569
+ // get could return a NotFoundError if the key is not found
2570
+ get(url) {
2571
+ const x = this.memorys.get(url.toString());
2572
+ if (!x) {
2573
+ return Promise.resolve(Result6.Err(new NotFoundError("not found")));
2574
+ }
2575
+ return Promise.resolve(Result6.Ok(x));
2576
+ }
2577
+ delete(url) {
2578
+ this.memorys.delete(url.toString());
2579
+ return Promise.resolve(Result6.Ok(void 0));
2580
+ }
2581
+ async getPlain(url, key) {
2582
+ const x = this.memorys.get(url.build().setParam("key" /* KEY */, key).toString());
2583
+ if (!x) {
2584
+ return Result6.Err(new NotFoundError("not found"));
2056
2585
  }
2586
+ return Result6.Ok(x);
2587
+ }
2588
+ };
2589
+
2590
+ // src/runtime/index.ts
2591
+ var runtime_exports = {};
2592
+ __export(runtime_exports, {
2593
+ FILESTORE_VERSION: () => FILESTORE_VERSION,
2594
+ INDEXDB_VERSION: () => INDEXDB_VERSION,
2595
+ KeyBag: () => KeyBag,
2596
+ defaultKeyBagOpts: () => defaultKeyBagOpts,
2597
+ defaultKeyBagUrl: () => defaultKeyBagUrl,
2598
+ files: () => files_exports,
2599
+ getFileName: () => getFileName,
2600
+ getKeyBag: () => getKeyBag,
2601
+ getPath: () => getPath,
2602
+ gw: () => gateways_exports,
2603
+ kb: () => key_bag_exports,
2604
+ kc: () => keyed_crypto_exports,
2605
+ mf: () => wait_pr_multiformats_exports,
2606
+ registerKeyBagProviderFactory: () => registerKeyBagProviderFactory,
2607
+ runtimeFn: () => runtimeFn3
2608
+ });
2609
+
2610
+ // src/runtime/gateways/file/utils.ts
2611
+ import { getStore as getStore2 } from "@fireproof/core";
2612
+ function getPath(url, sthis) {
2613
+ const basePath = url.pathname;
2614
+ const name = url.getParam("name");
2615
+ if (name) {
2616
+ return sthis.pathOps.join(basePath, name);
2617
+ }
2618
+ return sthis.pathOps.join(basePath);
2619
+ }
2620
+ function getFileName(url, sthis) {
2621
+ const key = url.getParam("key");
2622
+ if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
2623
+ const res = getStore2(url, sthis, (...a) => a.join("-"));
2624
+ switch (res.store) {
2625
+ case "data":
2626
+ return sthis.pathOps.join(res.name, key + ".car");
2627
+ case "wal":
2628
+ case "meta":
2629
+ return sthis.pathOps.join(res.name, key + ".json");
2630
+ default:
2631
+ throw sthis.logger.Error().Url(url).Msg(`unsupported store type`).AsError();
2632
+ }
2633
+ }
2634
+
2635
+ // src/runtime/wait-pr-multiformats/index.ts
2636
+ var wait_pr_multiformats_exports = {};
2637
+ __export(wait_pr_multiformats_exports, {
2638
+ block: () => block_exports,
2639
+ codec: () => codec_interface_exports
2640
+ });
2641
+
2642
+ // src/runtime/wait-pr-multiformats/codec-interface.ts
2643
+ var codec_interface_exports = {};
2644
+
2645
+ // src/runtime/index.ts
2646
+ import { runtimeFn as runtimeFn3 } from "@adviser/cement";
2647
+
2648
+ // src/runtime/gateways/index.ts
2649
+ var gateways_exports = {};
2650
+ __export(gateways_exports, {
2651
+ file: () => file_exports,
2652
+ fpDeserialize: () => fpDeserialize,
2653
+ fpSerialize: () => fpSerialize
2654
+ });
2655
+
2656
+ // src/runtime/gateways/fp-envelope-serialize.ts
2657
+ import { exception2Result as exception2Result2, Result as Result7 } from "@adviser/cement";
2658
+ import { decodeEventBlock, EventBlock as EventBlock2 } from "@fireproof/vendor/@web3-storage/pail/clock";
2659
+ import { base64pad } from "multiformats/bases/base64";
2660
+ import { CID as CID2 } from "multiformats";
2661
+ import { fromJSON } from "multiformats/link";
2662
+ import { format as format2, parse } from "@fireproof/vendor/@ipld/dag-json";
2663
+ async function dbMetaEvent2Serialized(sthis, dbEvents) {
2664
+ return await Promise.all(
2665
+ dbEvents.map(async (dbEvent) => {
2666
+ const event = await EventBlock2.create(
2667
+ {
2668
+ dbMeta: sthis.txt.encode(format2(dbEvent.dbMeta))
2669
+ },
2670
+ dbEvent.parents
2671
+ );
2672
+ return {
2673
+ cid: event.cid.toString(),
2674
+ parents: dbEvent.parents.map((i) => i.toString()),
2675
+ data: base64pad.encode(event.bytes)
2676
+ };
2677
+ })
2678
+ );
2679
+ }
2680
+ function WALState2Serialized(sthis, wal) {
2681
+ const serializedWAL = {
2682
+ fileOperations: wal.fileOperations.map((fop) => ({
2683
+ cid: fop.cid.toString(),
2684
+ public: fop.public
2685
+ })),
2686
+ noLoaderOps: wal.noLoaderOps.map((nop) => ({
2687
+ cars: nop.cars.map((i) => i.toString())
2688
+ })),
2689
+ operations: wal.operations.map((op) => ({
2690
+ cars: op.cars.map((i) => i.toString())
2691
+ }))
2692
+ };
2693
+ return serializedWAL;
2694
+ }
2695
+ var defaultEncoder = {
2696
+ car: async (sthis, payload) => Result7.Ok(payload),
2697
+ file: async (sthis, payload) => Result7.Ok(payload),
2698
+ meta: async (sthis, payload) => Result7.Ok(sthis.txt.encode(JSON.stringify(payload))),
2699
+ wal: async (sthis, payload) => Result7.Ok(sthis.txt.encode(JSON.stringify(payload)))
2700
+ };
2701
+ async function fpSerialize(sthis, env, pencoder) {
2702
+ const encoder = {
2703
+ ...defaultEncoder,
2704
+ ...pencoder
2705
+ };
2706
+ switch (env.type) {
2707
+ case "file" /* FILE */:
2708
+ return encoder.file(sthis, env.payload);
2709
+ case "car" /* CAR */:
2710
+ return encoder.car(sthis, env.payload);
2711
+ case "wal" /* WAL */:
2712
+ return encoder.wal(sthis, WALState2Serialized(sthis, env.payload));
2713
+ case "meta" /* META */:
2714
+ return encoder.meta(sthis, await dbMetaEvent2Serialized(sthis, env.payload));
2715
+ default:
2716
+ throw sthis.logger.Error().Str("type", env.type).Msg("unsupported store").AsError();
2717
+ }
2718
+ }
2719
+ async function decode2DbMetaEvents(sthis, rserializedMeta) {
2720
+ if (rserializedMeta.isErr()) {
2721
+ return Result7.Err(rserializedMeta.Err());
2722
+ }
2723
+ const serializedMeta = rserializedMeta.unwrap();
2724
+ if (!Array.isArray(serializedMeta)) {
2725
+ return sthis.logger.Debug().Any("metaEntries", serializedMeta).Msg("No data in MetaEntries").ResultError();
2726
+ }
2727
+ if (!serializedMeta.length) {
2728
+ return sthis.logger.Debug().Msg("No MetaEntries found").ResultError();
2729
+ }
2730
+ return Result7.Ok(
2731
+ await Promise.all(
2732
+ serializedMeta.map(async (metaEntry) => {
2733
+ const eventBlock = await decodeEventBlock(base64pad.decode(metaEntry.data));
2734
+ const dbMeta = parse(sthis.txt.decode(eventBlock.value.data.dbMeta));
2735
+ return {
2736
+ eventCid: eventBlock.cid,
2737
+ parents: metaEntry.parents.map((i) => CID2.parse(i)),
2738
+ dbMeta
2739
+ };
2740
+ })
2741
+ )
2742
+ );
2743
+ }
2744
+ function toCid(sthis, link) {
2745
+ if (typeof link === "string") {
2746
+ return CID2.parse(link);
2747
+ }
2748
+ return fromJSON(link);
2749
+ }
2750
+ async function decode2WalState(sthis, rserializedWAL) {
2751
+ if (rserializedWAL.isErr()) {
2752
+ return Result7.Err(rserializedWAL.Err());
2753
+ }
2754
+ const serializedWAL = rserializedWAL.unwrap();
2755
+ return Result7.Ok({
2756
+ fileOperations: (serializedWAL.fileOperations || []).map((fop) => ({
2757
+ cid: toCid(sthis, fop.cid),
2758
+ public: !!fop.public
2759
+ })),
2760
+ noLoaderOps: (serializedWAL.noLoaderOps || []).map((nop) => ({
2761
+ cars: (nop.cars || []).map((i) => toCid(sthis, i))
2762
+ })),
2763
+ operations: (serializedWAL.operations || []).map((op) => ({
2764
+ cars: (op.cars || []).map((i) => toCid(sthis, i))
2765
+ }))
2766
+ });
2767
+ }
2768
+ var defaultDecoder = {
2769
+ car: async (sthis, payload) => Result7.Ok(payload),
2770
+ file: async (sthis, payload) => Result7.Ok(payload),
2771
+ meta: async (sthis, payload) => exception2Result2(() => JSON.parse(sthis.txt.decode(payload))),
2772
+ wal: async (sthis, payload) => exception2Result2(() => JSON.parse(sthis.txt.decode(payload)))
2773
+ };
2774
+ function makeFPEnvelope(type, payload) {
2775
+ if (payload.isErr()) {
2776
+ return Result7.Err(payload.Err());
2777
+ }
2778
+ return Result7.Ok({
2779
+ type,
2780
+ payload: payload.unwrap()
2781
+ });
2782
+ }
2783
+ async function fpDeserialize(sthis, url, intoRaw, pdecoder) {
2784
+ const rraw = await coercePromiseIntoUint8(intoRaw);
2785
+ if (rraw.isErr()) {
2786
+ return Result7.Err(rraw.Err());
2787
+ }
2788
+ const raw2 = rraw.unwrap();
2789
+ const decoder = {
2790
+ ...defaultDecoder,
2791
+ ...pdecoder
2792
+ };
2793
+ switch (url.getParam("store" /* STORE */)) {
2794
+ case "data":
2795
+ if (url.getParam("suffix" /* SUFFIX */) === ".car") {
2796
+ return makeFPEnvelope("car" /* CAR */, await decoder.car(sthis, raw2));
2797
+ }
2798
+ return makeFPEnvelope("file" /* FILE */, await decoder.file(sthis, raw2));
2799
+ case "wal":
2800
+ return makeFPEnvelope("wal" /* WAL */, await decode2WalState(sthis, await decoder.wal(sthis, raw2)));
2801
+ case "meta":
2802
+ return makeFPEnvelope("meta" /* META */, await decode2DbMetaEvents(sthis, await decoder.meta(sthis, raw2)));
2803
+ default:
2804
+ return sthis.logger.Error().Str("store", url.getParam("store" /* STORE */)).Msg("unsupported store").ResultError();
2805
+ }
2806
+ }
2807
+
2808
+ // src/runtime/gateways/file/index.ts
2809
+ var file_exports = {};
2810
+ __export(file_exports, {
2811
+ KeyBagProviderFile: () => KeyBagProviderFile,
2812
+ sysFileSystemFactory: () => sysFileSystemFactory
2813
+ });
2814
+
2815
+ // src/runtime/gateways/indexdb/version.ts
2816
+ var INDEXDB_VERSION = "v0.19-indexdb";
2817
+
2818
+ // src/runtime/gateways/file/gateway-impl.ts
2819
+ import { exception2Result as exception2Result3, KeyedResolvOnce as KeyedResolvOnce2, Result as Result8 } from "@adviser/cement";
2820
+ var versionFiles = new KeyedResolvOnce2();
2821
+ var FileGateway = class {
2822
+ constructor(sthis, fs) {
2823
+ this.fs = fs;
2824
+ }
2825
+ async getVersionFromFile(path, sthis) {
2826
+ return versionFiles.get(path).once(async () => {
2827
+ await this.fs.mkdir(path, { recursive: true });
2828
+ const vFile = sthis.pathOps.join(path, "version");
2829
+ const vFileStat = await this.fs.stat(vFile).catch(() => void 0);
2830
+ if (!vFileStat) {
2831
+ await this.fs.writefile(sthis.pathOps.join(path, "version"), FILESTORE_VERSION);
2832
+ return FILESTORE_VERSION;
2833
+ } else if (!vFileStat.isFile()) {
2834
+ throw sthis.logger.Error().Str("file", vFile).Msg(`version file is a directory`).AsError();
2835
+ }
2836
+ const v = await this.fs.readfile(vFile);
2837
+ const vStr = sthis.txt.decode(v);
2838
+ if (vStr !== FILESTORE_VERSION) {
2839
+ sthis.logger.Warn().Str("file", vFile).Str("from", vStr).Str("expected", FILESTORE_VERSION).Msg(`version mismatch`);
2840
+ }
2841
+ return vStr;
2842
+ });
2843
+ }
2844
+ start(baseURL, sthis) {
2845
+ return exception2Result3(async () => {
2846
+ await this.fs.start();
2847
+ const url = baseURL.build();
2848
+ url.defParam("version" /* VERSION */, FILESTORE_VERSION);
2849
+ const dbUrl = await this.buildUrl(url.URI(), "dummy");
2850
+ const dbdirFile = this.getFilePath(dbUrl.Ok(), sthis);
2851
+ await this.fs.mkdir(sthis.pathOps.dirname(dbdirFile), { recursive: true });
2852
+ const dbroot = sthis.pathOps.dirname(dbdirFile);
2853
+ sthis.logger.Debug().Url(url.URI()).Str("dbroot", dbroot).Msg("start");
2854
+ url.setParam("version" /* VERSION */, await this.getVersionFromFile(dbroot, sthis));
2855
+ return url.URI();
2856
+ });
2857
+ }
2858
+ async buildUrl(baseUrl, key) {
2859
+ return Result8.Ok(baseUrl.build().setParam("key" /* KEY */, key).URI());
2860
+ }
2861
+ async close() {
2862
+ return Result8.Ok(void 0);
2863
+ }
2864
+ getFilePath(url, sthis) {
2865
+ const key = url.getParam("key" /* KEY */);
2866
+ if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
2867
+ return sthis.pathOps.join(getPath(url, sthis), getFileName(url, sthis));
2868
+ }
2869
+ async put(url, bytes, sthis) {
2870
+ return exception2Result3(async () => {
2871
+ const file = await this.getFilePath(url, sthis);
2872
+ sthis.logger.Debug().Str("url", url.toString()).Str("file", file).Msg("put");
2873
+ await this.fs.writefile(file, bytes);
2874
+ });
2875
+ }
2876
+ async get(url, sthis) {
2877
+ return exceptionWrapper(async () => {
2878
+ const file = this.getFilePath(url, sthis);
2879
+ try {
2880
+ sthis.logger.Debug().Url(url).Str("file", file).Msg("get");
2881
+ const res = await this.fs.readfile(file);
2882
+ return Result8.Ok(res);
2883
+ } catch (e) {
2884
+ if (isNotFoundError(e)) {
2885
+ return Result8.Err(new NotFoundError(`file not found: ${file}`));
2886
+ }
2887
+ return Result8.Err(e);
2888
+ }
2889
+ });
2057
2890
  }
2058
- async save(state) {
2059
- const filepath = await this.gateway.buildUrl(this.url(), "main");
2060
- if (filepath.isErr()) {
2061
- throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2062
- }
2063
- let encoded;
2891
+ async delete(url, sthis) {
2892
+ return exception2Result3(async () => {
2893
+ await this.fs.unlink(this.getFilePath(url, sthis));
2894
+ });
2895
+ }
2896
+ async destroy(baseURL, sthis) {
2897
+ const url = await this.buildUrl(baseURL, "x");
2898
+ if (url.isErr()) return url;
2899
+ const filepath = sthis.pathOps.dirname(this.getFilePath(url.Ok(), sthis));
2900
+ let files = [];
2064
2901
  try {
2065
- encoded = format2(state);
2902
+ files = await this.fs.readdir(filepath);
2066
2903
  } catch (e) {
2067
- throw this.logger.Error().Err(e).Any("state", state).Msg("error format").AsError();
2904
+ if (!isNotFoundError(e)) {
2905
+ throw sthis.logger.Error().Err(e).Str("dir", filepath).Msg("destroy:readdir").AsError();
2906
+ }
2068
2907
  }
2069
- const res = await this.gateway.put(filepath.Ok(), this.sthis.txt.encode(encoded));
2070
- if (res.isErr()) {
2071
- throw this.logger.Error().Err(res.Err()).Str("filePath", filepath.Ok().toString()).Msg("error saving").AsError();
2908
+ for (const file of files) {
2909
+ const pathed = sthis.pathOps.join(filepath, file);
2910
+ try {
2911
+ await this.fs.unlink(pathed);
2912
+ } catch (e) {
2913
+ if (!isNotFoundError(e)) {
2914
+ throw sthis.logger.Error().Err(e).Str("file", pathed).Msg("destroy:unlink").AsError();
2915
+ }
2916
+ }
2072
2917
  }
2918
+ return Result8.Ok(void 0);
2073
2919
  }
2074
- async close() {
2075
- await this.gateway.close(this.url());
2076
- this._onClosed.forEach((fn) => fn());
2077
- return Result5.Ok(void 0);
2078
- }
2079
- destroy() {
2080
- return this.gateway.destroy(this.url());
2920
+ async getPlain(iurl, key, sthis) {
2921
+ const url = iurl.build().setParam("key" /* KEY */, key).URI();
2922
+ const dbFile = sthis.pathOps.join(getPath(url, sthis), getFileName(url, sthis));
2923
+ sthis.logger.Debug().Url(url).Str("dbFile", dbFile).Msg("get");
2924
+ const buffer = await this.fs.readfile(dbFile);
2925
+ sthis.logger.Debug().Url(url).Str("dbFile", dbFile).Len(buffer).Msg("got");
2926
+ return Result8.Ok(buffer);
2081
2927
  }
2082
2928
  };
2083
2929
 
2084
- // src/blockstore/store-factory.ts
2085
- function ensureIsIndex(url, isIndex) {
2086
- if (isIndex) {
2087
- return url.build().setParam("index", isIndex).URI();
2930
+ // src/runtime/gateways/def-serde-gateway.ts
2931
+ import { Result as Result9 } from "@adviser/cement";
2932
+ var DefSerdeGateway = class {
2933
+ constructor(gw) {
2934
+ this.gw = gw;
2088
2935
  }
2089
- return url.build().delParam("index").URI();
2090
- }
2091
- function ensureName(name, url) {
2092
- if (!url.hasParam("name")) {
2093
- return url.build().setParam("name", name).URI();
2936
+ start(sthis, baseURL) {
2937
+ return this.gw.start(baseURL, sthis);
2094
2938
  }
2095
- return url;
2096
- }
2939
+ async buildUrl(sthis, baseUrl, key) {
2940
+ return this.gw.buildUrl(baseUrl, key, sthis);
2941
+ }
2942
+ async close(sthis, uri) {
2943
+ return this.gw.close(uri, sthis);
2944
+ }
2945
+ async put(sthis, url, env) {
2946
+ const rUint8 = await fpSerialize(sthis, env);
2947
+ if (rUint8.isErr()) return rUint8;
2948
+ return this.gw.put(url, rUint8.Ok(), sthis);
2949
+ }
2950
+ async get(sthis, url) {
2951
+ const res = await this.gw.get(url, sthis);
2952
+ if (res.isErr()) return Result9.Err(res.Err());
2953
+ return fpDeserialize(sthis, url, res);
2954
+ }
2955
+ async delete(sthis, url) {
2956
+ return this.gw.delete(url, sthis);
2957
+ }
2958
+ async destroy(sthis, baseURL) {
2959
+ return this.gw.destroy(baseURL, sthis);
2960
+ }
2961
+ async getPlain(sthis, iurl, key) {
2962
+ return this.gw.getPlain(iurl, key, sthis);
2963
+ }
2964
+ };
2965
+
2966
+ // src/blockstore/register-store-protocol.ts
2097
2967
  var storeFactory = /* @__PURE__ */ new Map();
2098
- function buildURL(optURL, loader) {
2099
- const storeOpts = loader.ebOpts.store;
2100
- const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
2101
- let obuUrl;
2102
- if (obuItem && obuItem.overrideBaseURL) {
2103
- obuUrl = URI5.from(obuItem.overrideBaseURL);
2104
- }
2105
- const ret = ensureIsIndex(
2106
- URI5.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
2107
- storeOpts.isIndex
2108
- );
2109
- return ret;
2110
- }
2111
- var onceGateway = new KeyedResolvOnce2();
2112
- async function getGatewayFromURL(url, sthis) {
2113
- return onceGateway.get(url.toString()).once(async () => {
2114
- const item = storeFactory.get(url.protocol);
2115
- if (item) {
2116
- const ret = {
2117
- gateway: await item.gateway(sthis),
2118
- test: await item.test(sthis)
2119
- };
2120
- const res = await ret.gateway.start(url);
2121
- if (res.isErr()) {
2122
- sthis.logger.Error().Result("start", res).Msg("start failed");
2123
- return void 0;
2124
- }
2125
- return ret;
2968
+ function getDefaultURI(sthis, protocol) {
2969
+ if (protocol) {
2970
+ if (!protocol.endsWith(":")) {
2971
+ protocol += ":";
2126
2972
  }
2127
- sthis.logger.Warn().Url(url).Msg("unsupported protocol");
2128
- return void 0;
2129
- });
2973
+ const gfi = storeFactory.get(protocol);
2974
+ if (gfi) {
2975
+ return gfi.defaultURI(sthis);
2976
+ }
2977
+ }
2978
+ const found = Array.from(storeFactory.values()).find((item) => item.isDefault);
2979
+ if (!found) {
2980
+ throw sthis.logger.Error().Msg("no default found").AsError();
2981
+ }
2982
+ return found.defaultURI(sthis);
2130
2983
  }
2131
2984
  function registerStoreProtocol(item) {
2132
2985
  let protocol = item.protocol;
2133
2986
  if (!protocol.endsWith(":")) {
2134
2987
  protocol += ":";
2135
2988
  }
2136
- if (storeFactory.has(protocol)) {
2137
- if (!item.overrideBaseURL && storeFactory.get(protocol) !== item) {
2138
- throw new Error(`we need a logger here`);
2139
- return () => {
2140
- };
2141
- }
2989
+ if (!item.serdegateway && !item.gateway) {
2990
+ throw new Error(`registerStoreProtocol needs a gateway or serdegateway`);
2142
2991
  }
2143
- if (item.overrideBaseURL) {
2992
+ let serdegateway;
2993
+ if (item.gateway) {
2994
+ serdegateway = async (sthis) => {
2995
+ const m = await item.gateway(sthis);
2996
+ return new DefSerdeGateway(m);
2997
+ };
2998
+ } else {
2999
+ serdegateway = item.serdegateway;
3000
+ }
3001
+ if (item.isDefault) {
2144
3002
  Array.from(storeFactory.values()).forEach((items) => {
2145
- items.overrideBaseURL = void 0;
3003
+ items.isDefault = false;
2146
3004
  });
2147
3005
  }
2148
- storeFactory.set(protocol, item);
3006
+ storeFactory.set(protocol, {
3007
+ ...item,
3008
+ serdegateway
3009
+ });
2149
3010
  return () => {
2150
3011
  storeFactory.delete(protocol);
2151
3012
  };
2152
3013
  }
2153
- var onceDataStoreFactory = new KeyedResolvOnce2();
2154
- async function dataStoreFactory(loader) {
2155
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
2156
- const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
2157
- return onceDataStoreFactory.get(url.toString()).once(async () => {
2158
- const gateway = await getGatewayFromURL(url, sthis);
2159
- if (!gateway) {
2160
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
3014
+ function getGatewayFactoryItem(protocol) {
3015
+ return storeFactory.get(protocol);
3016
+ }
3017
+ function defaultGatewayFactoryItem() {
3018
+ const found = Array.from(storeFactory.values()).find((item) => item.isDefault);
3019
+ if (!found) {
3020
+ throw new Error("no default found");
3021
+ }
3022
+ return found;
3023
+ }
3024
+ function defaultURI(sthis) {
3025
+ const rt = runtimeFn4();
3026
+ return 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();
3027
+ }
3028
+ if (runtimeFn4().isNodeIsh || runtimeFn4().isDeno) {
3029
+ registerStoreProtocol({
3030
+ protocol: "file:",
3031
+ isDefault: true,
3032
+ defaultURI,
3033
+ gateway: async (sthis) => {
3034
+ return new FileGateway(sthis, await sysFileSystemFactory(defaultURI(sthis)));
2161
3035
  }
2162
- const store = new DataStoreImpl(sthis, loader.name, url, {
2163
- gateway: gateway.gateway,
2164
- keybag: () => getKeyBag(loader.sthis, {
2165
- ...loader.ebOpts.keyBag
2166
- })
2167
- });
2168
- return store;
2169
3036
  });
2170
3037
  }
2171
- var onceMetaStoreFactory = new KeyedResolvOnce2();
2172
- async function metaStoreFactory(loader) {
2173
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
2174
- const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
2175
- return onceMetaStoreFactory.get(url.toString()).once(async () => {
2176
- sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
2177
- const gateway = await getGatewayFromURL(url, sthis);
2178
- if (!gateway) {
2179
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2180
- }
2181
- const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
2182
- gateway: gateway.gateway,
2183
- keybag: () => getKeyBag(loader.sthis, {
2184
- ...loader.ebOpts.keyBag
2185
- })
2186
- });
2187
- return store;
3038
+ if (runtimeFn4().isBrowser) {
3039
+ registerStoreProtocol({
3040
+ protocol: "indexdb:",
3041
+ isDefault: true,
3042
+ defaultURI: () => {
3043
+ return BuildURI.from("indexdb://").pathname("fp").setParam("version" /* VERSION */, INDEXDB_VERSION).setParam("runtime" /* RUNTIME */, "browser").URI();
3044
+ },
3045
+ gateway: async () => {
3046
+ const { GatewayImpl } = await import("@fireproof/core/web");
3047
+ return new GatewayImpl();
3048
+ }
2188
3049
  });
2189
3050
  }
2190
- var onceRemoteWalFactory = new KeyedResolvOnce2();
2191
- async function remoteWalFactory(loader) {
2192
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
2193
- const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
2194
- return onceRemoteWalFactory.get(url.toString()).once(async () => {
2195
- const gateway = await getGatewayFromURL(url, sthis);
2196
- if (!gateway) {
2197
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2198
- }
2199
- sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
2200
- const store = new WALStoreImpl(loader, url, {
2201
- gateway: gateway.gateway,
2202
- keybag: () => getKeyBag(loader.sthis, {
2203
- ...loader.ebOpts.keyBag
2204
- })
2205
- });
2206
- return store;
3051
+ var memory = /* @__PURE__ */ new Map();
3052
+ registerStoreProtocol({
3053
+ protocol: "memory:",
3054
+ isDefault: false,
3055
+ defaultURI: () => {
3056
+ return BuildURI.from("memory://").pathname("ram").URI();
3057
+ },
3058
+ gateway: async (sthis) => {
3059
+ return new MemoryGateway(sthis, memory);
3060
+ }
3061
+ });
3062
+
3063
+ // src/blockstore/store-factory.ts
3064
+ var onceGateway = new KeyedResolvOnce3();
3065
+ var gatewayInstances = new KeyedResolvOnce3();
3066
+ async function getStartedGateway(sthis, url) {
3067
+ return onceGateway.get(url.toString()).once(async () => {
3068
+ const item = getGatewayFactoryItem(url.protocol);
3069
+ if (item) {
3070
+ const ret = {
3071
+ url,
3072
+ ...await gatewayInstances.get(url.protocol).once(async () => ({})),
3073
+ gateway: await item.serdegateway(sthis)
3074
+ };
3075
+ const res = await ret.gateway.start(sthis, url);
3076
+ if (res.isErr()) {
3077
+ return Result10.Err(sthis.logger.Error().Result("start", res).Msg("start failed").AsError());
3078
+ }
3079
+ ret.url = res.Ok();
3080
+ return Result10.Ok(ret);
3081
+ }
3082
+ return Result10.Err(sthis.logger.Warn().Url(url).Msg("unsupported protocol").AsError());
2207
3083
  });
2208
3084
  }
2209
- async function testStoreFactory(url, sthis) {
2210
- sthis = ensureSuperLog(sthis, "testStoreFactory");
2211
- const gateway = await getGatewayFromURL(url, sthis);
2212
- if (!gateway) {
2213
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2214
- }
2215
- return gateway.test;
3085
+ async function dataStoreFactory(sfi) {
3086
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "data").URI();
3087
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3088
+ if (rgateway.isErr()) {
3089
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3090
+ }
3091
+ const gateway = rgateway.Ok();
3092
+ const store = new DataStoreImpl(sfi.sthis, gateway.url, {
3093
+ gateway: gateway.gateway,
3094
+ gatewayInterceptor: sfi.gatewayInterceptor,
3095
+ loader: sfi.loader
3096
+ });
3097
+ return store;
3098
+ }
3099
+ async function metaStoreFactory(sfi) {
3100
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "meta").URI();
3101
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3102
+ if (rgateway.isErr()) {
3103
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3104
+ }
3105
+ const gateway = rgateway.Ok();
3106
+ const store = new MetaStoreImpl(sfi.sthis, gateway.url, {
3107
+ gateway: gateway.gateway,
3108
+ gatewayInterceptor: sfi.gatewayInterceptor,
3109
+ loader: sfi.loader
3110
+ });
3111
+ return store;
3112
+ }
3113
+ async function WALStoreFactory(sfi) {
3114
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "wal").URI();
3115
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3116
+ if (rgateway.isErr()) {
3117
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3118
+ }
3119
+ const gateway = rgateway.Ok();
3120
+ const store = new WALStoreImpl(sfi.sthis, gateway.url, {
3121
+ gateway: gateway.gateway,
3122
+ gatewayInterceptor: sfi.gatewayInterceptor,
3123
+ loader: sfi.loader
3124
+ });
3125
+ return store;
2216
3126
  }
2217
- async function ensureStart(store, logger) {
3127
+ async function ensureStart(store) {
2218
3128
  const ret = await store.start();
2219
3129
  if (ret.isErr()) {
2220
- throw logger.Error().Result("start", ret).Msg("start failed").AsError();
3130
+ throw store.logger.Error().Result("start", ret).Msg("start failed").AsError();
2221
3131
  }
2222
- logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
3132
+ store.logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
2223
3133
  return store;
2224
3134
  }
2225
- function toStoreRuntime(opts, sthis) {
2226
- const logger = ensureLogger(sthis, "toStoreRuntime", {});
3135
+ function ensureStoreEnDeFile(ende) {
3136
+ ende = ende || {};
2227
3137
  return {
2228
- makeMetaStore: async (loader) => {
2229
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeMetaStore).Msg("makeMetaStore");
2230
- return ensureStart(await (loader.ebOpts.store.makeMetaStore || metaStoreFactory)(loader), logger);
2231
- },
2232
- makeDataStore: async (loader) => {
2233
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeDataStore).Msg("makeDataStore");
2234
- return ensureStart(await (loader.ebOpts.store.makeDataStore || dataStoreFactory)(loader), logger);
2235
- },
2236
- makeWALStore: async (loader) => {
2237
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeWALStore).Msg("makeRemoteWAL");
2238
- return ensureStart(await (loader.ebOpts.store.makeWALStore || remoteWalFactory)(loader), logger);
2239
- },
2240
- encodeFile: opts.encodeFile || encodeFile,
2241
- decodeFile: opts.decodeFile || decodeFile
3138
+ encodeFile: ende.encodeFile || encodeFile,
3139
+ decodeFile: ende.decodeFile || decodeFile
3140
+ };
3141
+ }
3142
+ function toStoreRuntime(sthis, endeOpts = {}) {
3143
+ return {
3144
+ makeMetaStore: async (sfi) => ensureStart(await metaStoreFactory(sfi)),
3145
+ // async (loader: Loadable) => {
3146
+ // logger
3147
+ // .Debug()
3148
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeMetaStore)
3149
+ // .Msg("makeMetaStore");
3150
+ // return ensureStart(await (endeOpts.func?.makeMetaStore || metaStoreFactory)(loader), logger);
3151
+ // },
3152
+ makeDataStore: async (sfi) => ensureStart(await dataStoreFactory(sfi)),
3153
+ // async (loader: Loadable) => {
3154
+ // logger
3155
+ // .Debug()
3156
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeDataStore)
3157
+ // .Msg("makeDataStore");
3158
+ // return ensureStart(await (endeOpts.func?.makeDataStore || dataStoreFactory)(loader), logger);
3159
+ // },
3160
+ makeWALStore: async (sfi) => ensureStart(await WALStoreFactory(sfi)),
3161
+ // async (loader: Loadable) => {
3162
+ // logger
3163
+ // .Debug()
3164
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeWALStore)
3165
+ // .Msg("makeRemoteWAL");
3166
+ // return ensureStart(await (endeOpts.func?.makeWALStore || remoteWalFactory)(loader), logger);
3167
+ // },
3168
+ ...ensureStoreEnDeFile(endeOpts)
2242
3169
  };
2243
3170
  }
2244
- registerStoreProtocol({
2245
- protocol: "file:",
2246
- gateway: async (sthis) => {
2247
- const { FileGateway } = await import("./gateway-VVS4QWDA.js");
2248
- return new FileGateway(sthis);
2249
- },
2250
- test: async (sthis) => {
2251
- const { FileTestStore } = await import("./gateway-VVS4QWDA.js");
2252
- return new FileTestStore(sthis);
2253
- }
2254
- });
2255
- registerStoreProtocol({
2256
- protocol: "indexdb:",
2257
- gateway: async (sthis) => {
2258
- const { IndexDBGateway } = await import("./gateway-C62S56GY.js");
2259
- return new IndexDBGateway(sthis);
2260
- },
2261
- test: async (sthis) => {
2262
- const { IndexDBTestStore } = await import("./gateway-C62S56GY.js");
2263
- return new IndexDBTestStore(sthis);
2264
- }
2265
- });
2266
3171
 
2267
3172
  // src/blockstore/store-remote.ts
2268
- async function RemoteDataStore(sthis, name, url, opts) {
2269
- const ds = new DataStoreImpl(sthis, name, url, opts);
3173
+ async function RemoteDataStore(sthis, url, opts) {
3174
+ const ds = new DataStoreImpl(sthis, url, opts);
2270
3175
  await ds.start();
2271
3176
  return ds;
2272
3177
  }
2273
- async function RemoteMetaStore(sthis, name, url, opts) {
2274
- const ms = new MetaStoreImpl(
2275
- sthis,
2276
- name,
2277
- url,
2278
- opts
2279
- /* , true*/
2280
- );
3178
+ async function RemoteMetaStore(sthis, url, opts) {
3179
+ const ms = new MetaStoreImpl(sthis, url, opts);
2281
3180
  await ms.start();
2282
3181
  return ms;
2283
3182
  }
2284
3183
 
2285
3184
  // src/blockstore/connection-base.ts
3185
+ function coerceLoader(ref) {
3186
+ const refl = ref;
3187
+ if (refl.loader) {
3188
+ return refl.loader;
3189
+ }
3190
+ const refb = ref;
3191
+ if (refb.blockstore) {
3192
+ return coerceLoader(refb.blockstore);
3193
+ }
3194
+ return void 0;
3195
+ }
2286
3196
  var ConnectionBase = class {
2287
3197
  constructor(url, logger) {
2288
3198
  this.loaded = Promise.resolve();
@@ -2293,23 +3203,26 @@ var ConnectionBase = class {
2293
3203
  await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
2294
3204
  await (await throwFalsy(this.loader).WALStore()).process();
2295
3205
  }
2296
- async connect_X({ loader }) {
2297
- if (!loader) throw this.logger.Error().Msg("loader is required").AsError();
2298
- await this.connectMeta_X({ loader });
2299
- await this.connectStorage_X({ loader });
3206
+ async connect(refl) {
3207
+ await this.connectMeta(refl);
3208
+ await this.connectStorage(refl);
2300
3209
  }
2301
- async connectMeta_X({ loader }) {
2302
- if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
3210
+ async connectMeta(refl) {
3211
+ const loader = coerceLoader(refl);
3212
+ if (!loader) throw this.logger.Error().Msg("connectMeta: loader is required").AsError();
2303
3213
  this.loader = loader;
2304
3214
  await this.onConnect();
2305
- const metaUrl = this.url.build().defParam("store", "meta").URI();
2306
- const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
2307
- if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
2308
- const dbName = metaUrl.getParam("name");
2309
- if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: name is required").AsError();
2310
- const remote = await RemoteMetaStore(loader.sthis, dbName, metaUrl, {
3215
+ const metaUrl = this.url.build().defParam("store" /* STORE */, "meta").URI();
3216
+ const rgateway = await getStartedGateway(loader.sthis, metaUrl);
3217
+ if (rgateway.isErr())
3218
+ throw this.logger.Error().Result("err", rgateway).Url(metaUrl).Msg("connectMeta: gateway is required").AsError();
3219
+ const dbName = metaUrl.getParam("name" /* NAME */);
3220
+ if (!dbName) {
3221
+ throw this.logger.Error().Url(metaUrl).Msg("connectMeta: dbName is required").AsError();
3222
+ }
3223
+ const gateway = rgateway.Ok();
3224
+ const remote = await RemoteMetaStore(loader.sthis, metaUrl, {
2311
3225
  gateway: gateway.gateway,
2312
- keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag),
2313
3226
  loader
2314
3227
  });
2315
3228
  this.loader.remoteMetaStore = remote;
@@ -2319,17 +3232,19 @@ var ConnectionBase = class {
2319
3232
  });
2320
3233
  });
2321
3234
  }
2322
- async connectStorage_X({ loader }) {
3235
+ async connectStorage(refl) {
3236
+ const loader = coerceLoader(refl);
2323
3237
  if (!loader) throw this.logger.Error().Msg("connectStorage_X: loader is required").AsError();
2324
3238
  this.loader = loader;
2325
- const dataUrl = this.url.build().defParam("store", "data").URI();
2326
- const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
2327
- if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
2328
- const name = dataUrl.getParam("name");
3239
+ const dataUrl = this.url.build().defParam("store" /* STORE */, "data").URI();
3240
+ const rgateway = await getStartedGateway(loader.sthis, dataUrl);
3241
+ if (rgateway.isErr())
3242
+ throw this.logger.Error().Result("err", rgateway).Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
3243
+ const name = dataUrl.getParam("name" /* NAME */);
2329
3244
  if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: name is required").AsError;
2330
- loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
2331
- gateway: gateway.gateway,
2332
- keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
3245
+ loader.remoteCarStore = await RemoteDataStore(loader.sthis, this.url, {
3246
+ gateway: rgateway.Ok().gateway,
3247
+ loader
2333
3248
  });
2334
3249
  loader.remoteFileStore = loader.remoteCarStore;
2335
3250
  }
@@ -2341,9 +3256,9 @@ var ConnectionBase = class {
2341
3256
  // // await this.compact()
2342
3257
  // // }
2343
3258
  // const currents = await this.loader?.metaStore?.load()
2344
- // if (!currents) throw new Error("Can't sync empty database: save data first")
3259
+ // if (!currents) throw new Error("Can't sync empty ledger: save data first")
2345
3260
  // if (currents.length > 1)
2346
- // throw new Error("Can't sync database with split heads: make an update first")
3261
+ // throw new Error("Can't sync ledger with split heads: make an update first")
2347
3262
  // const current = currents[0]
2348
3263
  // const params = {
2349
3264
  // car: current.car.toString()
@@ -2369,6 +3284,12 @@ var ConnectionBase = class {
2369
3284
  };
2370
3285
 
2371
3286
  // src/crdt-helpers.ts
3287
+ import { parse as parse2 } from "multiformats/link";
3288
+ import { sha256 as hasher5 } from "multiformats/hashes/sha2";
3289
+ import * as codec from "@fireproof/vendor/@ipld/dag-cbor";
3290
+ import { put, get, entries, root } from "@fireproof/vendor/@web3-storage/pail/crdt";
3291
+ import { EventFetcher, vis } from "@fireproof/vendor/@web3-storage/pail/clock";
3292
+ import * as Batch from "@fireproof/vendor/@web3-storage/pail/crdt/batch";
2372
3293
  function time(tag) {
2373
3294
  }
2374
3295
  function timeEnd(tag) {
@@ -2436,7 +3357,7 @@ async function processFiles(store, blocks, doc, logger) {
2436
3357
  }
2437
3358
  async function processFileset(logger, store, blocks, files) {
2438
3359
  const dbBlockstore = blocks.parent;
2439
- if (!dbBlockstore.loader) throw logger.Error().Msg("Missing loader, database name is required").AsError();
3360
+ if (!dbBlockstore.loader) throw logger.Error().Msg("Missing loader, ledger name is required").AsError();
2440
3361
  const t = new CarTransaction(dbBlockstore);
2441
3362
  const didPut = [];
2442
3363
  for (const filename in files) {
@@ -2468,7 +3389,7 @@ async function processFileset(logger, store, blocks, files) {
2468
3389
  }
2469
3390
  }
2470
3391
  async function getValueFromCrdt(blocks, head, key, logger) {
2471
- if (!head.length) throw logger.Debug().Msg("Getting from an empty database").AsError();
3392
+ if (!head.length) throw logger.Debug().Msg("Getting from an empty ledger").AsError();
2472
3393
  const link = await get(blocks, head, key);
2473
3394
  if (!link) throw logger.Error().Str("key", key).Msg(`Missing key`).AsError();
2474
3395
  return await getValueFromLink(blocks, link, logger);
@@ -2626,7 +3547,7 @@ async function doCompact(blockLog, head, logger) {
2626
3547
  isCompacting = false;
2627
3548
  }
2628
3549
  async function getBlock(blocks, cidString) {
2629
- const block = await blocks.get(parse3(cidString));
3550
+ const block = await blocks.get(parse2(cidString));
2630
3551
  if (!block) throw new Error(`Missing block ${cidString}`);
2631
3552
  const { cid, value } = await decode({ bytes: block.bytes, codec, hasher: hasher5 });
2632
3553
  return new Block({ cid, value, bytes: block.bytes });
@@ -2686,7 +3607,8 @@ function makeProllyGetBlock(blocks) {
2686
3607
  return create({ cid, bytes, hasher: hasher6, codec: codec2 });
2687
3608
  };
2688
3609
  }
2689
- async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
3610
+ async function bulkIndex(logger, tblocks, inIndex, indexEntries, opts) {
3611
+ logger.Debug().Msg("enter bulkIndex");
2690
3612
  if (!indexEntries.length) return inIndex;
2691
3613
  if (!inIndex.root) {
2692
3614
  if (!inIndex.cid) {
@@ -2703,18 +3625,22 @@ async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
2703
3625
  returnNode = node;
2704
3626
  }
2705
3627
  if (!returnNode || !returnRootBlock) throw new Error("failed to create index");
3628
+ logger.Debug().Msg("exit !root bulkIndex");
2706
3629
  return { root: returnNode, cid: returnRootBlock.cid };
2707
3630
  } else {
2708
3631
  inIndex.root = await DbIndex.load({ cid: inIndex.cid, get: makeProllyGetBlock(tblocks), ...opts });
2709
3632
  }
2710
3633
  }
3634
+ logger.Debug().Msg("pre bulk bulkIndex");
2711
3635
  const { root: root3, blocks: newBlocks } = await inIndex.root.bulk(indexEntries);
2712
3636
  if (root3) {
3637
+ logger.Debug().Msg("pre root put bulkIndex");
2713
3638
  for await (const block of newBlocks) {
2714
3639
  await tblocks.put(block.cid, block.bytes);
2715
3640
  }
2716
3641
  return { root: root3, cid: (await root3.block).cid };
2717
3642
  } else {
3643
+ logger.Debug().Msg("pre !root bulkIndex");
2718
3644
  return { root: void 0, cid: void 0 };
2719
3645
  }
2720
3646
  }
@@ -2754,17 +3680,17 @@ function encodeKey(key) {
2754
3680
  }
2755
3681
 
2756
3682
  // src/indexer.ts
2757
- function index(sthis, { _crdt }, name, mapFn, meta) {
2758
- if (mapFn && meta) throw _crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
2759
- if (mapFn && mapFn.constructor.name !== "Function") throw _crdt.logger.Error().Msg("mapFn must be a function").AsError();
2760
- if (_crdt.indexers.has(name)) {
2761
- const idx = _crdt.indexers.get(name);
3683
+ function index(refDb, name, mapFn, meta) {
3684
+ if (mapFn && meta) throw refDb.crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
3685
+ if (mapFn && mapFn.constructor.name !== "Function") throw refDb.crdt.logger.Error().Msg("mapFn must be a function").AsError();
3686
+ if (refDb.crdt.indexers.has(name)) {
3687
+ const idx = refDb.crdt.indexers.get(name);
2762
3688
  idx.applyMapFn(name, mapFn, meta);
2763
3689
  } else {
2764
- const idx = new Index(sthis, _crdt, name, mapFn, meta);
2765
- _crdt.indexers.set(name, idx);
3690
+ const idx = new Index(refDb.crdt.sthis, refDb.crdt, name, mapFn, meta);
3691
+ refDb.crdt.indexers.set(name, idx);
2766
3692
  }
2767
- return _crdt.indexers.get(name);
3693
+ return refDb.crdt.indexers.get(name);
2768
3694
  }
2769
3695
  var Index = class {
2770
3696
  constructor(sthis, crdt, name, mapFn, meta) {
@@ -2783,18 +3709,9 @@ var Index = class {
2783
3709
  return Promise.all([this.blockstore.ready(), this.crdt.ready()]).then(() => {
2784
3710
  });
2785
3711
  }
2786
- close() {
2787
- return Promise.all([this.blockstore.close(), this.crdt.close()]).then(() => {
2788
- });
2789
- }
2790
- destroy() {
2791
- return Promise.all([this.blockstore.destroy(), this.crdt.destroy()]).then(() => {
2792
- });
2793
- }
2794
3712
  applyMapFn(name, mapFn, meta) {
2795
3713
  if (mapFn && meta) throw this.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
2796
3714
  if (this.name && this.name !== name) throw this.logger.Error().Msg("cannot change name").AsError();
2797
- this.name = name;
2798
3715
  try {
2799
3716
  if (meta) {
2800
3717
  if (this.indexHead && this.indexHead.map((c) => c.toString()).join() !== meta.head.map((c) => c.toString()).join()) {
@@ -2842,9 +3759,13 @@ var Index = class {
2842
3759
  }
2843
3760
  }
2844
3761
  async query(opts = {}) {
3762
+ this.logger.Debug().Msg("enter query");
2845
3763
  await this.ready();
3764
+ this.logger.Debug().Msg("post ready query");
2846
3765
  await this._updateIndex();
3766
+ this.logger.Debug().Msg("post _updateIndex query");
2847
3767
  await this._hydrateIndex();
3768
+ this.logger.Debug().Msg("post _hydrateIndex query");
2848
3769
  if (!this.byKey.root) {
2849
3770
  return await applyQuery(this.crdt, { result: [] }, opts);
2850
3771
  }
@@ -2900,13 +3821,16 @@ var Index = class {
2900
3821
  }
2901
3822
  async _updateIndex() {
2902
3823
  await this.ready();
3824
+ this.logger.Debug().Msg("enter _updateIndex");
2903
3825
  if (this.initError) throw this.initError;
2904
3826
  if (!this.mapFn) throw this.logger.Error().Msg("No map function defined").AsError();
2905
3827
  let result, head;
2906
3828
  if (!this.indexHead || this.indexHead.length === 0) {
2907
3829
  ({ result, head } = await this.crdt.allDocs());
3830
+ this.logger.Debug().Msg("enter crdt.allDocs");
2908
3831
  } else {
2909
3832
  ({ result, head } = await this.crdt.changes(this.indexHead));
3833
+ this.logger.Debug().Msg("enter crdt.changes");
2910
3834
  }
2911
3835
  if (result.length === 0) {
2912
3836
  this.indexHead = head;
@@ -2939,9 +3863,22 @@ var Index = class {
2939
3863
  if (result.length === 0) {
2940
3864
  return indexerMeta;
2941
3865
  }
3866
+ this.logger.Debug().Msg("pre this.blockstore.transaction");
2942
3867
  const { meta } = await this.blockstore.transaction(async (tblocks) => {
2943
- this.byId = await bulkIndex(tblocks, this.byId, removeIdIndexEntries.concat(byIdIndexEntries), byIdOpts);
2944
- this.byKey = await bulkIndex(tblocks, this.byKey, staleKeyIndexEntries.concat(indexEntries), byKeyOpts);
3868
+ this.byId = await bulkIndex(
3869
+ this.logger,
3870
+ tblocks,
3871
+ this.byId,
3872
+ removeIdIndexEntries.concat(byIdIndexEntries),
3873
+ byIdOpts
3874
+ );
3875
+ this.byKey = await bulkIndex(
3876
+ this.logger,
3877
+ tblocks,
3878
+ this.byKey,
3879
+ staleKeyIndexEntries.concat(indexEntries),
3880
+ byKeyOpts
3881
+ );
2945
3882
  this.indexHead = head;
2946
3883
  if (this.byId.cid && this.byKey.cid) {
2947
3884
  const idxMeta = {
@@ -2953,8 +3890,10 @@ var Index = class {
2953
3890
  };
2954
3891
  indexerMeta.indexes?.set(this.name, idxMeta);
2955
3892
  }
3893
+ this.logger.Debug().Any("indexerMeta", new Array(indexerMeta.indexes?.entries())).Msg("exit this.blockstore.transaction fn");
2956
3894
  return indexerMeta;
2957
3895
  });
3896
+ this.logger.Debug().Msg("post this.blockstore.transaction");
2958
3897
  return meta;
2959
3898
  }
2960
3899
  };
@@ -2962,7 +3901,7 @@ var Index = class {
2962
3901
  // src/crdt-clock.ts
2963
3902
  import { advance } from "@fireproof/vendor/@web3-storage/pail/clock";
2964
3903
  import { root as root2 } from "@fireproof/vendor/@web3-storage/pail/crdt";
2965
- import { ResolveOnce as ResolveOnce4 } from "@adviser/cement";
3904
+ import { ResolveOnce as ResolveOnce5 } from "@adviser/cement";
2966
3905
 
2967
3906
  // src/apply-head-queue.ts
2968
3907
  function applyHeadQueue(worker, logger) {
@@ -3019,7 +3958,7 @@ var CRDTClock = class {
3019
3958
  this.zoomers = /* @__PURE__ */ new Set();
3020
3959
  this.watchers = /* @__PURE__ */ new Set();
3021
3960
  this.emptyWatchers = /* @__PURE__ */ new Set();
3022
- this._ready = new ResolveOnce4();
3961
+ this._ready = new ResolveOnce5();
3023
3962
  this.blockstore = blockstore;
3024
3963
  this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
3025
3964
  this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
@@ -3130,15 +4069,13 @@ async function advanceBlocks(logger, newHead, tblocks, head) {
3130
4069
 
3131
4070
  // src/crdt.ts
3132
4071
  var CRDT = class {
3133
- constructor(sthis, name, opts = {}) {
4072
+ constructor(sthis, opts) {
3134
4073
  this.indexers = /* @__PURE__ */ new Map();
3135
- this.onceReady = new ResolveOnce5();
4074
+ this.onceReady = new ResolveOnce6();
3136
4075
  this.sthis = sthis;
3137
- this.name = name;
3138
4076
  this.logger = ensureLogger(sthis, "CRDT");
3139
4077
  this.opts = opts;
3140
- this.blockstore = blockstoreFactory(sthis, {
3141
- name,
4078
+ this.blockstore = new EncryptedBlockstore(sthis, {
3142
4079
  applyMeta: async (meta) => {
3143
4080
  const crdtMeta = meta;
3144
4081
  if (!crdtMeta.head) throw this.logger.Error().Msg("missing head").AsError();
@@ -3148,23 +4085,29 @@ var CRDT = class {
3148
4085
  await doCompact(blocks, this.clock.head, this.logger);
3149
4086
  return { head: this.clock.head };
3150
4087
  },
3151
- autoCompact: this.opts.autoCompact || 100,
3152
- store: { ...this.opts.store, isIndex: void 0 },
3153
- public: this.opts.public,
3154
- meta: this.opts.meta,
3155
- threshold: this.opts.threshold
4088
+ gatewayInterceptor: opts.gatewayInterceptor,
4089
+ // autoCompact: this.opts.autoCompact || 100,
4090
+ storeRuntime: toStoreRuntime(this.sthis, this.opts.storeEnDe),
4091
+ storeUrls: this.opts.storeUrls.data,
4092
+ keyBag: this.opts.keyBag,
4093
+ // public: this.opts.public,
4094
+ meta: this.opts.meta
4095
+ // threshold: this.opts.threshold,
3156
4096
  });
3157
- this.indexBlockstore = blockstoreFactory(sthis, {
3158
- name,
4097
+ this.indexBlockstore = new EncryptedBlockstore(sthis, {
4098
+ // name: opts.name,
3159
4099
  applyMeta: async (meta) => {
3160
4100
  const idxCarMeta = meta;
3161
4101
  if (!idxCarMeta.indexes) throw this.logger.Error().Msg("missing indexes").AsError();
3162
- for (const [name2, idx] of Object.entries(idxCarMeta.indexes)) {
3163
- index(this.sthis, { _crdt: this }, name2, void 0, idx);
4102
+ for (const [name, idx] of Object.entries(idxCarMeta.indexes)) {
4103
+ index({ crdt: this }, name, void 0, idx);
3164
4104
  }
3165
4105
  },
3166
- store: { ...this.opts.store, isIndex: this.opts.store?.isIndex || "idx" },
3167
- public: this.opts.public
4106
+ gatewayInterceptor: opts.gatewayInterceptor,
4107
+ storeRuntime: toStoreRuntime(this.sthis, this.opts.storeEnDe),
4108
+ storeUrls: this.opts.storeUrls.idx,
4109
+ keyBag: this.opts.keyBag
4110
+ // public: this.opts.public,
3168
4111
  });
3169
4112
  this.clock = new CRDTClock(this.blockstore);
3170
4113
  this.clock.onZoom(() => {
@@ -3245,75 +4188,169 @@ var CRDT = class {
3245
4188
  }
3246
4189
  };
3247
4190
 
3248
- // src/database.ts
3249
- var Database = class {
3250
- constructor(name, opts) {
3251
- this.opts = {};
4191
+ // src/ledger.ts
4192
+ var ledgers = new KeyedResolvOnce4();
4193
+ function keyConfigOpts(sthis, name, opts) {
4194
+ return JSON.stringify(
4195
+ toSortedArray({
4196
+ name,
4197
+ stores: toSortedArray(JSON.parse(JSON.stringify(toStoreURIRuntime(sthis, name, opts?.storeUrls))))
4198
+ })
4199
+ );
4200
+ }
4201
+ function isLedger(db) {
4202
+ return db instanceof LedgerImpl || db instanceof LedgerShell;
4203
+ }
4204
+ function LedgerFactory(name, opts) {
4205
+ const sthis = ensureSuperThis(opts);
4206
+ return new LedgerShell(
4207
+ ledgers.get(keyConfigOpts(sthis, name, opts)).once((key) => {
4208
+ const db = new LedgerImpl(sthis, {
4209
+ name,
4210
+ meta: opts?.meta,
4211
+ keyBag: defaultKeyBagOpts(sthis, opts?.keyBag),
4212
+ storeUrls: toStoreURIRuntime(sthis, name, opts?.storeUrls),
4213
+ gatewayInterceptor: opts?.gatewayInterceptor,
4214
+ writeQueue: defaultWriteQueueOpts(opts?.writeQueue),
4215
+ storeEnDe: {
4216
+ encodeFile,
4217
+ decodeFile,
4218
+ ...opts?.storeEnDe
4219
+ }
4220
+ });
4221
+ db.onClosed(() => {
4222
+ ledgers.unget(key);
4223
+ });
4224
+ return db;
4225
+ })
4226
+ );
4227
+ }
4228
+ var LedgerShell = class {
4229
+ constructor(ref) {
4230
+ this.ref = ref;
4231
+ ref.addShell(this);
4232
+ }
4233
+ get id() {
4234
+ return this.ref.id;
4235
+ }
4236
+ get logger() {
4237
+ return this.ref.logger;
4238
+ }
4239
+ get sthis() {
4240
+ return this.ref.sthis;
4241
+ }
4242
+ get crdt() {
4243
+ return this.ref.crdt;
4244
+ }
4245
+ get name() {
4246
+ return this.ref.name;
4247
+ }
4248
+ onClosed(fn) {
4249
+ return this.ref.onClosed(fn);
4250
+ }
4251
+ close() {
4252
+ return this.ref.shellClose(this);
4253
+ }
4254
+ destroy() {
4255
+ return this.ref.destroy();
4256
+ }
4257
+ ready() {
4258
+ return this.ref.ready();
4259
+ }
4260
+ get(id) {
4261
+ return this.ref.get(id);
4262
+ }
4263
+ put(doc) {
4264
+ return this.ref.put(doc);
4265
+ }
4266
+ bulk(docs) {
4267
+ return this.ref.bulk(docs);
4268
+ }
4269
+ del(id) {
4270
+ return this.ref.del(id);
4271
+ }
4272
+ changes(since, opts) {
4273
+ return this.ref.changes(since, opts);
4274
+ }
4275
+ allDocs(opts) {
4276
+ return this.ref.allDocs(opts);
4277
+ }
4278
+ allDocuments() {
4279
+ return this.ref.allDocuments();
4280
+ }
4281
+ subscribe(listener, updates) {
4282
+ return this.ref.subscribe(listener, updates);
4283
+ }
4284
+ query(field, opts) {
4285
+ return this.ref.query(field, opts);
4286
+ }
4287
+ compact() {
4288
+ return this.ref.compact();
4289
+ }
4290
+ };
4291
+ var LedgerImpl = class {
4292
+ constructor(sthis, opts) {
3252
4293
  this._listening = false;
3253
4294
  this._listeners = /* @__PURE__ */ new Set();
3254
4295
  this._noupdate_listeners = /* @__PURE__ */ new Set();
3255
- this._ready = new ResolveOnce6();
3256
- this.name = name;
3257
- this.opts = opts || this.opts;
3258
- this.sthis = ensureSuperThis(this.opts);
3259
- this.logger = ensureLogger(this.sthis, "Database");
3260
- this._crdt = new CRDT(this.sthis, name, this.opts);
3261
- this.blockstore = this._crdt.blockstore;
3262
- this._writeQueue = writeQueue(async (updates) => {
3263
- return await this._crdt.bulk(updates);
3264
- });
3265
- this._crdt.clock.onTock(() => {
3266
- this._no_update_notify();
3267
- });
4296
+ // readonly blockstore: BaseBlockstore;
4297
+ this.shells = /* @__PURE__ */ new Set();
4298
+ this._onClosedFns = /* @__PURE__ */ new Set();
4299
+ this._ready = new ResolveOnce7();
4300
+ this.opts = opts;
4301
+ this.sthis = sthis;
4302
+ this.id = sthis.timeOrderedNextId().str;
4303
+ this.logger = ensureLogger(this.sthis, "Ledger");
4304
+ this.crdt = new CRDT(this.sthis, this.opts);
4305
+ this._writeQueue = writeQueue(this.sthis, async (updates) => this.crdt.bulk(updates), this.opts.writeQueue);
4306
+ this.crdt.clock.onTock(() => this._no_update_notify());
3268
4307
  }
3269
- static {
3270
- this.databases = /* @__PURE__ */ new Map();
4308
+ addShell(shell) {
4309
+ this.shells.add(shell);
4310
+ }
4311
+ onClosed(fn) {
4312
+ this._onClosedFns.add(fn);
3271
4313
  }
3272
- /**
3273
- * Close the database and release resources
3274
- */
3275
4314
  async close() {
3276
- await this.ready();
3277
- await this._crdt.close();
3278
- await this.blockstore.close();
4315
+ throw this.logger.Error().Str("db", this.name).Msg(`use shellClose`).AsError();
4316
+ }
4317
+ async shellClose(db) {
4318
+ if (!this.shells.has(db)) {
4319
+ throw this.logger.Error().Str("db", this.name).Msg(`LedgerShell mismatch`).AsError();
4320
+ }
4321
+ this.shells.delete(db);
4322
+ if (this.shells.size === 0) {
4323
+ await this.ready();
4324
+ await this.crdt.close();
4325
+ await this._writeQueue.close();
4326
+ this._onClosedFns.forEach((fn) => fn());
4327
+ }
3279
4328
  }
3280
- /**
3281
- * Destroy the database and release all resources
3282
- */
3283
4329
  async destroy() {
3284
4330
  await this.ready();
3285
- await this._crdt.destroy();
3286
- await this.blockstore.destroy();
4331
+ await this.crdt.destroy();
3287
4332
  }
3288
4333
  async ready() {
3289
- return this._ready.once(async () => {
4334
+ const ret = await this._ready.once(async () => {
3290
4335
  await this.sthis.start();
3291
- await this._crdt.ready();
3292
- await this.blockstore.ready();
4336
+ await this.crdt.ready();
3293
4337
  });
4338
+ return ret;
4339
+ }
4340
+ get name() {
4341
+ return this.opts.storeUrls.data.data.getParam("name" /* NAME */) || "default";
3294
4342
  }
3295
- /**
3296
- * Get a document from the database
3297
- * @param id - the document id
3298
- * @returns the document with the _id
3299
- * @throws NotFoundError if the document is not found
3300
- */
3301
4343
  async get(id) {
3302
4344
  if (!id) throw this.logger.Error().Str("db", this.name).Msg(`Doc id is required`).AsError();
3303
4345
  await this.ready();
3304
4346
  this.logger.Debug().Str("id", id).Msg("get");
3305
- const got = await this._crdt.get(id).catch((e) => {
4347
+ const got = await this.crdt.get(id).catch((e) => {
3306
4348
  throw new NotFoundError(`Not found: ${id} - ${e.message}`);
3307
4349
  });
3308
4350
  if (!got) throw new NotFoundError(`Not found: ${id}`);
3309
4351
  const { doc } = got;
3310
4352
  return { ...doc, _id: id };
3311
4353
  }
3312
- /**
3313
- * Put a document from the database
3314
- * @param doc - the document to put
3315
- * @returns add DocResponse with the id and clock
3316
- */
3317
4354
  async put(doc) {
3318
4355
  await this.ready();
3319
4356
  this.logger.Debug().Str("id", doc._id).Msg("put");
@@ -3328,11 +4365,21 @@ var Database = class {
3328
4365
  });
3329
4366
  return { id: docId, clock: result?.head, name: this.name };
3330
4367
  }
3331
- /**
3332
- * delete a document from the database
3333
- * @param id Document id
3334
- * @returns DocResponse with the id and clock
3335
- */
4368
+ async bulk(docs) {
4369
+ await this.ready();
4370
+ const updates = docs.map((doc) => {
4371
+ const id = doc._id || this.sthis.timeOrderedNextId().str;
4372
+ return {
4373
+ id,
4374
+ value: {
4375
+ ...doc,
4376
+ _id: id
4377
+ }
4378
+ };
4379
+ });
4380
+ const result = await this._writeQueue.bulk(updates);
4381
+ return { ids: updates.map((u) => u.id), clock: result.head, name: this.name };
4382
+ }
3336
4383
  async del(id) {
3337
4384
  await this.ready();
3338
4385
  this.logger.Debug().Str("id", id).Msg("del");
@@ -3342,7 +4389,7 @@ var Database = class {
3342
4389
  async changes(since = [], opts = {}) {
3343
4390
  await this.ready();
3344
4391
  this.logger.Debug().Any("since", since).Any("opts", opts).Msg("changes");
3345
- const { result, head } = await this._crdt.changes(since, opts);
4392
+ const { result, head } = await this.crdt.changes(since, opts);
3346
4393
  const rows = result.map(({ id: key, value, del, clock }) => ({
3347
4394
  key,
3348
4395
  value: del ? { _id: key, _deleted: true } : { _id: key, ...value },
@@ -3353,7 +4400,7 @@ var Database = class {
3353
4400
  async allDocs(opts = {}) {
3354
4401
  await this.ready();
3355
4402
  this.logger.Debug().Msg("allDocs");
3356
- const { result, head } = await this._crdt.allDocs();
4403
+ const { result, head } = await this.crdt.allDocs();
3357
4404
  const rows = result.map(({ id: key, value, del }) => ({
3358
4405
  key,
3359
4406
  value: del ? { _id: key, _deleted: true } : { _id: key, ...value }
@@ -3368,7 +4415,7 @@ var Database = class {
3368
4415
  if (updates) {
3369
4416
  if (!this._listening) {
3370
4417
  this._listening = true;
3371
- this._crdt.clock.onTick((updates2) => {
4418
+ this.crdt.clock.onTick((updates2) => {
3372
4419
  void this._notify(updates2);
3373
4420
  });
3374
4421
  }
@@ -3387,13 +4434,13 @@ var Database = class {
3387
4434
  async query(field, opts = {}) {
3388
4435
  await this.ready();
3389
4436
  this.logger.Debug().Any("field", field).Any("opts", opts).Msg("query");
3390
- const _crdt = this._crdt;
3391
- const idx = typeof field === "string" ? index(this.sthis, { _crdt }, field) : index(this.sthis, { _crdt }, makeName(field.toString()), field);
4437
+ const _crdt = this.crdt;
4438
+ const idx = typeof field === "string" ? index({ crdt: _crdt }, field) : index({ crdt: _crdt }, makeName(field.toString()), field);
3392
4439
  return await idx.query(opts);
3393
4440
  }
3394
4441
  async compact() {
3395
4442
  await this.ready();
3396
- await this._crdt.compact();
4443
+ await this.crdt.compact();
3397
4444
  }
3398
4445
  async _notify(updates) {
3399
4446
  await this.ready();
@@ -3417,23 +4464,62 @@ var Database = class {
3417
4464
  }
3418
4465
  }
3419
4466
  };
3420
- function toSortedArray(set) {
3421
- if (!set) return [];
3422
- return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
4467
+ function defaultURI2(sthis, curi, uri, store, ctx) {
4468
+ ctx = ctx || {};
4469
+ const ret = (curi ? URI12.from(curi) : uri).build().setParam("store" /* STORE */, store);
4470
+ if (!ret.hasParam("name" /* NAME */)) {
4471
+ const name = sthis.pathOps.basename(ret.URI().pathname);
4472
+ if (!name) {
4473
+ throw sthis.logger.Error().Url(ret).Any("ctx", ctx).Msg("Ledger name is required").AsError();
4474
+ }
4475
+ ret.setParam("name" /* NAME */, name);
4476
+ }
4477
+ if (ctx.idx) {
4478
+ ret.defParam("index" /* INDEX */, "idx");
4479
+ ret.defParam("storekey" /* STORE_KEY */, `@${ret.getParam("name" /* NAME */)}-${store}-idx@`);
4480
+ } else {
4481
+ ret.defParam("storekey" /* STORE_KEY */, `@${ret.getParam("name" /* NAME */)}-${store}@`);
4482
+ }
4483
+ if (store === "data") {
4484
+ if (ctx.file) {
4485
+ } else {
4486
+ ret.defParam("suffix" /* SUFFIX */, ".car");
4487
+ }
4488
+ }
4489
+ return ret.URI();
3423
4490
  }
3424
- function fireproof(name, opts) {
3425
- const key = JSON.stringify(
3426
- toSortedArray({
3427
- name,
3428
- stores: toSortedArray(opts?.store?.stores)
3429
- })
3430
- );
3431
- let db = Database.databases.get(key);
3432
- if (!db) {
3433
- db = new Database(name, opts);
3434
- Database.databases.set(key, db);
4491
+ function toStoreURIRuntime(sthis, name, sopts) {
4492
+ sopts = sopts || {};
4493
+ if (!sopts.base) {
4494
+ const fp_env = sthis.env.get("FP_STORAGE_URL");
4495
+ if (fp_env) {
4496
+ sopts = { ...sopts, base: BuildURI2.from(fp_env).setParam("urlGen" /* URL_GEN */, "fromEnv") };
4497
+ } else {
4498
+ sopts = { ...sopts, base: getDefaultURI(sthis).build().setParam("urlGen" /* URL_GEN */, "default") };
4499
+ }
3435
4500
  }
3436
- return db;
4501
+ const bbase = BuildURI2.from(sopts.base);
4502
+ if (name) {
4503
+ bbase.setParam("name" /* NAME */, name);
4504
+ }
4505
+ const base = bbase.URI();
4506
+ return {
4507
+ idx: {
4508
+ data: defaultURI2(sthis, sopts.idx?.data, base, "data", { idx: true }),
4509
+ file: defaultURI2(sthis, sopts.idx?.data, base, "data", { file: true, idx: true }),
4510
+ meta: defaultURI2(sthis, sopts.idx?.meta, base, "meta", { idx: true }),
4511
+ wal: defaultURI2(sthis, sopts.idx?.wal, base, "wal", { idx: true })
4512
+ },
4513
+ data: {
4514
+ data: defaultURI2(sthis, sopts.data?.data, base, "data"),
4515
+ file: defaultURI2(sthis, sopts.data?.data, base, "data", { file: true }),
4516
+ meta: defaultURI2(sthis, sopts.data?.meta, base, "meta"),
4517
+ wal: defaultURI2(sthis, sopts.data?.wal, base, "wal")
4518
+ }
4519
+ };
4520
+ }
4521
+ function fireproof(name, opts) {
4522
+ return LedgerFactory(name, opts);
3437
4523
  }
3438
4524
  function makeName(fnString) {
3439
4525
  const regex = /\(([^,()]+,\s*[^,()]+|\[[^\]]+\],\s*[^,()]+)\)/g;
@@ -3452,52 +4538,24 @@ function makeName(fnString) {
3452
4538
  }
3453
4539
  }
3454
4540
 
3455
- // src/runtime/index.ts
3456
- var runtime_exports = {};
3457
- __export(runtime_exports, {
3458
- FILESTORE_VERSION: () => FILESTORE_VERSION,
3459
- INDEXDB_VERSION: () => INDEXDB_VERSION,
3460
- files: () => files_exports,
3461
- getFileName: () => getFileName,
3462
- getFileSystem: () => getFileSystem,
3463
- getPath: () => getPath,
3464
- kb: () => key_bag_exports,
3465
- kc: () => keyed_crypto_exports,
3466
- mf: () => wait_pr_multiformats_exports,
3467
- runtimeFn: () => runtimeFn2
3468
- });
3469
-
3470
- // src/runtime/wait-pr-multiformats/index.ts
3471
- var wait_pr_multiformats_exports = {};
3472
- __export(wait_pr_multiformats_exports, {
3473
- block: () => block_exports,
3474
- codec: () => codec_interface_exports
3475
- });
3476
-
3477
- // src/runtime/wait-pr-multiformats/codec-interface.ts
3478
- var codec_interface_exports = {};
3479
-
3480
- // src/runtime/index.ts
3481
- import { runtimeFn as runtimeFn2 } from "@adviser/cement";
3482
-
3483
- // src/runtime/gateways/indexdb/version.ts
3484
- var INDEXDB_VERSION = "v0.19-indexdb";
3485
-
3486
4541
  // src/version.ts
3487
4542
  var PACKAGE_VERSION = Object.keys({
3488
- "0.19.121-dev": "xxxx"
4543
+ "0.20.0-dev-preview-05": "xxxx"
3489
4544
  })[0];
3490
4545
  export {
3491
4546
  CRDT,
3492
- Database,
3493
4547
  Index,
4548
+ LedgerFactory,
4549
+ LedgerShell,
3494
4550
  NotFoundError,
3495
4551
  PACKAGE_VERSION,
3496
- Result,
4552
+ PARAM,
3497
4553
  UInt8ArrayEqual,
3498
4554
  blockstore_exports as blockstore,
3499
4555
  blockstore_exports as bs,
3500
- dataDir,
4556
+ coerceIntoUint8,
4557
+ coercePromiseIntoUint8,
4558
+ defaultWriteQueueOpts,
3501
4559
  ensureLogger,
3502
4560
  ensureSuperLog,
3503
4561
  ensureSuperThis,
@@ -3508,11 +4566,16 @@ export {
3508
4566
  getName,
3509
4567
  getStore,
3510
4568
  index,
4569
+ inplaceFilter,
3511
4570
  isFalsy,
4571
+ isLedger,
3512
4572
  isNotFoundError,
4573
+ keyConfigOpts,
3513
4574
  onSuperThis,
3514
4575
  runtime_exports as rt,
3515
4576
  runtime_exports as runtime,
3516
- throwFalsy
4577
+ throwFalsy,
4578
+ toSortedArray,
4579
+ toStoreURIRuntime
3517
4580
  };
3518
4581
  //# sourceMappingURL=index.js.map