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

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 (63) hide show
  1. package/README.md +3 -2
  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 +2 -3
  7. package/index.cjs +1819 -1051
  8. package/index.cjs.map +1 -1
  9. package/index.d.cts +746 -333
  10. package/index.d.ts +746 -333
  11. package/index.js +1792 -1026
  12. package/index.js.map +1 -1
  13. package/metafile-cjs.json +1 -1
  14. package/metafile-esm.json +1 -1
  15. package/node/index.cjs +16 -293
  16. package/node/index.cjs.map +1 -1
  17. package/node/index.d.cts +4 -40
  18. package/node/index.d.ts +4 -40
  19. package/node/index.js +22 -237
  20. package/node/index.js.map +1 -1
  21. package/node/metafile-cjs.json +1 -1
  22. package/node/metafile-esm.json +1 -1
  23. package/package.json +12 -4
  24. package/react/index.cjs.map +1 -1
  25. package/react/index.js.map +1 -1
  26. package/react/metafile-cjs.json +1 -1
  27. package/react/metafile-esm.json +1 -1
  28. package/tests/blockstore/fp-envelope.test.ts-off +65 -0
  29. package/tests/blockstore/interceptor-gateway.test.ts +122 -0
  30. package/tests/blockstore/keyed-crypto-indexdb-file.test.ts +130 -0
  31. package/tests/blockstore/keyed-crypto.test.ts +73 -118
  32. package/tests/blockstore/loader.test.ts +18 -9
  33. package/tests/blockstore/store.test.ts +40 -31
  34. package/tests/blockstore/transaction.test.ts +14 -13
  35. package/tests/fireproof/all-gateway.test.ts +283 -213
  36. package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.ts +324 -316
  37. package/tests/fireproof/crdt.test.ts +78 -19
  38. package/tests/fireproof/database.test.ts +225 -29
  39. package/tests/fireproof/fireproof.test.ts +92 -73
  40. package/tests/fireproof/hello.test.ts +17 -13
  41. package/tests/fireproof/indexer.test.ts +67 -43
  42. package/tests/fireproof/utils.test.ts +47 -6
  43. package/tests/gateway/file/loader-config.test.ts +307 -0
  44. package/tests/gateway/fp-envelope-serialize.test.ts +256 -0
  45. package/tests/gateway/indexdb/loader-config.test.ts +79 -0
  46. package/tests/helpers.ts +44 -17
  47. package/tests/react/useFireproof.test.tsx +1 -1
  48. package/tests/www/todo.html +24 -3
  49. package/web/index.cjs +102 -116
  50. package/web/index.cjs.map +1 -1
  51. package/web/index.d.cts +15 -29
  52. package/web/index.d.ts +15 -29
  53. package/web/index.js +91 -105
  54. package/web/index.js.map +1 -1
  55. package/web/metafile-cjs.json +1 -1
  56. package/web/metafile-esm.json +1 -1
  57. package/node/chunk-4A4RAVNS.js +0 -17
  58. package/node/chunk-4A4RAVNS.js.map +0 -1
  59. package/node/mem-filesystem-LPPT7QV5.js +0 -40
  60. package/node/mem-filesystem-LPPT7QV5.js.map +0 -1
  61. package/tests/fireproof/config.test.ts +0 -163
  62. /package/tests/blockstore/{fragment-gateway.test.ts → fragment-gateway.test.ts-off} +0 -0
  63. /package/tests/fireproof/{multiple-ledger.test.ts → multiple-database.test.ts} +0 -0
package/index.cjs CHANGED
@@ -31,15 +31,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  CRDT: () => CRDT,
34
- Database: () => Database,
34
+ DatabaseFactory: () => DatabaseFactory,
35
+ DatabaseShell: () => DatabaseShell,
35
36
  Index: () => Index,
36
37
  NotFoundError: () => NotFoundError,
37
38
  PACKAGE_VERSION: () => PACKAGE_VERSION,
38
- Result: () => import_cement.Result,
39
+ PARAM: () => PARAM,
39
40
  UInt8ArrayEqual: () => UInt8ArrayEqual,
40
41
  blockstore: () => blockstore_exports,
41
42
  bs: () => blockstore_exports,
42
- dataDir: () => dataDir,
43
+ coerceIntoUint8: () => coerceIntoUint8,
44
+ coercePromiseIntoUint8: () => coercePromiseIntoUint8,
45
+ defaultWriteQueueOpts: () => defaultWriteQueueOpts,
43
46
  ensureLogger: () => ensureLogger,
44
47
  ensureSuperLog: () => ensureSuperLog,
45
48
  ensureSuperThis: () => ensureSuperThis,
@@ -50,248 +53,50 @@ __export(index_exports, {
50
53
  getName: () => getName,
51
54
  getStore: () => getStore,
52
55
  index: () => index,
56
+ inplaceFilter: () => inplaceFilter,
57
+ isDatabase: () => isDatabase,
53
58
  isFalsy: () => isFalsy,
54
59
  isNotFoundError: () => isNotFoundError,
60
+ keyConfigOpts: () => keyConfigOpts,
55
61
  onSuperThis: () => onSuperThis,
56
62
  rt: () => runtime_exports,
57
63
  runtime: () => runtime_exports,
58
- throwFalsy: () => throwFalsy
64
+ throwFalsy: () => throwFalsy,
65
+ toSortedArray: () => toSortedArray,
66
+ toStoreURIRuntime: () => toStoreURIRuntime
59
67
  });
60
68
  module.exports = __toCommonJS(index_exports);
61
69
 
62
70
  // src/database.ts
63
- var import_cement12 = require("@adviser/cement");
64
-
65
- // src/write-queue.ts
66
- function writeQueue(worker, payload = Infinity, unbounded = false) {
67
- const queue = [];
68
- let isProcessing = false;
69
- async function process() {
70
- if (isProcessing || queue.length === 0) return;
71
- isProcessing = true;
72
- const tasksToProcess = queue.splice(0, payload);
73
- const updates = tasksToProcess.map((item) => item.task);
74
- if (unbounded) {
75
- const promises = updates.map(async (update, index2) => {
76
- try {
77
- const result = await worker([update]);
78
- tasksToProcess[index2].resolve(result);
79
- } catch (error) {
80
- tasksToProcess[index2].reject(error);
81
- }
82
- });
83
- await Promise.all(promises);
84
- } else {
85
- try {
86
- const result = await worker(updates);
87
- tasksToProcess.forEach((task) => task.resolve(result));
88
- } catch (error) {
89
- tasksToProcess.forEach((task) => task.reject(error));
90
- }
91
- }
92
- isProcessing = false;
93
- void process();
94
- }
95
- return {
96
- push(task) {
97
- return new Promise((resolve, reject) => {
98
- queue.push({ task, resolve, reject });
99
- void process();
100
- });
101
- }
102
- };
103
- }
104
-
105
- // src/crdt.ts
106
- var import_cement11 = require("@adviser/cement");
107
-
108
- // src/runtime/wait-pr-multiformats/block.ts
109
- var block_exports = {};
110
- __export(block_exports, {
111
- Block: () => Block,
112
- create: () => create,
113
- createUnsafe: () => createUnsafe,
114
- decode: () => decode,
115
- encode: () => encode
116
- });
117
- var import_multiformats = require("multiformats");
118
- var import_block = require("multiformats/block");
119
- var Block = import_block.Block;
120
- async function decode({
121
- bytes,
122
- codec: codec3,
123
- hasher: hasher7
124
- }) {
125
- if (bytes == null) throw new Error('Missing required argument "bytes"');
126
- if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
127
- const value = await Promise.resolve(codec3.decode(bytes));
128
- const hash = await hasher7.digest(bytes);
129
- const cid = import_multiformats.CID.create(1, codec3.code, hash);
130
- return new import_block.Block({ value, bytes, cid });
131
- }
132
- async function encode({
133
- value,
134
- codec: codec3,
135
- hasher: hasher7
136
- }) {
137
- if (typeof value === "undefined") throw new Error('Missing required argument "value"');
138
- if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
139
- const bytes = await Promise.resolve(codec3.encode(value));
140
- const hash = await hasher7.digest(bytes);
141
- const cid = import_multiformats.CID.create(1, codec3.code, hash);
142
- return new import_block.Block({ value, bytes, cid });
143
- }
144
- async function create({
145
- bytes,
146
- cid,
147
- hasher: hasher7,
148
- codec: codec3
149
- }) {
150
- if (bytes == null) throw new Error('Missing required argument "bytes"');
151
- if (hasher7 == null) throw new Error('Missing required argument "hasher"');
152
- const value = await Promise.resolve(codec3.decode(bytes));
153
- const hash = await hasher7.digest(bytes);
154
- if (!import_multiformats.bytes.equals(cid.multihash.bytes, hash.bytes)) {
155
- throw new Error("CID hash does not match bytes");
156
- }
157
- return createUnsafe({
158
- bytes,
159
- cid,
160
- value,
161
- codec: codec3
162
- });
163
- }
164
- async function createUnsafe({
165
- bytes,
166
- cid,
167
- value: maybeValue,
168
- codec: codec3
169
- }) {
170
- const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
171
- if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
172
- return new Block({
173
- cid,
174
- bytes,
175
- value
176
- });
177
- }
178
-
179
- // src/crdt-helpers.ts
180
- var import_link = require("multiformats/link");
181
- var import_sha25 = require("multiformats/hashes/sha2");
182
- var codec = __toESM(require("@fireproof/vendor/@ipld/dag-cbor"), 1);
183
- var import_crdt = require("@fireproof/vendor/@web3-storage/pail/crdt");
184
- var import_clock2 = require("@fireproof/vendor/@web3-storage/pail/clock");
185
- var Batch = __toESM(require("@fireproof/vendor/@web3-storage/pail/crdt/batch"), 1);
186
-
187
- // src/blockstore/index.ts
188
- var blockstore_exports = {};
189
- __export(blockstore_exports, {
190
- BaseBlockstore: () => BaseBlockstore,
191
- CarTransaction: () => CarTransaction,
192
- CompactionFetcher: () => CompactionFetcher,
193
- ConnectionBase: () => ConnectionBase,
194
- EncryptedBlockstore: () => EncryptedBlockstore,
195
- FragmentGateway: () => FragmentGateway,
196
- Loader: () => Loader,
197
- addCryptoKeyToGatewayMetaPayload: () => addCryptoKeyToGatewayMetaPayload,
198
- ensureStart: () => ensureStart,
199
- getGatewayFromURL: () => getGatewayFromURL,
200
- parseCarFile: () => parseCarFile,
201
- registerStoreProtocol: () => registerStoreProtocol,
202
- setCryptoKeyFromGatewayMetaPayload: () => setCryptoKeyFromGatewayMetaPayload,
203
- testStoreFactory: () => testStoreFactory,
204
- toCIDBlock: () => toCIDBlock,
205
- toStoreRuntime: () => toStoreRuntime
206
- });
207
-
208
- // src/blockstore/types.ts
209
- function toCIDBlock(block) {
210
- return block;
211
- }
212
-
213
- // src/blockstore/store-factory.ts
214
- var import_cement9 = require("@adviser/cement");
215
-
216
- // src/runtime/files.ts
217
- var files_exports = {};
218
- __export(files_exports, {
219
- decodeFile: () => decodeFile,
220
- encodeFile: () => encodeFile
221
- });
222
- var UnixFS = __toESM(require("@ipld/unixfs"), 1);
223
- var raw = __toESM(require("multiformats/codecs/raw"), 1);
224
- var import_fixed = require("@ipld/unixfs/file/chunker/fixed");
225
- var import_balanced = require("@ipld/unixfs/file/layout/balanced");
226
- var import_ipfs_unixfs_exporter = require("@fireproof/vendor/ipfs-unixfs-exporter");
227
- var queuingStrategy = UnixFS.withCapacity();
228
- var settings = UnixFS.configure({
229
- fileChunkEncoder: raw,
230
- smallFileEncoder: raw,
231
- chunker: (0, import_fixed.withMaxChunkSize)(1024 * 1024),
232
- fileLayout: (0, import_balanced.withWidth)(1024)
233
- });
234
- async function collect(collectable) {
235
- const chunks = [];
236
- await collectable.pipeTo(
237
- new WritableStream({
238
- write(chunk) {
239
- chunks.push(chunk);
240
- }
241
- })
242
- );
243
- return chunks;
244
- }
245
- async function encodeFile(blob) {
246
- const readable = createFileEncoderStream(blob);
247
- const blocks = await collect(readable);
248
- return { cid: blocks.at(-1).cid, blocks };
249
- }
250
- async function decodeFile(blocks, cid, meta) {
251
- const entry = await (0, import_ipfs_unixfs_exporter.exporter)(cid.toString(), blocks, { length: meta.size });
252
- const chunks = [];
253
- for await (const chunk of entry.content()) {
254
- chunks.push(chunk);
255
- }
256
- return new File(chunks, entry.name, { type: meta.type, lastModified: 0 });
257
- }
258
- function createFileEncoderStream(blob) {
259
- const { readable, writable } = new TransformStream({}, queuingStrategy);
260
- const unixfsWriter = UnixFS.createWriter({ writable, settings });
261
- const fileBuilder = new UnixFSFileBuilder("", blob);
262
- void (async () => {
263
- await fileBuilder.finalize(unixfsWriter);
264
- await unixfsWriter.close();
265
- })();
266
- return readable;
267
- }
268
- var UnixFSFileBuilder = class {
269
- #file;
270
- constructor(name, file) {
271
- this.name = name;
272
- this.#file = file;
273
- }
274
- async finalize(writer) {
275
- const unixfsFileWriter = UnixFS.createFileWriter(writer);
276
- await this.#file.stream().pipeTo(
277
- new WritableStream({
278
- async write(chunk) {
279
- await unixfsFileWriter.write(chunk);
280
- }
281
- })
282
- );
283
- return await unixfsFileWriter.close();
284
- }
285
- };
71
+ var import_cement20 = require("@adviser/cement");
286
72
 
287
- // src/blockstore/store.ts
288
- var import_dag_json2 = require("@fireproof/vendor/@ipld/dag-json");
289
- var import_cement8 = require("@adviser/cement");
73
+ // src/utils.ts
74
+ var import_cement = require("@adviser/cement");
290
75
 
291
76
  // src/types.ts
292
77
  function isFalsy(value) {
293
78
  return value === false && value === null && value === void 0;
294
79
  }
80
+ var PARAM = /* @__PURE__ */ ((PARAM2) => {
81
+ PARAM2["SUFFIX"] = "suffix";
82
+ PARAM2["URL_GEN"] = "urlGen";
83
+ PARAM2["STORE_KEY"] = "storekey";
84
+ PARAM2["STORE"] = "store";
85
+ PARAM2["KEY"] = "key";
86
+ PARAM2["INDEX"] = "index";
87
+ PARAM2["NAME"] = "name";
88
+ PARAM2["VERSION"] = "version";
89
+ PARAM2["RUNTIME"] = "runtime";
90
+ PARAM2["FRAG_SIZE"] = "fragSize";
91
+ PARAM2["IV_VERIFY"] = "ivVerify";
92
+ PARAM2["IV_HASH"] = "ivHash";
93
+ PARAM2["FRAG_FID"] = "fid";
94
+ PARAM2["FRAG_OFS"] = "ofs";
95
+ PARAM2["FRAG_LEN"] = "len";
96
+ PARAM2["FRAG_HEAD"] = "headerSize";
97
+ PARAM2["EXTRACTKEY"] = "extractKey";
98
+ return PARAM2;
99
+ })(PARAM || {});
295
100
  function throwFalsy(value) {
296
101
  if (isFalsy(value)) {
297
102
  throw new Error("value is Falsy");
@@ -306,7 +111,6 @@ function falsyToUndef(value) {
306
111
  }
307
112
 
308
113
  // src/utils.ts
309
- var import_cement = require("@adviser/cement");
310
114
  var import_base58 = require("multiformats/bases/base58");
311
115
  var _globalLogger = new import_cement.ResolveOnce();
312
116
  function globalLogger() {
@@ -374,17 +178,19 @@ var pathOpsImpl = class {
374
178
  dirname(path) {
375
179
  return path.split("/").slice(0, -1).join("/");
376
180
  }
181
+ basename(path) {
182
+ return path.split("/").pop() || "";
183
+ }
377
184
  // homedir() {
378
185
  // throw new Error("SysContainer:homedir is not available in seeded state");
379
186
  // }
380
187
  };
381
188
  var pathOps = new pathOpsImpl();
382
- var txtOps = {
383
- // eslint-disable-next-line no-restricted-globals
384
- encode: (input) => new TextEncoder().encode(input),
189
+ var txtOps = /* @__PURE__ */ ((txtEncoder, txtDecoder) => ({
190
+ encode: (input) => txtEncoder.encode(input),
191
+ decode: (input) => txtDecoder.decode(coerceIntoUint8(input).Ok())
385
192
  // eslint-disable-next-line no-restricted-globals
386
- decode: (input) => new TextDecoder().decode(input)
387
- };
193
+ }))(new TextEncoder(), new TextDecoder());
388
194
  var _onSuperThis = /* @__PURE__ */ new Map();
389
195
  function onSuperThis(fn) {
390
196
  const key = `onSuperThis-${Math.random().toString(36).slice(2)}`;
@@ -416,9 +222,7 @@ function ensureSuperLog(sthis, componentName, ctx) {
416
222
  }
417
223
  function ensureLogger(sthis, componentName, ctx) {
418
224
  let logger;
419
- if ((0, import_cement.IsLogger)(sthis)) {
420
- logger = sthis;
421
- } else if (sthis && (0, import_cement.IsLogger)(sthis.logger)) {
225
+ if (sthis && (0, import_cement.IsLogger)(sthis.logger)) {
422
226
  logger = sthis.logger;
423
227
  } else {
424
228
  logger = globalLogger();
@@ -439,6 +243,10 @@ function ensureLogger(sthis, componentName, ctx) {
439
243
  exposeStack = true;
440
244
  delete ctx.exposeStack;
441
245
  }
246
+ if ("exposeStack" in ctx) {
247
+ exposeStack = true;
248
+ delete ctx.exposeStack;
249
+ }
442
250
  if ("this" in ctx) {
443
251
  cLogger.Str("this", sthis.nextId(4).str);
444
252
  delete ctx.this;
@@ -505,10 +313,13 @@ function ensureLogger(sthis, componentName, ctx) {
505
313
  logger.SetExposeStack(true);
506
314
  }
507
315
  const out = cLogger.Logger();
316
+ if (sthis.env.get("FP_CONSTRUCTOR_DEBUG")) {
317
+ out.Debug().Msg("constructor");
318
+ }
508
319
  return out;
509
320
  }
510
321
  function getStore(url, sthis, joiner) {
511
- const store = url.getParam("store");
322
+ const store = url.getParam("store" /* STORE */);
512
323
  switch (store) {
513
324
  case "data":
514
325
  case "wal":
@@ -516,20 +327,21 @@ function getStore(url, sthis, joiner) {
516
327
  break;
517
328
  default:
518
329
  throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
330
+ throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
519
331
  }
520
332
  let name = store;
521
333
  if (url.hasParam("index")) {
522
- name = joiner(url.getParam("index") || "idx", name);
334
+ name = joiner(url.getParam("index" /* INDEX */) || "idx", name);
523
335
  }
524
336
  return { store, name };
525
337
  }
526
338
  function getKey(url, logger) {
527
- const result = url.getParam("key");
339
+ const result = url.getParam("key" /* KEY */);
528
340
  if (!result) throw logger.Error().Str("url", url.toString()).Msg(`key not found`).AsError();
529
341
  return result;
530
342
  }
531
343
  function getName(sthis, url) {
532
- let result = url.getParam("name");
344
+ let result = url.getParam("name" /* NAME */);
533
345
  if (!result) {
534
346
  result = sthis.pathOps.dirname(url.pathname);
535
347
  if (result.length === 0) {
@@ -538,50 +350,337 @@ function getName(sthis, url) {
538
350
  }
539
351
  return result;
540
352
  }
541
- async function exceptionWrapper(fn) {
542
- return fn().catch((e) => import_cement.Result.Err(e));
353
+ async function exceptionWrapper(fn) {
354
+ return fn().catch((e) => import_cement.Result.Err(e));
355
+ }
356
+ var NotFoundError = class extends Error {
357
+ constructor() {
358
+ super(...arguments);
359
+ this.code = "ENOENT";
360
+ }
361
+ };
362
+ function isNotFoundError(e) {
363
+ if (import_cement.Result.Is(e)) {
364
+ if (e.isOk()) return false;
365
+ e = e.Err();
366
+ }
367
+ if (e.code === "ENOENT") return true;
368
+ return false;
369
+ }
370
+ function UInt8ArrayEqual(a, b) {
371
+ if (a.length !== b.length) {
372
+ return false;
373
+ }
374
+ for (let i = 0; i < a.length; i++) {
375
+ if (a[i] !== b[i]) {
376
+ return false;
377
+ }
378
+ }
379
+ return true;
380
+ }
381
+ function inplaceFilter(i, pred) {
382
+ const founds = [];
383
+ for (let j = 0; j < i.length; j++) {
384
+ if (!pred(i[j], j)) {
385
+ founds.push(j);
386
+ }
387
+ }
388
+ for (let j = founds.length - 1; j >= 0; j--) {
389
+ i.splice(founds[j], 1);
390
+ }
391
+ return i;
392
+ }
393
+ function toSortedArray(set) {
394
+ if (!set) return [];
395
+ return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
396
+ }
397
+ function coerceIntoUint8(raw2) {
398
+ if (raw2 instanceof Uint8Array) {
399
+ return import_cement.Result.Ok(raw2);
400
+ }
401
+ if (import_cement.Result.Is(raw2)) {
402
+ return raw2;
403
+ }
404
+ return import_cement.Result.Err("Not a Uint8Array");
405
+ }
406
+ async function coercePromiseIntoUint8(raw2) {
407
+ if (raw2 instanceof Uint8Array) {
408
+ return import_cement.Result.Ok(raw2);
409
+ }
410
+ if (import_cement.Result.Is(raw2)) {
411
+ return raw2;
412
+ }
413
+ if (typeof raw2.then === "function") {
414
+ try {
415
+ return coercePromiseIntoUint8(await raw2);
416
+ } catch (e) {
417
+ return import_cement.Result.Err(e);
418
+ }
419
+ }
420
+ return import_cement.Result.Err("Not a Uint8Array");
421
+ }
422
+
423
+ // src/write-queue.ts
424
+ var import_cement2 = require("@adviser/cement");
425
+ function defaultWriteQueueOpts(opts = {}) {
426
+ return {
427
+ ...opts,
428
+ chunkSize: opts.chunkSize && opts.chunkSize > 0 ? opts.chunkSize : 32
429
+ };
430
+ }
431
+ var WriteQueueImpl = class {
432
+ constructor(sthis, worker, opts) {
433
+ this.queue = [];
434
+ this.isProcessing = false;
435
+ this.logger = ensureLogger(sthis, "WriteQueueImpl");
436
+ this.worker = worker;
437
+ this.opts = defaultWriteQueueOpts(opts);
438
+ }
439
+ testEmptyQueue() {
440
+ if (this.waitForEmptyQueue && this.queue.length === 0) {
441
+ this.waitForEmptyQueue.resolve();
442
+ }
443
+ }
444
+ async process() {
445
+ if (this.isProcessing || this.queue.length === 0) {
446
+ this.testEmptyQueue();
447
+ return;
448
+ }
449
+ this.isProcessing = true;
450
+ try {
451
+ this.logger.Debug().Any("opts", this.opts).Len(this.queue).Msg("Processing tasks");
452
+ const tasksToProcess = this.queue.splice(0, this.opts.chunkSize);
453
+ const updates = tasksToProcess.map((item) => item.tasks).filter((item) => item);
454
+ const promises = updates.map(async (update, index2) => {
455
+ try {
456
+ const result = await this.worker(update);
457
+ tasksToProcess[index2].resolve(result);
458
+ } catch (error) {
459
+ tasksToProcess[index2].reject(this.logger.Error().Err(error).Msg("Error processing task").AsError());
460
+ }
461
+ });
462
+ await Promise.allSettled(promises);
463
+ this.logger.Debug().Any("opts", this.opts).Len(this.queue).Msg("Processed tasks");
464
+ } catch (error) {
465
+ this.logger.Error().Err(error).Msg("Error processing tasks");
466
+ } finally {
467
+ this.isProcessing = false;
468
+ setTimeout(() => this.process(), 0);
469
+ }
470
+ }
471
+ bulk(tasks) {
472
+ return new Promise((resolve, reject) => {
473
+ this.queue.push({ tasks, resolve, reject });
474
+ this.process();
475
+ });
476
+ }
477
+ push(task) {
478
+ return this.bulk([task]);
479
+ }
480
+ close() {
481
+ this.waitForEmptyQueue = new import_cement2.Future();
482
+ this.testEmptyQueue();
483
+ return this.waitForEmptyQueue.asPromise();
484
+ }
485
+ };
486
+ function writeQueue(sthis, worker, opts) {
487
+ return new WriteQueueImpl(sthis, worker, opts);
488
+ }
489
+
490
+ // src/crdt.ts
491
+ var import_cement19 = require("@adviser/cement");
492
+
493
+ // src/blockstore/index.ts
494
+ var blockstore_exports = {};
495
+ __export(blockstore_exports, {
496
+ BaseBlockstore: () => BaseBlockstore,
497
+ Car2FPMsg: () => Car2FPMsg,
498
+ CarTransaction: () => CarTransaction,
499
+ CompactionFetcher: () => CompactionFetcher,
500
+ ConnectionBase: () => ConnectionBase,
501
+ DbMetaEventEqual: () => DbMetaEventEqual,
502
+ DbMetaEventsEqual: () => DbMetaEventsEqual,
503
+ EncryptedBlockstore: () => EncryptedBlockstore,
504
+ FPEnvelopeType: () => FPEnvelopeType,
505
+ File2FPMsg: () => File2FPMsg,
506
+ InterceptorGateway: () => InterceptorGateway,
507
+ Loader: () => Loader,
508
+ PassThroughGateway: () => PassThroughGateway,
509
+ createDbMetaEvent: () => createDbMetaEvent,
510
+ defaultGatewayFactoryItem: () => defaultGatewayFactoryItem,
511
+ ensureStoreEnDeFile: () => ensureStoreEnDeFile,
512
+ getDefaultURI: () => getDefaultURI,
513
+ getGatewayFactoryItem: () => getGatewayFactoryItem,
514
+ getStartedGateway: () => getStartedGateway,
515
+ parseCarFile: () => parseCarFile,
516
+ registerStoreProtocol: () => registerStoreProtocol,
517
+ toCIDBlock: () => toCIDBlock,
518
+ toStoreRuntime: () => toStoreRuntime
519
+ });
520
+
521
+ // src/blockstore/types.ts
522
+ function toCIDBlock(block) {
523
+ return block;
524
+ }
525
+ function DbMetaEventEqual(a, b) {
526
+ return a.eventCid.equals(b.eventCid) && a.parents.length === b.parents.length && a.parents.every((p, i) => p.equals(b.parents[i])) && a.dbMeta.cars.length === b.dbMeta.cars.length && a.dbMeta.cars.every((c, i) => c.equals(b.dbMeta.cars[i]));
527
+ }
528
+ function DbMetaEventsEqual(a, b) {
529
+ return a.length === b.length && a.every((e, i) => DbMetaEventEqual(e, b[i]));
530
+ }
531
+
532
+ // src/blockstore/store-factory.ts
533
+ var import_cement17 = require("@adviser/cement");
534
+
535
+ // src/runtime/files.ts
536
+ var files_exports = {};
537
+ __export(files_exports, {
538
+ decodeFile: () => decodeFile,
539
+ encodeFile: () => encodeFile
540
+ });
541
+ var UnixFS = __toESM(require("@ipld/unixfs"), 1);
542
+ var raw = __toESM(require("multiformats/codecs/raw"), 1);
543
+ var import_fixed = require("@ipld/unixfs/file/chunker/fixed");
544
+ var import_balanced = require("@ipld/unixfs/file/layout/balanced");
545
+ var import_ipfs_unixfs_exporter = require("@fireproof/vendor/ipfs-unixfs-exporter");
546
+ var queuingStrategy = UnixFS.withCapacity();
547
+ var settings = UnixFS.configure({
548
+ fileChunkEncoder: raw,
549
+ smallFileEncoder: raw,
550
+ chunker: (0, import_fixed.withMaxChunkSize)(1024 * 1024),
551
+ fileLayout: (0, import_balanced.withWidth)(1024)
552
+ });
553
+ async function collect(collectable) {
554
+ const chunks = [];
555
+ await collectable.pipeTo(
556
+ new WritableStream({
557
+ write(chunk) {
558
+ chunks.push(chunk);
559
+ }
560
+ })
561
+ );
562
+ return chunks;
563
+ }
564
+ async function encodeFile(blob) {
565
+ const readable = createFileEncoderStream(blob);
566
+ const blocks = await collect(readable);
567
+ return { cid: blocks.at(-1).cid, blocks };
543
568
  }
544
- var NotFoundError = class extends Error {
545
- constructor() {
546
- super(...arguments);
547
- this.code = "ENOENT";
548
- }
549
- };
550
- function isNotFoundError(e) {
551
- if (import_cement.Result.Is(e)) {
552
- if (e.isOk()) return false;
553
- e = e.Err();
569
+ async function decodeFile(blocks, cid, meta) {
570
+ const entry = await (0, import_ipfs_unixfs_exporter.exporter)(cid.toString(), blocks, { length: meta.size });
571
+ const chunks = [];
572
+ for await (const chunk of entry.content()) {
573
+ chunks.push(chunk);
554
574
  }
555
- if (e.code === "ENOENT") return true;
556
- return false;
575
+ return new File(chunks, entry.name, { type: meta.type, lastModified: 0 });
557
576
  }
558
- function dataDir(sthis, name, base) {
559
- if (!base) {
560
- if (!(0, import_cement.runtimeFn)().isBrowser) {
561
- const home = sthis.env.get("HOME") || "./";
562
- base = sthis.env.get("FP_STORAGE_URL") || `file://${sthis.pathOps.join(home, ".fireproof")}`;
563
- } else {
564
- base = sthis.env.get("FP_STORAGE_URL") || `indexdb://fp`;
565
- }
566
- }
567
- return import_cement.URI.from(base.toString()).build().setParam("name", name || "").URI();
577
+ function createFileEncoderStream(blob) {
578
+ const { readable, writable } = new TransformStream({}, queuingStrategy);
579
+ const unixfsWriter = UnixFS.createWriter({ writable, settings });
580
+ const fileBuilder = new UnixFSFileBuilder("", blob);
581
+ void (async () => {
582
+ await fileBuilder.finalize(unixfsWriter);
583
+ await unixfsWriter.close();
584
+ })();
585
+ return readable;
568
586
  }
569
- function UInt8ArrayEqual(a, b) {
570
- if (a.length !== b.length) {
571
- return false;
587
+ var UnixFSFileBuilder = class {
588
+ #file;
589
+ constructor(name, file) {
590
+ this.name = name;
591
+ this.#file = file;
572
592
  }
573
- for (let i = 0; i < a.length; i++) {
574
- if (a[i] !== b[i]) {
575
- return false;
576
- }
593
+ async finalize(writer) {
594
+ const unixfsFileWriter = UnixFS.createFileWriter(writer);
595
+ await this.#file.stream().pipeTo(
596
+ new WritableStream({
597
+ async write(chunk) {
598
+ await unixfsFileWriter.write(chunk);
599
+ }
600
+ })
601
+ );
602
+ return await unixfsFileWriter.close();
577
603
  }
578
- return true;
579
- }
604
+ };
605
+
606
+ // src/blockstore/store.ts
607
+ var import_cement10 = require("@adviser/cement");
580
608
 
581
609
  // src/blockstore/loader.ts
582
610
  var import_p_limit = __toESM(require("p-limit"), 1);
583
611
  var import_reader = require("@fireproof/vendor/@ipld/car/reader");
584
- var import_cement5 = require("@adviser/cement");
612
+ var import_cement7 = require("@adviser/cement");
613
+
614
+ // src/runtime/wait-pr-multiformats/block.ts
615
+ var block_exports = {};
616
+ __export(block_exports, {
617
+ Block: () => Block,
618
+ create: () => create,
619
+ createUnsafe: () => createUnsafe,
620
+ decode: () => decode,
621
+ encode: () => encode
622
+ });
623
+ var import_multiformats = require("multiformats");
624
+ var import_block = require("multiformats/block");
625
+ var Block = import_block.Block;
626
+ async function decode({
627
+ bytes,
628
+ codec: codec3,
629
+ hasher: hasher7
630
+ }) {
631
+ if (bytes == null) throw new Error('Missing required argument "bytes"');
632
+ if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
633
+ const value = await Promise.resolve(codec3.decode(bytes));
634
+ const hash = await hasher7.digest(bytes);
635
+ const cid = import_multiformats.CID.create(1, codec3.code, hash);
636
+ return new import_block.Block({ value, bytes, cid });
637
+ }
638
+ async function encode({
639
+ value,
640
+ codec: codec3,
641
+ hasher: hasher7
642
+ }) {
643
+ if (typeof value === "undefined") throw new Error('Missing required argument "value"');
644
+ if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
645
+ const bytes = await Promise.resolve(codec3.encode(value));
646
+ const hash = await hasher7.digest(bytes);
647
+ const cid = import_multiformats.CID.create(1, codec3.code, hash);
648
+ return new import_block.Block({ value, bytes, cid });
649
+ }
650
+ async function create({
651
+ bytes,
652
+ cid,
653
+ hasher: hasher7,
654
+ codec: codec3
655
+ }) {
656
+ if (bytes == null) throw new Error('Missing required argument "bytes"');
657
+ if (hasher7 == null) throw new Error('Missing required argument "hasher"');
658
+ const value = await Promise.resolve(codec3.decode(bytes));
659
+ const hash = await hasher7.digest(bytes);
660
+ if (!import_multiformats.bytes.equals(cid.multihash.bytes, hash.bytes)) {
661
+ throw new Error("CID hash does not match bytes");
662
+ }
663
+ return createUnsafe({
664
+ bytes,
665
+ cid,
666
+ value,
667
+ codec: codec3
668
+ });
669
+ }
670
+ async function createUnsafe({
671
+ bytes,
672
+ cid,
673
+ value: maybeValue,
674
+ codec: codec3
675
+ }) {
676
+ const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
677
+ if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
678
+ return new Block({
679
+ cid,
680
+ bytes,
681
+ value
682
+ });
683
+ }
585
684
 
586
685
  // src/blockstore/loader-helpers.ts
587
686
  var import_sha2 = require("multiformats/hashes/sha2");
@@ -600,7 +699,7 @@ async function parseCarFile(reader, logger) {
600
699
 
601
700
  // src/blockstore/transaction.ts
602
701
  var import_block3 = require("@fireproof/vendor/@web3-storage/pail/block");
603
- var import_cement2 = require("@adviser/cement");
702
+ var import_cement3 = require("@adviser/cement");
604
703
  var CarTransaction = class extends import_block3.MemoryBlockstore {
605
704
  constructor(parent, opts = { add: true, noLoader: false }) {
606
705
  super();
@@ -618,7 +717,6 @@ var CarTransaction = class extends import_block3.MemoryBlockstore {
618
717
  };
619
718
  function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
620
719
  const logger = ensureLogger(sthis, component, ctx);
621
- const store = opts.store || {};
622
720
  return {
623
721
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
624
722
  applyMeta: (meta, snap) => {
@@ -630,30 +728,27 @@ function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
630
728
  },
631
729
  autoCompact: 100,
632
730
  public: false,
633
- name: void 0,
731
+ // name: undefined,
634
732
  threshold: 1e3 * 1e3,
635
733
  ...opts,
636
734
  logger,
637
735
  keyBag: opts.keyBag || {},
638
- crypto: (0, import_cement2.toCryptoRuntime)(opts.crypto),
639
- store,
640
- storeRuntime: toStoreRuntime(store, sthis)
736
+ crypto: (0, import_cement3.toCryptoRuntime)(opts.crypto),
737
+ storeUrls: opts.storeUrls,
738
+ // storeEnDeFile: ensureStoreEnDeFile(opts.storeEnDeFile),
739
+ // store,
740
+ storeRuntime: toStoreRuntime(sthis, ensureStoreEnDeFile(opts.storeEnDeFile))
641
741
  };
642
742
  }
643
- function blockstoreFactory(sthis, opts) {
644
- if (opts.name) {
645
- return new EncryptedBlockstore(sthis, opts);
646
- } else {
647
- return new BaseBlockstore(opts);
648
- }
649
- }
650
743
  var BaseBlockstore = class {
651
- constructor(ebOpts = {}) {
744
+ constructor(ebOpts) {
652
745
  this.transactions = /* @__PURE__ */ new Set();
653
746
  this.sthis = ensureSuperThis(ebOpts);
654
747
  this.ebOpts = defaultedBlockstoreRuntime(this.sthis, ebOpts, "BaseBlockstore");
655
748
  this.logger = this.ebOpts.logger;
749
+ this.loader = new Loader(this.sthis, ebOpts);
656
750
  }
751
+ // readonly name?: string;
657
752
  // ready: Promise<void>;
658
753
  ready() {
659
754
  return Promise.resolve();
@@ -677,8 +772,11 @@ var BaseBlockstore = class {
677
772
  }
678
773
  // TransactionMeta
679
774
  async transaction(fn, _opts) {
775
+ this.logger.Debug().Msg("enter transaction");
680
776
  const t = new CarTransaction(this, _opts);
777
+ this.logger.Debug().Msg("post CarTransaction");
681
778
  const done = await fn(t);
779
+ this.logger.Debug().Msg("post fn");
682
780
  this.lastTxMeta = done;
683
781
  return { t, meta: done };
684
782
  }
@@ -687,7 +785,7 @@ var BaseBlockstore = class {
687
785
  }
688
786
  async commitTransaction(t, done, opts) {
689
787
  if (!this.loader) throw this.logger.Error().Msg("loader required to commit").AsError();
690
- const cars = await this.loader?.commit(t, done, opts);
788
+ const cars = await this.loader.commit(t, done, opts);
691
789
  if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
692
790
  setTimeout(() => void this.compact(), 10);
693
791
  }
@@ -712,14 +810,11 @@ var EncryptedBlockstore = class extends BaseBlockstore {
712
810
  constructor(sthis, ebOpts) {
713
811
  super(ebOpts);
714
812
  this.compacting = false;
715
- this.logger = ensureLogger(this.sthis, "EncryptedBlockstore");
716
- const { name } = ebOpts;
717
- if (!name) {
718
- throw this.logger.Error().Msg("name required").AsError();
719
- }
720
- this.name = name;
721
- this.loader = new Loader(this.name, ebOpts, sthis);
813
+ this.logger = ensureLogger(this.sthis, "EncryptedBlockstore", {
814
+ this: 1
815
+ });
722
816
  }
817
+ // readonly name: string;
723
818
  ready() {
724
819
  return this.loader.ready();
725
820
  }
@@ -738,8 +833,11 @@ var EncryptedBlockstore = class extends BaseBlockstore {
738
833
  return falsyToUndef(await this.loader.getBlock(cid));
739
834
  }
740
835
  async transaction(fn, opts = { noLoader: false }) {
836
+ this.logger.Debug().Msg("enter transaction");
741
837
  const { t, meta: done } = await super.transaction(fn);
838
+ this.logger.Debug().Msg("post super.transaction");
742
839
  const cars = await this.loader.commit(t, done, opts);
840
+ this.logger.Debug().Msg("post this.loader.commit");
743
841
  if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
744
842
  setTimeout(() => void this.compact(), 10);
745
843
  }
@@ -769,7 +867,7 @@ var EncryptedBlockstore = class extends BaseBlockstore {
769
867
  const blockLog = new CompactionFetcher(this);
770
868
  this.compacting = true;
771
869
  const meta = await compactFn(blockLog);
772
- await this.loader?.commit(blockLog.loggedBlocks, meta, {
870
+ await this.loader.commit(blockLog.loggedBlocks, meta, {
773
871
  compact: true,
774
872
  noLoader: true
775
873
  });
@@ -811,7 +909,7 @@ var CompactionFetcher = class {
811
909
  };
812
910
 
813
911
  // src/blockstore/commit-queue.ts
814
- var import_cement3 = require("@adviser/cement");
912
+ var import_cement4 = require("@adviser/cement");
815
913
  var CommitQueue = class {
816
914
  constructor() {
817
915
  this.queue = [];
@@ -822,7 +920,7 @@ var CommitQueue = class {
822
920
  if (this.queue.length === 0 && !this.processing) {
823
921
  return Promise.resolve();
824
922
  }
825
- const fn = new import_cement3.Future();
923
+ const fn = new import_cement4.Future();
826
924
  this._waitIdleItems.add(fn);
827
925
  return fn.asPromise();
828
926
  }
@@ -865,22 +963,103 @@ var CommitQueue = class {
865
963
  var key_bag_exports = {};
866
964
  __export(key_bag_exports, {
867
965
  KeyBag: () => KeyBag,
966
+ defaultKeyBagOpts: () => defaultKeyBagOpts,
868
967
  defaultKeyBagUrl: () => defaultKeyBagUrl,
869
968
  getKeyBag: () => getKeyBag,
870
969
  registerKeyBagProviderFactory: () => registerKeyBagProviderFactory
871
970
  });
872
- var import_cement4 = require("@adviser/cement");
971
+ var import_cement6 = require("@adviser/cement");
873
972
  var import_base582 = require("multiformats/bases/base58");
973
+
974
+ // src/runtime/gateways/file/sys-file-system-factory.ts
975
+ var import_cement5 = require("@adviser/cement");
976
+ function sysFileSystemFactory(uri) {
977
+ const rt = (0, import_cement5.runtimeFn)();
978
+ switch (true) {
979
+ case rt.isNodeIsh:
980
+ return import("@fireproof/core/node").then((m) => m.getSysFileSystem(uri));
981
+ case rt.isDeno:
982
+ return import("@fireproof/core/deno").then((m) => m.getSysFileSystem(uri));
983
+ default:
984
+ throw new Error(`unsupported runtime:${rt}`);
985
+ }
986
+ }
987
+
988
+ // src/runtime/gateways/file/key-bag-file.ts
989
+ var KeyBagProviderFile = class {
990
+ async _prepare(id) {
991
+ await this.sthis.start();
992
+ const sysFS = await sysFileSystemFactory(this.url);
993
+ const dirName = this.url.pathname;
994
+ await sysFS.mkdir(dirName, { recursive: true });
995
+ return {
996
+ dirName,
997
+ sysFS,
998
+ fName: this.sthis.pathOps.join(dirName, `${id.replace(/[^a-zA-Z0-9]/g, "_")}.json`)
999
+ };
1000
+ }
1001
+ constructor(url, sthis) {
1002
+ this.url = url;
1003
+ this.sthis = sthis;
1004
+ this.logger = sthis.logger;
1005
+ }
1006
+ async get(id) {
1007
+ const ctx = await this._prepare(id);
1008
+ try {
1009
+ const p = await ctx.sysFS.readfile(ctx.fName);
1010
+ const ki = JSON.parse(this.sthis.txt.decode(p));
1011
+ return ki;
1012
+ } catch (e) {
1013
+ if (isNotFoundError(e)) {
1014
+ return void 0;
1015
+ }
1016
+ throw this.logger.Error().Err(e).Str("file", ctx.dirName).Msg("read bag failed").AsError();
1017
+ }
1018
+ }
1019
+ async set(id, item) {
1020
+ const ctx = await this._prepare(id);
1021
+ const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
1022
+ await ctx.sysFS.writefile(ctx.fName, p);
1023
+ }
1024
+ };
1025
+
1026
+ // src/runtime/key-bag-memory.ts
1027
+ var memoryKeyBag = /* @__PURE__ */ new Map();
1028
+ var KeyBagProviderMemory = class {
1029
+ constructor(url, sthis) {
1030
+ this.url = url;
1031
+ this.sthis = sthis;
1032
+ }
1033
+ key(id) {
1034
+ return `${this.url.pathname}/${id}`;
1035
+ }
1036
+ async get(id) {
1037
+ const binKeyItem = memoryKeyBag.get(this.key(id));
1038
+ if (binKeyItem) {
1039
+ const ki = JSON.parse(this.sthis.txt.decode(binKeyItem));
1040
+ return ki;
1041
+ }
1042
+ return void 0;
1043
+ }
1044
+ async set(id, item) {
1045
+ const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
1046
+ memoryKeyBag.set(this.key(id), p);
1047
+ }
1048
+ };
1049
+
1050
+ // src/runtime/key-bag.ts
874
1051
  var KeyBag = class {
875
1052
  constructor(rt) {
876
1053
  this.rt = rt;
877
- this._warnOnce = new import_cement4.ResolveOnce();
878
- this._seq = new import_cement4.ResolveSeq();
879
- this.logger = ensureLogger(rt.sthis, "KeyBag");
1054
+ this._warnOnce = new import_cement6.ResolveOnce();
1055
+ this._seq = new import_cement6.ResolveSeq();
1056
+ this.logger = ensureLogger(rt.sthis, "KeyBag", {
1057
+ // id: rt.id(),
1058
+ });
880
1059
  this.logger.Debug().Msg("KeyBag created");
881
1060
  }
882
1061
  async subtleKey(key) {
883
- const extractable = this.rt.url.getParam("extractKey") === "_deprecated_internal_api";
1062
+ const extractable = this.rt.url.getParam("extractKey" /* EXTRACTKEY */) === "_deprecated_internal_api";
884
1063
  if (extractable) {
885
1064
  this._warnOnce.once(
886
1065
  () => this.logger.Warn().Msg("extractKey is enabled via _deprecated_internal_api --- handle keys safely!!!")
@@ -897,9 +1076,9 @@ var KeyBag = class {
897
1076
  );
898
1077
  }
899
1078
  async ensureKeyFromUrl(url, keyFactory) {
900
- const storeKey = url.getParam("storekey");
1079
+ const storeKey = url.getParam("storekey" /* STORE_KEY */);
901
1080
  if (storeKey === "insecure") {
902
- return import_cement4.Result.Ok(url);
1081
+ return import_cement6.Result.Ok(url);
903
1082
  }
904
1083
  if (!storeKey) {
905
1084
  const keyName = `@${keyFactory()}@`;
@@ -907,8 +1086,8 @@ var KeyBag = class {
907
1086
  if (ret.isErr()) {
908
1087
  return ret;
909
1088
  }
910
- const urb = url.build().setParam("storekey", keyName);
911
- return import_cement4.Result.Ok(urb.URI());
1089
+ const urb = url.build().setParam("storekey" /* STORE_KEY */, keyName);
1090
+ return import_cement6.Result.Ok(urb.URI());
912
1091
  }
913
1092
  if (storeKey.startsWith("@") && storeKey.endsWith("@")) {
914
1093
  const ret = await this.getNamedKey(storeKey);
@@ -916,13 +1095,13 @@ var KeyBag = class {
916
1095
  return ret;
917
1096
  }
918
1097
  }
919
- return import_cement4.Result.Ok(url);
1098
+ return import_cement6.Result.Ok(url);
920
1099
  }
921
1100
  async toKeyWithFingerPrint(keyStr) {
922
1101
  const material = import_base582.base58btc.decode(keyStr);
923
1102
  const key = await this.subtleKey(keyStr);
924
1103
  const fpr = await this.rt.crypto.digestSHA256(material);
925
- return import_cement4.Result.Ok({
1104
+ return import_cement6.Result.Ok({
926
1105
  key,
927
1106
  fingerPrint: import_base582.base58btc.encode(new Uint8Array(fpr))
928
1107
  });
@@ -947,7 +1126,7 @@ var KeyBag = class {
947
1126
  return ret;
948
1127
  }
949
1128
  const named = ret.Ok();
950
- return import_cement4.Result.Ok({
1129
+ return import_cement6.Result.Ok({
951
1130
  ...named,
952
1131
  extract: async () => {
953
1132
  const ext = new Uint8Array(await this.rt.crypto.exportKey("raw", named.key));
@@ -970,7 +1149,7 @@ var KeyBag = class {
970
1149
  }
971
1150
  if (failIfNotFound) {
972
1151
  this.logger.Debug().Str("id", id).Str("name", name).Msg("failIfNotFound getNamedKey");
973
- return import_cement4.Result.Err(new Error(`Key not found: ${name}`));
1152
+ return import_cement6.Result.Err(new Error(`Key not found: ${name}`));
974
1153
  }
975
1154
  const ret = await this._setNamedKey(name, import_base582.base58btc.encode(this.rt.crypto.randomBytes(this.rt.keyLength)));
976
1155
  this.logger.Debug().Str("id", id).Str("name", name).Result("fpr", ret).Msg("createKey getNamedKey-post");
@@ -983,8 +1162,7 @@ var keyBagProviderFactories = new Map(
983
1162
  {
984
1163
  protocol: "file:",
985
1164
  factory: async (url, sthis) => {
986
- const { KeyBagProviderImpl } = await import("@fireproof/core/node");
987
- return new KeyBagProviderImpl(url, sthis);
1165
+ return new KeyBagProviderFile(url, sthis);
988
1166
  }
989
1167
  },
990
1168
  {
@@ -993,6 +1171,12 @@ var keyBagProviderFactories = new Map(
993
1171
  const { KeyBagProviderImpl } = await import("@fireproof/core/web");
994
1172
  return new KeyBagProviderImpl(url, sthis);
995
1173
  }
1174
+ },
1175
+ {
1176
+ protocol: "memory:",
1177
+ factory: async (url, sthis) => {
1178
+ return new KeyBagProviderMemory(url, sthis);
1179
+ }
996
1180
  }
997
1181
  ].map((i) => [i.protocol, i])
998
1182
  );
@@ -1006,15 +1190,15 @@ function registerKeyBagProviderFactory(item) {
1006
1190
  function defaultKeyBagUrl(sthis) {
1007
1191
  let bagFnameOrUrl = sthis.env.get("FP_KEYBAG_URL");
1008
1192
  let url;
1009
- if ((0, import_cement4.runtimeFn)().isBrowser) {
1010
- url = import_cement4.URI.from(bagFnameOrUrl || "indexdb://fp-keybag");
1193
+ if ((0, import_cement6.runtimeFn)().isBrowser) {
1194
+ url = import_cement6.URI.from(bagFnameOrUrl || "indexdb://fp-keybag");
1011
1195
  } else {
1012
1196
  if (!bagFnameOrUrl) {
1013
1197
  const home = sthis.env.get("HOME");
1014
1198
  bagFnameOrUrl = `${home}/.fireproof/keybag`;
1015
- url = import_cement4.URI.from(`file://${bagFnameOrUrl}`);
1199
+ url = import_cement6.URI.from(`file://${bagFnameOrUrl}`);
1016
1200
  } else {
1017
- url = import_cement4.URI.from(bagFnameOrUrl);
1201
+ url = import_cement6.URI.from(bagFnameOrUrl);
1018
1202
  }
1019
1203
  }
1020
1204
  const logger = ensureLogger(sthis, "defaultKeyBagUrl");
@@ -1022,38 +1206,50 @@ function defaultKeyBagUrl(sthis) {
1022
1206
  return url;
1023
1207
  }
1024
1208
  function defaultKeyBagOpts(sthis, kbo) {
1209
+ kbo = kbo || {};
1025
1210
  if (kbo.keyRuntime) {
1026
1211
  return kbo.keyRuntime;
1027
1212
  }
1028
1213
  const logger = ensureLogger(sthis, "KeyBag");
1029
1214
  let url;
1030
1215
  if (kbo.url) {
1031
- url = import_cement4.URI.from(kbo.url);
1216
+ url = import_cement6.URI.from(kbo.url);
1032
1217
  logger.Debug().Url(url).Msg("from opts");
1033
1218
  } else {
1034
- url = defaultKeyBagUrl(sthis);
1219
+ let bagFnameOrUrl = sthis.env.get("FP_KEYBAG_URL");
1220
+ if ((0, import_cement6.runtimeFn)().isBrowser) {
1221
+ url = import_cement6.URI.from(bagFnameOrUrl || "indexdb://fp-keybag");
1222
+ } else {
1223
+ if (!bagFnameOrUrl) {
1224
+ const home = sthis.env.get("HOME");
1225
+ bagFnameOrUrl = `${home}/.fireproof/keybag`;
1226
+ url = import_cement6.URI.from(`file://${bagFnameOrUrl}`);
1227
+ } else {
1228
+ url = import_cement6.URI.from(bagFnameOrUrl);
1229
+ }
1230
+ }
1231
+ logger.Debug().Url(url).Msg("from env");
1035
1232
  }
1036
1233
  const kitem = keyBagProviderFactories.get(url.protocol);
1037
1234
  if (!kitem) {
1038
1235
  throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
1039
1236
  }
1040
- const getBag = async () => kitem.factory(url, sthis);
1041
1237
  if (url.hasParam("masterkey")) {
1042
1238
  throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
1043
1239
  }
1044
1240
  return {
1045
1241
  url,
1046
- crypto: kbo.crypto || (0, import_cement4.toCryptoRuntime)({}),
1242
+ crypto: kbo.crypto || (0, import_cement6.toCryptoRuntime)({}),
1047
1243
  sthis,
1048
1244
  logger,
1049
1245
  keyLength: kbo.keyLength || 16,
1050
- getBag,
1246
+ getBag: () => kitem.factory(url, sthis),
1051
1247
  id: () => {
1052
1248
  return url.toString();
1053
1249
  }
1054
1250
  };
1055
1251
  }
1056
- var _keyBags = new import_cement4.KeyedResolvOnce();
1252
+ var _keyBags = new import_cement6.KeyedResolvOnce();
1057
1253
  async function getKeyBag(sthis, kbo = {}) {
1058
1254
  await sthis.start();
1059
1255
  const rt = defaultKeyBagOpts(sthis, kbo);
@@ -1072,7 +1268,7 @@ async function encodeCarFile(roots, t, codec3) {
1072
1268
  size += CBW.blockLength({ cid, bytes });
1073
1269
  }
1074
1270
  const buffer = new Uint8Array(size);
1075
- const writer = CBW.createWriter(buffer, { headerSize });
1271
+ const writer = CBW.createWriter(buffer.buffer, { headerSize });
1076
1272
  for (const r of roots) {
1077
1273
  writer.addRoot(r);
1078
1274
  }
@@ -1227,7 +1423,7 @@ function uniqueCids(list, remove = /* @__PURE__ */ new Set()) {
1227
1423
  return [...byString.values()];
1228
1424
  }
1229
1425
  var Loader = class {
1230
- constructor(name, ebOpts, sthis) {
1426
+ constructor(sthis, ebOpts) {
1231
1427
  this.commitQueue = new CommitQueue();
1232
1428
  this.isCompacting = false;
1233
1429
  this.carReaders = /* @__PURE__ */ new Map();
@@ -1237,14 +1433,17 @@ var Loader = class {
1237
1433
  this.getBlockCache = /* @__PURE__ */ new Map();
1238
1434
  this.seenMeta = /* @__PURE__ */ new Set();
1239
1435
  this.writeLimit = (0, import_p_limit.default)(1);
1240
- this.onceReady = new import_cement5.ResolveOnce();
1241
- this.name = name;
1436
+ this._carStore = new import_cement7.ResolveOnce();
1437
+ this._fileStore = new import_cement7.ResolveOnce();
1438
+ this._WALStore = new import_cement7.ResolveOnce();
1439
+ this._metaStore = new import_cement7.ResolveOnce();
1440
+ this.onceReady = new import_cement7.ResolveOnce();
1242
1441
  this.sthis = sthis;
1243
1442
  this.ebOpts = defaultedBlockstoreRuntime(
1244
1443
  sthis,
1245
1444
  {
1246
- ...ebOpts,
1247
- name
1445
+ ...ebOpts
1446
+ // name,
1248
1447
  },
1249
1448
  "Loader"
1250
1449
  );
@@ -1253,21 +1452,52 @@ var Loader = class {
1253
1452
  await this.handleDbMetasFromStore([dbMeta]);
1254
1453
  });
1255
1454
  }
1256
- // readonly id = uuidv4();
1257
- async keyBag() {
1258
- return getKeyBag(this.sthis, this.ebOpts.keyBag);
1259
- }
1260
1455
  async carStore() {
1261
- return this.ebOpts.storeRuntime.makeDataStore(this);
1456
+ return this._carStore.once(
1457
+ async () => this.ebOpts.storeRuntime.makeDataStore({
1458
+ sthis: this.sthis,
1459
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1460
+ url: this.ebOpts.storeUrls.data,
1461
+ // keybag: await this.keyBag(),
1462
+ loader: this
1463
+ })
1464
+ );
1262
1465
  }
1263
1466
  async fileStore() {
1264
- return this.ebOpts.storeRuntime.makeDataStore(this);
1467
+ return this._fileStore.once(
1468
+ async () => this.ebOpts.storeRuntime.makeDataStore({
1469
+ sthis: this.sthis,
1470
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1471
+ url: this.ebOpts.storeUrls.file,
1472
+ // keybag: await this.keyBag(),
1473
+ loader: this
1474
+ })
1475
+ );
1265
1476
  }
1266
1477
  async WALStore() {
1267
- return this.ebOpts.storeRuntime.makeWALStore(this);
1478
+ return this._WALStore.once(
1479
+ async () => this.ebOpts.storeRuntime.makeWALStore({
1480
+ sthis: this.sthis,
1481
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1482
+ url: this.ebOpts.storeUrls.wal,
1483
+ // keybag: await this.keyBag(),
1484
+ loader: this
1485
+ })
1486
+ );
1268
1487
  }
1269
1488
  async metaStore() {
1270
- return this.ebOpts.storeRuntime.makeMetaStore(this);
1489
+ return this._metaStore.once(
1490
+ async () => this.ebOpts.storeRuntime.makeMetaStore({
1491
+ sthis: this.sthis,
1492
+ gatewayInterceptor: this.ebOpts.gatewayInterceptor,
1493
+ url: this.ebOpts.storeUrls.meta,
1494
+ // keybag: await this.keyBag(),
1495
+ loader: this
1496
+ })
1497
+ );
1498
+ }
1499
+ keyBag() {
1500
+ return getKeyBag(this.sthis, this.ebOpts.keyBag);
1271
1501
  }
1272
1502
  async ready() {
1273
1503
  return this.onceReady.once(async () => {
@@ -1280,6 +1510,7 @@ var Loader = class {
1280
1510
  });
1281
1511
  }
1282
1512
  async close() {
1513
+ await this.commitQueue.waitIdle();
1283
1514
  const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
1284
1515
  await Promise.all(toClose.map((store) => store.close()));
1285
1516
  }
@@ -1349,11 +1580,11 @@ var Loader = class {
1349
1580
  }
1350
1581
  async commit(t, done, opts = { noLoader: false, compact: false }) {
1351
1582
  await this.ready();
1352
- const fstore = await this.fileStore();
1583
+ const carStore = await this.carStore();
1353
1584
  const params = {
1354
- encoder: (await fstore.keyedCrypto()).codec(),
1585
+ encoder: (await carStore.keyedCrypto()).codec(),
1355
1586
  carLog: this.carLog,
1356
- carStore: fstore,
1587
+ carStore,
1357
1588
  WALStore: await this.WALStore(),
1358
1589
  metaStore: await this.metaStore(),
1359
1590
  threshold: this.ebOpts.threshold
@@ -1587,12 +1818,12 @@ var generateIV = {
1587
1818
  return hashArray;
1588
1819
  },
1589
1820
  verify: async function(ko, crypto, iv, data) {
1590
- return ko.url.getParam("ivverify") !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
1821
+ return ko.url.getParam("ivVerify" /* IV_VERIFY */) !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
1591
1822
  }
1592
1823
  }
1593
1824
  };
1594
1825
  function getGenerateIVFn(url, opts) {
1595
- const ivhash = opts.ivCalc || url.getParam("ivhash") || "hash";
1826
+ const ivhash = opts.ivCalc || url.getParam("ivHash" /* IV_HASH */) || "hash";
1596
1827
  return generateIV[ivhash] || generateIV["hash"];
1597
1828
  }
1598
1829
  var BlockIvKeyIdCodec = class {
@@ -1713,7 +1944,7 @@ var noCrypto = class {
1713
1944
  }
1714
1945
  };
1715
1946
  async function keyedCryptoFactory(url, kb, sthis) {
1716
- const storekey = url.getParam("storekey");
1947
+ const storekey = url.getParam("storekey" /* STORE_KEY */);
1717
1948
  if (storekey && storekey !== "insecure") {
1718
1949
  let rkey = await kb.getNamedKey(storekey, true);
1719
1950
  if (rkey.isErr()) {
@@ -1728,294 +1959,189 @@ async function keyedCryptoFactory(url, kb, sthis) {
1728
1959
  return new noCrypto(url, kb.rt.crypto, sthis);
1729
1960
  }
1730
1961
 
1731
- // src/blockstore/fragment-gateway.ts
1732
- var import_cement6 = require("@adviser/cement");
1733
- var import_base584 = require("multiformats/bases/base58");
1734
- var import_cborg = require("@fireproof/vendor/cborg");
1735
- function getFragSize(url) {
1736
- const fragSize = url.getParam("fragSize");
1737
- let ret = 0;
1738
- if (fragSize) {
1739
- ret = parseInt(fragSize);
1962
+ // src/blockstore/fp-envelope.ts
1963
+ var import_cement8 = require("@adviser/cement");
1964
+ var FPEnvelopeType = /* @__PURE__ */ ((FPEnvelopeType2) => {
1965
+ FPEnvelopeType2["CAR"] = "car";
1966
+ FPEnvelopeType2["FILE"] = "file";
1967
+ FPEnvelopeType2["META"] = "meta";
1968
+ FPEnvelopeType2["WAL"] = "wal";
1969
+ return FPEnvelopeType2;
1970
+ })(FPEnvelopeType || {});
1971
+ function Car2FPMsg(fpcar) {
1972
+ return import_cement8.Result.Ok({ type: "car" /* CAR */, payload: fpcar });
1973
+ }
1974
+ function File2FPMsg(fpfile) {
1975
+ return import_cement8.Result.Ok({ type: "file" /* FILE */, payload: fpfile });
1976
+ }
1977
+
1978
+ // src/blockstore/store.ts
1979
+ var import_clock = require("@fireproof/vendor/@web3-storage/pail/clock");
1980
+ var import_dag_json = require("@fireproof/vendor/@ipld/dag-json");
1981
+ var import_p_retry = __toESM(require("p-retry"), 1);
1982
+ var import_p_map = __toESM(require("p-map"), 1);
1983
+
1984
+ // src/blockstore/interceptor-gateway.ts
1985
+ var import_cement9 = require("@adviser/cement");
1986
+ var PassThroughGateway = class {
1987
+ async buildUrl(sthis, url, key) {
1988
+ const op = { url, key };
1989
+ return import_cement9.Result.Ok({ op });
1740
1990
  }
1741
- if (isNaN(ret) || ret <= 0) {
1742
- ret = 0;
1991
+ async start(sthis, url) {
1992
+ const op = { url };
1993
+ return import_cement9.Result.Ok({ op });
1743
1994
  }
1744
- return ret;
1745
- }
1746
- async function getFrags(url, innerGW, headerSize, logger) {
1747
- const fragSize = getFragSize(url);
1748
- if (!fragSize) {
1749
- const res = await innerGW.get(url);
1750
- if (res.isErr()) {
1751
- return [res];
1752
- }
1753
- const data = res.unwrap();
1754
- return [
1755
- import_cement6.Result.Ok({
1756
- fid: new Uint8Array(0),
1757
- ofs: 0,
1758
- len: data.length,
1759
- data
1760
- })
1761
- ];
1762
- }
1763
- const firstRaw = await innerGW.get(url.build().setParam("ofs", "0").URI());
1764
- if (firstRaw.isErr()) {
1765
- return [firstRaw];
1766
- }
1767
- const firstFragment = (0, import_cborg.decode)(firstRaw.unwrap());
1768
- const blockSize = firstFragment.data.length;
1769
- const ops = [Promise.resolve(import_cement6.Result.Ok(firstFragment))];
1770
- const fidStr = import_base584.base58btc.encode(firstFragment.fid);
1771
- const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
1772
- for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
1773
- ops.push(
1774
- (async (furl, ofs2) => {
1775
- const raw2 = await innerGW.get(furl);
1776
- if (raw2.isErr()) {
1777
- return raw2;
1778
- }
1779
- const fragment = (0, import_cborg.decode)(raw2.unwrap());
1780
- if (import_base584.base58btc.encode(fragment.fid) !== fidStr) {
1781
- return import_cement6.Result.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
1782
- }
1783
- if (fragment.ofs !== ofs2) {
1784
- return import_cement6.Result.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
1785
- }
1786
- return import_cement6.Result.Ok(fragment);
1787
- })(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
1788
- );
1995
+ async close(sthis, url) {
1996
+ const op = { url };
1997
+ return import_cement9.Result.Ok({ op });
1789
1998
  }
1790
- return Promise.all(ops);
1791
- }
1792
- var FragmentGateway = class {
1793
- constructor(sthis, innerGW) {
1794
- this.fidLength = 4;
1795
- this.headerSize = 32;
1796
- this.sthis = ensureSuperLog(sthis, "FragmentGateway");
1797
- this.logger = this.sthis.logger;
1999
+ async delete(sthis, url) {
2000
+ const op = { url };
2001
+ return import_cement9.Result.Ok({ op });
2002
+ }
2003
+ async destroy(sthis, url) {
2004
+ const op = { url };
2005
+ return import_cement9.Result.Ok({ op });
2006
+ }
2007
+ async put(sthis, url, body) {
2008
+ const op = { url, body };
2009
+ return import_cement9.Result.Ok({ op });
2010
+ }
2011
+ async get(sthis, url) {
2012
+ const op = { url };
2013
+ return import_cement9.Result.Ok({ op });
2014
+ }
2015
+ async subscribe(sthis, url, callback) {
2016
+ const op = { url, callback };
2017
+ return import_cement9.Result.Ok({ op });
2018
+ }
2019
+ };
2020
+ var passThrougthGateway = new PassThroughGateway();
2021
+ var InterceptorGateway = class {
2022
+ constructor(sthis, innerGW, interceptor) {
1798
2023
  this.innerGW = innerGW;
2024
+ this.interceptor = interceptor || passThrougthGateway;
1799
2025
  }
1800
- slicer(url, body) {
1801
- const fragSize = getFragSize(url);
1802
- if (!fragSize) {
1803
- return [this.innerGW.put(url, body)];
1804
- }
1805
- const blocksize = fragSize - this.headerSize;
1806
- if (blocksize <= 0) {
1807
- throw this.logger.Error().Uint64("fragSize", fragSize).Uint64("headerSize", this.headerSize).Msg("Fragment size is too small").AsError();
1808
- }
1809
- const ops = [];
1810
- const fid = this.sthis.nextId(this.fidLength);
1811
- const fragUrl = url.build().setParam("fid", fid.str).setParam("len", body.length.toString()).setParam("headerSize", this.headerSize.toString());
1812
- for (let ofs = 0; ofs < body.length; ofs += blocksize) {
1813
- const block = (0, import_cborg.encode)({
1814
- fid: fid.bin,
1815
- ofs,
1816
- len: body.length,
1817
- data: body.slice(ofs, ofs + blocksize)
1818
- });
1819
- if (block.length > fragSize) {
1820
- throw this.logger.Error().Uint64("block", block.length).Uint64("fragSize", fragSize).Msg("Block size to big").AsError();
1821
- }
1822
- ops.push(this.innerGW.put(fragUrl.setParam("ofs", ofs.toString()).URI(), block));
2026
+ async buildUrl(sthis, baseUrl, key, loader) {
2027
+ const rret = await this.interceptor.buildUrl(sthis, baseUrl, key, loader);
2028
+ if (rret.isErr()) {
2029
+ return import_cement9.Result.Err(rret.Err());
2030
+ }
2031
+ const ret = rret.unwrap();
2032
+ if (ret.stop && ret.value) {
2033
+ return ret.value;
2034
+ }
2035
+ return this.innerGW.buildUrl(sthis, ret.op.url, ret.op.key, loader);
2036
+ }
2037
+ async destroy(sthis, iurl, loader) {
2038
+ const rret = await this.interceptor.destroy(sthis, iurl, loader);
2039
+ if (rret.isErr()) {
2040
+ return import_cement9.Result.Err(rret.Err());
2041
+ }
2042
+ const ret = rret.unwrap();
2043
+ if (ret.stop && ret.value) {
2044
+ return ret.value;
2045
+ }
2046
+ return this.innerGW.destroy(sthis, ret.op.url, loader);
2047
+ }
2048
+ async start(sthis, url, loader) {
2049
+ const rret = await this.interceptor.start(sthis, url, loader);
2050
+ if (rret.isErr()) {
2051
+ return import_cement9.Result.Err(rret.Err());
2052
+ }
2053
+ const ret = rret.unwrap();
2054
+ if (ret.stop && ret.value) {
2055
+ return ret.value;
2056
+ }
2057
+ return await this.innerGW.start(sthis, ret.op.url, loader);
2058
+ }
2059
+ async close(sthis, url, loader) {
2060
+ const rret = await this.interceptor.close(sthis, url, loader);
2061
+ if (rret.isErr()) {
2062
+ return import_cement9.Result.Err(rret.Err());
2063
+ }
2064
+ const ret = rret.unwrap();
2065
+ if (ret.stop && ret.value) {
2066
+ return ret.value;
1823
2067
  }
1824
- return ops;
2068
+ return await this.innerGW.close(sthis, ret.op.url, loader);
1825
2069
  }
1826
- buildUrl(baseUrl, key) {
1827
- return this.innerGW.buildUrl(baseUrl, key);
1828
- }
1829
- async destroy(iurl) {
1830
- return this.innerGW.destroy(iurl);
1831
- }
1832
- async start(url) {
1833
- this.headerSize = (0, import_cborg.encode)({
1834
- fid: this.sthis.nextId(this.fidLength).bin,
1835
- ofs: 1024 * 1024,
1836
- // 32bit
1837
- len: 16 * 1024 * 1024,
1838
- // 32bit
1839
- data: new Uint8Array(1024)
1840
- }).length - 1024;
1841
- return this.innerGW.start(url);
1842
- }
1843
- async close(url) {
1844
- return this.innerGW.close(url);
1845
- }
1846
- async put(url, body) {
1847
- await Promise.all(this.slicer(url, body));
1848
- return import_cement6.Result.Ok(void 0);
1849
- }
1850
- async get(url) {
1851
- const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
1852
- let buffer = void 0;
1853
- for (const rfrag of rfrags) {
1854
- if (rfrag.isErr()) {
1855
- return import_cement6.Result.Err(rfrag.Err());
1856
- }
1857
- const frag = rfrag.Ok();
1858
- buffer = buffer || new Uint8Array(frag.len);
1859
- buffer.set(frag.data, frag.ofs);
1860
- }
1861
- return import_cement6.Result.Ok(buffer || new Uint8Array(0));
1862
- }
1863
- async subscribe(url, callback) {
1864
- if (this.innerGW.subscribe) {
1865
- return this.innerGW.subscribe(url, callback);
1866
- } else {
1867
- return import_cement6.Result.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
2070
+ async put(sthis, url, fpEnv, loader) {
2071
+ const rret = await this.interceptor.put(sthis, url, fpEnv, loader);
2072
+ if (rret.isErr()) {
2073
+ return import_cement9.Result.Err(rret.Err());
1868
2074
  }
2075
+ const ret = rret.unwrap();
2076
+ if (ret.stop && ret.value) {
2077
+ return ret.value;
2078
+ }
2079
+ return this.innerGW.put(sthis, ret.op.url, ret.op.body, loader);
1869
2080
  }
1870
- async delete(url) {
1871
- const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
1872
- for (const rfrag of rfrags) {
1873
- if (rfrag.isErr()) {
1874
- return import_cement6.Result.Err(rfrag.Err());
1875
- }
1876
- const frag = rfrag.Ok();
1877
- const fidStr = import_base584.base58btc.encode(frag.fid);
1878
- const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
1879
- await this.innerGW.delete(fragUrl);
2081
+ async get(sthis, url, loader) {
2082
+ const rret = await this.interceptor.get(sthis, url, loader);
2083
+ if (rret.isErr()) {
2084
+ return import_cement9.Result.Err(rret.Err());
1880
2085
  }
1881
- return import_cement6.Result.Ok(void 0);
2086
+ const ret = rret.unwrap();
2087
+ if (ret.stop && ret.value) {
2088
+ return ret.value;
2089
+ }
2090
+ return this.innerGW.get(sthis, ret.op.url, loader);
1882
2091
  }
1883
- };
1884
-
1885
- // src/blockstore/meta-key-helper.ts
1886
- var import_dag_json = require("@fireproof/vendor/@ipld/dag-json");
1887
- var import_clock = require("@fireproof/vendor/@web3-storage/pail/clock");
1888
- var import_multiformats2 = require("multiformats");
1889
- var import_base64 = require("multiformats/bases/base64");
1890
- var import_cement7 = require("@adviser/cement");
1891
- async function decodeGatewayMetaBytesToDbMeta(sthis, byteHeads) {
1892
- const crdtEntries = JSON.parse(sthis.txt.decode(byteHeads));
1893
- if (!Array.isArray(crdtEntries)) {
1894
- sthis.logger.Debug().Str("crdtEntries", JSON.stringify(crdtEntries)).Msg("No data in CRDT entries");
1895
- return [];
1896
- }
1897
- if (!crdtEntries.length) {
1898
- sthis.logger.Debug().Any("byteHeads", byteHeads).Msg("No CRDT entries found");
1899
- return [];
1900
- }
1901
- const logger = ensureLogger(sthis, "decodeGatewayMetaBytesToDbMeta");
1902
- return Promise.all(
1903
- crdtEntries.map(async (crdtEntry) => {
1904
- const eventBlock = await (0, import_clock.decodeEventBlock)(import_base64.base64pad.decode(crdtEntry.data));
1905
- const dbMeta = (0, import_dag_json.parse)(sthis.txt.decode(eventBlock.value.data.dbMeta));
1906
- logger.Debug().Any("crdtEntry", {
1907
- crdtEntry,
1908
- eventBlock,
1909
- dbMeta,
1910
- dbMetaStrings: dbMeta.cars.map((car) => car.toString())
1911
- }).Msg("CRDT entry");
1912
- return {
1913
- eventCid: eventBlock.cid,
1914
- parents: crdtEntry.parents,
1915
- dbMeta
1916
- };
1917
- })
1918
- );
1919
- }
1920
- async function setCryptoKeyFromGatewayMetaPayload(uri, sthis, data) {
1921
- try {
1922
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Setting crypto key from gateway meta payload");
1923
- const keyInfo = await decodeGatewayMetaBytesToDbMeta(sthis, data);
1924
- if (keyInfo.length) {
1925
- const dbMeta = keyInfo[0].dbMeta;
1926
- if (dbMeta.key) {
1927
- const kb = await getKeyBag(sthis);
1928
- const keyName = getStoreKeyName(uri);
1929
- const res = await kb.setNamedKey(keyName, dbMeta.key);
1930
- if (res.isErr()) {
1931
- sthis.logger.Debug().Str("keyName", keyName).Str("dbMeta.key", dbMeta.key).Msg("Failed to set named key");
1932
- throw res.Err();
1933
- }
1934
- }
1935
- sthis.logger.Debug().Str("dbMeta.key", dbMeta.key).Str("uri", uri.toString()).Msg("Set crypto key from gateway meta payload");
1936
- return import_cement7.Result.Ok(dbMeta);
2092
+ async subscribe(sthis, url, callback, loader) {
2093
+ if (!this.innerGW.subscribe) {
2094
+ return import_cement9.Result.Err(sthis.logger.Error().Url(url).Msg("subscribe not supported").AsError());
2095
+ }
2096
+ const rret = await this.interceptor.subscribe(sthis, url, callback, loader);
2097
+ if (rret.isErr()) {
2098
+ return import_cement9.Result.Err(rret.Err());
1937
2099
  }
1938
- sthis.logger.Debug().Any("data", data).Msg("No crypto in gateway meta payload");
1939
- return import_cement7.Result.Ok(void 0);
1940
- } catch (error) {
1941
- sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
1942
- return import_cement7.Result.Err(error);
2100
+ const ret = rret.unwrap();
2101
+ if (ret.stop && ret.value) {
2102
+ return ret.value;
2103
+ }
2104
+ return this.innerGW.subscribe(sthis, ret.op.url, ret.op.callback, loader);
1943
2105
  }
1944
- }
1945
- async function addCryptoKeyToGatewayMetaPayload(uri, sthis, body) {
1946
- try {
1947
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Adding crypto key to gateway meta payload");
1948
- const keyName = getStoreKeyName(uri);
1949
- const kb = await getKeyBag(sthis);
1950
- const res = await kb.getNamedExtractableKey(keyName, true);
1951
- if (res.isErr()) {
1952
- sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
1953
- throw res.Err();
2106
+ async delete(sthis, url, loader) {
2107
+ const rret = await this.interceptor.delete(sthis, url, loader);
2108
+ if (rret.isErr()) {
2109
+ return import_cement9.Result.Err(rret.Err());
1954
2110
  }
1955
- const keyData = await res.Ok().extract();
1956
- const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
1957
- const { dbMeta, parents } = dbMetas[0];
1958
- const parentLinks = parents.map((p) => import_multiformats2.CID.parse(p));
1959
- dbMeta.key = keyData.keyStr;
1960
- const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
1961
- const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
1962
- sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
1963
- return import_cement7.Result.Ok(encoded);
1964
- } catch (error) {
1965
- sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
1966
- return import_cement7.Result.Err(error);
1967
- }
1968
- }
1969
- function getStoreKeyName(url) {
1970
- const storeKeyName = [url.getParam("localName") || url.getParam("name")];
1971
- const idx = url.getParam("index");
1972
- if (idx) {
1973
- storeKeyName.push(idx);
1974
- }
1975
- storeKeyName.push("data");
1976
- return `@${storeKeyName.join(":")}@`;
1977
- }
1978
- async function createDbMetaEventBlock(sthis, dbMeta, parents) {
1979
- const event = await import_clock.EventBlock.create(
1980
- {
1981
- dbMeta: sthis.txt.encode((0, import_dag_json.format)(dbMeta))
1982
- },
1983
- parents
1984
- );
1985
- return event;
1986
- }
1987
- async function encodeEventsWithParents(sthis, events, parents) {
1988
- const crdtEntries = events.map((event) => {
1989
- const base64String = import_base64.base64pad.encode(event.bytes);
1990
- return {
1991
- cid: event.cid.toString(),
1992
- data: base64String,
1993
- parents: parents.map((p) => p.toString())
1994
- };
1995
- });
1996
- return sthis.txt.encode(JSON.stringify(crdtEntries));
1997
- }
2111
+ const ret = rret.unwrap();
2112
+ if (ret.stop && ret.value) {
2113
+ return ret.value;
2114
+ }
2115
+ return this.innerGW.delete(sthis, url, loader);
2116
+ }
2117
+ async getPlain(sthis, url, key, loader) {
2118
+ return this.innerGW.getPlain(sthis, url, key, loader);
2119
+ }
2120
+ };
1998
2121
 
1999
2122
  // src/blockstore/store.ts
2000
- var import_p_retry = __toESM(require("p-retry"), 1);
2001
- var import_p_map = __toESM(require("p-map"), 1);
2002
2123
  function guardVersion(url) {
2003
2124
  if (!url.hasParam("version")) {
2004
- return import_cement8.Result.Err(`missing version: ${url.toString()}`);
2125
+ return import_cement10.Result.Err(`missing version: ${url.toString()}`);
2005
2126
  }
2006
- return import_cement8.Result.Ok(url);
2127
+ return import_cement10.Result.Ok(url);
2007
2128
  }
2008
2129
  var BaseStoreImpl = class {
2009
- constructor(name, url, opts, sthis, logger) {
2130
+ // readonly loader: Loadable;
2131
+ constructor(sthis, url, opts, logger) {
2010
2132
  this._onStarted = [];
2011
2133
  this._onClosed = [];
2012
- this.name = name;
2013
2134
  this._url = url;
2014
- this.keybag = opts.keybag;
2015
- this.sthis = sthis;
2016
- this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
2017
- this.gateway = new FragmentGateway(this.sthis, opts.gateway);
2135
+ this.opts = opts;
2018
2136
  this.loader = opts.loader;
2137
+ this.sthis = sthis;
2138
+ const name = this._url.getParam("name" /* NAME */);
2139
+ if (!name) {
2140
+ throw logger.Error().Url(this._url).Msg("missing name").AsError();
2141
+ }
2142
+ this.logger = logger.With().Str("this", this.sthis.nextId().str).Ref("url", () => this._url.toString()).Logger();
2143
+ this.realGateway = opts.gateway;
2144
+ this.gateway = new InterceptorGateway(this.sthis, opts.gateway, opts.gatewayInterceptor);
2019
2145
  }
2020
2146
  url() {
2021
2147
  return this._url;
@@ -2030,21 +2156,21 @@ var BaseStoreImpl = class {
2030
2156
  return;
2031
2157
  }
2032
2158
  async keyedCrypto() {
2033
- return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
2159
+ return keyedCryptoFactory(this._url, await this.loader.keyBag(), this.sthis);
2034
2160
  }
2035
2161
  async start() {
2036
2162
  this.logger.Debug().Str("storeType", this.storeType).Msg("starting-gateway-pre");
2037
- this._url = this._url.build().setParam("store", this.storeType).URI();
2038
- const res = await this.gateway.start(this._url);
2163
+ this._url = this._url.build().setParam("store" /* STORE */, this.storeType).URI();
2164
+ const res = await this.gateway.start(this.sthis, this._url, this.loader);
2039
2165
  if (res.isErr()) {
2040
2166
  this.logger.Error().Result("gw-start", res).Msg("started-gateway");
2041
2167
  return res;
2042
2168
  }
2043
2169
  this._url = res.Ok();
2044
- const kb = await this.keybag();
2170
+ const kb = await this.loader.keyBag();
2045
2171
  const skRes = await kb.ensureKeyFromUrl(this._url, () => {
2046
- const idx = this._url.getParam("index");
2047
- const storeKeyName = [this.name];
2172
+ const idx = this._url.getParam("index" /* INDEX */);
2173
+ const storeKeyName = [this.url().getParam("name" /* NAME */)];
2048
2174
  if (idx) {
2049
2175
  storeKeyName.push(idx);
2050
2176
  }
@@ -2063,7 +2189,7 @@ var BaseStoreImpl = class {
2063
2189
  }
2064
2190
  if (this.ready) {
2065
2191
  const fn = this.ready.bind(this);
2066
- const ready = await (0, import_cement8.exception2Result)(fn);
2192
+ const ready = await (0, import_cement10.exception2Result)(fn);
2067
2193
  if (ready.isErr()) {
2068
2194
  await this.close();
2069
2195
  return ready;
@@ -2074,10 +2200,23 @@ var BaseStoreImpl = class {
2074
2200
  return version;
2075
2201
  }
2076
2202
  };
2203
+ async function createDbMetaEvent(sthis, dbMeta, parents) {
2204
+ const event = await import_clock.EventBlock.create(
2205
+ {
2206
+ dbMeta: sthis.txt.encode((0, import_dag_json.format)(dbMeta))
2207
+ },
2208
+ parents
2209
+ );
2210
+ return {
2211
+ eventCid: event.cid,
2212
+ dbMeta,
2213
+ parents
2214
+ };
2215
+ }
2077
2216
  var MetaStoreImpl = class extends BaseStoreImpl {
2078
2217
  // remote: boolean;
2079
- constructor(sthis, name, url, opts) {
2080
- super(name, url, { ...opts }, sthis, ensureLogger(sthis, "MetaStoreImpl"));
2218
+ constructor(sthis, url, opts) {
2219
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "MetaStoreImpl"));
2081
2220
  this.storeType = "meta";
2082
2221
  this.subscribers = /* @__PURE__ */ new Map();
2083
2222
  this.parents = [];
@@ -2087,14 +2226,18 @@ var MetaStoreImpl = class extends BaseStoreImpl {
2087
2226
  ) {
2088
2227
  this.onStarted(async () => {
2089
2228
  this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
2090
- opts.gateway.subscribe?.(this.url(), async (message) => {
2091
- this.logger.Debug().Msg("Received message from gateway");
2092
- const dbMetas = await decodeGatewayMetaBytesToDbMeta(this.sthis, message);
2093
- await Promise.all(
2094
- dbMetas.map((dbMeta) => this.loader?.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
2095
- );
2096
- this.updateParentsFromDbMetas(dbMetas);
2097
- });
2229
+ opts.gateway.subscribe?.(
2230
+ this.sthis,
2231
+ this.url(),
2232
+ async ({ payload: dbMetas }) => {
2233
+ this.logger.Debug().Msg("Received message from gateway");
2234
+ await Promise.all(
2235
+ dbMetas.map((dbMeta) => this.loader.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
2236
+ );
2237
+ this.updateParentsFromDbMetas(dbMetas);
2238
+ },
2239
+ this.loader
2240
+ );
2098
2241
  });
2099
2242
  }
2100
2243
  }
@@ -2105,129 +2248,165 @@ var MetaStoreImpl = class extends BaseStoreImpl {
2105
2248
  const dbMetaParentsSet = new Set(dbMetaParents.map((p) => p.toString()));
2106
2249
  this.parents = Array.from(uniqueParentsMap.values()).filter((p) => !dbMetaParentsSet.has(p.toString()));
2107
2250
  }
2108
- async handleByteHeads(byteHeads) {
2109
- return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
2110
- }
2251
+ // async handleByteHeads(byteHeads: Uint8Array) {
2252
+ // // return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
2253
+ // const rDbMeta = await fpDeserialize(this.sthis, byteHeads, this.url());
2254
+ // if (rDbMeta.isErr()) {
2255
+ // throw this.logger.Error().Err(rDbMeta).Msg("error deserializing").AsError();
2256
+ // }
2257
+ // return (rDbMeta.Ok() as FPEnvelopeMeta).payload;
2258
+ // }
2111
2259
  async load() {
2112
2260
  const branch = "main";
2113
- const url = await this.gateway.buildUrl(this.url(), branch);
2261
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), branch, this.loader);
2114
2262
  if (url.isErr()) {
2115
2263
  throw this.logger.Error().Result("buildUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
2116
2264
  }
2117
- const bytes = await this.gateway.get(url.Ok());
2118
- if (bytes.isErr()) {
2119
- if (isNotFoundError(bytes)) {
2265
+ const rfpEnv = await this.gateway.get(this.sthis, url.Ok(), this.loader);
2266
+ if (rfpEnv.isErr()) {
2267
+ if (isNotFoundError(rfpEnv)) {
2120
2268
  return void 0;
2121
2269
  }
2122
- throw this.logger.Error().Url(url.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
2270
+ throw this.logger.Error().Url(url.Ok()).Err(rfpEnv).Msg("gateway get").AsError();
2123
2271
  }
2124
- const dbMetas = await this.handleByteHeads(bytes.Ok());
2125
- await this.loader?.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
2272
+ const dbMetas = rfpEnv.Ok().payload;
2273
+ await this.loader.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
2126
2274
  this.updateParentsFromDbMetas(dbMetas);
2127
2275
  return dbMetas.map((m) => m.dbMeta);
2128
2276
  }
2129
2277
  async save(meta, branch) {
2130
2278
  branch = branch || "main";
2131
2279
  this.logger.Debug().Str("branch", branch).Any("meta", meta).Msg("saving meta");
2132
- const event = await createDbMetaEventBlock(this.sthis, meta, this.parents);
2133
- const bytes = await encodeEventsWithParents(this.sthis, [event], this.parents);
2134
- const url = await this.gateway.buildUrl(this.url(), branch);
2280
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), branch, this.loader);
2135
2281
  if (url.isErr()) {
2136
2282
  throw this.logger.Error().Err(url.Err()).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
2137
2283
  }
2138
- this.parents = [event.cid];
2139
- const res = await this.gateway.put(url.Ok(), bytes);
2284
+ const dbMetaEvent = await createDbMetaEvent(this.sthis, meta, this.parents);
2285
+ const res = await this.gateway.put(
2286
+ this.sthis,
2287
+ url.Ok(),
2288
+ {
2289
+ type: "meta",
2290
+ payload: [dbMetaEvent]
2291
+ },
2292
+ this.loader
2293
+ );
2140
2294
  if (res.isErr()) {
2141
2295
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
2142
2296
  }
2143
2297
  return res;
2144
2298
  }
2145
2299
  async close() {
2146
- await this.gateway.close(this.url());
2300
+ await this.gateway.close(this.sthis, this.url(), this.loader);
2147
2301
  this._onClosed.forEach((fn) => fn());
2148
- return import_cement8.Result.Ok(void 0);
2302
+ return import_cement10.Result.Ok(void 0);
2149
2303
  }
2150
2304
  async destroy() {
2151
- return this.gateway.destroy(this.url());
2305
+ this.logger.Debug().Msg("destroy");
2306
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
2152
2307
  }
2153
2308
  };
2154
2309
  var DataStoreImpl = class extends BaseStoreImpl {
2155
- // readonly tag: string = "car-base";
2156
- constructor(sthis, name, url, opts) {
2157
- super(name, url, { ...opts }, sthis, ensureLogger(sthis, "DataStoreImpl"));
2310
+ constructor(sthis, url, opts) {
2311
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "DataStoreImpl"));
2158
2312
  this.storeType = "data";
2159
2313
  }
2160
2314
  async load(cid) {
2161
2315
  this.logger.Debug().Any("cid", cid).Msg("loading");
2162
- const url = await this.gateway.buildUrl(this.url(), cid.toString());
2316
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), cid.toString(), this.loader);
2163
2317
  if (url.isErr()) {
2164
2318
  throw this.logger.Error().Err(url.Err()).Str("cid", cid.toString()).Msg("got error from gateway.buildUrl").AsError();
2165
2319
  }
2166
- const res = await this.gateway.get(url.Ok());
2320
+ const res = await this.gateway.get(this.sthis, url.Ok(), this.loader);
2167
2321
  if (res.isErr()) {
2168
2322
  throw res.Err();
2169
2323
  }
2170
- return { cid, bytes: res.Ok() };
2324
+ const fpenv = res.Ok();
2325
+ switch (fpenv.type) {
2326
+ case "car":
2327
+ return { cid, bytes: fpenv.payload };
2328
+ case "file":
2329
+ return { cid, bytes: fpenv.payload };
2330
+ default:
2331
+ throw this.logger.Error().Msg("unexpected type").AsError();
2332
+ }
2171
2333
  }
2172
2334
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2173
2335
  async save(car, opts) {
2174
2336
  this.logger.Debug().Any("cid", car.cid.toString()).Msg("saving");
2175
- const url = await this.gateway.buildUrl(this.url(), car.cid.toString());
2337
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), car.cid.toString(), this.loader);
2176
2338
  if (url.isErr()) {
2177
2339
  throw this.logger.Error().Err(url.Err()).Ref("cid", car.cid).Msg("got error from gateway.buildUrl").AsError();
2178
2340
  }
2179
- const res = await this.gateway.put(url.Ok(), car.bytes);
2341
+ let fpMsg;
2342
+ switch (url.Ok().getParam("store" /* STORE */)) {
2343
+ case "data":
2344
+ if (url.Ok().getParam("suffix" /* SUFFIX */)) {
2345
+ fpMsg = Car2FPMsg(car.bytes);
2346
+ } else {
2347
+ fpMsg = File2FPMsg(car.bytes);
2348
+ }
2349
+ break;
2350
+ default:
2351
+ throw this.logger.Error().Str("store", url.Ok().getParam("store" /* STORE */)).Msg("unexpected store").AsError();
2352
+ }
2353
+ if (fpMsg.isErr()) {
2354
+ throw this.logger.Error().Err(fpMsg).Msg("got error from FPMsg2Car").AsError();
2355
+ }
2356
+ const res = await this.gateway.put(this.sthis, url.Ok(), fpMsg.Ok(), this.loader);
2180
2357
  if (res.isErr()) {
2181
2358
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
2182
2359
  }
2183
2360
  return res.Ok();
2184
2361
  }
2185
2362
  async remove(cid) {
2186
- const url = await this.gateway.buildUrl(this.url(), cid.toString());
2363
+ const url = await this.gateway.buildUrl(this.sthis, this.url(), cid.toString(), this.loader);
2187
2364
  if (url.isErr()) {
2188
2365
  return url;
2189
2366
  }
2190
- return this.gateway.delete(url.Ok());
2367
+ return this.gateway.delete(this.sthis, url.Ok(), this.loader);
2191
2368
  }
2192
2369
  async close() {
2193
- await this.gateway.close(this.url());
2370
+ await this.gateway.close(this.sthis, this.url(), this.loader);
2194
2371
  this._onClosed.forEach((fn) => fn());
2195
- return import_cement8.Result.Ok(void 0);
2372
+ return import_cement10.Result.Ok(void 0);
2196
2373
  }
2197
2374
  destroy() {
2198
- return this.gateway.destroy(this.url());
2375
+ this.logger.Debug().Msg("destroy");
2376
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
2199
2377
  }
2200
2378
  };
2201
2379
  var WALStoreImpl = class extends BaseStoreImpl {
2202
- constructor(loader, url, opts) {
2203
- super(loader.name, url, { ...opts }, loader.sthis, ensureLogger(loader.sthis, "WALStoreImpl"));
2380
+ constructor(sthis, url, opts) {
2381
+ super(sthis, url, { ...opts }, ensureLogger(sthis, "WALStoreImpl"));
2204
2382
  this.storeType = "wal";
2205
- this._ready = new import_cement8.ResolveOnce();
2383
+ // readonly tag: string = "rwal-base";
2384
+ // readonly loader: Loadable;
2385
+ this._ready = new import_cement10.ResolveOnce();
2206
2386
  this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
2207
2387
  this.processing = void 0;
2208
2388
  this.processQueue = new CommitQueue();
2209
- this.loader = loader;
2210
2389
  }
2211
2390
  async ready() {
2212
2391
  return this._ready.once(async () => {
2213
2392
  const walState = await this.load().catch((e) => {
2214
- this.logger.Error().Any("error", e).Msg("error loading wal");
2393
+ this.logger.Error().Err(e).Msg("error loading wal");
2215
2394
  return void 0;
2216
2395
  });
2217
- if (!walState) {
2218
- this.walState.operations = [];
2219
- this.walState.fileOperations = [];
2220
- } else {
2221
- this.walState.operations = walState.operations || [];
2222
- this.walState.fileOperations = walState.fileOperations || [];
2396
+ this.walState.operations.splice(0, this.walState.operations.length);
2397
+ this.walState.fileOperations.splice(0, this.walState.fileOperations.length);
2398
+ if (walState) {
2399
+ this.walState.operations.push(...walState.operations);
2400
+ this.walState.fileOperations.push(...walState.fileOperations);
2223
2401
  }
2224
2402
  });
2225
2403
  }
2226
2404
  async enqueue(dbMeta, opts) {
2227
2405
  await this.ready();
2228
2406
  if (opts.compact) {
2229
- this.walState.operations = [];
2230
- this.walState.noLoaderOps = [dbMeta];
2407
+ this.walState.operations.splice(0, this.walState.operations.length);
2408
+ this.walState.noLoaderOps.splice(0, this.walState.noLoaderOps.length);
2409
+ this.walState.noLoaderOps.push(dbMeta);
2231
2410
  } else if (opts.noLoader) {
2232
2411
  this.walState.noLoaderOps.push(dbMeta);
2233
2412
  } else {
@@ -2257,6 +2436,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
2257
2436
  });
2258
2437
  }
2259
2438
  async _doProcess() {
2439
+ if (!this.loader) return;
2260
2440
  if (!this.loader.remoteCarStore) return;
2261
2441
  const operations = [...this.walState.operations];
2262
2442
  const noLoaderOps = [...this.walState.noLoaderOps];
@@ -2274,6 +2454,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
2274
2454
  noLoaderOps,
2275
2455
  async (dbMeta) => {
2276
2456
  await retryableUpload(async () => {
2457
+ if (!this.loader) {
2458
+ return;
2459
+ }
2277
2460
  for (const cid of dbMeta.cars) {
2278
2461
  const car = await (await this.loader.carStore()).load(cid);
2279
2462
  if (!car) {
@@ -2284,7 +2467,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
2284
2467
  await throwFalsy(this.loader.remoteCarStore).save(car);
2285
2468
  }
2286
2469
  }
2287
- this.walState.noLoaderOps = this.walState.noLoaderOps.filter((op) => op !== dbMeta);
2470
+ inplaceFilter(this.walState.noLoaderOps, (op) => op !== dbMeta);
2288
2471
  }, `noLoaderOp with dbMeta.cars=${dbMeta.cars.toString()}`);
2289
2472
  },
2290
2473
  { concurrency: concurrencyLimit }
@@ -2293,6 +2476,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
2293
2476
  operations,
2294
2477
  async (dbMeta) => {
2295
2478
  await retryableUpload(async () => {
2479
+ if (!this.loader) {
2480
+ return;
2481
+ }
2296
2482
  for (const cid of dbMeta.cars) {
2297
2483
  const car = await (await this.loader.carStore()).load(cid);
2298
2484
  if (!car) {
@@ -2303,7 +2489,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
2303
2489
  await throwFalsy(this.loader.remoteCarStore).save(car);
2304
2490
  }
2305
2491
  }
2306
- this.walState.operations = this.walState.operations.filter((op) => op !== dbMeta);
2492
+ inplaceFilter(this.walState.operations, (op) => op !== dbMeta);
2307
2493
  }, `operation with dbMeta.cars=${dbMeta.cars.toString()}`);
2308
2494
  },
2309
2495
  { concurrency: concurrencyLimit }
@@ -2312,12 +2498,15 @@ var WALStoreImpl = class extends BaseStoreImpl {
2312
2498
  fileOperations,
2313
2499
  async ({ cid: fileCid, public: publicFile }) => {
2314
2500
  await retryableUpload(async () => {
2501
+ if (!this.loader) {
2502
+ return;
2503
+ }
2315
2504
  const fileBlock = await (await this.loader.fileStore()).load(fileCid);
2316
2505
  if (!fileBlock) {
2317
2506
  throw this.logger.Error().Ref("cid", fileCid).Msg("missing file block").AsError();
2318
2507
  }
2319
2508
  await this.loader.remoteFileStore?.save(fileBlock, { public: publicFile });
2320
- this.walState.fileOperations = this.walState.fileOperations.filter((op) => op.cid !== fileCid);
2509
+ inplaceFilter(this.walState.fileOperations, (op) => op.cid !== fileCid);
2321
2510
  }, `fileOperation with cid=${fileCid.toString()}`);
2322
2511
  },
2323
2512
  { concurrency: concurrencyLimit }
@@ -2325,6 +2514,9 @@ var WALStoreImpl = class extends BaseStoreImpl {
2325
2514
  if (operations.length) {
2326
2515
  const lastOp = operations[operations.length - 1];
2327
2516
  await retryableUpload(async () => {
2517
+ if (!this.loader) {
2518
+ return;
2519
+ }
2328
2520
  await this.loader.remoteMetaStore?.save(lastOp);
2329
2521
  }, `remoteMetaStore save with dbMeta.cars=${lastOp.cars.toString()}`);
2330
2522
  }
@@ -2337,255 +2529,715 @@ var WALStoreImpl = class extends BaseStoreImpl {
2337
2529
  }
2338
2530
  async load() {
2339
2531
  this.logger.Debug().Msg("loading");
2340
- const filepath = await this.gateway.buildUrl(this.url(), "main");
2532
+ const filepath = await this.gateway.buildUrl(this.sthis, this.url(), "main", this.loader);
2341
2533
  if (filepath.isErr()) {
2342
2534
  throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2343
2535
  }
2344
- const bytes = await this.gateway.get(filepath.Ok());
2536
+ const bytes = await this.gateway.get(this.sthis, filepath.Ok(), this.loader);
2345
2537
  if (bytes.isErr()) {
2346
2538
  if (isNotFoundError(bytes)) {
2347
2539
  return void 0;
2348
2540
  }
2349
2541
  throw this.logger.Error().Err(bytes.Err()).Msg("error get").AsError();
2350
2542
  }
2351
- try {
2352
- return bytes && (0, import_dag_json2.parse)(this.sthis.txt.decode(bytes.Ok()));
2353
- } catch (e) {
2354
- throw this.logger.Error().Err(e).Msg("error parse").AsError();
2543
+ if (bytes.Ok().type !== "wal") {
2544
+ throw this.logger.Error().Str("type", bytes.Ok().type).Msg("unexpected type").AsError();
2355
2545
  }
2546
+ return bytes.Ok().payload;
2356
2547
  }
2357
2548
  async save(state) {
2358
- const filepath = await this.gateway.buildUrl(this.url(), "main");
2549
+ const filepath = await this.gateway.buildUrl(this.sthis, this.url(), "main", this.loader);
2359
2550
  if (filepath.isErr()) {
2360
2551
  throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2361
2552
  }
2362
- let encoded;
2363
- try {
2364
- encoded = (0, import_dag_json2.format)(state);
2365
- } catch (e) {
2366
- throw this.logger.Error().Err(e).Any("state", state).Msg("error format").AsError();
2367
- }
2368
- const res = await this.gateway.put(filepath.Ok(), this.sthis.txt.encode(encoded));
2553
+ const res = await this.gateway.put(
2554
+ this.sthis,
2555
+ filepath.Ok(),
2556
+ {
2557
+ type: "wal",
2558
+ payload: state
2559
+ },
2560
+ this.loader
2561
+ );
2369
2562
  if (res.isErr()) {
2370
2563
  throw this.logger.Error().Err(res.Err()).Str("filePath", filepath.Ok().toString()).Msg("error saving").AsError();
2371
2564
  }
2372
2565
  }
2373
2566
  async close() {
2374
- await this.gateway.close(this.url());
2567
+ await this.gateway.close(this.sthis, this.url(), this.loader);
2375
2568
  this._onClosed.forEach((fn) => fn());
2376
- return import_cement8.Result.Ok(void 0);
2569
+ return import_cement10.Result.Ok(void 0);
2377
2570
  }
2378
2571
  destroy() {
2379
- return this.gateway.destroy(this.url());
2572
+ this.logger.Debug().Msg("destroy");
2573
+ return this.gateway.destroy(this.sthis, this.url(), this.loader);
2380
2574
  }
2381
2575
  };
2382
2576
 
2383
- // src/blockstore/store-factory.ts
2384
- function ensureIsIndex(url, isIndex) {
2385
- if (isIndex) {
2386
- return url.build().setParam("index", isIndex).URI();
2577
+ // src/blockstore/register-store-protocol.ts
2578
+ var import_cement16 = require("@adviser/cement");
2579
+
2580
+ // src/runtime/gateways/file/version.ts
2581
+ var FILESTORE_VERSION = "v0.19-file";
2582
+
2583
+ // src/runtime/gateways/memory/gateway.ts
2584
+ var import_cement11 = require("@adviser/cement");
2585
+
2586
+ // src/runtime/gateways/memory/version.ts
2587
+ var MEMORY_VERSION = "v0.19-memory";
2588
+
2589
+ // src/runtime/gateways/memory/gateway.ts
2590
+ var MemoryGateway = class {
2591
+ constructor(sthis, memorys) {
2592
+ this.memorys = memorys;
2593
+ this.sthis = sthis;
2594
+ }
2595
+ buildUrl(baseUrl, key) {
2596
+ return Promise.resolve(import_cement11.Result.Ok(baseUrl.build().setParam("key" /* KEY */, key).URI()));
2597
+ }
2598
+ start(baseUrl) {
2599
+ return Promise.resolve(import_cement11.Result.Ok(baseUrl.build().setParam("version" /* VERSION */, MEMORY_VERSION).URI()));
2600
+ }
2601
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2602
+ close(baseUrl) {
2603
+ return Promise.resolve(import_cement11.Result.Ok(void 0));
2604
+ }
2605
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2606
+ destroy(baseUrl) {
2607
+ this.memorys.clear();
2608
+ return Promise.resolve(import_cement11.Result.Ok(void 0));
2609
+ }
2610
+ async put(url, bytes) {
2611
+ this.memorys.set(url.toString(), bytes);
2612
+ return import_cement11.Result.Ok(void 0);
2613
+ }
2614
+ // get could return a NotFoundError if the key is not found
2615
+ get(url) {
2616
+ const x = this.memorys.get(url.toString());
2617
+ if (!x) {
2618
+ return Promise.resolve(import_cement11.Result.Err(new NotFoundError("not found")));
2619
+ }
2620
+ return Promise.resolve(import_cement11.Result.Ok(x));
2621
+ }
2622
+ delete(url) {
2623
+ this.memorys.delete(url.toString());
2624
+ return Promise.resolve(import_cement11.Result.Ok(void 0));
2625
+ }
2626
+ async getPlain(url, key) {
2627
+ const x = this.memorys.get(url.build().setParam("key" /* KEY */, key).toString());
2628
+ if (!x) {
2629
+ return import_cement11.Result.Err(new NotFoundError("not found"));
2630
+ }
2631
+ return import_cement11.Result.Ok(x);
2632
+ }
2633
+ };
2634
+
2635
+ // src/runtime/index.ts
2636
+ var runtime_exports = {};
2637
+ __export(runtime_exports, {
2638
+ FILESTORE_VERSION: () => FILESTORE_VERSION,
2639
+ INDEXDB_VERSION: () => INDEXDB_VERSION,
2640
+ KeyBag: () => KeyBag,
2641
+ defaultKeyBagOpts: () => defaultKeyBagOpts,
2642
+ defaultKeyBagUrl: () => defaultKeyBagUrl,
2643
+ files: () => files_exports,
2644
+ getFileName: () => getFileName,
2645
+ getKeyBag: () => getKeyBag,
2646
+ getPath: () => getPath,
2647
+ gw: () => gateways_exports,
2648
+ kb: () => key_bag_exports,
2649
+ kc: () => keyed_crypto_exports,
2650
+ mf: () => wait_pr_multiformats_exports,
2651
+ registerKeyBagProviderFactory: () => registerKeyBagProviderFactory,
2652
+ runtimeFn: () => import_cement13.runtimeFn
2653
+ });
2654
+
2655
+ // src/runtime/gateways/file/utils.ts
2656
+ var import_core = require("@fireproof/core");
2657
+ function getPath(url, sthis) {
2658
+ const basePath = url.pathname;
2659
+ const name = url.getParam("name");
2660
+ if (name) {
2661
+ return sthis.pathOps.join(basePath, name);
2387
2662
  }
2388
- return url.build().delParam("index").URI();
2663
+ return sthis.pathOps.join(basePath);
2389
2664
  }
2390
- function ensureName(name, url) {
2391
- if (!url.hasParam("name")) {
2392
- return url.build().setParam("name", name).URI();
2665
+ function getFileName(url, sthis) {
2666
+ const key = url.getParam("key");
2667
+ if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
2668
+ const res = (0, import_core.getStore)(url, sthis, (...a) => a.join("-"));
2669
+ switch (res.store) {
2670
+ case "data":
2671
+ return sthis.pathOps.join(res.name, key + ".car");
2672
+ case "wal":
2673
+ case "meta":
2674
+ return sthis.pathOps.join(res.name, key + ".json");
2675
+ default:
2676
+ throw sthis.logger.Error().Url(url).Msg(`unsupported store type`).AsError();
2393
2677
  }
2394
- return url;
2395
2678
  }
2679
+
2680
+ // src/runtime/wait-pr-multiformats/index.ts
2681
+ var wait_pr_multiformats_exports = {};
2682
+ __export(wait_pr_multiformats_exports, {
2683
+ block: () => block_exports,
2684
+ codec: () => codec_interface_exports
2685
+ });
2686
+
2687
+ // src/runtime/wait-pr-multiformats/codec-interface.ts
2688
+ var codec_interface_exports = {};
2689
+
2690
+ // src/runtime/index.ts
2691
+ var import_cement13 = require("@adviser/cement");
2692
+
2693
+ // src/runtime/gateways/index.ts
2694
+ var gateways_exports = {};
2695
+ __export(gateways_exports, {
2696
+ file: () => file_exports,
2697
+ fpDeserialize: () => fpDeserialize,
2698
+ fpSerialize: () => fpSerialize
2699
+ });
2700
+
2701
+ // src/runtime/gateways/fp-envelope-serialize.ts
2702
+ var import_cement12 = require("@adviser/cement");
2703
+ var import_clock2 = require("@fireproof/vendor/@web3-storage/pail/clock");
2704
+ var import_base64 = require("multiformats/bases/base64");
2705
+ var import_multiformats2 = require("multiformats");
2706
+ var import_link = require("multiformats/link");
2707
+ var import_dag_json2 = require("@fireproof/vendor/@ipld/dag-json");
2708
+ async function dbMetaEvent2Serialized(sthis, dbEvents) {
2709
+ return await Promise.all(
2710
+ dbEvents.map(async (dbEvent) => {
2711
+ const event = await import_clock2.EventBlock.create(
2712
+ {
2713
+ dbMeta: sthis.txt.encode((0, import_dag_json2.format)(dbEvent.dbMeta))
2714
+ },
2715
+ dbEvent.parents
2716
+ );
2717
+ return {
2718
+ cid: event.cid.toString(),
2719
+ parents: dbEvent.parents.map((i) => i.toString()),
2720
+ data: import_base64.base64pad.encode(event.bytes)
2721
+ };
2722
+ })
2723
+ );
2724
+ }
2725
+ function WALState2Serialized(sthis, wal) {
2726
+ const serializedWAL = {
2727
+ fileOperations: wal.fileOperations.map((fop) => ({
2728
+ cid: fop.cid.toString(),
2729
+ public: fop.public
2730
+ })),
2731
+ noLoaderOps: wal.noLoaderOps.map((nop) => ({
2732
+ cars: nop.cars.map((i) => i.toString())
2733
+ })),
2734
+ operations: wal.operations.map((op) => ({
2735
+ cars: op.cars.map((i) => i.toString())
2736
+ }))
2737
+ };
2738
+ return serializedWAL;
2739
+ }
2740
+ var defaultEncoder = {
2741
+ car: async (sthis, payload) => import_cement12.Result.Ok(payload),
2742
+ file: async (sthis, payload) => import_cement12.Result.Ok(payload),
2743
+ meta: async (sthis, payload) => import_cement12.Result.Ok(sthis.txt.encode(JSON.stringify(payload))),
2744
+ wal: async (sthis, payload) => import_cement12.Result.Ok(sthis.txt.encode(JSON.stringify(payload)))
2745
+ };
2746
+ async function fpSerialize(sthis, env, pencoder) {
2747
+ const encoder = {
2748
+ ...defaultEncoder,
2749
+ ...pencoder
2750
+ };
2751
+ switch (env.type) {
2752
+ case "file" /* FILE */:
2753
+ return encoder.file(sthis, env.payload);
2754
+ case "car" /* CAR */:
2755
+ return encoder.car(sthis, env.payload);
2756
+ case "wal" /* WAL */:
2757
+ return encoder.wal(sthis, WALState2Serialized(sthis, env.payload));
2758
+ case "meta" /* META */:
2759
+ return encoder.meta(sthis, await dbMetaEvent2Serialized(sthis, env.payload));
2760
+ default:
2761
+ throw sthis.logger.Error().Str("type", env.type).Msg("unsupported store").AsError();
2762
+ }
2763
+ }
2764
+ async function decode2DbMetaEvents(sthis, rserializedMeta) {
2765
+ if (rserializedMeta.isErr()) {
2766
+ return import_cement12.Result.Err(rserializedMeta.Err());
2767
+ }
2768
+ const serializedMeta = rserializedMeta.unwrap();
2769
+ if (!Array.isArray(serializedMeta)) {
2770
+ return sthis.logger.Debug().Any("metaEntries", serializedMeta).Msg("No data in MetaEntries").ResultError();
2771
+ }
2772
+ if (!serializedMeta.length) {
2773
+ return sthis.logger.Debug().Msg("No MetaEntries found").ResultError();
2774
+ }
2775
+ return import_cement12.Result.Ok(
2776
+ await Promise.all(
2777
+ serializedMeta.map(async (metaEntry) => {
2778
+ const eventBlock = await (0, import_clock2.decodeEventBlock)(import_base64.base64pad.decode(metaEntry.data));
2779
+ const dbMeta = (0, import_dag_json2.parse)(sthis.txt.decode(eventBlock.value.data.dbMeta));
2780
+ return {
2781
+ eventCid: eventBlock.cid,
2782
+ parents: metaEntry.parents.map((i) => import_multiformats2.CID.parse(i)),
2783
+ dbMeta
2784
+ };
2785
+ })
2786
+ )
2787
+ );
2788
+ }
2789
+ function toCid(sthis, link) {
2790
+ if (typeof link === "string") {
2791
+ return import_multiformats2.CID.parse(link);
2792
+ }
2793
+ return (0, import_link.fromJSON)(link);
2794
+ }
2795
+ async function decode2WalState(sthis, rserializedWAL) {
2796
+ if (rserializedWAL.isErr()) {
2797
+ return import_cement12.Result.Err(rserializedWAL.Err());
2798
+ }
2799
+ const serializedWAL = rserializedWAL.unwrap();
2800
+ return import_cement12.Result.Ok({
2801
+ fileOperations: (serializedWAL.fileOperations || []).map((fop) => ({
2802
+ cid: toCid(sthis, fop.cid),
2803
+ public: !!fop.public
2804
+ })),
2805
+ noLoaderOps: (serializedWAL.noLoaderOps || []).map((nop) => ({
2806
+ cars: (nop.cars || []).map((i) => toCid(sthis, i))
2807
+ })),
2808
+ operations: (serializedWAL.operations || []).map((op) => ({
2809
+ cars: (op.cars || []).map((i) => toCid(sthis, i))
2810
+ }))
2811
+ });
2812
+ }
2813
+ var defaultDecoder = {
2814
+ car: async (sthis, payload) => import_cement12.Result.Ok(payload),
2815
+ file: async (sthis, payload) => import_cement12.Result.Ok(payload),
2816
+ meta: async (sthis, payload) => (0, import_cement12.exception2Result)(() => JSON.parse(sthis.txt.decode(payload))),
2817
+ wal: async (sthis, payload) => (0, import_cement12.exception2Result)(() => JSON.parse(sthis.txt.decode(payload)))
2818
+ };
2819
+ function makeFPEnvelope(type, payload) {
2820
+ if (payload.isErr()) {
2821
+ return import_cement12.Result.Err(payload.Err());
2822
+ }
2823
+ return import_cement12.Result.Ok({
2824
+ type,
2825
+ payload: payload.unwrap()
2826
+ });
2827
+ }
2828
+ async function fpDeserialize(sthis, url, intoRaw, pdecoder) {
2829
+ const rraw = await coercePromiseIntoUint8(intoRaw);
2830
+ if (rraw.isErr()) {
2831
+ return import_cement12.Result.Err(rraw.Err());
2832
+ }
2833
+ const raw2 = rraw.unwrap();
2834
+ const decoder = {
2835
+ ...defaultDecoder,
2836
+ ...pdecoder
2837
+ };
2838
+ switch (url.getParam("store" /* STORE */)) {
2839
+ case "data":
2840
+ if (url.getParam("suffix" /* SUFFIX */) === ".car") {
2841
+ return makeFPEnvelope("car" /* CAR */, await decoder.car(sthis, raw2));
2842
+ }
2843
+ return makeFPEnvelope("file" /* FILE */, await decoder.file(sthis, raw2));
2844
+ case "wal":
2845
+ return makeFPEnvelope("wal" /* WAL */, await decode2WalState(sthis, await decoder.wal(sthis, raw2)));
2846
+ case "meta":
2847
+ return makeFPEnvelope("meta" /* META */, await decode2DbMetaEvents(sthis, await decoder.meta(sthis, raw2)));
2848
+ default:
2849
+ return sthis.logger.Error().Str("store", url.getParam("store" /* STORE */)).Msg("unsupported store").ResultError();
2850
+ }
2851
+ }
2852
+
2853
+ // src/runtime/gateways/file/index.ts
2854
+ var file_exports = {};
2855
+ __export(file_exports, {
2856
+ KeyBagProviderFile: () => KeyBagProviderFile,
2857
+ sysFileSystemFactory: () => sysFileSystemFactory
2858
+ });
2859
+
2860
+ // src/runtime/gateways/indexdb/version.ts
2861
+ var INDEXDB_VERSION = "v0.19-indexdb";
2862
+
2863
+ // src/runtime/gateways/file/gateway-impl.ts
2864
+ var import_cement14 = require("@adviser/cement");
2865
+ var versionFiles = new import_cement14.KeyedResolvOnce();
2866
+ var FileGateway = class {
2867
+ constructor(sthis, fs) {
2868
+ this.fs = fs;
2869
+ }
2870
+ async getVersionFromFile(path, sthis) {
2871
+ return versionFiles.get(path).once(async () => {
2872
+ await this.fs.mkdir(path, { recursive: true });
2873
+ const vFile = sthis.pathOps.join(path, "version");
2874
+ const vFileStat = await this.fs.stat(vFile).catch(() => void 0);
2875
+ if (!vFileStat) {
2876
+ await this.fs.writefile(sthis.pathOps.join(path, "version"), FILESTORE_VERSION);
2877
+ return FILESTORE_VERSION;
2878
+ } else if (!vFileStat.isFile()) {
2879
+ throw sthis.logger.Error().Str("file", vFile).Msg(`version file is a directory`).AsError();
2880
+ }
2881
+ const v = await this.fs.readfile(vFile);
2882
+ const vStr = sthis.txt.decode(v);
2883
+ if (vStr !== FILESTORE_VERSION) {
2884
+ sthis.logger.Warn().Str("file", vFile).Str("from", vStr).Str("expected", FILESTORE_VERSION).Msg(`version mismatch`);
2885
+ }
2886
+ return vStr;
2887
+ });
2888
+ }
2889
+ start(baseURL, sthis) {
2890
+ return (0, import_cement14.exception2Result)(async () => {
2891
+ await this.fs.start();
2892
+ const url = baseURL.build();
2893
+ url.defParam("version" /* VERSION */, FILESTORE_VERSION);
2894
+ const dbUrl = await this.buildUrl(url.URI(), "dummy");
2895
+ const dbdirFile = this.getFilePath(dbUrl.Ok(), sthis);
2896
+ await this.fs.mkdir(sthis.pathOps.dirname(dbdirFile), { recursive: true });
2897
+ const dbroot = sthis.pathOps.dirname(dbdirFile);
2898
+ sthis.logger.Debug().Url(url.URI()).Str("dbroot", dbroot).Msg("start");
2899
+ url.setParam("version" /* VERSION */, await this.getVersionFromFile(dbroot, sthis));
2900
+ return url.URI();
2901
+ });
2902
+ }
2903
+ async buildUrl(baseUrl, key) {
2904
+ return import_cement14.Result.Ok(baseUrl.build().setParam("key" /* KEY */, key).URI());
2905
+ }
2906
+ async close() {
2907
+ return import_cement14.Result.Ok(void 0);
2908
+ }
2909
+ getFilePath(url, sthis) {
2910
+ const key = url.getParam("key" /* KEY */);
2911
+ if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
2912
+ return sthis.pathOps.join(getPath(url, sthis), getFileName(url, sthis));
2913
+ }
2914
+ async put(url, bytes, sthis) {
2915
+ return (0, import_cement14.exception2Result)(async () => {
2916
+ const file = await this.getFilePath(url, sthis);
2917
+ sthis.logger.Debug().Str("url", url.toString()).Str("file", file).Msg("put");
2918
+ await this.fs.writefile(file, bytes);
2919
+ });
2920
+ }
2921
+ async get(url, sthis) {
2922
+ return exceptionWrapper(async () => {
2923
+ const file = this.getFilePath(url, sthis);
2924
+ try {
2925
+ sthis.logger.Debug().Url(url).Str("file", file).Msg("get");
2926
+ const res = await this.fs.readfile(file);
2927
+ return import_cement14.Result.Ok(res);
2928
+ } catch (e) {
2929
+ if (isNotFoundError(e)) {
2930
+ return import_cement14.Result.Err(new NotFoundError(`file not found: ${file}`));
2931
+ }
2932
+ return import_cement14.Result.Err(e);
2933
+ }
2934
+ });
2935
+ }
2936
+ async delete(url, sthis) {
2937
+ return (0, import_cement14.exception2Result)(async () => {
2938
+ await this.fs.unlink(this.getFilePath(url, sthis));
2939
+ });
2940
+ }
2941
+ async destroy(baseURL, sthis) {
2942
+ const url = await this.buildUrl(baseURL, "x");
2943
+ if (url.isErr()) return url;
2944
+ const filepath = sthis.pathOps.dirname(this.getFilePath(url.Ok(), sthis));
2945
+ let files = [];
2946
+ try {
2947
+ files = await this.fs.readdir(filepath);
2948
+ } catch (e) {
2949
+ if (!isNotFoundError(e)) {
2950
+ throw sthis.logger.Error().Err(e).Str("dir", filepath).Msg("destroy:readdir").AsError();
2951
+ }
2952
+ }
2953
+ for (const file of files) {
2954
+ const pathed = sthis.pathOps.join(filepath, file);
2955
+ try {
2956
+ await this.fs.unlink(pathed);
2957
+ } catch (e) {
2958
+ if (!isNotFoundError(e)) {
2959
+ throw sthis.logger.Error().Err(e).Str("file", pathed).Msg("destroy:unlink").AsError();
2960
+ }
2961
+ }
2962
+ }
2963
+ return import_cement14.Result.Ok(void 0);
2964
+ }
2965
+ async getPlain(iurl, key, sthis) {
2966
+ const url = iurl.build().setParam("key" /* KEY */, key).URI();
2967
+ const dbFile = sthis.pathOps.join(getPath(url, sthis), getFileName(url, sthis));
2968
+ sthis.logger.Debug().Url(url).Str("dbFile", dbFile).Msg("get");
2969
+ const buffer = await this.fs.readfile(dbFile);
2970
+ sthis.logger.Debug().Url(url).Str("dbFile", dbFile).Len(buffer).Msg("got");
2971
+ return import_cement14.Result.Ok(buffer);
2972
+ }
2973
+ };
2974
+
2975
+ // src/runtime/gateways/def-serde-gateway.ts
2976
+ var import_cement15 = require("@adviser/cement");
2977
+ var DefSerdeGateway = class {
2978
+ constructor(gw) {
2979
+ this.gw = gw;
2980
+ }
2981
+ start(sthis, baseURL) {
2982
+ return this.gw.start(baseURL, sthis);
2983
+ }
2984
+ async buildUrl(sthis, baseUrl, key) {
2985
+ return this.gw.buildUrl(baseUrl, key, sthis);
2986
+ }
2987
+ async close(sthis, uri) {
2988
+ return this.gw.close(uri, sthis);
2989
+ }
2990
+ async put(sthis, url, env) {
2991
+ const rUint8 = await fpSerialize(sthis, env);
2992
+ if (rUint8.isErr()) return rUint8;
2993
+ return this.gw.put(url, rUint8.Ok(), sthis);
2994
+ }
2995
+ async get(sthis, url) {
2996
+ const res = await this.gw.get(url, sthis);
2997
+ if (res.isErr()) return import_cement15.Result.Err(res.Err());
2998
+ return fpDeserialize(sthis, url, res);
2999
+ }
3000
+ async delete(sthis, url) {
3001
+ return this.gw.delete(url, sthis);
3002
+ }
3003
+ async destroy(sthis, baseURL) {
3004
+ return this.gw.destroy(baseURL, sthis);
3005
+ }
3006
+ async getPlain(sthis, iurl, key) {
3007
+ return this.gw.getPlain(iurl, key, sthis);
3008
+ }
3009
+ };
3010
+
3011
+ // src/blockstore/register-store-protocol.ts
2396
3012
  var storeFactory = /* @__PURE__ */ new Map();
2397
- function buildURL(optURL, loader) {
2398
- const storeOpts = loader.ebOpts.store;
2399
- const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
2400
- let obuUrl;
2401
- if (obuItem && obuItem.overrideBaseURL) {
2402
- obuUrl = import_cement9.URI.from(obuItem.overrideBaseURL);
2403
- }
2404
- const ret = ensureIsIndex(
2405
- import_cement9.URI.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
2406
- storeOpts.isIndex
2407
- );
2408
- return ret;
2409
- }
2410
- var onceGateway = new import_cement9.KeyedResolvOnce();
2411
- async function getGatewayFromURL(url, sthis) {
2412
- return onceGateway.get(url.toString()).once(async () => {
2413
- const item = storeFactory.get(url.protocol);
2414
- if (item) {
2415
- const ret = {
2416
- gateway: await item.gateway(sthis),
2417
- test: await item.test(sthis)
2418
- };
2419
- const res = await ret.gateway.start(url);
2420
- if (res.isErr()) {
2421
- sthis.logger.Error().Result("start", res).Msg("start failed");
2422
- return void 0;
2423
- }
2424
- return ret;
3013
+ function getDefaultURI(sthis, protocol) {
3014
+ if (protocol) {
3015
+ if (!protocol.endsWith(":")) {
3016
+ protocol += ":";
2425
3017
  }
2426
- sthis.logger.Warn().Url(url).Msg("unsupported protocol");
2427
- return void 0;
2428
- });
3018
+ const gfi = storeFactory.get(protocol);
3019
+ if (gfi) {
3020
+ return gfi.defaultURI(sthis);
3021
+ }
3022
+ }
3023
+ const found = Array.from(storeFactory.values()).find((item) => item.isDefault);
3024
+ if (!found) {
3025
+ throw sthis.logger.Error().Msg("no default found").AsError();
3026
+ }
3027
+ return found.defaultURI(sthis);
2429
3028
  }
2430
3029
  function registerStoreProtocol(item) {
2431
3030
  let protocol = item.protocol;
2432
3031
  if (!protocol.endsWith(":")) {
2433
3032
  protocol += ":";
2434
3033
  }
2435
- if (storeFactory.has(protocol)) {
2436
- if (!item.overrideBaseURL && storeFactory.get(protocol) !== item) {
2437
- throw new Error(`we need a logger here`);
2438
- return () => {
2439
- };
2440
- }
3034
+ if (!item.serdegateway && !item.gateway) {
3035
+ throw new Error(`registerStoreProtocol needs a gateway or serdegateway`);
2441
3036
  }
2442
- if (item.overrideBaseURL) {
3037
+ let serdegateway;
3038
+ if (item.gateway) {
3039
+ serdegateway = async (sthis) => {
3040
+ const m = await item.gateway(sthis);
3041
+ return new DefSerdeGateway(m);
3042
+ };
3043
+ } else {
3044
+ serdegateway = item.serdegateway;
3045
+ }
3046
+ if (item.isDefault) {
2443
3047
  Array.from(storeFactory.values()).forEach((items) => {
2444
- items.overrideBaseURL = void 0;
3048
+ items.isDefault = false;
2445
3049
  });
2446
3050
  }
2447
- storeFactory.set(protocol, item);
3051
+ storeFactory.set(protocol, {
3052
+ ...item,
3053
+ serdegateway
3054
+ });
2448
3055
  return () => {
2449
3056
  storeFactory.delete(protocol);
2450
3057
  };
2451
3058
  }
2452
- var onceDataStoreFactory = new import_cement9.KeyedResolvOnce();
2453
- async function dataStoreFactory(loader) {
2454
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
2455
- const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
2456
- return onceDataStoreFactory.get(url.toString()).once(async () => {
2457
- const gateway = await getGatewayFromURL(url, sthis);
2458
- if (!gateway) {
2459
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
3059
+ function getGatewayFactoryItem(protocol) {
3060
+ return storeFactory.get(protocol);
3061
+ }
3062
+ function defaultGatewayFactoryItem() {
3063
+ const found = Array.from(storeFactory.values()).find((item) => item.isDefault);
3064
+ if (!found) {
3065
+ throw new Error("no default found");
3066
+ }
3067
+ return found;
3068
+ }
3069
+ function defaultURI(sthis) {
3070
+ const rt = (0, import_cement16.runtimeFn)();
3071
+ return import_cement16.BuildURI.from("file://").pathname(`${sthis.env.get("HOME")}/.fireproof/${FILESTORE_VERSION.replace(/-.*$/, "")}`).setParam("version" /* VERSION */, FILESTORE_VERSION).setParam("urlGen" /* URL_GEN */, "default").setParam("runtime" /* RUNTIME */, rt.isNodeIsh ? "node" : rt.isDeno ? "deno" : "unknown").URI();
3072
+ }
3073
+ if ((0, import_cement16.runtimeFn)().isNodeIsh || (0, import_cement16.runtimeFn)().isDeno) {
3074
+ registerStoreProtocol({
3075
+ protocol: "file:",
3076
+ isDefault: true,
3077
+ defaultURI,
3078
+ gateway: async (sthis) => {
3079
+ return new FileGateway(sthis, await sysFileSystemFactory(defaultURI(sthis)));
3080
+ }
3081
+ });
3082
+ }
3083
+ if ((0, import_cement16.runtimeFn)().isBrowser) {
3084
+ registerStoreProtocol({
3085
+ protocol: "indexdb:",
3086
+ isDefault: true,
3087
+ defaultURI: () => {
3088
+ return import_cement16.BuildURI.from("indexdb://").pathname("fp").setParam("version" /* VERSION */, INDEXDB_VERSION).setParam("runtime" /* RUNTIME */, "browser").URI();
3089
+ },
3090
+ gateway: async () => {
3091
+ const { GatewayImpl } = await import("@fireproof/core/web");
3092
+ return new GatewayImpl();
2460
3093
  }
2461
- const store = new DataStoreImpl(sthis, loader.name, url, {
2462
- gateway: gateway.gateway,
2463
- keybag: () => getKeyBag(loader.sthis, {
2464
- ...loader.ebOpts.keyBag
2465
- })
2466
- });
2467
- return store;
2468
3094
  });
2469
3095
  }
2470
- var onceMetaStoreFactory = new import_cement9.KeyedResolvOnce();
2471
- async function metaStoreFactory(loader) {
2472
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
2473
- const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
2474
- return onceMetaStoreFactory.get(url.toString()).once(async () => {
2475
- sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
2476
- const gateway = await getGatewayFromURL(url, sthis);
2477
- if (!gateway) {
2478
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2479
- }
2480
- const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
2481
- gateway: gateway.gateway,
2482
- keybag: () => getKeyBag(loader.sthis, {
2483
- ...loader.ebOpts.keyBag
2484
- })
2485
- });
2486
- return store;
3096
+ var memory = /* @__PURE__ */ new Map();
3097
+ registerStoreProtocol({
3098
+ protocol: "memory:",
3099
+ isDefault: false,
3100
+ defaultURI: () => {
3101
+ return import_cement16.BuildURI.from("memory://").pathname("ram").URI();
3102
+ },
3103
+ gateway: async (sthis) => {
3104
+ return new MemoryGateway(sthis, memory);
3105
+ }
3106
+ });
3107
+
3108
+ // src/blockstore/store-factory.ts
3109
+ var onceGateway = new import_cement17.KeyedResolvOnce();
3110
+ var gatewayInstances = new import_cement17.KeyedResolvOnce();
3111
+ async function getStartedGateway(sthis, url) {
3112
+ return onceGateway.get(url.toString()).once(async () => {
3113
+ const item = getGatewayFactoryItem(url.protocol);
3114
+ if (item) {
3115
+ const ret = {
3116
+ url,
3117
+ ...await gatewayInstances.get(url.protocol).once(async () => ({})),
3118
+ gateway: await item.serdegateway(sthis)
3119
+ };
3120
+ const res = await ret.gateway.start(sthis, url);
3121
+ if (res.isErr()) {
3122
+ return import_cement17.Result.Err(sthis.logger.Error().Result("start", res).Msg("start failed").AsError());
3123
+ }
3124
+ ret.url = res.Ok();
3125
+ return import_cement17.Result.Ok(ret);
3126
+ }
3127
+ return import_cement17.Result.Err(sthis.logger.Warn().Url(url).Msg("unsupported protocol").AsError());
2487
3128
  });
2488
3129
  }
2489
- var onceRemoteWalFactory = new import_cement9.KeyedResolvOnce();
2490
- async function remoteWalFactory(loader) {
2491
- const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
2492
- const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
2493
- return onceRemoteWalFactory.get(url.toString()).once(async () => {
2494
- const gateway = await getGatewayFromURL(url, sthis);
2495
- if (!gateway) {
2496
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2497
- }
2498
- sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
2499
- const store = new WALStoreImpl(loader, url, {
2500
- gateway: gateway.gateway,
2501
- keybag: () => getKeyBag(loader.sthis, {
2502
- ...loader.ebOpts.keyBag
2503
- })
2504
- });
2505
- return store;
3130
+ async function dataStoreFactory(sfi) {
3131
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "data").URI();
3132
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3133
+ if (rgateway.isErr()) {
3134
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3135
+ }
3136
+ const gateway = rgateway.Ok();
3137
+ const store = new DataStoreImpl(sfi.sthis, gateway.url, {
3138
+ gateway: gateway.gateway,
3139
+ gatewayInterceptor: sfi.gatewayInterceptor,
3140
+ loader: sfi.loader
2506
3141
  });
3142
+ return store;
2507
3143
  }
2508
- async function testStoreFactory(url, sthis) {
2509
- sthis = ensureSuperLog(sthis, "testStoreFactory");
2510
- const gateway = await getGatewayFromURL(url, sthis);
2511
- if (!gateway) {
2512
- throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2513
- }
2514
- return gateway.test;
3144
+ async function metaStoreFactory(sfi) {
3145
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "meta").URI();
3146
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3147
+ if (rgateway.isErr()) {
3148
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3149
+ }
3150
+ const gateway = rgateway.Ok();
3151
+ const store = new MetaStoreImpl(sfi.sthis, gateway.url, {
3152
+ gateway: gateway.gateway,
3153
+ gatewayInterceptor: sfi.gatewayInterceptor,
3154
+ loader: sfi.loader
3155
+ });
3156
+ return store;
3157
+ }
3158
+ async function WALStoreFactory(sfi) {
3159
+ const storeUrl = sfi.url.build().setParam("store" /* STORE */, "wal").URI();
3160
+ const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
3161
+ if (rgateway.isErr()) {
3162
+ throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
3163
+ }
3164
+ const gateway = rgateway.Ok();
3165
+ const store = new WALStoreImpl(sfi.sthis, gateway.url, {
3166
+ gateway: gateway.gateway,
3167
+ gatewayInterceptor: sfi.gatewayInterceptor,
3168
+ loader: sfi.loader
3169
+ });
3170
+ return store;
2515
3171
  }
2516
- async function ensureStart(store, logger) {
3172
+ async function ensureStart(store) {
2517
3173
  const ret = await store.start();
2518
3174
  if (ret.isErr()) {
2519
- throw logger.Error().Result("start", ret).Msg("start failed").AsError();
3175
+ throw store.logger.Error().Result("start", ret).Msg("start failed").AsError();
2520
3176
  }
2521
- logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
3177
+ store.logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
2522
3178
  return store;
2523
3179
  }
2524
- function toStoreRuntime(opts, sthis) {
2525
- const logger = ensureLogger(sthis, "toStoreRuntime", {});
3180
+ function ensureStoreEnDeFile(ende) {
3181
+ ende = ende || {};
2526
3182
  return {
2527
- makeMetaStore: async (loader) => {
2528
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeMetaStore).Msg("makeMetaStore");
2529
- return ensureStart(await (loader.ebOpts.store.makeMetaStore || metaStoreFactory)(loader), logger);
2530
- },
2531
- makeDataStore: async (loader) => {
2532
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeDataStore).Msg("makeDataStore");
2533
- return ensureStart(await (loader.ebOpts.store.makeDataStore || dataStoreFactory)(loader), logger);
2534
- },
2535
- makeWALStore: async (loader) => {
2536
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeWALStore).Msg("makeRemoteWAL");
2537
- return ensureStart(await (loader.ebOpts.store.makeWALStore || remoteWalFactory)(loader), logger);
2538
- },
2539
- encodeFile: opts.encodeFile || encodeFile,
2540
- decodeFile: opts.decodeFile || decodeFile
3183
+ encodeFile: ende.encodeFile || encodeFile,
3184
+ decodeFile: ende.decodeFile || decodeFile
2541
3185
  };
2542
3186
  }
2543
- if ((0, import_cement9.runtimeFn)().isNodeIsh || (0, import_cement9.runtimeFn)().isDeno) {
2544
- registerStoreProtocol({
2545
- protocol: "file:",
2546
- gateway: async (sthis) => {
2547
- const { GatewayImpl } = await import("@fireproof/core/node");
2548
- return new GatewayImpl(sthis);
2549
- },
2550
- test: async (sthis) => {
2551
- const { GatewayTestImpl } = await import("@fireproof/core/node");
2552
- return new GatewayTestImpl(sthis);
2553
- }
2554
- });
2555
- }
2556
- if ((0, import_cement9.runtimeFn)().isBrowser) {
2557
- registerStoreProtocol({
2558
- protocol: "indexdb:",
2559
- gateway: async (sthis) => {
2560
- const { GatewayImpl } = await import("@fireproof/core/web");
2561
- return new GatewayImpl(sthis);
2562
- },
2563
- test: async (sthis) => {
2564
- const { GatewayTestImpl } = await import("@fireproof/core/web");
2565
- return new GatewayTestImpl(sthis);
2566
- }
2567
- });
3187
+ function toStoreRuntime(sthis, endeOpts = {}) {
3188
+ return {
3189
+ makeMetaStore: async (sfi) => ensureStart(await metaStoreFactory(sfi)),
3190
+ // async (loader: Loadable) => {
3191
+ // logger
3192
+ // .Debug()
3193
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeMetaStore)
3194
+ // .Msg("makeMetaStore");
3195
+ // return ensureStart(await (endeOpts.func?.makeMetaStore || metaStoreFactory)(loader), logger);
3196
+ // },
3197
+ makeDataStore: async (sfi) => ensureStart(await dataStoreFactory(sfi)),
3198
+ // async (loader: Loadable) => {
3199
+ // logger
3200
+ // .Debug()
3201
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeDataStore)
3202
+ // .Msg("makeDataStore");
3203
+ // return ensureStart(await (endeOpts.func?.makeDataStore || dataStoreFactory)(loader), logger);
3204
+ // },
3205
+ makeWALStore: async (sfi) => ensureStart(await WALStoreFactory(sfi)),
3206
+ // async (loader: Loadable) => {
3207
+ // logger
3208
+ // .Debug()
3209
+ // .Str("fromOpts", "" + !!endeOpts.func?.makeWALStore)
3210
+ // .Msg("makeRemoteWAL");
3211
+ // return ensureStart(await (endeOpts.func?.makeWALStore || remoteWalFactory)(loader), logger);
3212
+ // },
3213
+ ...ensureStoreEnDeFile(endeOpts)
3214
+ };
2568
3215
  }
2569
3216
 
2570
3217
  // src/blockstore/store-remote.ts
2571
- async function RemoteDataStore(sthis, name, url, opts) {
2572
- const ds = new DataStoreImpl(sthis, name, url, opts);
3218
+ async function RemoteDataStore(sthis, url, opts) {
3219
+ const ds = new DataStoreImpl(sthis, url, opts);
2573
3220
  await ds.start();
2574
3221
  return ds;
2575
3222
  }
2576
- async function RemoteMetaStore(sthis, name, url, opts) {
2577
- const ms = new MetaStoreImpl(
2578
- sthis,
2579
- name,
2580
- url,
2581
- opts
2582
- /* , true*/
2583
- );
3223
+ async function RemoteMetaStore(sthis, url, opts) {
3224
+ const ms = new MetaStoreImpl(sthis, url, opts);
2584
3225
  await ms.start();
2585
3226
  return ms;
2586
3227
  }
2587
3228
 
2588
3229
  // src/blockstore/connection-base.ts
3230
+ function coerceLoader(ref) {
3231
+ const refl = ref;
3232
+ if (refl.loader) {
3233
+ return refl.loader;
3234
+ }
3235
+ const refb = ref;
3236
+ if (refb.blockstore) {
3237
+ return coerceLoader(refb.blockstore);
3238
+ }
3239
+ return void 0;
3240
+ }
2589
3241
  var ConnectionBase = class {
2590
3242
  constructor(url, logger) {
2591
3243
  this.loaded = Promise.resolve();
@@ -2596,23 +3248,26 @@ var ConnectionBase = class {
2596
3248
  await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
2597
3249
  await (await throwFalsy(this.loader).WALStore()).process();
2598
3250
  }
2599
- async connect_X({ loader }) {
2600
- if (!loader) throw this.logger.Error().Msg("loader is required").AsError();
2601
- await this.connectMeta_X({ loader });
2602
- await this.connectStorage_X({ loader });
3251
+ async connect(refl) {
3252
+ await this.connectMeta(refl);
3253
+ await this.connectStorage(refl);
2603
3254
  }
2604
- async connectMeta_X({ loader }) {
2605
- if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
3255
+ async connectMeta(refl) {
3256
+ const loader = coerceLoader(refl);
3257
+ if (!loader) throw this.logger.Error().Msg("connectMeta: loader is required").AsError();
2606
3258
  this.loader = loader;
2607
3259
  await this.onConnect();
2608
- const metaUrl = this.url.build().defParam("store", "meta").URI();
2609
- const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
2610
- if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
2611
- const dbName = metaUrl.getParam("name");
2612
- if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: name is required").AsError();
2613
- const remote = await RemoteMetaStore(loader.sthis, dbName, metaUrl, {
3260
+ const metaUrl = this.url.build().defParam("store" /* STORE */, "meta").URI();
3261
+ const rgateway = await getStartedGateway(loader.sthis, metaUrl);
3262
+ if (rgateway.isErr())
3263
+ throw this.logger.Error().Result("err", rgateway).Url(metaUrl).Msg("connectMeta: gateway is required").AsError();
3264
+ const dbName = metaUrl.getParam("name" /* NAME */);
3265
+ if (!dbName) {
3266
+ throw this.logger.Error().Url(metaUrl).Msg("connectMeta: dbName is required").AsError();
3267
+ }
3268
+ const gateway = rgateway.Ok();
3269
+ const remote = await RemoteMetaStore(loader.sthis, metaUrl, {
2614
3270
  gateway: gateway.gateway,
2615
- keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag),
2616
3271
  loader
2617
3272
  });
2618
3273
  this.loader.remoteMetaStore = remote;
@@ -2622,17 +3277,19 @@ var ConnectionBase = class {
2622
3277
  });
2623
3278
  });
2624
3279
  }
2625
- async connectStorage_X({ loader }) {
3280
+ async connectStorage(refl) {
3281
+ const loader = coerceLoader(refl);
2626
3282
  if (!loader) throw this.logger.Error().Msg("connectStorage_X: loader is required").AsError();
2627
3283
  this.loader = loader;
2628
- const dataUrl = this.url.build().defParam("store", "data").URI();
2629
- const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
2630
- if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
2631
- const name = dataUrl.getParam("name");
3284
+ const dataUrl = this.url.build().defParam("store" /* STORE */, "data").URI();
3285
+ const rgateway = await getStartedGateway(loader.sthis, dataUrl);
3286
+ if (rgateway.isErr())
3287
+ throw this.logger.Error().Result("err", rgateway).Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
3288
+ const name = dataUrl.getParam("name" /* NAME */);
2632
3289
  if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: name is required").AsError;
2633
- loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
2634
- gateway: gateway.gateway,
2635
- keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
3290
+ loader.remoteCarStore = await RemoteDataStore(loader.sthis, this.url, {
3291
+ gateway: rgateway.Ok().gateway,
3292
+ loader
2636
3293
  });
2637
3294
  loader.remoteFileStore = loader.remoteCarStore;
2638
3295
  }
@@ -2672,6 +3329,12 @@ var ConnectionBase = class {
2672
3329
  };
2673
3330
 
2674
3331
  // src/crdt-helpers.ts
3332
+ var import_link2 = require("multiformats/link");
3333
+ var import_sha25 = require("multiformats/hashes/sha2");
3334
+ var codec = __toESM(require("@fireproof/vendor/@ipld/dag-cbor"), 1);
3335
+ var import_crdt = require("@fireproof/vendor/@web3-storage/pail/crdt");
3336
+ var import_clock3 = require("@fireproof/vendor/@web3-storage/pail/clock");
3337
+ var Batch = __toESM(require("@fireproof/vendor/@web3-storage/pail/crdt/batch"), 1);
2675
3338
  function time(tag) {
2676
3339
  }
2677
3340
  function timeEnd(tag) {
@@ -2818,7 +3481,7 @@ async function getValueFromLink(blocks, link, logger) {
2818
3481
  readFiles(blocks, cvalue);
2819
3482
  return cvalue;
2820
3483
  }
2821
- var DirtyEventFetcher = class extends import_clock2.EventFetcher {
3484
+ var DirtyEventFetcher = class extends import_clock3.EventFetcher {
2822
3485
  constructor(logger, blocks) {
2823
3486
  super(blocks);
2824
3487
  this.logger = logger;
@@ -2833,7 +3496,7 @@ var DirtyEventFetcher = class extends import_clock2.EventFetcher {
2833
3496
  }
2834
3497
  };
2835
3498
  async function clockChangesSince(blocks, head, since, opts, logger) {
2836
- const eventsFetcher = opts.dirty ? new DirtyEventFetcher(logger, blocks) : new import_clock2.EventFetcher(blocks);
3499
+ const eventsFetcher = opts.dirty ? new DirtyEventFetcher(logger, blocks) : new import_clock3.EventFetcher(blocks);
2837
3500
  const keys = /* @__PURE__ */ new Set();
2838
3501
  const updates = await gatherUpdates(
2839
3502
  blocks,
@@ -2890,7 +3553,7 @@ async function* getAllEntries(blocks, head, logger) {
2890
3553
  }
2891
3554
  }
2892
3555
  async function* clockVis(blocks, head) {
2893
- for await (const line of (0, import_clock2.vis)(blocks, head)) {
3556
+ for await (const line of (0, import_clock3.vis)(blocks, head)) {
2894
3557
  yield line;
2895
3558
  }
2896
3559
  }
@@ -2912,7 +3575,7 @@ async function doCompact(blockLog, head, logger) {
2912
3575
  }
2913
3576
  timeEnd("compact all entries");
2914
3577
  time("compact clock vis");
2915
- for await (const _line of (0, import_clock2.vis)(blockLog, head)) {
3578
+ for await (const _line of (0, import_clock3.vis)(blockLog, head)) {
2916
3579
  }
2917
3580
  timeEnd("compact clock vis");
2918
3581
  time("compact root");
@@ -2929,7 +3592,7 @@ async function doCompact(blockLog, head, logger) {
2929
3592
  isCompacting = false;
2930
3593
  }
2931
3594
  async function getBlock(blocks, cidString) {
2932
- const block = await blocks.get((0, import_link.parse)(cidString));
3595
+ const block = await blocks.get((0, import_link2.parse)(cidString));
2933
3596
  if (!block) throw new Error(`Missing block ${cidString}`);
2934
3597
  const { cid, value } = await decode({ bytes: block.bytes, codec, hasher: import_sha25.sha256 });
2935
3598
  return new Block({ cid, value, bytes: block.bytes });
@@ -2940,7 +3603,7 @@ var import_sha26 = require("multiformats/hashes/sha2");
2940
3603
  var codec2 = __toESM(require("@fireproof/vendor/@ipld/dag-cbor"), 1);
2941
3604
  var import_charwise = __toESM(require("charwise"), 1);
2942
3605
  var DbIndex = __toESM(require("prolly-trees/db-index"), 1);
2943
- var import_utils9 = require("prolly-trees/utils");
3606
+ var import_utils12 = require("prolly-trees/utils");
2944
3607
  var import_cache = require("prolly-trees/cache");
2945
3608
  var IndexTree = class {
2946
3609
  };
@@ -2948,17 +3611,17 @@ function refCompare(aRef, bRef) {
2948
3611
  if (Number.isNaN(aRef)) return -1;
2949
3612
  if (Number.isNaN(bRef)) throw new Error("ref may not be Infinity or NaN");
2950
3613
  if (aRef === Infinity) return 1;
2951
- return (0, import_utils9.simpleCompare)(aRef, bRef);
3614
+ return (0, import_utils12.simpleCompare)(aRef, bRef);
2952
3615
  }
2953
3616
  function compare(a, b) {
2954
3617
  const [aKey, aRef] = a;
2955
3618
  const [bKey, bRef] = b;
2956
- const comp = (0, import_utils9.simpleCompare)(aKey, bKey);
3619
+ const comp = (0, import_utils12.simpleCompare)(aKey, bKey);
2957
3620
  if (comp !== 0) return comp;
2958
3621
  return refCompare(aRef, bRef);
2959
3622
  }
2960
- var byKeyOpts = { cache: import_cache.nocache, chunker: (0, import_utils9.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare };
2961
- var byIdOpts = { cache: import_cache.nocache, chunker: (0, import_utils9.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare: import_utils9.simpleCompare };
3623
+ var byKeyOpts = { cache: import_cache.nocache, chunker: (0, import_utils12.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare };
3624
+ var byIdOpts = { cache: import_cache.nocache, chunker: (0, import_utils12.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare: import_utils12.simpleCompare };
2962
3625
  function indexEntriesForChanges(changes, mapFn) {
2963
3626
  const indexEntries = [];
2964
3627
  changes.forEach(({ id: key, value, del }) => {
@@ -2989,7 +3652,8 @@ function makeProllyGetBlock(blocks) {
2989
3652
  return create({ cid, bytes, hasher: import_sha26.sha256, codec: codec2 });
2990
3653
  };
2991
3654
  }
2992
- async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
3655
+ async function bulkIndex(logger, tblocks, inIndex, indexEntries, opts) {
3656
+ logger.Debug().Msg("enter bulkIndex");
2993
3657
  if (!indexEntries.length) return inIndex;
2994
3658
  if (!inIndex.root) {
2995
3659
  if (!inIndex.cid) {
@@ -3006,18 +3670,22 @@ async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
3006
3670
  returnNode = node;
3007
3671
  }
3008
3672
  if (!returnNode || !returnRootBlock) throw new Error("failed to create index");
3673
+ logger.Debug().Msg("exit !root bulkIndex");
3009
3674
  return { root: returnNode, cid: returnRootBlock.cid };
3010
3675
  } else {
3011
3676
  inIndex.root = await DbIndex.load({ cid: inIndex.cid, get: makeProllyGetBlock(tblocks), ...opts });
3012
3677
  }
3013
3678
  }
3679
+ logger.Debug().Msg("pre bulk bulkIndex");
3014
3680
  const { root: root3, blocks: newBlocks } = await inIndex.root.bulk(indexEntries);
3015
3681
  if (root3) {
3682
+ logger.Debug().Msg("pre root put bulkIndex");
3016
3683
  for await (const block of newBlocks) {
3017
3684
  await tblocks.put(block.cid, block.bytes);
3018
3685
  }
3019
3686
  return { root: root3, cid: (await root3.block).cid };
3020
3687
  } else {
3688
+ logger.Debug().Msg("pre !root bulkIndex");
3021
3689
  return { root: void 0, cid: void 0 };
3022
3690
  }
3023
3691
  }
@@ -3057,17 +3725,17 @@ function encodeKey(key) {
3057
3725
  }
3058
3726
 
3059
3727
  // src/indexer.ts
3060
- function index(sthis, { _crdt }, name, mapFn, meta) {
3061
- if (mapFn && meta) throw _crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
3062
- if (mapFn && mapFn.constructor.name !== "Function") throw _crdt.logger.Error().Msg("mapFn must be a function").AsError();
3063
- if (_crdt.indexers.has(name)) {
3064
- const idx = _crdt.indexers.get(name);
3728
+ function index(refDb, name, mapFn, meta) {
3729
+ if (mapFn && meta) throw refDb.crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
3730
+ if (mapFn && mapFn.constructor.name !== "Function") throw refDb.crdt.logger.Error().Msg("mapFn must be a function").AsError();
3731
+ if (refDb.crdt.indexers.has(name)) {
3732
+ const idx = refDb.crdt.indexers.get(name);
3065
3733
  idx.applyMapFn(name, mapFn, meta);
3066
3734
  } else {
3067
- const idx = new Index(sthis, _crdt, name, mapFn, meta);
3068
- _crdt.indexers.set(name, idx);
3735
+ const idx = new Index(refDb.crdt.sthis, refDb.crdt, name, mapFn, meta);
3736
+ refDb.crdt.indexers.set(name, idx);
3069
3737
  }
3070
- return _crdt.indexers.get(name);
3738
+ return refDb.crdt.indexers.get(name);
3071
3739
  }
3072
3740
  var Index = class {
3073
3741
  constructor(sthis, crdt, name, mapFn, meta) {
@@ -3086,18 +3754,9 @@ var Index = class {
3086
3754
  return Promise.all([this.blockstore.ready(), this.crdt.ready()]).then(() => {
3087
3755
  });
3088
3756
  }
3089
- close() {
3090
- return Promise.all([this.blockstore.close(), this.crdt.close()]).then(() => {
3091
- });
3092
- }
3093
- destroy() {
3094
- return Promise.all([this.blockstore.destroy(), this.crdt.destroy()]).then(() => {
3095
- });
3096
- }
3097
3757
  applyMapFn(name, mapFn, meta) {
3098
3758
  if (mapFn && meta) throw this.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
3099
3759
  if (this.name && this.name !== name) throw this.logger.Error().Msg("cannot change name").AsError();
3100
- this.name = name;
3101
3760
  try {
3102
3761
  if (meta) {
3103
3762
  if (this.indexHead && this.indexHead.map((c) => c.toString()).join() !== meta.head.map((c) => c.toString()).join()) {
@@ -3145,9 +3804,13 @@ var Index = class {
3145
3804
  }
3146
3805
  }
3147
3806
  async query(opts = {}) {
3807
+ this.logger.Debug().Msg("enter query");
3148
3808
  await this.ready();
3809
+ this.logger.Debug().Msg("post ready query");
3149
3810
  await this._updateIndex();
3811
+ this.logger.Debug().Msg("post _updateIndex query");
3150
3812
  await this._hydrateIndex();
3813
+ this.logger.Debug().Msg("post _hydrateIndex query");
3151
3814
  if (!this.byKey.root) {
3152
3815
  return await applyQuery(this.crdt, { result: [] }, opts);
3153
3816
  }
@@ -3203,13 +3866,16 @@ var Index = class {
3203
3866
  }
3204
3867
  async _updateIndex() {
3205
3868
  await this.ready();
3869
+ this.logger.Debug().Msg("enter _updateIndex");
3206
3870
  if (this.initError) throw this.initError;
3207
3871
  if (!this.mapFn) throw this.logger.Error().Msg("No map function defined").AsError();
3208
3872
  let result, head;
3209
3873
  if (!this.indexHead || this.indexHead.length === 0) {
3210
3874
  ({ result, head } = await this.crdt.allDocs());
3875
+ this.logger.Debug().Msg("enter crdt.allDocs");
3211
3876
  } else {
3212
3877
  ({ result, head } = await this.crdt.changes(this.indexHead));
3878
+ this.logger.Debug().Msg("enter crdt.changes");
3213
3879
  }
3214
3880
  if (result.length === 0) {
3215
3881
  this.indexHead = head;
@@ -3242,9 +3908,22 @@ var Index = class {
3242
3908
  if (result.length === 0) {
3243
3909
  return indexerMeta;
3244
3910
  }
3911
+ this.logger.Debug().Msg("pre this.blockstore.transaction");
3245
3912
  const { meta } = await this.blockstore.transaction(async (tblocks) => {
3246
- this.byId = await bulkIndex(tblocks, this.byId, removeIdIndexEntries.concat(byIdIndexEntries), byIdOpts);
3247
- this.byKey = await bulkIndex(tblocks, this.byKey, staleKeyIndexEntries.concat(indexEntries), byKeyOpts);
3913
+ this.byId = await bulkIndex(
3914
+ this.logger,
3915
+ tblocks,
3916
+ this.byId,
3917
+ removeIdIndexEntries.concat(byIdIndexEntries),
3918
+ byIdOpts
3919
+ );
3920
+ this.byKey = await bulkIndex(
3921
+ this.logger,
3922
+ tblocks,
3923
+ this.byKey,
3924
+ staleKeyIndexEntries.concat(indexEntries),
3925
+ byKeyOpts
3926
+ );
3248
3927
  this.indexHead = head;
3249
3928
  if (this.byId.cid && this.byKey.cid) {
3250
3929
  const idxMeta = {
@@ -3256,16 +3935,18 @@ var Index = class {
3256
3935
  };
3257
3936
  indexerMeta.indexes?.set(this.name, idxMeta);
3258
3937
  }
3938
+ this.logger.Debug().Any("indexerMeta", new Array(indexerMeta.indexes?.entries())).Msg("exit this.blockstore.transaction fn");
3259
3939
  return indexerMeta;
3260
3940
  });
3941
+ this.logger.Debug().Msg("post this.blockstore.transaction");
3261
3942
  return meta;
3262
3943
  }
3263
3944
  };
3264
3945
 
3265
3946
  // src/crdt-clock.ts
3266
- var import_clock3 = require("@fireproof/vendor/@web3-storage/pail/clock");
3947
+ var import_clock4 = require("@fireproof/vendor/@web3-storage/pail/clock");
3267
3948
  var import_crdt2 = require("@fireproof/vendor/@web3-storage/pail/crdt");
3268
- var import_cement10 = require("@adviser/cement");
3949
+ var import_cement18 = require("@adviser/cement");
3269
3950
 
3270
3951
  // src/apply-head-queue.ts
3271
3952
  function applyHeadQueue(worker, logger) {
@@ -3322,7 +4003,7 @@ var CRDTClock = class {
3322
4003
  this.zoomers = /* @__PURE__ */ new Set();
3323
4004
  this.watchers = /* @__PURE__ */ new Set();
3324
4005
  this.emptyWatchers = /* @__PURE__ */ new Set();
3325
- this._ready = new import_cement10.ResolveOnce();
4006
+ this._ready = new import_cement18.ResolveOnce();
3326
4007
  this.blockstore = blockstore;
3327
4008
  this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
3328
4009
  this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
@@ -3422,7 +4103,7 @@ function compareClockHeads(head1, head2) {
3422
4103
  async function advanceBlocks(logger, newHead, tblocks, head) {
3423
4104
  for (const cid of newHead) {
3424
4105
  try {
3425
- head = await (0, import_clock3.advance)(tblocks, head, cid);
4106
+ head = await (0, import_clock4.advance)(tblocks, head, cid);
3426
4107
  } catch (e) {
3427
4108
  logger.Debug().Err(e).Msg("failed to advance head");
3428
4109
  continue;
@@ -3433,15 +4114,13 @@ async function advanceBlocks(logger, newHead, tblocks, head) {
3433
4114
 
3434
4115
  // src/crdt.ts
3435
4116
  var CRDT = class {
3436
- constructor(sthis, name, opts = {}) {
4117
+ constructor(sthis, opts) {
3437
4118
  this.indexers = /* @__PURE__ */ new Map();
3438
- this.onceReady = new import_cement11.ResolveOnce();
4119
+ this.onceReady = new import_cement19.ResolveOnce();
3439
4120
  this.sthis = sthis;
3440
- this.name = name;
3441
4121
  this.logger = ensureLogger(sthis, "CRDT");
3442
4122
  this.opts = opts;
3443
- this.blockstore = blockstoreFactory(sthis, {
3444
- name,
4123
+ this.blockstore = new EncryptedBlockstore(sthis, {
3445
4124
  applyMeta: async (meta) => {
3446
4125
  const crdtMeta = meta;
3447
4126
  if (!crdtMeta.head) throw this.logger.Error().Msg("missing head").AsError();
@@ -3451,23 +4130,29 @@ var CRDT = class {
3451
4130
  await doCompact(blocks, this.clock.head, this.logger);
3452
4131
  return { head: this.clock.head };
3453
4132
  },
3454
- autoCompact: this.opts.autoCompact || 100,
3455
- store: { ...this.opts.store, isIndex: void 0 },
3456
- public: this.opts.public,
3457
- meta: this.opts.meta,
3458
- threshold: this.opts.threshold
4133
+ gatewayInterceptor: opts.gatewayInterceptor,
4134
+ // autoCompact: this.opts.autoCompact || 100,
4135
+ storeRuntime: toStoreRuntime(this.sthis, this.opts.storeEnDe),
4136
+ storeUrls: this.opts.storeUrls.data,
4137
+ keyBag: this.opts.keyBag,
4138
+ // public: this.opts.public,
4139
+ meta: this.opts.meta
4140
+ // threshold: this.opts.threshold,
3459
4141
  });
3460
- this.indexBlockstore = blockstoreFactory(sthis, {
3461
- name,
4142
+ this.indexBlockstore = new EncryptedBlockstore(sthis, {
4143
+ // name: opts.name,
3462
4144
  applyMeta: async (meta) => {
3463
4145
  const idxCarMeta = meta;
3464
4146
  if (!idxCarMeta.indexes) throw this.logger.Error().Msg("missing indexes").AsError();
3465
- for (const [name2, idx] of Object.entries(idxCarMeta.indexes)) {
3466
- index(this.sthis, { _crdt: this }, name2, void 0, idx);
4147
+ for (const [name, idx] of Object.entries(idxCarMeta.indexes)) {
4148
+ index({ crdt: this }, name, void 0, idx);
3467
4149
  }
3468
4150
  },
3469
- store: { ...this.opts.store, isIndex: this.opts.store?.isIndex || "idx" },
3470
- public: this.opts.public
4151
+ gatewayInterceptor: opts.gatewayInterceptor,
4152
+ storeRuntime: toStoreRuntime(this.sthis, this.opts.storeEnDe),
4153
+ storeUrls: this.opts.storeUrls.idx,
4154
+ keyBag: this.opts.keyBag
4155
+ // public: this.opts.public,
3471
4156
  });
3472
4157
  this.clock = new CRDTClock(this.blockstore);
3473
4158
  this.clock.onZoom(() => {
@@ -3549,74 +4234,168 @@ var CRDT = class {
3549
4234
  };
3550
4235
 
3551
4236
  // src/database.ts
3552
- var Database = class {
3553
- constructor(name, opts) {
3554
- this.opts = {};
4237
+ var databases = new import_cement20.KeyedResolvOnce();
4238
+ function keyConfigOpts(sthis, name, opts) {
4239
+ return JSON.stringify(
4240
+ toSortedArray({
4241
+ name,
4242
+ stores: toSortedArray(JSON.parse(JSON.stringify(toStoreURIRuntime(sthis, name, opts?.storeUrls))))
4243
+ })
4244
+ );
4245
+ }
4246
+ function isDatabase(db) {
4247
+ return db instanceof DatabaseImpl || db instanceof DatabaseShell;
4248
+ }
4249
+ function DatabaseFactory(name, opts) {
4250
+ const sthis = ensureSuperThis(opts);
4251
+ return new DatabaseShell(
4252
+ databases.get(keyConfigOpts(sthis, name, opts)).once((key) => {
4253
+ const db = new DatabaseImpl(sthis, {
4254
+ name,
4255
+ meta: opts?.meta,
4256
+ keyBag: defaultKeyBagOpts(sthis, opts?.keyBag),
4257
+ storeUrls: toStoreURIRuntime(sthis, name, opts?.storeUrls),
4258
+ gatewayInterceptor: opts?.gatewayInterceptor,
4259
+ writeQueue: defaultWriteQueueOpts(opts?.writeQueue),
4260
+ storeEnDe: {
4261
+ encodeFile,
4262
+ decodeFile,
4263
+ ...opts?.storeEnDe
4264
+ }
4265
+ });
4266
+ db.onClosed(() => {
4267
+ databases.unget(key);
4268
+ });
4269
+ return db;
4270
+ })
4271
+ );
4272
+ }
4273
+ var DatabaseShell = class {
4274
+ constructor(ref) {
4275
+ this.ref = ref;
4276
+ ref.addShell(this);
4277
+ }
4278
+ get id() {
4279
+ return this.ref.id;
4280
+ }
4281
+ get logger() {
4282
+ return this.ref.logger;
4283
+ }
4284
+ get sthis() {
4285
+ return this.ref.sthis;
4286
+ }
4287
+ get crdt() {
4288
+ return this.ref.crdt;
4289
+ }
4290
+ get name() {
4291
+ return this.ref.name;
4292
+ }
4293
+ onClosed(fn) {
4294
+ return this.ref.onClosed(fn);
4295
+ }
4296
+ close() {
4297
+ return this.ref.shellClose(this);
4298
+ }
4299
+ destroy() {
4300
+ return this.ref.destroy();
4301
+ }
4302
+ ready() {
4303
+ return this.ref.ready();
4304
+ }
4305
+ get(id) {
4306
+ return this.ref.get(id);
4307
+ }
4308
+ put(doc) {
4309
+ return this.ref.put(doc);
4310
+ }
4311
+ bulk(docs) {
4312
+ return this.ref.bulk(docs);
4313
+ }
4314
+ del(id) {
4315
+ return this.ref.del(id);
4316
+ }
4317
+ changes(since, opts) {
4318
+ return this.ref.changes(since, opts);
4319
+ }
4320
+ allDocs(opts) {
4321
+ return this.ref.allDocs(opts);
4322
+ }
4323
+ allDocuments() {
4324
+ return this.ref.allDocuments();
4325
+ }
4326
+ subscribe(listener, updates) {
4327
+ return this.ref.subscribe(listener, updates);
4328
+ }
4329
+ query(field, opts) {
4330
+ return this.ref.query(field, opts);
4331
+ }
4332
+ compact() {
4333
+ return this.ref.compact();
4334
+ }
4335
+ };
4336
+ var DatabaseImpl = class {
4337
+ constructor(sthis, opts) {
3555
4338
  this._listening = false;
3556
4339
  this._listeners = /* @__PURE__ */ new Set();
3557
4340
  this._noupdate_listeners = /* @__PURE__ */ new Set();
3558
- this._ready = new import_cement12.ResolveOnce();
3559
- this.name = name;
3560
- this.opts = opts || this.opts;
3561
- this.sthis = ensureSuperThis(this.opts);
4341
+ // readonly blockstore: BaseBlockstore;
4342
+ this.shells = /* @__PURE__ */ new Set();
4343
+ this._onClosedFns = /* @__PURE__ */ new Set();
4344
+ this._ready = new import_cement20.ResolveOnce();
4345
+ this.opts = opts;
4346
+ this.sthis = sthis;
4347
+ this.id = sthis.timeOrderedNextId().str;
3562
4348
  this.logger = ensureLogger(this.sthis, "Database");
3563
- this._crdt = new CRDT(this.sthis, name, this.opts);
3564
- this.blockstore = this._crdt.blockstore;
3565
- this._writeQueue = writeQueue(async (updates) => {
3566
- return await this._crdt.bulk(updates);
3567
- });
3568
- this._crdt.clock.onTock(() => {
3569
- this._no_update_notify();
3570
- });
4349
+ this.crdt = new CRDT(this.sthis, this.opts);
4350
+ this._writeQueue = writeQueue(this.sthis, async (updates) => this.crdt.bulk(updates), this.opts.writeQueue);
4351
+ this.crdt.clock.onTock(() => this._no_update_notify());
3571
4352
  }
3572
- static {
3573
- this.databases = /* @__PURE__ */ new Map();
4353
+ addShell(shell) {
4354
+ this.shells.add(shell);
4355
+ }
4356
+ onClosed(fn) {
4357
+ this._onClosedFns.add(fn);
3574
4358
  }
3575
- /**
3576
- * Close the database and release resources
3577
- */
3578
4359
  async close() {
3579
- await this.ready();
3580
- await this._crdt.close();
3581
- await this.blockstore.close();
4360
+ throw this.logger.Error().Str("db", this.name).Msg(`use shellClose`).AsError();
4361
+ }
4362
+ async shellClose(db) {
4363
+ if (!this.shells.has(db)) {
4364
+ throw this.logger.Error().Str("db", this.name).Msg(`DatabaseShell mismatch`).AsError();
4365
+ }
4366
+ this.shells.delete(db);
4367
+ if (this.shells.size === 0) {
4368
+ await this.ready();
4369
+ await this.crdt.close();
4370
+ await this._writeQueue.close();
4371
+ this._onClosedFns.forEach((fn) => fn());
4372
+ }
3582
4373
  }
3583
- /**
3584
- * Destroy the database and release all resources
3585
- */
3586
4374
  async destroy() {
3587
4375
  await this.ready();
3588
- await this._crdt.destroy();
3589
- await this.blockstore.destroy();
4376
+ await this.crdt.destroy();
3590
4377
  }
3591
4378
  async ready() {
3592
- return this._ready.once(async () => {
4379
+ const ret = await this._ready.once(async () => {
3593
4380
  await this.sthis.start();
3594
- await this._crdt.ready();
3595
- await this.blockstore.ready();
4381
+ await this.crdt.ready();
3596
4382
  });
4383
+ return ret;
4384
+ }
4385
+ get name() {
4386
+ return this.opts.storeUrls.data.data.getParam("name" /* NAME */) || "default";
3597
4387
  }
3598
- /**
3599
- * Get a document from the database
3600
- * @param id - the document id
3601
- * @returns the document with the _id
3602
- * @throws NotFoundError if the document is not found
3603
- */
3604
4388
  async get(id) {
3605
4389
  if (!id) throw this.logger.Error().Str("db", this.name).Msg(`Doc id is required`).AsError();
3606
4390
  await this.ready();
3607
4391
  this.logger.Debug().Str("id", id).Msg("get");
3608
- const got = await this._crdt.get(id).catch((e) => {
4392
+ const got = await this.crdt.get(id).catch((e) => {
3609
4393
  throw new NotFoundError(`Not found: ${id} - ${e.message}`);
3610
4394
  });
3611
4395
  if (!got) throw new NotFoundError(`Not found: ${id}`);
3612
4396
  const { doc } = got;
3613
4397
  return { ...doc, _id: id };
3614
4398
  }
3615
- /**
3616
- * Put a document from the database
3617
- * @param doc - the document to put
3618
- * @returns add DocResponse with the id and clock
3619
- */
3620
4399
  async put(doc) {
3621
4400
  await this.ready();
3622
4401
  this.logger.Debug().Str("id", doc._id).Msg("put");
@@ -3631,11 +4410,21 @@ var Database = class {
3631
4410
  });
3632
4411
  return { id: docId, clock: result?.head, name: this.name };
3633
4412
  }
3634
- /**
3635
- * delete a document from the database
3636
- * @param id Document id
3637
- * @returns DocResponse with the id and clock
3638
- */
4413
+ async bulk(docs) {
4414
+ await this.ready();
4415
+ const updates = docs.map((doc) => {
4416
+ const id = doc._id || this.sthis.timeOrderedNextId().str;
4417
+ return {
4418
+ id,
4419
+ value: {
4420
+ ...doc,
4421
+ _id: id
4422
+ }
4423
+ };
4424
+ });
4425
+ const result = await this._writeQueue.bulk(updates);
4426
+ return { ids: updates.map((u) => u.id), clock: result.head, name: this.name };
4427
+ }
3639
4428
  async del(id) {
3640
4429
  await this.ready();
3641
4430
  this.logger.Debug().Str("id", id).Msg("del");
@@ -3645,7 +4434,7 @@ var Database = class {
3645
4434
  async changes(since = [], opts = {}) {
3646
4435
  await this.ready();
3647
4436
  this.logger.Debug().Any("since", since).Any("opts", opts).Msg("changes");
3648
- const { result, head } = await this._crdt.changes(since, opts);
4437
+ const { result, head } = await this.crdt.changes(since, opts);
3649
4438
  const rows = result.map(({ id: key, value, del, clock }) => ({
3650
4439
  key,
3651
4440
  value: del ? { _id: key, _deleted: true } : { _id: key, ...value },
@@ -3656,7 +4445,7 @@ var Database = class {
3656
4445
  async allDocs(opts = {}) {
3657
4446
  await this.ready();
3658
4447
  this.logger.Debug().Msg("allDocs");
3659
- const { result, head } = await this._crdt.allDocs();
4448
+ const { result, head } = await this.crdt.allDocs();
3660
4449
  const rows = result.map(({ id: key, value, del }) => ({
3661
4450
  key,
3662
4451
  value: del ? { _id: key, _deleted: true } : { _id: key, ...value }
@@ -3671,7 +4460,7 @@ var Database = class {
3671
4460
  if (updates) {
3672
4461
  if (!this._listening) {
3673
4462
  this._listening = true;
3674
- this._crdt.clock.onTick((updates2) => {
4463
+ this.crdt.clock.onTick((updates2) => {
3675
4464
  void this._notify(updates2);
3676
4465
  });
3677
4466
  }
@@ -3690,13 +4479,13 @@ var Database = class {
3690
4479
  async query(field, opts = {}) {
3691
4480
  await this.ready();
3692
4481
  this.logger.Debug().Any("field", field).Any("opts", opts).Msg("query");
3693
- const _crdt = this._crdt;
3694
- const idx = typeof field === "string" ? index(this.sthis, { _crdt }, field) : index(this.sthis, { _crdt }, makeName(field.toString()), field);
4482
+ const _crdt = this.crdt;
4483
+ const idx = typeof field === "string" ? index({ crdt: _crdt }, field) : index({ crdt: _crdt }, makeName(field.toString()), field);
3695
4484
  return await idx.query(opts);
3696
4485
  }
3697
4486
  async compact() {
3698
4487
  await this.ready();
3699
- await this._crdt.compact();
4488
+ await this.crdt.compact();
3700
4489
  }
3701
4490
  async _notify(updates) {
3702
4491
  await this.ready();
@@ -3720,23 +4509,62 @@ var Database = class {
3720
4509
  }
3721
4510
  }
3722
4511
  };
3723
- function toSortedArray(set) {
3724
- if (!set) return [];
3725
- return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
4512
+ function defaultURI2(sthis, curi, uri, store, ctx) {
4513
+ ctx = ctx || {};
4514
+ const ret = (curi ? import_cement20.URI.from(curi) : uri).build().setParam("store" /* STORE */, store);
4515
+ if (!ret.hasParam("name" /* NAME */)) {
4516
+ const name = sthis.pathOps.basename(ret.URI().pathname);
4517
+ if (!name) {
4518
+ throw sthis.logger.Error().Url(ret).Any("ctx", ctx).Msg("Database name is required").AsError();
4519
+ }
4520
+ ret.setParam("name" /* NAME */, name);
4521
+ }
4522
+ if (ctx.idx) {
4523
+ ret.defParam("index" /* INDEX */, "idx");
4524
+ ret.defParam("storekey" /* STORE_KEY */, `@${ret.getParam("name" /* NAME */)}-${store}-idx@`);
4525
+ } else {
4526
+ ret.defParam("storekey" /* STORE_KEY */, `@${ret.getParam("name" /* NAME */)}-${store}@`);
4527
+ }
4528
+ if (store === "data") {
4529
+ if (ctx.file) {
4530
+ } else {
4531
+ ret.defParam("suffix" /* SUFFIX */, ".car");
4532
+ }
4533
+ }
4534
+ return ret.URI();
3726
4535
  }
3727
- function fireproof(name, opts) {
3728
- const key = JSON.stringify(
3729
- toSortedArray({
3730
- name,
3731
- stores: toSortedArray(opts?.store?.stores)
3732
- })
3733
- );
3734
- let db = Database.databases.get(key);
3735
- if (!db) {
3736
- db = new Database(name, opts);
3737
- Database.databases.set(key, db);
4536
+ function toStoreURIRuntime(sthis, name, sopts) {
4537
+ sopts = sopts || {};
4538
+ if (!sopts.base) {
4539
+ const fp_env = sthis.env.get("FP_STORAGE_URL");
4540
+ if (fp_env) {
4541
+ sopts = { ...sopts, base: import_cement20.BuildURI.from(fp_env).setParam("urlGen" /* URL_GEN */, "fromEnv") };
4542
+ } else {
4543
+ sopts = { ...sopts, base: getDefaultURI(sthis).build().setParam("urlGen" /* URL_GEN */, "default") };
4544
+ }
3738
4545
  }
3739
- return db;
4546
+ const bbase = import_cement20.BuildURI.from(sopts.base);
4547
+ if (name) {
4548
+ bbase.setParam("name" /* NAME */, name);
4549
+ }
4550
+ const base = bbase.URI();
4551
+ return {
4552
+ idx: {
4553
+ data: defaultURI2(sthis, sopts.idx?.data, base, "data", { idx: true }),
4554
+ file: defaultURI2(sthis, sopts.idx?.data, base, "data", { file: true, idx: true }),
4555
+ meta: defaultURI2(sthis, sopts.idx?.meta, base, "meta", { idx: true }),
4556
+ wal: defaultURI2(sthis, sopts.idx?.wal, base, "wal", { idx: true })
4557
+ },
4558
+ data: {
4559
+ data: defaultURI2(sthis, sopts.data?.data, base, "data"),
4560
+ file: defaultURI2(sthis, sopts.data?.data, base, "data", { file: true }),
4561
+ meta: defaultURI2(sthis, sopts.data?.meta, base, "meta"),
4562
+ wal: defaultURI2(sthis, sopts.data?.wal, base, "wal")
4563
+ }
4564
+ };
4565
+ }
4566
+ function fireproof(name, opts) {
4567
+ return DatabaseFactory(name, opts);
3740
4568
  }
3741
4569
  function makeName(fnString) {
3742
4570
  const regex = /\(([^,()]+,\s*[^,()]+|\[[^\]]+\],\s*[^,()]+)\)/g;
@@ -3755,68 +4583,8 @@ function makeName(fnString) {
3755
4583
  }
3756
4584
  }
3757
4585
 
3758
- // src/runtime/index.ts
3759
- var runtime_exports = {};
3760
- __export(runtime_exports, {
3761
- FILESTORE_VERSION: () => FILESTORE_VERSION,
3762
- INDEXDB_VERSION: () => INDEXDB_VERSION,
3763
- files: () => files_exports,
3764
- getFileName: () => getFileName,
3765
- getPath: () => getPath,
3766
- kb: () => key_bag_exports,
3767
- kc: () => keyed_crypto_exports,
3768
- mf: () => wait_pr_multiformats_exports,
3769
- runtimeFn: () => import_cement13.runtimeFn
3770
- });
3771
-
3772
- // src/runtime/gateways/file/node/utils.ts
3773
- var import_core = require("@fireproof/core");
3774
- function getPath(url, sthis) {
3775
- const basePath = url.pathname;
3776
- const name = url.getParam("name");
3777
- if (name) {
3778
- const version = url.getParam("version");
3779
- if (!version) throw sthis.logger.Error().Url(url).Msg(`version not found`).AsError();
3780
- return sthis.pathOps.join(basePath, version, name);
3781
- }
3782
- return sthis.pathOps.join(basePath);
3783
- }
3784
- function getFileName(url, sthis) {
3785
- const key = url.getParam("key");
3786
- if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
3787
- const res = (0, import_core.getStore)(url, sthis, (...a) => a.join("-"));
3788
- switch (res.store) {
3789
- case "data":
3790
- return sthis.pathOps.join(res.name, key + ".car");
3791
- case "wal":
3792
- case "meta":
3793
- return sthis.pathOps.join(res.name, key + ".json");
3794
- default:
3795
- throw sthis.logger.Error().Url(url).Msg(`unsupported store type`).AsError();
3796
- }
3797
- }
3798
-
3799
- // src/runtime/wait-pr-multiformats/index.ts
3800
- var wait_pr_multiformats_exports = {};
3801
- __export(wait_pr_multiformats_exports, {
3802
- block: () => block_exports,
3803
- codec: () => codec_interface_exports
3804
- });
3805
-
3806
- // src/runtime/wait-pr-multiformats/codec-interface.ts
3807
- var codec_interface_exports = {};
3808
-
3809
- // src/runtime/index.ts
3810
- var import_cement13 = require("@adviser/cement");
3811
-
3812
- // src/runtime/gateways/file/version.ts
3813
- var FILESTORE_VERSION = "v0.19-file";
3814
-
3815
- // src/runtime/gateways/indexdb/version.ts
3816
- var INDEXDB_VERSION = "v0.19-indexdb";
3817
-
3818
4586
  // src/version.ts
3819
4587
  var PACKAGE_VERSION = Object.keys({
3820
- "0.19.121": "xxxx"
4588
+ "0.20.0-dev-preview-06": "xxxx"
3821
4589
  })[0];
3822
4590
  //# sourceMappingURL=index.cjs.map