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

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