@fireproof/core 0.19.8-dev-global → 0.19.9-dev-frag

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. package/README.md +7 -0
  2. package/chunk-7EWIAXTM.js +7 -0
  3. package/chunk-7EWIAXTM.js.map +1 -0
  4. package/chunk-JO5AVWG7.js +67 -0
  5. package/chunk-JO5AVWG7.js.map +1 -0
  6. package/chunk-PB4BKL4O.js +7 -0
  7. package/chunk-PB4BKL4O.js.map +1 -0
  8. package/chunk-YS4GL6OK.js +266 -0
  9. package/chunk-YS4GL6OK.js.map +1 -0
  10. package/{store-indexdb-WLRSICCB.js → gateway-IZRHJWPE.js} +48 -80
  11. package/gateway-IZRHJWPE.js.map +1 -0
  12. package/gateway-YSNUK2L3.js +145 -0
  13. package/gateway-YSNUK2L3.js.map +1 -0
  14. package/index.cjs +2132 -1783
  15. package/index.cjs.map +1 -1
  16. package/index.d.cts +613 -513
  17. package/index.d.ts +613 -513
  18. package/index.global.js +19366 -20107
  19. package/index.global.js.map +1 -1
  20. package/index.js +1512 -1022
  21. package/index.js.map +1 -1
  22. package/key-bag-file-NMEBFSPM.js +54 -0
  23. package/key-bag-file-NMEBFSPM.js.map +1 -0
  24. package/key-bag-indexdb-X5V6GNBZ.js +50 -0
  25. package/key-bag-indexdb-X5V6GNBZ.js.map +1 -0
  26. package/mem-filesystem-B6C6QOIP.js +41 -0
  27. package/mem-filesystem-B6C6QOIP.js.map +1 -0
  28. package/metafile-cjs.json +1 -1
  29. package/metafile-esm.json +1 -1
  30. package/metafile-iife.json +1 -1
  31. package/node-filesystem-5JLBSHKQ.js +41 -0
  32. package/node-filesystem-5JLBSHKQ.js.map +1 -0
  33. package/package.json +8 -7
  34. package/tests/blockstore/fragment-gateway.test.ts +107 -0
  35. package/tests/blockstore/keyed-crypto.test.ts +302 -0
  36. package/tests/blockstore/loader.test.ts +24 -19
  37. package/tests/blockstore/store.test.ts +34 -28
  38. package/tests/blockstore/transaction.test.ts +19 -15
  39. package/tests/fireproof/config.test.ts +94 -78
  40. package/tests/fireproof/crdt.test.ts +34 -28
  41. package/tests/fireproof/database.test.ts +22 -14
  42. package/tests/fireproof/fireproof.test.fixture.ts +133 -0
  43. package/tests/fireproof/fireproof.test.ts +331 -219
  44. package/tests/fireproof/hello.test.ts +6 -4
  45. package/tests/fireproof/indexer.test.ts +34 -27
  46. package/tests/fireproof/utils.test.ts +65 -0
  47. package/tests/helpers.ts +25 -57
  48. package/utils-IZPK4QS7.js +14 -0
  49. package/utils-IZPK4QS7.js.map +1 -0
  50. package/chunk-BNL4PVBF.js +0 -314
  51. package/chunk-BNL4PVBF.js.map +0 -1
  52. package/chunk-JW2QT6BF.js +0 -184
  53. package/chunk-JW2QT6BF.js.map +0 -1
  54. package/node-sys-container-MIEX6ELJ.js +0 -29
  55. package/node-sys-container-MIEX6ELJ.js.map +0 -1
  56. package/store-file-VJ6BI4II.js +0 -191
  57. package/store-file-VJ6BI4II.js.map +0 -1
  58. package/store-indexdb-WLRSICCB.js.map +0 -1
package/index.cjs CHANGED
@@ -30,452 +30,50 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
- // src/types.ts
34
- function isFalsy(value) {
35
- return value === false && value === null && value === void 0;
36
- }
37
- function throwFalsy(value) {
38
- if (isFalsy(value)) {
39
- throw new Error("value is Falsy");
40
- }
41
- return value;
42
- }
43
- function falsyToUndef(value) {
44
- if (isFalsy(value)) {
45
- return void 0;
46
- }
47
- return value;
48
- }
49
- var init_types = __esm({
50
- "src/types.ts"() {
51
- "use strict";
52
- }
53
- });
54
-
55
- // src/runtime/node-sys-container.ts
56
- var node_sys_container_exports = {};
57
- __export(node_sys_container_exports, {
58
- createNodeSysContainer: () => createNodeSysContainer
59
- });
60
- async function createNodeSysContainer() {
61
- return {
62
- state: "node",
63
- ...path,
64
- // ...(await import("node:os")),
65
- // ...(await import("node:url")),
66
- ...os,
67
- ...url,
68
- ...fs,
69
- join,
70
- stat: fs.stat,
71
- readdir: fs.readdir,
72
- readfile: fs.readFile,
73
- writefile: fs.writeFile
74
- };
75
- }
76
- var fs, path, os, url;
77
- var init_node_sys_container = __esm({
78
- "src/runtime/node-sys-container.ts"() {
79
- "use strict";
80
- init_sys_container();
81
- fs = __toESM(require("fs/promises"), 1);
82
- path = __toESM(require("path"), 1);
83
- os = __toESM(require("os"), 1);
84
- url = __toESM(require("url"), 1);
85
- }
86
- });
87
-
88
- // src/runtime/sys-container.ts
89
- function isSet(value, ref = globalThis) {
90
- const [head, ...tail] = value.split(".");
91
- if (["object", "function"].includes(typeof ref) && ref && ["object", "function"].includes(typeof ref[head]) && ref[head]) {
92
- if (tail.length <= 1) {
93
- return true;
94
- }
95
- return isSet(tail.join("."), ref[head]);
96
- }
97
- return false;
98
- }
99
- function runtimeFn() {
100
- const isNodeIsh = isSet("process.versions.node");
101
- const isDeno = isSet("Deno");
102
- return {
103
- isNodeIsh,
104
- isBrowser: !(isNodeIsh || isDeno),
105
- isDeno,
106
- isReactNative: false
107
- };
108
- }
109
- function join(...paths) {
110
- return paths.map((i) => i.replace(/\/+$/, "")).join("/");
111
- }
112
- var import_uuidv7, import_cement, onceStart, envImpl, sysContainer, SysContainer;
113
- var init_sys_container = __esm({
114
- "src/runtime/sys-container.ts"() {
115
- "use strict";
116
- import_uuidv7 = require("uuidv7");
117
- import_cement = require("@adviser/cement");
118
- init_types();
119
- onceStart = new import_cement.ResolveOnce();
120
- envImpl = new import_cement.EnvImpl({
121
- symbol: "FP_ENV",
122
- presetEnv: /* @__PURE__ */ new Map([
123
- // ["FP_DEBUG", "xxx"],
124
- // ["FP_ENV", "development"],
125
- ])
126
- });
127
- sysContainer = class {
128
- constructor() {
129
- this.freight = {
130
- state: "seeded",
131
- join,
132
- dirname: (path2) => path2.split("/").slice(0, -1).join("/"),
133
- homedir: () => {
134
- throw new Error("SysContainer:homedir is not available in seeded state");
135
- },
136
- fileURLToPath: (strurl) => {
137
- let url2;
138
- if (typeof strurl === "string") {
139
- url2 = new URL(strurl);
140
- } else {
141
- url2 = strurl;
142
- }
143
- return url2.pathname;
144
- },
145
- // assert: (condition: unknown, message?: string | Error) => {
146
- // if (!condition) {
147
- // if (message instanceof Error) {
148
- // throw message;
149
- // } else {
150
- // throw new Error(message);
151
- // }
152
- // }
153
- // },
154
- mkdir: () => Promise.reject(new Error("SysContainer:mkdir is not available in seeded state")),
155
- readdir: () => Promise.reject(new Error("SysContainer:readdir is not available in seeded state")),
156
- rm: () => Promise.reject(new Error("SysContainer:rm is not available in seeded state")),
157
- copyFile: () => Promise.reject(new Error("SysContainer:copyFile is not available in seeded state")),
158
- readfile: () => Promise.reject(new Error("SysContainer:readfile is not available in seeded state")),
159
- unlink: () => Promise.reject(new Error("SysContainer:unlink is not available in seeded state")),
160
- writefile: () => Promise.reject(new Error("SysContainer:writefile is not available in seeded state")),
161
- stat: () => Promise.reject(new Error("SysContainer:stat is not available in seeded state"))
162
- };
163
- this.id = (0, import_uuidv7.uuidv4)();
164
- this.homedir = () => {
165
- this.logSeeded("homedir");
166
- return throwFalsy(this.freight).homedir();
167
- };
168
- this.runtime = runtimeFn;
169
- this.env = envImpl;
170
- }
171
- async start() {
172
- await onceStart.once(async () => {
173
- switch (this.freight.state) {
174
- case "seeded":
175
- if (this.runtime().isNodeIsh) {
176
- const { createNodeSysContainer: createNodeSysContainer2 } = await Promise.resolve().then(() => (init_node_sys_container(), node_sys_container_exports));
177
- this.freight = await createNodeSysContainer2();
178
- } else {
179
- this.freight.state = "browser";
180
- }
181
- return;
182
- case "browser":
183
- case "node":
184
- return;
185
- }
186
- });
187
- }
188
- async readdir(path2, options) {
189
- this.logSeeded("readdir");
190
- return throwFalsy(this.freight).readdir(path2, options) || [];
191
- }
192
- async readdirent(path2, options) {
193
- this.logSeeded("readdirent");
194
- return throwFalsy(this.freight).readdir(path2, { ...options, withFileTypes: true }) || [];
195
- }
196
- async readfile(path2, options) {
197
- this.logSeeded("readfile");
198
- return throwFalsy(this.freight).readfile(path2, options);
199
- }
200
- async mkdir(path2, options) {
201
- this.logSeeded("mkdir");
202
- return throwFalsy(this.freight).mkdir(path2, options);
203
- }
204
- async rm(path2, options) {
205
- this.logSeeded("rm");
206
- return throwFalsy(this.freight).rm(path2, options);
207
- }
208
- async unlink(path2) {
209
- this.logSeeded("unlink");
210
- return throwFalsy(this.freight).unlink(path2);
211
- }
212
- async writefile(path2, data) {
213
- this.logSeeded("writefile");
214
- return throwFalsy(this.freight).writefile(path2, data);
215
- }
216
- async copyFile(source, destination) {
217
- this.logSeeded("copyFile");
218
- return throwFalsy(this.freight).copyFile(source, destination);
219
- }
220
- async stat(path2) {
221
- this.logSeeded("stat");
222
- return throwFalsy(this.freight).stat(path2);
223
- }
224
- fileURLToPath(url2) {
225
- this.logSeeded("fileURLToPath");
226
- return throwFalsy(this.freight).fileURLToPath(url2);
227
- }
228
- dirname(path2) {
229
- this.logSeeded("dirname");
230
- return throwFalsy(this.freight).dirname(path2);
231
- }
232
- join(...args) {
233
- this.logSeeded("join");
234
- return throwFalsy(this.freight).join(...args);
235
- }
236
- logSeeded(method) {
237
- if (this.freight.state === "seeded") {
238
- const err = new Error();
239
- console.warn(`SysContainer.${method} is not available in seeded state:`, err.stack);
240
- }
241
- }
242
- };
243
- SysContainer = new sysContainer();
244
- }
245
- });
246
-
247
- // src/runtime/data-dir.ts
248
- function dataDir(name, base) {
249
- if (!base) {
250
- if (SysContainer.runtime().isNodeIsh || SysContainer.runtime().isDeno) {
251
- base = SysContainer.env.get("FP_STORAGE_URL") || `file://${SysContainer.join(SysContainer.homedir(), ".fireproof")}`;
252
- } else {
253
- base = `indexdb://fp`;
254
- }
255
- }
256
- let url2;
257
- if (typeof base === "string") {
258
- try {
259
- url2 = new URL(base.toString());
260
- } catch (e) {
261
- try {
262
- base = `file://${base}`;
263
- url2 = new URL(base);
264
- } catch (e2) {
265
- throw new Error(`invalid base url: ${base}`);
266
- }
267
- }
268
- } else {
269
- url2 = base;
270
- }
271
- url2.searchParams.set("name", name || "");
272
- return url2.toString();
273
- }
274
- var init_data_dir = __esm({
275
- "src/runtime/data-dir.ts"() {
276
- "use strict";
277
- init_sys_container();
278
- }
279
- });
280
-
281
- // src/runtime/store-file-utils.ts
282
- async function getPath(url2, logger) {
283
- const basePath = url2.toString().replace(new RegExp(`^${url2.protocol}//`), "").replace(/\?.*$/, "");
284
- const name = url2.searchParams.get("name");
285
- if (name) {
286
- const version = url2.searchParams.get("version");
287
- if (!version) throw logger.Error().Str("url", url2.toString()).Msg(`version not found`).AsError();
288
- return SysContainer.join(basePath, version, name);
289
- }
290
- return SysContainer.join(basePath);
291
- }
292
- function getFileName(url2, key, logger) {
293
- switch (getStore(url2, logger, (...a) => a.join("/"))) {
294
- case "data":
295
- return key + ".car";
296
- case "meta":
297
- return key + ".json";
298
- default:
299
- throw logger.Error().Str("url", url2.toString()).Msg(`unsupported store type`).AsError();
300
- }
301
- }
302
- function ensureIndexName(url2, name) {
303
- if (url2.searchParams.has("index")) {
304
- name = (url2.searchParams.get("index")?.replace(/[^a-zA-Z0-9]/g, "") || "idx") + "-" + name;
305
- }
306
- return name;
307
- }
308
- var init_store_file_utils = __esm({
309
- "src/runtime/store-file-utils.ts"() {
310
- "use strict";
311
- init_utils();
312
- init_sys_container();
313
- }
314
- });
315
-
316
- // src/runtime/crypto.ts
317
- var crypto_exports = {};
318
- __export(crypto_exports, {
319
- toCryptoOpts: () => toCryptoOpts
320
- });
321
- function randomBytes(size) {
322
- const bytes = new Uint8Array(size);
323
- if (size > 0) {
324
- crypto.getRandomValues(bytes);
325
- }
326
- return bytes;
327
- }
328
- function digestSHA256(data) {
329
- return Promise.resolve(crypto.subtle.digest("SHA-256", data));
330
- }
331
- function toCryptoOpts(cryptoOpts = {}) {
332
- const opts = {
333
- importKey: cryptoOpts.importKey || crypto.subtle.importKey.bind(crypto.subtle),
334
- encrypt: cryptoOpts.encrypt || crypto.subtle.encrypt.bind(crypto.subtle),
335
- decrypt: cryptoOpts.decrypt || crypto.subtle.decrypt.bind(crypto.subtle),
336
- randomBytes: cryptoOpts.randomBytes || randomBytes,
337
- digestSHA256: cryptoOpts.digestSHA256 || digestSHA256
338
- };
339
- return opts;
340
- }
341
- var init_crypto = __esm({
342
- "src/runtime/crypto.ts"() {
343
- "use strict";
344
- }
345
- });
346
-
347
- // src/runtime/files.ts
348
- var files_exports = {};
349
- __export(files_exports, {
350
- decodeFile: () => decodeFile,
351
- encodeFile: () => encodeFile
352
- });
353
- async function collect(collectable) {
354
- const chunks = [];
355
- await collectable.pipeTo(
356
- new WritableStream({
357
- write(chunk) {
358
- chunks.push(chunk);
359
- }
360
- })
361
- );
362
- return chunks;
363
- }
364
- async function encodeFile(blob) {
365
- const readable = createFileEncoderStream(blob);
366
- const blocks = await collect(readable);
367
- return { cid: blocks.at(-1).cid, blocks };
33
+ // src/utils.ts
34
+ function presetEnv() {
35
+ const penv = new Map([
36
+ // ["FP_DEBUG", "xxx"],
37
+ // ["FP_ENV", "development"],
38
+ ...Array.from(
39
+ Object.entries(
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ globalThis[Symbol.for("FP_PRESET_ENV")] || {}
42
+ )
43
+ )
44
+ // .map(([k, v]) => [k, v as string])
45
+ ]);
46
+ return penv;
368
47
  }
369
- async function decodeFile(blocks, cid, meta) {
370
- const entry = await (0, import_ipfs_unixfs_exporter.exporter)(cid.toString(), blocks, { length: meta.size });
371
- const chunks = [];
372
- for await (const chunk of entry.content()) {
373
- chunks.push(chunk);
374
- }
375
- return new File(chunks, entry.name, { type: meta.type, lastModified: 0 });
48
+ function ensureSuperThis(osthis) {
49
+ const env = (0, import_cement.envFactory)({
50
+ symbol: osthis?.env?.symbol || "FP_ENV",
51
+ presetEnv: osthis?.env?.presetEnv || presetEnv()
52
+ });
53
+ return new superThis({
54
+ logger: osthis?.logger || globalLogger,
55
+ env,
56
+ crypto: osthis?.crypto || (0, import_cement.toCryptoRuntime)(),
57
+ ctx: osthis?.ctx || {},
58
+ pathOps,
59
+ txt: osthis?.txt || txtOps
60
+ });
376
61
  }
377
- function createFileEncoderStream(blob) {
378
- const { readable, writable } = new TransformStream({}, queuingStrategy);
379
- const unixfsWriter = UnixFS.createWriter({ writable, settings });
380
- const fileBuilder = new UnixFSFileBuilder("", blob);
381
- void (async () => {
382
- await fileBuilder.finalize(unixfsWriter);
383
- await unixfsWriter.close();
384
- })();
385
- return readable;
62
+ function ensureSuperLog(sthis, componentName, ctx) {
63
+ return sthis.clone({
64
+ logger: ensureLogger(sthis, componentName, ctx)
65
+ });
386
66
  }
387
- var UnixFS, raw, import_fixed, import_balanced, import_ipfs_unixfs_exporter, queuingStrategy, settings, UnixFSFileBuilder;
388
- var init_files = __esm({
389
- "src/runtime/files.ts"() {
390
- "use strict";
391
- UnixFS = __toESM(require("@ipld/unixfs"), 1);
392
- raw = __toESM(require("multiformats/codecs/raw"), 1);
393
- import_fixed = require("@ipld/unixfs/file/chunker/fixed");
394
- import_balanced = require("@ipld/unixfs/file/layout/balanced");
395
- import_ipfs_unixfs_exporter = require("ipfs-unixfs-exporter");
396
- queuingStrategy = UnixFS.withCapacity();
397
- settings = UnixFS.configure({
398
- fileChunkEncoder: raw,
399
- smallFileEncoder: raw,
400
- chunker: (0, import_fixed.withMaxChunkSize)(1024 * 1024),
401
- fileLayout: (0, import_balanced.withWidth)(1024)
402
- });
403
- UnixFSFileBuilder = class {
404
- #file;
405
- constructor(name, file) {
406
- this.name = name;
407
- this.#file = file;
408
- }
409
- async finalize(writer) {
410
- const unixfsFileWriter = UnixFS.createFileWriter(writer);
411
- await this.#file.stream().pipeTo(
412
- new WritableStream({
413
- async write(chunk) {
414
- await unixfsFileWriter.write(chunk);
415
- }
416
- })
417
- );
418
- return await unixfsFileWriter.close();
419
- }
420
- };
421
- }
422
- });
423
-
424
- // src/runtime/store-file-version.ts
425
- var FILESTORE_VERSION;
426
- var init_store_file_version = __esm({
427
- "src/runtime/store-file-version.ts"() {
428
- "use strict";
429
- FILESTORE_VERSION = "v0.19-file";
430
- }
431
- });
432
-
433
- // src/runtime/store-indexdb-version.ts
434
- var INDEXDB_VERSION;
435
- var init_store_indexdb_version = __esm({
436
- "src/runtime/store-indexdb-version.ts"() {
437
- "use strict";
438
- INDEXDB_VERSION = "v0.19-indexdb";
439
- }
440
- });
441
-
442
- // src/runtime/index.ts
443
- var runtime_exports = {};
444
- __export(runtime_exports, {
445
- FILESTORE_VERSION: () => FILESTORE_VERSION,
446
- INDEXDB_VERSION: () => INDEXDB_VERSION,
447
- SysContainer: () => SysContainer,
448
- crypto: () => crypto_exports,
449
- dataDir: () => dataDir,
450
- ensureIndexName: () => ensureIndexName,
451
- files: () => files_exports,
452
- getFileName: () => getFileName,
453
- getPath: () => getPath,
454
- join: () => join
455
- });
456
- var init_runtime = __esm({
457
- "src/runtime/index.ts"() {
458
- "use strict";
459
- init_sys_container();
460
- init_data_dir();
461
- init_store_file_utils();
462
- init_crypto();
463
- init_files();
464
- init_store_file_version();
465
- init_store_indexdb_version();
466
- }
467
- });
468
-
469
- // src/utils.ts
470
- function ensureLogger(optsOrLogger, componentName, ctx) {
67
+ function ensureLogger(sthis, componentName, ctx) {
471
68
  let logger = globalLogger;
472
- if ((0, import_cement2.IsLogger)(optsOrLogger)) {
473
- logger = optsOrLogger;
474
- } else if (optsOrLogger && (0, import_cement2.IsLogger)(optsOrLogger.logger)) {
475
- logger = optsOrLogger.logger;
69
+ if ((0, import_cement.IsLogger)(sthis)) {
70
+ logger = sthis;
71
+ } else if (sthis && (0, import_cement.IsLogger)(sthis.logger)) {
72
+ logger = sthis.logger;
476
73
  }
477
74
  const cLogger = logger.With().Module(componentName);
478
75
  const debug = [];
76
+ let exposeStack = false;
479
77
  if (ctx) {
480
78
  if ("debug" in ctx) {
481
79
  if (typeof ctx.debug === "string" && ctx.debug.length > 0) {
@@ -485,8 +83,12 @@ function ensureLogger(optsOrLogger, componentName, ctx) {
485
83
  }
486
84
  delete ctx.debug;
487
85
  }
86
+ if ("exposeStack" in ctx) {
87
+ exposeStack = true;
88
+ delete ctx.exposeStack;
89
+ }
488
90
  if ("this" in ctx) {
489
- cLogger.Str("this", (0, import_uuidv72.uuidv7)());
91
+ cLogger.Str("this", sthis.nextId(4).str);
490
92
  delete ctx.this;
491
93
  }
492
94
  for (const [key, value] of Object.entries(ctx)) {
@@ -500,7 +102,7 @@ function ensureLogger(optsOrLogger, componentName, ctx) {
500
102
  default:
501
103
  if (value instanceof Date) {
502
104
  cLogger.Str(key, value.toISOString());
503
- } else if (value instanceof URL) {
105
+ } else if ((0, import_cement.isURL)(value)) {
504
106
  cLogger.Str(key, value.toString());
505
107
  } else if (typeof value === "function") {
506
108
  cLogger.Ref(key, value);
@@ -512,74 +114,152 @@ function ensureLogger(optsOrLogger, componentName, ctx) {
512
114
  }
513
115
  }
514
116
  registerFP_DEBUG.once(async () => {
515
- SysContainer.env.onSet((key, value) => {
516
- if (value) {
517
- logger.SetDebug(value);
518
- }
519
- }, "FP_DEBUG");
117
+ sthis.env.onSet(
118
+ (key, value) => {
119
+ switch (key) {
120
+ case "FP_DEBUG":
121
+ logger.SetDebug(value || []);
122
+ break;
123
+ case "FP_STACK":
124
+ logger.SetExposeStack(!!value);
125
+ break;
126
+ }
127
+ },
128
+ "FP_DEBUG",
129
+ "FP_STACK"
130
+ );
520
131
  }).finally(() => {
521
132
  });
522
133
  if (debug.length > 0) {
523
134
  logger.SetDebug(debug);
524
135
  }
136
+ if (exposeStack) {
137
+ logger.SetExposeStack(true);
138
+ }
525
139
  const out = cLogger.Logger();
526
140
  return out;
527
141
  }
528
- function getStore(url2, logger, joiner) {
529
- let result = url2.searchParams.get("store");
530
- if (!result) throw logger.Error().Str("url", url2.toString()).Msg(`store not found`).AsError();
531
- if (url2.searchParams.has("index")) {
532
- result = joiner(url2.searchParams.get("index") || "idx", result);
142
+ function getStore(url, sthis, joiner) {
143
+ const store = url.getParam("store");
144
+ switch (store) {
145
+ case "data":
146
+ case "wal":
147
+ case "meta":
148
+ break;
149
+ default:
150
+ throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
533
151
  }
534
- return result;
152
+ let name = store;
153
+ if (url.hasParam("index")) {
154
+ name = joiner(url.getParam("index") || "idx", name);
155
+ }
156
+ return { store, name };
535
157
  }
536
- function getKey(url2, logger) {
537
- const result = url2.searchParams.get("key");
538
- if (!result) throw logger.Error().Str("url", url2.toString()).Msg(`key not found`).AsError();
158
+ function getKey(url, logger) {
159
+ const result = url.getParam("key");
160
+ if (!result) throw logger.Error().Str("url", url.toString()).Msg(`key not found`).AsError();
539
161
  return result;
540
162
  }
541
- function getName(url2, logger) {
542
- let result = url2.searchParams.get("name");
163
+ function getName(sthis, url) {
164
+ let result = url.getParam("name");
543
165
  if (!result) {
544
- result = SysContainer.dirname(url2.pathname);
166
+ result = sthis.pathOps.dirname(url.pathname);
545
167
  if (result.length === 0) {
546
- throw logger.Error().Str("url", url2.toString()).Msg(`name not found`).AsError();
168
+ throw sthis.logger.Error().Str("url", url.toString()).Msg(`name not found`).AsError();
547
169
  }
548
170
  }
549
171
  return result;
550
172
  }
551
173
  function exception2Result(fn) {
552
- return fn().then((value) => import_cement2.Result.Ok(value)).catch((e) => import_cement2.Result.Err(e));
174
+ return fn().then((value) => import_cement.Result.Ok(value)).catch((e) => import_cement.Result.Err(e));
553
175
  }
554
176
  async function exceptionWrapper(fn) {
555
- return fn().catch((e) => import_cement2.Result.Err(e));
177
+ return fn().catch((e) => import_cement.Result.Err(e));
556
178
  }
557
- var import_cement2, import_uuidv72, globalLogger, registerFP_DEBUG;
558
- var init_utils = __esm({
559
- "src/utils.ts"() {
560
- "use strict";
561
- import_cement2 = require("@adviser/cement");
562
- init_runtime();
563
- import_uuidv72 = require("uuidv7");
564
- globalLogger = new import_cement2.LoggerImpl();
565
- registerFP_DEBUG = new import_cement2.ResolveOnce();
566
- }
567
- });
568
-
569
- // src/blockstore/gateway.ts
570
179
  function isNotFoundError(e) {
571
- if (import_cement3.Result.Is(e)) {
180
+ if (import_cement.Result.Is(e)) {
572
181
  if (e.isOk()) return false;
573
182
  e = e.Err();
574
183
  }
575
184
  if (e.code === "ENOENT") return true;
576
185
  return false;
577
186
  }
578
- var import_cement3, NotFoundError;
579
- var init_gateway = __esm({
580
- "src/blockstore/gateway.ts"() {
187
+ function dataDir(sthis, name, base) {
188
+ if (!base) {
189
+ if (!(0, import_cement.runtimeFn)().isBrowser) {
190
+ const home = sthis.env.get("HOME") || "./";
191
+ base = sthis.env.get("FP_STORAGE_URL") || `file://${sthis.pathOps.join(home, ".fireproof")}`;
192
+ } else {
193
+ base = sthis.env.get("FP_STORAGE_URL") || `indexdb://fp`;
194
+ }
195
+ }
196
+ return import_cement.URI.from(base.toString()).build().setParam("name", name || "").URI();
197
+ }
198
+ function UInt8ArrayEqual(a, b) {
199
+ if (a.length !== b.length) {
200
+ return false;
201
+ }
202
+ for (let i = 0; i < a.length; i++) {
203
+ if (a[i] !== b[i]) {
204
+ return false;
205
+ }
206
+ }
207
+ return true;
208
+ }
209
+ var import_cement, import_base58, globalLogger, registerFP_DEBUG, superThis, pathOpsImpl, pathOps, txtOps, NotFoundError;
210
+ var init_utils = __esm({
211
+ "src/utils.ts"() {
581
212
  "use strict";
582
- import_cement3 = require("@adviser/cement");
213
+ import_cement = require("@adviser/cement");
214
+ import_base58 = require("multiformats/bases/base58");
215
+ globalLogger = new import_cement.LoggerImpl();
216
+ registerFP_DEBUG = new import_cement.ResolveOnce();
217
+ superThis = class _superThis {
218
+ constructor(opts) {
219
+ this.logger = opts.logger;
220
+ this.env = opts.env;
221
+ this.crypto = opts.crypto;
222
+ this.pathOps = opts.pathOps;
223
+ this.txt = opts.txt;
224
+ this.ctx = { ...opts.ctx };
225
+ }
226
+ nextId(bytes = 6) {
227
+ const bin = this.crypto.randomBytes(bytes);
228
+ return {
229
+ str: import_base58.base58btc.encode(bin),
230
+ bin
231
+ };
232
+ }
233
+ start() {
234
+ return Promise.resolve();
235
+ }
236
+ clone(override) {
237
+ return new _superThis({
238
+ logger: override.logger || this.logger,
239
+ env: (0, import_cement.envFactory)(override.env) || this.env,
240
+ crypto: override.crypto || this.crypto,
241
+ pathOps: override.pathOps || this.pathOps,
242
+ txt: override.txt || this.txt,
243
+ ctx: { ...this.ctx, ...override.ctx }
244
+ });
245
+ }
246
+ };
247
+ pathOpsImpl = class {
248
+ join(...paths) {
249
+ return paths.map((i) => i.replace(/\/+$/, "")).join("/");
250
+ }
251
+ dirname(path) {
252
+ return path.split("/").slice(0, -1).join("/");
253
+ }
254
+ // homedir() {
255
+ // throw new Error("SysContainer:homedir is not available in seeded state");
256
+ // }
257
+ };
258
+ pathOps = new pathOpsImpl();
259
+ txtOps = {
260
+ encode: (input) => new TextEncoder().encode(input),
261
+ decode: (input) => new TextDecoder().decode(input)
262
+ };
583
263
  NotFoundError = class extends Error {
584
264
  constructor() {
585
265
  super(...arguments);
@@ -589,38 +269,149 @@ var init_gateway = __esm({
589
269
  }
590
270
  });
591
271
 
592
- // src/runtime/store-file.ts
593
- var store_file_exports = {};
594
- __export(store_file_exports, {
595
- FileDataGateway: () => FileDataGateway,
596
- FileMetaGateway: () => FileMetaGateway,
597
- FileTestStore: () => FileTestStore,
598
- FileWALGateway: () => FileWALGateway
272
+ // src/runtime/gateways/file/mem-filesystem.ts
273
+ var mem_filesystem_exports = {};
274
+ __export(mem_filesystem_exports, {
275
+ MemFileSystem: () => MemFileSystem
276
+ });
277
+ var import_memfs, MemFileSystem;
278
+ var init_mem_filesystem = __esm({
279
+ "src/runtime/gateways/file/mem-filesystem.ts"() {
280
+ "use strict";
281
+ import_memfs = require("memfs");
282
+ init_utils2();
283
+ MemFileSystem = class {
284
+ async start() {
285
+ return this;
286
+ }
287
+ mkdir(path, options) {
288
+ return import_memfs.fs.promises.mkdir(path, options);
289
+ }
290
+ readdir(path, options) {
291
+ return import_memfs.fs.promises.readdir(path, options);
292
+ }
293
+ rm(path, options) {
294
+ return import_memfs.fs.promises.rm(path, options);
295
+ }
296
+ copyFile(source, destination) {
297
+ return import_memfs.fs.promises.copyFile(source, destination);
298
+ }
299
+ async readfile(path, options) {
300
+ const ret = await import_memfs.fs.promises.readFile(path, options);
301
+ return toArrayBuffer(ret);
302
+ }
303
+ stat(path) {
304
+ return import_memfs.fs.promises.stat(path);
305
+ }
306
+ unlink(path) {
307
+ return import_memfs.fs.promises.unlink(path);
308
+ }
309
+ writefile(path, data) {
310
+ return import_memfs.fs.promises.writeFile(path, Buffer.from(data));
311
+ }
312
+ };
313
+ }
314
+ });
315
+
316
+ // src/runtime/gateways/file/node-filesystem.ts
317
+ var node_filesystem_exports = {};
318
+ __export(node_filesystem_exports, {
319
+ NodeFileSystem: () => NodeFileSystem
320
+ });
321
+ var NodeFileSystem;
322
+ var init_node_filesystem = __esm({
323
+ "src/runtime/gateways/file/node-filesystem.ts"() {
324
+ "use strict";
325
+ init_utils2();
326
+ NodeFileSystem = class {
327
+ async start() {
328
+ this.fs = await import("fs/promises");
329
+ return this;
330
+ }
331
+ async mkdir(path, options) {
332
+ return this.fs?.mkdir(path, options);
333
+ }
334
+ async readdir(path, options) {
335
+ return this.fs?.readdir(path, options);
336
+ }
337
+ async rm(path, options) {
338
+ return this.fs?.rm(path, options);
339
+ }
340
+ async copyFile(source, destination) {
341
+ return this.fs?.copyFile(source, destination);
342
+ }
343
+ async readfile(path, options) {
344
+ const ret = await this.fs?.readFile(path, options);
345
+ return toArrayBuffer(ret);
346
+ }
347
+ stat(path) {
348
+ return this.fs?.stat(path);
349
+ }
350
+ async unlink(path) {
351
+ return this.fs?.unlink(path);
352
+ }
353
+ async writefile(path, data) {
354
+ return this.fs?.writeFile(path, Buffer.from(data));
355
+ }
356
+ };
357
+ }
358
+ });
359
+
360
+ // src/runtime/gateways/file/utils.ts
361
+ var utils_exports = {};
362
+ __export(utils_exports, {
363
+ getFileName: () => getFileName,
364
+ getFileSystem: () => getFileSystem,
365
+ getPath: () => getPath,
366
+ toArrayBuffer: () => toArrayBuffer
599
367
  });
600
- async function ensureVersionFile(path2, logger) {
601
- let once = versionFiles.get(path2);
602
- if (!once) {
603
- once = new import_cement6.ResolveOnce();
604
- versionFiles.set(path2, once);
605
- }
606
- await once.once(async () => {
607
- await SysContainer.mkdir(path2, { recursive: true });
608
- const vFile = SysContainer.join(path2, "version");
609
- const vFileStat = await SysContainer.stat(vFile).catch(() => void 0);
610
- if (!vFileStat) {
611
- await SysContainer.writefile(SysContainer.join(path2, "version"), FILESTORE_VERSION);
612
- return;
613
- } else if (!vFileStat.isFile()) {
614
- throw logger.Error().Str("file", vFile).Msg(`version file is a directory`).AsError();
615
- }
616
- const v = await SysContainer.readfile(vFile);
617
- if (v.toString() !== FILESTORE_VERSION) {
618
- console.warn(`version mismatch:${vFile}: ${v.toString()}!=${FILESTORE_VERSION}`);
368
+ async function getFileSystem(url) {
369
+ const name = url.getParam("fs");
370
+ let fs2;
371
+ switch (name) {
372
+ case "mem":
373
+ {
374
+ const { MemFileSystem: MemFileSystem2 } = await Promise.resolve().then(() => (init_mem_filesystem(), mem_filesystem_exports));
375
+ fs2 = new MemFileSystem2();
376
+ }
377
+ break;
378
+ case "node":
379
+ case "sys":
380
+ default: {
381
+ const { NodeFileSystem: NodeFileSystem2 } = await Promise.resolve().then(() => (init_node_filesystem(), node_filesystem_exports));
382
+ fs2 = new NodeFileSystem2();
619
383
  }
620
- });
621
- return path2;
384
+ }
385
+ return fs2.start();
386
+ }
387
+ function getPath(url, sthis) {
388
+ const basePath = url.pathname;
389
+ const name = url.getParam("name");
390
+ if (name) {
391
+ const version = url.getParam("version");
392
+ if (!version) throw sthis.logger.Error().Url(url).Msg(`version not found`).AsError();
393
+ return sthis.pathOps.join(basePath, version, name);
394
+ }
395
+ return sthis.pathOps.join(basePath);
396
+ }
397
+ function getFileName(url, sthis) {
398
+ const key = url.getParam("key");
399
+ if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
400
+ const res = getStore(url, sthis, (...a) => a.join("-"));
401
+ switch (res.store) {
402
+ case "data":
403
+ return sthis.pathOps.join(res.name, key + ".car");
404
+ case "wal":
405
+ case "meta":
406
+ return sthis.pathOps.join(res.name, key + ".json");
407
+ default:
408
+ throw sthis.logger.Error().Url(url).Msg(`unsupported store type`).AsError();
409
+ }
622
410
  }
623
411
  function toArrayBuffer(buffer) {
412
+ if (typeof buffer === "string") {
413
+ buffer = Buffer.from(buffer);
414
+ }
624
415
  const ab = new ArrayBuffer(buffer.length);
625
416
  const view = new Uint8Array(ab);
626
417
  for (let i = 0; i < buffer.length; ++i) {
@@ -628,167 +419,290 @@ function toArrayBuffer(buffer) {
628
419
  }
629
420
  return view;
630
421
  }
631
- var import_cement6, versionFiles, FileGateway, FileWALGateway, FileMetaGateway, FileDataGateway, FileTestStore;
632
- var init_store_file = __esm({
633
- "src/runtime/store-file.ts"() {
422
+ var init_utils2 = __esm({
423
+ "src/runtime/gateways/file/utils.ts"() {
424
+ "use strict";
425
+ init_utils();
426
+ }
427
+ });
428
+
429
+ // src/runtime/key-bag-file.ts
430
+ var key_bag_file_exports = {};
431
+ __export(key_bag_file_exports, {
432
+ KeyBagProviderFile: () => KeyBagProviderFile
433
+ });
434
+ var KeyBagProviderFile;
435
+ var init_key_bag_file = __esm({
436
+ "src/runtime/key-bag-file.ts"() {
437
+ "use strict";
438
+ init_utils();
439
+ KeyBagProviderFile = class {
440
+ async _prepare(id) {
441
+ await this.sthis.start();
442
+ let sysFS;
443
+ switch (this.url.protocol) {
444
+ case "file:": {
445
+ const { getFileSystem: getFileSystem2 } = await Promise.resolve().then(() => (init_utils2(), utils_exports));
446
+ sysFS = await getFileSystem2(this.url);
447
+ break;
448
+ }
449
+ default:
450
+ throw this.logger.Error().Url(this.url).Msg("unsupported protocol").AsError();
451
+ }
452
+ const dirName = this.url.pathname;
453
+ await sysFS.mkdir(dirName, { recursive: true });
454
+ return {
455
+ dirName,
456
+ sysFS,
457
+ fName: this.sthis.pathOps.join(dirName, `${id.replace(/[^a-zA-Z0-9]/g, "_")}.json`)
458
+ };
459
+ }
460
+ constructor(url, sthis) {
461
+ this.url = url;
462
+ this.sthis = sthis;
463
+ this.logger = sthis.logger;
464
+ }
465
+ async get(id) {
466
+ const ctx = await this._prepare(id);
467
+ try {
468
+ const p = await ctx.sysFS.readfile(ctx.fName);
469
+ const ki = JSON.parse(this.sthis.txt.decode(p));
470
+ return ki;
471
+ } catch (e) {
472
+ if (isNotFoundError(e)) {
473
+ return void 0;
474
+ }
475
+ throw this.logger.Error().Err(e).Str("file", ctx.dirName).Msg("read bag failed").AsError();
476
+ }
477
+ }
478
+ async set(id, item) {
479
+ const ctx = await this._prepare(id);
480
+ const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
481
+ await ctx.sysFS.writefile(ctx.fName, p);
482
+ }
483
+ };
484
+ }
485
+ });
486
+
487
+ // src/runtime/key-bag-indexdb.ts
488
+ var key_bag_indexdb_exports = {};
489
+ __export(key_bag_indexdb_exports, {
490
+ KeyBagProviderIndexDB: () => KeyBagProviderIndexDB
491
+ });
492
+ var import_idb, import_cement4, KeyBagProviderIndexDB;
493
+ var init_key_bag_indexdb = __esm({
494
+ "src/runtime/key-bag-indexdb.ts"() {
495
+ "use strict";
496
+ import_idb = require("idb");
497
+ init_utils2();
498
+ import_cement4 = require("@adviser/cement");
499
+ KeyBagProviderIndexDB = class {
500
+ constructor(url, sthis) {
501
+ this._db = new import_cement4.ResolveOnce();
502
+ this.sthis = sthis;
503
+ this.logger = sthis.logger;
504
+ this.url = url;
505
+ this.dbName = getPath(this.url, this.sthis);
506
+ }
507
+ async _prepare() {
508
+ return this._db.once(async () => {
509
+ return await (0, import_idb.openDB)(this.dbName, 1, {
510
+ upgrade(db) {
511
+ ["bag"].map((store) => {
512
+ db.createObjectStore(store, {
513
+ autoIncrement: false
514
+ });
515
+ });
516
+ }
517
+ });
518
+ });
519
+ }
520
+ async get(id) {
521
+ const db = await this._prepare();
522
+ const tx = db.transaction(["bag"], "readonly");
523
+ const keyItem = await tx.objectStore("bag").get(id);
524
+ await tx.done;
525
+ if (!keyItem) {
526
+ return void 0;
527
+ }
528
+ return keyItem;
529
+ }
530
+ async set(id, item) {
531
+ const db = await this._prepare();
532
+ const tx = db.transaction(["bag"], "readwrite");
533
+ await tx.objectStore("bag").put(item, id);
534
+ await tx.done;
535
+ }
536
+ };
537
+ }
538
+ });
539
+
540
+ // src/runtime/gateways/file/version.ts
541
+ var FILESTORE_VERSION;
542
+ var init_version = __esm({
543
+ "src/runtime/gateways/file/version.ts"() {
634
544
  "use strict";
635
- init_sys_container();
636
- init_store_file_version();
637
- import_cement6 = require("@adviser/cement");
545
+ FILESTORE_VERSION = "v0.19-file";
546
+ }
547
+ });
548
+
549
+ // src/runtime/gateways/file/gateway.ts
550
+ var gateway_exports = {};
551
+ __export(gateway_exports, {
552
+ FileGateway: () => FileGateway,
553
+ FileTestStore: () => FileTestStore
554
+ });
555
+ var import_cement8, versionFiles, FileGateway, FileTestStore;
556
+ var init_gateway = __esm({
557
+ "src/runtime/gateways/file/gateway.ts"() {
558
+ "use strict";
559
+ init_version();
560
+ import_cement8 = require("@adviser/cement");
638
561
  init_utils();
639
- init_gateway();
640
- init_store_file_utils();
641
- versionFiles = /* @__PURE__ */ new Map();
562
+ init_utils2();
563
+ versionFiles = new import_cement8.KeyedResolvOnce();
642
564
  FileGateway = class {
643
- constructor(logger) {
644
- this.logger = logger;
565
+ get fs() {
566
+ if (!this._fs) throw this.logger.Error().Msg("fs not initialized").AsError();
567
+ return this._fs;
568
+ }
569
+ constructor(sthis) {
570
+ this.sthis = sthis;
571
+ this.logger = sthis.logger;
572
+ }
573
+ async getVersionFromFile(path, logger) {
574
+ return versionFiles.get(path).once(async () => {
575
+ await this.fs.mkdir(path, { recursive: true });
576
+ const vFile = this.sthis.pathOps.join(path, "version");
577
+ const vFileStat = await this.fs.stat(vFile).catch(() => void 0);
578
+ if (!vFileStat) {
579
+ await this.fs.writefile(this.sthis.pathOps.join(path, "version"), FILESTORE_VERSION);
580
+ return FILESTORE_VERSION;
581
+ } else if (!vFileStat.isFile()) {
582
+ throw logger.Error().Str("file", vFile).Msg(`version file is a directory`).AsError();
583
+ }
584
+ const v = await this.fs.readfile(vFile);
585
+ const vStr = new TextDecoder().decode(v);
586
+ if (vStr !== FILESTORE_VERSION) {
587
+ logger.Warn().Str("file", vFile).Str("from", vStr).Str("expected", FILESTORE_VERSION).Msg(`version mismatch`);
588
+ }
589
+ return vStr;
590
+ });
645
591
  }
646
592
  start(baseURL) {
647
593
  return exception2Result(async () => {
648
- await SysContainer.start();
649
- baseURL.searchParams.set("version", baseURL.searchParams.get("version") || FILESTORE_VERSION);
650
- const url2 = await this.buildUrl(baseURL, "dummy");
651
- if (url2.isErr()) return url2;
652
- const dbdir = this.getFilePath(url2.Ok());
653
- await SysContainer.mkdir(SysContainer.dirname(dbdir), { recursive: true });
654
- const dbroot = SysContainer.dirname(dbdir);
655
- this.logger.Debug().Str("url", url2.Ok().toString()).Str("dbroot", SysContainer.dirname(dbroot)).Msg("start");
656
- await ensureVersionFile(dbroot, this.logger);
594
+ this._fs = await getFileSystem(baseURL);
595
+ await this.fs.start();
596
+ const url = baseURL.build();
597
+ url.defParam("version", FILESTORE_VERSION);
598
+ const dbUrl = await this.buildUrl(url.URI(), "dummy");
599
+ const dbdirFile = this.getFilePath(dbUrl.Ok());
600
+ await this.fs.mkdir(this.sthis.pathOps.dirname(dbdirFile), { recursive: true });
601
+ const dbroot = this.sthis.pathOps.dirname(dbdirFile);
602
+ this.logger.Debug().Url(url.URI()).Str("dbroot", dbroot).Msg("start");
603
+ url.setParam("version", await this.getVersionFromFile(dbroot, this.logger));
604
+ return url.URI();
657
605
  });
658
606
  }
607
+ async buildUrl(baseUrl, key) {
608
+ return import_cement8.Result.Ok(baseUrl.build().setParam("key", key).URI());
609
+ }
659
610
  async close() {
660
- return import_cement6.Result.Ok(void 0);
611
+ return import_cement8.Result.Ok(void 0);
661
612
  }
662
- getFilePath(url2) {
663
- const path2 = url2.toString().replace(/^file:\/\//, "").replace(/\?.*$/, "");
664
- this.logger.Debug().Str("url", url2.toString()).Str("path", path2).Msg("getFilePath");
665
- return path2;
613
+ // abstract buildUrl(baseUrl: URL, key: string): Promise<Result<URL>>;
614
+ getFilePath(url) {
615
+ const key = url.getParam("key");
616
+ if (!key) throw this.logger.Error().Url(url).Msg(`key not found`).AsError();
617
+ return this.sthis.pathOps.join(getPath(url, this.sthis), getFileName(url, this.sthis));
666
618
  }
667
- async put(url2, body) {
619
+ async put(url, body) {
668
620
  return exception2Result(async () => {
669
- const file = this.getFilePath(url2);
670
- this.logger.Debug().Str("url", url2.toString()).Str("file", file).Msg("put");
671
- await SysContainer.writefile(file, body);
621
+ const file = await this.getFilePath(url);
622
+ this.logger.Debug().Str("url", url.toString()).Str("file", file).Msg("put");
623
+ await this.fs.writefile(file, body);
672
624
  });
673
625
  }
674
- async get(url2) {
626
+ async get(url) {
675
627
  return exceptionWrapper(async () => {
676
- const file = this.getFilePath(url2);
628
+ const file = this.getFilePath(url);
677
629
  try {
678
- const res = await SysContainer.readfile(file);
679
- this.logger.Debug().Url(url2).Str("file", file).Msg("get");
680
- return import_cement6.Result.Ok(new Uint8Array(res));
630
+ const res = await this.fs.readfile(file);
631
+ this.logger.Debug().Url(url.asURL()).Str("file", file).Msg("get");
632
+ return import_cement8.Result.Ok(new Uint8Array(res));
681
633
  } catch (e) {
682
634
  if (isNotFoundError(e)) {
683
- return import_cement6.Result.Err(new NotFoundError(`file not found: ${file}`));
635
+ return import_cement8.Result.Err(new NotFoundError(`file not found: ${file}`));
684
636
  }
685
- return import_cement6.Result.Err(e);
637
+ return import_cement8.Result.Err(e);
686
638
  }
687
639
  });
688
640
  }
689
- async delete(url2) {
641
+ async delete(url) {
690
642
  return exception2Result(async () => {
691
- await SysContainer.unlink(this.getFilePath(url2));
643
+ await this.fs.unlink(this.getFilePath(url));
692
644
  });
693
645
  }
694
- async destroyDir(baseURL) {
695
- const url2 = await this.buildUrl(baseURL, "x");
696
- if (url2.isErr()) return url2;
697
- const filepath = SysContainer.dirname(this.getFilePath(url2.Ok()));
698
- let dir = [];
646
+ async destroy(baseURL) {
647
+ const url = await this.buildUrl(baseURL, "x");
648
+ if (url.isErr()) return url;
649
+ const filepath = this.sthis.pathOps.dirname(this.getFilePath(url.Ok()));
650
+ let files = [];
699
651
  try {
700
- dir = await SysContainer.readdir(filepath);
652
+ files = await this.fs.readdir(filepath);
701
653
  } catch (e) {
702
654
  if (!isNotFoundError(e)) {
703
655
  throw this.logger.Error().Err(e).Str("dir", filepath).Msg("destroy:readdir").AsError();
704
656
  }
705
657
  }
706
- for (const file of dir) {
707
- const pathed = SysContainer.join(filepath, file);
658
+ for (const file of files) {
659
+ const pathed = this.sthis.pathOps.join(filepath, file);
708
660
  try {
709
- await SysContainer.unlink(pathed);
661
+ await this.fs.unlink(pathed);
710
662
  } catch (e) {
711
663
  if (!isNotFoundError(e)) {
712
664
  throw this.logger.Error().Err(e).Str("file", pathed).Msg("destroy:unlink").AsError();
713
665
  }
714
666
  }
715
667
  }
716
- return import_cement6.Result.Ok(void 0);
717
- }
718
- };
719
- FileWALGateway = class extends FileGateway {
720
- constructor(logger) {
721
- super(ensureLogger(logger, "FileWALGateway"));
722
- }
723
- async destroy(baseURL) {
724
- return this.destroyDir(baseURL);
725
- }
726
- async buildUrl(baseUrl, key) {
727
- const url2 = new URL(baseUrl.toString());
728
- url2.pathname = SysContainer.join(await getPath(baseUrl, this.logger), ensureIndexName(baseUrl, "wal"), key + ".json");
729
- return import_cement6.Result.Ok(url2);
730
- }
731
- };
732
- FileMetaGateway = class extends FileGateway {
733
- constructor(logger) {
734
- super(ensureLogger(logger, "FileMetaGateway"));
735
- }
736
- async destroy(baseURL) {
737
- return this.destroyDir(baseURL);
738
- }
739
- async buildUrl(baseUrl, key) {
740
- const url2 = new URL(baseUrl.toString());
741
- url2.pathname = SysContainer.join(await getPath(baseUrl, this.logger), ensureIndexName(baseUrl, "meta"), key + ".json");
742
- return import_cement6.Result.Ok(url2);
743
- }
744
- };
745
- FileDataGateway = class extends FileGateway {
746
- constructor(logger) {
747
- super(ensureLogger(logger, "FileDataGateway"));
748
- this.branches = /* @__PURE__ */ new Set();
749
- }
750
- async destroy(baseURL) {
751
- return this.destroyDir(baseURL);
752
- }
753
- async buildUrl(baseUrl, key) {
754
- const url2 = new URL(baseUrl.toString());
755
- url2.pathname = SysContainer.join(await getPath(baseUrl, this.logger), ensureIndexName(baseUrl, "data"), key + ".car");
756
- return import_cement6.Result.Ok(url2);
668
+ return import_cement8.Result.Ok(void 0);
757
669
  }
758
670
  };
759
671
  FileTestStore = class {
760
- constructor(logger) {
761
- this.logger = ensureLogger(logger, "FileTestStore");
762
- }
763
- async get(url2, key) {
764
- const logger = ensureLogger(this.logger, "get", { url: url2.toString(), key });
765
- const dbFile = SysContainer.join(
766
- await getPath(url2, this.logger),
767
- getStore(url2, this.logger, SysContainer.join),
768
- getFileName(url2, key, this.logger)
769
- );
770
- logger.Debug().Str("dbFile", dbFile).Msg("get");
771
- const buffer = await SysContainer.readfile(dbFile);
772
- logger.Debug().Str("dbFile", dbFile).Len(buffer).Msg("got");
773
- return toArrayBuffer(buffer);
672
+ constructor(sthis) {
673
+ this.logger = ensureLogger(sthis, "FileTestStore");
674
+ this.sthis = sthis;
675
+ }
676
+ async get(iurl, key) {
677
+ const url = iurl.build().setParam("key", key).URI();
678
+ const dbFile = this.sthis.pathOps.join(getPath(url, this.sthis), getFileName(url, this.sthis));
679
+ this.logger.Debug().Url(url).Str("dbFile", dbFile).Msg("get");
680
+ const buffer = await (await getFileSystem(url)).readfile(dbFile);
681
+ this.logger.Debug().Url(url).Str("dbFile", dbFile).Len(buffer).Msg("got");
682
+ return buffer;
774
683
  }
775
684
  };
776
685
  }
777
686
  });
778
687
 
779
- // src/runtime/store-indexdb.ts
780
- var store_indexdb_exports = {};
781
- __export(store_indexdb_exports, {
782
- IndexDBDataGateway: () => IndexDBDataGateway,
783
- IndexDBMetaGateway: () => IndexDBMetaGateway,
688
+ // src/runtime/gateways/indexdb/version.ts
689
+ var INDEXDB_VERSION;
690
+ var init_version2 = __esm({
691
+ "src/runtime/gateways/indexdb/version.ts"() {
692
+ "use strict";
693
+ INDEXDB_VERSION = "v0.19-indexdb";
694
+ }
695
+ });
696
+
697
+ // src/runtime/gateways/indexdb/gateway.ts
698
+ var gateway_exports2 = {};
699
+ __export(gateway_exports2, {
700
+ IndexDBGateway: () => IndexDBGateway,
784
701
  IndexDBTestStore: () => IndexDBTestStore,
785
- IndexDBWalGateway: () => IndexDBWalGateway,
786
702
  getIndexDBName: () => getIndexDBName
787
703
  });
788
- function ensureVersion(url2) {
789
- const ret = new URL(url2.toString());
790
- ret.searchParams.set("version", url2.searchParams.get("version") || INDEXDB_VERSION);
791
- return ret;
704
+ function ensureVersion(url) {
705
+ return url.build().defParam("version", INDEXDB_VERSION).URI();
792
706
  }
793
707
  function sanitzeKey(key) {
794
708
  if (key.length === 1) {
@@ -796,10 +710,10 @@ function sanitzeKey(key) {
796
710
  }
797
711
  return key;
798
712
  }
799
- async function connectIdb(url2, logger) {
800
- const dbName = getIndexDBName(url2, logger);
713
+ async function connectIdb(url, sthis) {
714
+ const dbName = getIndexDBName(url, sthis);
801
715
  const once = await onceIndexDB.get(dbName.fullDb).once(async () => {
802
- const db = await (0, import_idb.openDB)(dbName.fullDb, 1, {
716
+ const db = await (0, import_idb2.openDB)(dbName.fullDb, 1, {
803
717
  upgrade(db2) {
804
718
  ["version", "data", "wal", "meta", "idx.data", "idx.wal", "idx.meta"].map((store) => {
805
719
  db2.createObjectStore(store, {
@@ -809,27 +723,29 @@ async function connectIdb(url2, logger) {
809
723
  }
810
724
  });
811
725
  const found = await db.get("version", "version");
812
- const version = url2.searchParams.get("version") || INDEXDB_VERSION;
726
+ const version = ensureVersion(url).getParam("version");
813
727
  if (!found) {
814
728
  await db.put("version", { version }, "version");
815
729
  } else if (found.version !== version) {
816
- logger.Warn().Str("url", url2.toString()).Str("version", version).Str("found", found.version).Msg("version mismatch");
730
+ sthis.logger.Warn().Str("url", url.toString()).Str("version", version).Str("found", found.version).Msg("version mismatch");
817
731
  }
818
- return { db, dbName, version };
732
+ return { db, dbName, version, url };
819
733
  });
820
- url2.searchParams.set("version", once.version);
821
- return once.db;
734
+ return {
735
+ ...once,
736
+ url: url.build().setParam("version", once.version).URI()
737
+ };
822
738
  }
823
739
  function joinDBName(...names) {
824
740
  return names.map((i) => i.replace(/^[^a-zA-Z0-9]+/g, "").replace(/[^a-zA-Z0-9]+/g, "_")).filter((i) => i.length).join(".");
825
741
  }
826
- function getIndexDBName(iurl, logger) {
827
- const url2 = ensureVersion(iurl);
828
- const fullDb = url2.pathname.replace(/^\/+/, "").replace(/\?.*$/, "");
829
- const dbName = url2.searchParams.get("name");
830
- if (!dbName) throw logger.Error().Str("url", url2.toString()).Msg(`name not found`).AsError();
742
+ function getIndexDBName(iurl, sthis) {
743
+ const url = ensureVersion(iurl);
744
+ const fullDb = url.pathname.replace(/^\/+/, "").replace(/\?.*$/, "");
745
+ const dbName = url.getParam("name");
746
+ if (!dbName) throw sthis.logger.Error().Str("url", url.toString()).Msg(`name not found`).AsError();
831
747
  const result = joinDBName(fullDb, dbName);
832
- const objStore = getStore(url2, logger, joinDBName);
748
+ const objStore = getStore(url, sthis, joinDBName).name;
833
749
  const connectionKey = [result, objStore].join(":");
834
750
  return {
835
751
  fullDb: result,
@@ -838,40 +754,38 @@ function getIndexDBName(iurl, logger) {
838
754
  dbName
839
755
  };
840
756
  }
841
- var import_idb, import_cement7, onceIndexDB, IndexDBGateway, IndexDBDataGateway, IndexDBWalGateway, IndexDBMetaGateway, txtEncoder, IndexDBTestStore;
842
- var init_store_indexdb = __esm({
843
- "src/runtime/store-indexdb.ts"() {
757
+ var import_idb2, import_cement9, onceIndexDB, IndexDBGateway, IndexDBTestStore;
758
+ var init_gateway2 = __esm({
759
+ "src/runtime/gateways/indexdb/gateway.ts"() {
844
760
  "use strict";
845
- import_idb = require("idb");
846
- import_cement7 = require("@adviser/cement");
847
- init_store_indexdb_version();
761
+ import_idb2 = require("idb");
762
+ import_cement9 = require("@adviser/cement");
763
+ init_version2();
848
764
  init_utils();
849
- init_gateway();
850
- init_sys_container();
851
- onceIndexDB = new import_cement7.KeyedResolvOnce();
765
+ onceIndexDB = new import_cement9.KeyedResolvOnce();
852
766
  IndexDBGateway = class {
853
- constructor(logger) {
854
- this.db = {};
855
- this.logger = logger;
856
- }
857
- idb() {
858
- this.db;
767
+ constructor(sthis) {
768
+ this._db = {};
769
+ this.logger = ensureLogger(sthis, "IndexDBGateway");
770
+ this.sthis = sthis;
859
771
  }
860
772
  async start(baseURL) {
861
773
  return exception2Result(async () => {
862
774
  this.logger.Debug().Url(baseURL).Msg("starting");
863
- await SysContainer.start();
864
- this.db = await connectIdb(baseURL, this.logger);
865
- this.logger.Debug().Url(baseURL).Msg("started");
775
+ await this.sthis.start();
776
+ const ic = await connectIdb(baseURL, this.sthis);
777
+ this._db = ic.db;
778
+ this.logger.Debug().Url(ic.url).Msg("started");
779
+ return ic.url;
866
780
  });
867
781
  }
868
782
  async close() {
869
- return import_cement7.Result.Ok(void 0);
783
+ return import_cement9.Result.Ok(void 0);
870
784
  }
871
785
  async destroy(baseUrl) {
872
786
  return exception2Result(async () => {
873
- const type = getStore(baseUrl, this.logger, joinDBName);
874
- const idb = this.db;
787
+ const type = getStore(baseUrl, this.sthis, joinDBName).name;
788
+ const idb = this._db;
875
789
  const trans = idb.transaction(type, "readwrite");
876
790
  const object_store = trans.objectStore(type);
877
791
  const toDelete = [];
@@ -884,87 +798,58 @@ var init_store_indexdb = __esm({
884
798
  await trans.done;
885
799
  });
886
800
  }
887
- async get(url2) {
801
+ buildUrl(baseUrl, key) {
802
+ return Promise.resolve(import_cement9.Result.Ok(baseUrl.build().setParam("key", key).URI()));
803
+ }
804
+ async get(url) {
888
805
  return exceptionWrapper(async () => {
889
- const key = getKey(url2, this.logger);
890
- const store = getStore(url2, this.logger, joinDBName);
891
- this.logger.Debug().Url(url2).Str("key", key).Str("store", store).Msg("getting");
892
- const tx = this.db.transaction([store], "readonly");
806
+ const key = getKey(url, this.logger);
807
+ const store = getStore(url, this.sthis, joinDBName).name;
808
+ this.logger.Debug().Url(url).Str("key", key).Str("store", store).Msg("getting");
809
+ const tx = this._db.transaction([store], "readonly");
893
810
  const bytes = await tx.objectStore(store).get(sanitzeKey(key));
894
811
  await tx.done;
895
812
  if (!bytes) {
896
- return import_cement7.Result.Err(new NotFoundError(`missing ${key}`));
813
+ return import_cement9.Result.Err(new NotFoundError(`missing ${key}`));
897
814
  }
898
- return import_cement7.Result.Ok(bytes);
815
+ return import_cement9.Result.Ok(bytes);
899
816
  });
900
817
  }
901
- async put(url2, value) {
818
+ async put(url, value) {
902
819
  return exception2Result(async () => {
903
- const key = getKey(url2, this.logger);
904
- const store = getStore(url2, this.logger, joinDBName);
905
- this.logger.Debug().Url(url2).Str("key", key).Str("store", store).Msg("putting");
906
- const tx = this.db.transaction([store], "readwrite");
820
+ const key = getKey(url, this.logger);
821
+ const store = getStore(url, this.sthis, joinDBName).name;
822
+ this.logger.Debug().Url(url).Str("key", key).Str("store", store).Msg("putting");
823
+ const tx = this._db.transaction([store], "readwrite");
907
824
  await tx.objectStore(store).put(value, sanitzeKey(key));
908
825
  await tx.done;
909
826
  });
910
827
  }
911
- async delete(url2) {
828
+ async delete(url) {
912
829
  return exception2Result(async () => {
913
- const key = getKey(url2, this.logger);
914
- const store = getStore(url2, this.logger, joinDBName);
915
- this.logger.Debug().Url(url2).Str("key", key).Str("store", store).Msg("deleting");
916
- const tx = this.db.transaction([store], "readwrite");
830
+ const key = getKey(url, this.logger);
831
+ const store = getStore(url, this.sthis, joinDBName).name;
832
+ this.logger.Debug().Url(url).Str("key", key).Str("store", store).Msg("deleting");
833
+ const tx = this._db.transaction([store], "readwrite");
917
834
  await tx.objectStore(store).delete(sanitzeKey(key));
918
835
  await tx.done;
919
- return import_cement7.Result.Ok(void 0);
836
+ return import_cement9.Result.Ok(void 0);
920
837
  });
921
838
  }
922
839
  };
923
- IndexDBDataGateway = class extends IndexDBGateway {
924
- constructor(logger) {
925
- super(ensureLogger(logger, "IndexDBDataGateway", {}));
926
- }
927
- buildUrl(baseUrl, key) {
928
- const url2 = new URL(baseUrl.toString());
929
- url2.searchParams.set("key", key);
930
- return Promise.resolve(import_cement7.Result.Ok(url2));
931
- }
932
- };
933
- IndexDBWalGateway = class extends IndexDBGateway {
934
- constructor(logger) {
935
- super(ensureLogger(logger, "IndexDBWalGateway", {}));
936
- }
937
- buildUrl(baseUrl, key) {
938
- const url2 = new URL(baseUrl.toString());
939
- url2.searchParams.set("key", key);
940
- return Promise.resolve(import_cement7.Result.Ok(url2));
941
- }
942
- };
943
- IndexDBMetaGateway = class extends IndexDBGateway {
944
- constructor(logger) {
945
- super(ensureLogger(logger, "IndexDBDataGateway", {}));
946
- this.branches = /* @__PURE__ */ new Set();
947
- }
948
- async buildUrl(baseUrl, key) {
949
- const url2 = new URL(baseUrl.toString());
950
- this.branches.add(key);
951
- url2.searchParams.set("key", key);
952
- return import_cement7.Result.Ok(url2);
953
- }
954
- };
955
- txtEncoder = new TextEncoder();
956
840
  IndexDBTestStore = class {
957
- constructor(logger) {
958
- this.logger = ensureLogger(logger, "IndexDBTestStore", {});
841
+ constructor(sthis) {
842
+ this.sthis = sthis;
843
+ this.logger = ensureLogger(sthis, "IndexDBTestStore", {});
959
844
  }
960
- async get(url2, key) {
961
- const db = await connectIdb(url2, this.logger);
962
- const store = getStore(url2, this.logger, joinDBName);
845
+ async get(url, key) {
846
+ const ic = await connectIdb(url, this.sthis);
847
+ const store = getStore(ic.url, this.sthis, joinDBName).name;
963
848
  this.logger.Debug().Str("key", key).Str("store", store).Msg("getting");
964
- let bytes = await db.get(store, sanitzeKey(key));
849
+ let bytes = await ic.db.get(store, sanitzeKey(key));
965
850
  this.logger.Debug().Str("key", key).Str("store", store).Int("len", bytes.length).Msg("got");
966
851
  if (typeof bytes === "string") {
967
- bytes = txtEncoder.encode(bytes);
852
+ bytes = this.sthis.txt.encode(bytes);
968
853
  }
969
854
  return bytes;
970
855
  }
@@ -978,11 +863,16 @@ __export(src_exports, {
978
863
  CRDT: () => CRDT,
979
864
  Database: () => Database,
980
865
  Index: () => Index,
866
+ NotFoundError: () => NotFoundError,
981
867
  PACKAGE_VERSION: () => PACKAGE_VERSION,
982
- Result: () => import_cement2.Result,
868
+ Result: () => import_cement.Result,
869
+ UInt8ArrayEqual: () => UInt8ArrayEqual,
983
870
  blockstore: () => blockstore_exports,
984
871
  bs: () => blockstore_exports,
872
+ dataDir: () => dataDir,
985
873
  ensureLogger: () => ensureLogger,
874
+ ensureSuperLog: () => ensureSuperLog,
875
+ ensureSuperThis: () => ensureSuperThis,
986
876
  exception2Result: () => exception2Result,
987
877
  exceptionWrapper: () => exceptionWrapper,
988
878
  falsyToUndef: () => falsyToUndef,
@@ -992,6 +882,7 @@ __export(src_exports, {
992
882
  getStore: () => getStore,
993
883
  index: () => index,
994
884
  isFalsy: () => isFalsy,
885
+ isNotFoundError: () => isNotFoundError,
995
886
  rt: () => runtime_exports,
996
887
  runtime: () => runtime_exports,
997
888
  throwFalsy: () => throwFalsy
@@ -999,8 +890,7 @@ __export(src_exports, {
999
890
  module.exports = __toCommonJS(src_exports);
1000
891
 
1001
892
  // src/database.ts
1002
- var import_uuidv73 = require("uuidv7");
1003
- var import_cement11 = require("@adviser/cement");
893
+ var import_cement13 = require("@adviser/cement");
1004
894
 
1005
895
  // src/write-queue.ts
1006
896
  function writeQueue(worker, payload = Infinity, unbounded = false) {
@@ -1043,13 +933,83 @@ function writeQueue(worker, payload = Infinity, unbounded = false) {
1043
933
  }
1044
934
 
1045
935
  // src/crdt.ts
1046
- var import_cement10 = require("@adviser/cement");
936
+ var import_cement12 = require("@adviser/cement");
937
+
938
+ // src/runtime/wait-pr-multiformats/block.ts
939
+ var block_exports = {};
940
+ __export(block_exports, {
941
+ Block: () => Block,
942
+ create: () => create,
943
+ createUnsafe: () => createUnsafe,
944
+ decode: () => decode,
945
+ encode: () => encode
946
+ });
947
+ var import_multiformats = require("multiformats");
948
+ var import_block = require("multiformats/block");
949
+ var Block = import_block.Block;
950
+ async function decode({
951
+ bytes,
952
+ codec: codec3,
953
+ hasher: hasher7
954
+ }) {
955
+ if (bytes == null) throw new Error('Missing required argument "bytes"');
956
+ if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
957
+ const value = await Promise.resolve(codec3.decode(bytes));
958
+ const hash = await hasher7.digest(bytes);
959
+ const cid = import_multiformats.CID.create(1, codec3.code, hash);
960
+ return new import_block.Block({ value, bytes, cid });
961
+ }
962
+ async function encode({
963
+ value,
964
+ codec: codec3,
965
+ hasher: hasher7
966
+ }) {
967
+ if (typeof value === "undefined") throw new Error('Missing required argument "value"');
968
+ if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
969
+ const bytes = await Promise.resolve(codec3.encode(value));
970
+ const hash = await hasher7.digest(bytes);
971
+ const cid = import_multiformats.CID.create(1, codec3.code, hash);
972
+ return new import_block.Block({ value, bytes, cid });
973
+ }
974
+ async function create({
975
+ bytes,
976
+ cid,
977
+ hasher: hasher7,
978
+ codec: codec3
979
+ }) {
980
+ if (bytes == null) throw new Error('Missing required argument "bytes"');
981
+ if (hasher7 == null) throw new Error('Missing required argument "hasher"');
982
+ const value = await Promise.resolve(codec3.decode(bytes));
983
+ const hash = await hasher7.digest(bytes);
984
+ if (!import_multiformats.bytes.equals(cid.multihash.bytes, hash.bytes)) {
985
+ throw new Error("CID hash does not match bytes");
986
+ }
987
+ return createUnsafe({
988
+ bytes,
989
+ cid,
990
+ value,
991
+ codec: codec3
992
+ });
993
+ }
994
+ async function createUnsafe({
995
+ bytes,
996
+ cid,
997
+ value: maybeValue,
998
+ codec: codec3
999
+ }) {
1000
+ const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
1001
+ if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
1002
+ return new Block({
1003
+ cid,
1004
+ bytes,
1005
+ value
1006
+ });
1007
+ }
1047
1008
 
1048
1009
  // src/crdt-helpers.ts
1049
- var import_block6 = require("multiformats/block");
1050
1010
  var import_link = require("multiformats/link");
1051
- var import_sha23 = require("multiformats/hashes/sha2");
1052
- var codec2 = __toESM(require("@ipld/dag-cbor"), 1);
1011
+ var import_sha25 = require("multiformats/hashes/sha2");
1012
+ var codec = __toESM(require("@ipld/dag-cbor"), 1);
1053
1013
  var import_crdt = require("@web3-storage/pail/crdt");
1054
1014
  var import_clock2 = require("@web3-storage/pail/clock");
1055
1015
  var Batch = __toESM(require("@web3-storage/pail/crdt/batch"), 1);
@@ -1060,525 +1020,149 @@ __export(blockstore_exports, {
1060
1020
  BaseBlockstore: () => BaseBlockstore,
1061
1021
  CarTransaction: () => CarTransaction,
1062
1022
  CompactionFetcher: () => CompactionFetcher,
1063
- ConnectREST: () => ConnectREST,
1064
1023
  ConnectionBase: () => ConnectionBase,
1065
- DataStore: () => DataStore,
1066
1024
  EncryptedBlockstore: () => EncryptedBlockstore,
1067
- Loadable: () => Loadable,
1025
+ FragmentGateway: () => FragmentGateway,
1068
1026
  Loader: () => Loader,
1069
- MetaStore: () => MetaStore,
1070
- NotFoundError: () => NotFoundError,
1071
- RemoteWAL: () => RemoteWAL,
1072
- isNotFoundError: () => isNotFoundError,
1027
+ ensureStart: () => ensureStart,
1028
+ getGatewayFromURL: () => getGatewayFromURL,
1073
1029
  parseCarFile: () => parseCarFile,
1074
1030
  registerStoreProtocol: () => registerStoreProtocol,
1075
1031
  testStoreFactory: () => testStoreFactory,
1076
- toStoreRuntime: () => toStoreRuntime,
1077
- toURL: () => toURL
1032
+ toCIDBlock: () => toCIDBlock,
1033
+ toStoreRuntime: () => toStoreRuntime
1078
1034
  });
1079
1035
 
1080
- // src/blockstore/connection-base.ts
1081
- var import_clock = require("@web3-storage/pail/clock");
1082
- var import_block = require("@web3-storage/pail/block");
1083
- init_types();
1036
+ // src/blockstore/types.ts
1037
+ function toCIDBlock(block) {
1038
+ return block;
1039
+ }
1084
1040
 
1085
- // src/blockstore/task-manager.ts
1086
- init_utils();
1087
- var TaskManager = class {
1088
- constructor(loader) {
1089
- this.eventsWeHandled = /* @__PURE__ */ new Set();
1090
- this.queue = [];
1091
- this.isProcessing = false;
1092
- this.loader = loader;
1093
- this.logger = ensureLogger(loader.logger, "TaskManager");
1094
- }
1095
- async handleEvent(eventBlock) {
1096
- const cid = eventBlock.cid.toString();
1097
- const parents = eventBlock.value.parents.map((cid2) => cid2.toString());
1098
- for (const parent of parents) {
1099
- this.eventsWeHandled.add(parent);
1100
- }
1101
- this.queue.push({ cid, eventBlock, retries: 0 });
1102
- this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
1103
- void this.processQueue();
1104
- }
1105
- async processQueue() {
1106
- if (this.isProcessing) return;
1107
- this.isProcessing = true;
1108
- const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
1109
- const first = filteredQueue[0];
1110
- if (!first) {
1111
- return;
1112
- }
1113
- try {
1114
- this.loader?.remoteMetaStore?.handleByteHeads([first.eventBlock.value.data.dbMeta]);
1115
- this.eventsWeHandled.add(first.cid);
1116
- this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
1117
- } catch (err) {
1118
- if (first.retries++ > 3) {
1119
- this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
1120
- this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
1121
- }
1122
- await new Promise((resolve) => setTimeout(resolve, 50));
1123
- throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
1124
- } finally {
1125
- this.isProcessing = false;
1126
- if (this.queue.length > 0) {
1127
- void this.processQueue();
1128
- }
1129
- }
1130
- }
1131
- };
1041
+ // src/blockstore/store-factory.ts
1042
+ var import_cement10 = require("@adviser/cement");
1132
1043
 
1133
- // src/blockstore/connection-base.ts
1134
- init_utils();
1135
- var ConnectionBase = class {
1136
- constructor(logger) {
1137
- // readonly ready: Promise<unknown>;
1138
- // todo move to LRU blockstore https://github.com/web3-storage/w3clock/blob/main/src/worker/block.js
1139
- this.eventBlocks = new import_block.MemoryBlockstore();
1140
- this.parents = [];
1141
- this.loaded = Promise.resolve();
1142
- this.logger = ensureLogger(logger, "ConnectionBase");
1143
- }
1144
- async refresh() {
1145
- await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load("main");
1146
- await (await throwFalsy(this.loader).remoteWAL())._process();
1147
- }
1148
- connect({ loader }) {
1149
- if (!loader) throw this.logger.Error().Msg("loader is required").AsError();
1150
- this.connectMeta({ loader });
1151
- this.connectStorage({ loader });
1152
- }
1153
- connectMeta({ loader }) {
1154
- if (!loader) throw this.logger.Error().Msg("loader is required").AsError();
1155
- this.loader = loader;
1156
- this.taskManager = new TaskManager(loader);
1157
- this.onConnect();
1158
- this.logger.Warn().Msg("connectMeta: connecting to remote meta store is disabled");
1159
- }
1160
- async onConnect() {
1161
- return;
1162
- }
1163
- connectStorage({ loader }) {
1164
- if (!loader) throw this.logger.Error().Msg("loader is required").AsError();
1165
- this.loader = loader;
1166
- this.logger.Warn().Msg("connectStorage: connecting to remote meta store is disabled");
1044
+ // src/runtime/files.ts
1045
+ var files_exports = {};
1046
+ __export(files_exports, {
1047
+ decodeFile: () => decodeFile,
1048
+ encodeFile: () => encodeFile
1049
+ });
1050
+ var UnixFS = __toESM(require("@ipld/unixfs"), 1);
1051
+ var raw = __toESM(require("multiformats/codecs/raw"), 1);
1052
+ var import_fixed = require("@ipld/unixfs/file/chunker/fixed");
1053
+ var import_balanced = require("@ipld/unixfs/file/layout/balanced");
1054
+ var import_ipfs_unixfs_exporter = require("ipfs-unixfs-exporter");
1055
+ var queuingStrategy = UnixFS.withCapacity();
1056
+ var settings = UnixFS.configure({
1057
+ fileChunkEncoder: raw,
1058
+ smallFileEncoder: raw,
1059
+ chunker: (0, import_fixed.withMaxChunkSize)(1024 * 1024),
1060
+ fileLayout: (0, import_balanced.withWidth)(1024)
1061
+ });
1062
+ async function collect(collectable) {
1063
+ const chunks = [];
1064
+ await collectable.pipeTo(
1065
+ new WritableStream({
1066
+ write(chunk) {
1067
+ chunks.push(chunk);
1068
+ }
1069
+ })
1070
+ );
1071
+ return chunks;
1072
+ }
1073
+ async function encodeFile(blob) {
1074
+ const readable = createFileEncoderStream(blob);
1075
+ const blocks = await collect(readable);
1076
+ return { cid: blocks.at(-1).cid, blocks };
1077
+ }
1078
+ async function decodeFile(blocks, cid, meta) {
1079
+ const entry = await (0, import_ipfs_unixfs_exporter.exporter)(cid.toString(), blocks, { length: meta.size });
1080
+ const chunks = [];
1081
+ for await (const chunk of entry.content()) {
1082
+ chunks.push(chunk);
1167
1083
  }
1168
- async createEventBlock(bytes) {
1169
- const data = {
1170
- dbMeta: bytes
1171
- };
1172
- const event = await import_clock.EventBlock.create(
1173
- data,
1174
- this.parents
1084
+ return new File(chunks, entry.name, { type: meta.type, lastModified: 0 });
1085
+ }
1086
+ function createFileEncoderStream(blob) {
1087
+ const { readable, writable } = new TransformStream({}, queuingStrategy);
1088
+ const unixfsWriter = UnixFS.createWriter({ writable, settings });
1089
+ const fileBuilder = new UnixFSFileBuilder("", blob);
1090
+ void (async () => {
1091
+ await fileBuilder.finalize(unixfsWriter);
1092
+ await unixfsWriter.close();
1093
+ })();
1094
+ return readable;
1095
+ }
1096
+ var UnixFSFileBuilder = class {
1097
+ #file;
1098
+ constructor(name, file) {
1099
+ this.name = name;
1100
+ this.#file = file;
1101
+ }
1102
+ async finalize(writer) {
1103
+ const unixfsFileWriter = UnixFS.createFileWriter(writer);
1104
+ await this.#file.stream().pipeTo(
1105
+ new WritableStream({
1106
+ async write(chunk) {
1107
+ await unixfsFileWriter.write(chunk);
1108
+ }
1109
+ })
1175
1110
  );
1176
- await this.eventBlocks.put(event.cid, event.bytes);
1177
- return event;
1178
- }
1179
- async decodeEventBlock(bytes) {
1180
- const event = await (0, import_clock.decodeEventBlock)(bytes);
1181
- return event;
1111
+ return await unixfsFileWriter.close();
1182
1112
  }
1183
- // move this stuff to connect
1184
- // async getDashboardURL(compact = true) {
1185
- // const baseUrl = 'https://dashboard.fireproof.storage/'
1186
- // if (!this.loader?.remoteCarStore) return new URL('/howto', baseUrl)
1187
- // // if (compact) {
1188
- // // await this.compact()
1189
- // // }
1190
- // const currents = await this.loader?.metaStore?.load()
1191
- // if (!currents) throw new Error("Can't sync empty database: save data first")
1192
- // if (currents.length > 1)
1193
- // throw new Error("Can't sync database with split heads: make an update first")
1194
- // const current = currents[0]
1195
- // const params = {
1196
- // car: current.car.toString()
1197
- // }
1198
- // if (current.key) {
1199
- // // @ts-ignore
1200
- // params.key = current.key.toString()
1201
- // }
1202
- // // @ts-ignore
1203
- // if (this.name) {
1204
- // // @ts-ignore
1205
- // params.name = this.name
1206
- // }
1207
- // const url = new URL('/import#' + new URLSearchParams(params).toString(), baseUrl)
1208
- // console.log('Import to dashboard: ' + url.toString())
1209
- // return url
1210
- // }
1211
- // openDashboard() {
1212
- // void this.getDashboardURL().then(url => {
1213
- // if (url) window.open(url.toString(), '_blank')
1214
- // })
1215
- // }
1216
1113
  };
1217
1114
 
1218
- // src/blockstore/connect-rest.ts
1219
- init_utils();
1220
- var ConnectREST = class extends ConnectionBase {
1221
- constructor(base, logger) {
1222
- super(ensureLogger(logger, "ConnectREST"));
1223
- this.baseUrl = new URL(base);
1224
- }
1225
- async dataUpload(bytes, params) {
1226
- const carCid = params.car.toString();
1227
- const uploadURL = new URL(`/cars/${carCid}.car`, this.baseUrl);
1228
- const done = await fetch(uploadURL, { method: "PUT", body: bytes });
1229
- if (!done.ok) {
1230
- throw this.logger.Error().Msg("failed to upload data " + done.statusText);
1231
- }
1232
- }
1233
- async dataDownload(params) {
1234
- const { car } = params;
1235
- const fetchFromUrl = new URL(`/cars/${car.toString()}.car`, this.baseUrl);
1236
- const response = await fetch(fetchFromUrl);
1237
- if (!response.ok) {
1238
- return void 0;
1239
- }
1240
- const bytes = new Uint8Array(await response.arrayBuffer());
1241
- return bytes;
1115
+ // src/blockstore/store.ts
1116
+ var import_p_limit2 = __toESM(require("p-limit"), 1);
1117
+ var import_dag_json = require("@ipld/dag-json");
1118
+ var import_cement7 = require("@adviser/cement");
1119
+
1120
+ // src/types.ts
1121
+ function isFalsy(value) {
1122
+ return value === false && value === null && value === void 0;
1123
+ }
1124
+ function throwFalsy(value) {
1125
+ if (isFalsy(value)) {
1126
+ throw new Error("value is Falsy");
1242
1127
  }
1243
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1244
- async metaUpload(bytes, params) {
1128
+ return value;
1129
+ }
1130
+ function falsyToUndef(value) {
1131
+ if (isFalsy(value)) {
1245
1132
  return void 0;
1246
1133
  }
1247
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1248
- async metaDownload(params) {
1249
- return [];
1250
- }
1251
- };
1252
-
1253
- // src/blockstore/store-factory.ts
1254
- var import_cement8 = require("@adviser/cement");
1255
- init_data_dir();
1256
- init_files();
1134
+ return value;
1135
+ }
1257
1136
 
1258
1137
  // src/blockstore/store.ts
1259
- var import_p_limit2 = __toESM(require("p-limit"), 1);
1260
- var import_dag_json = require("@ipld/dag-json");
1261
- var import_cement5 = require("@adviser/cement");
1262
- init_types();
1263
- init_gateway();
1264
1138
  init_utils();
1265
1139
 
1266
1140
  // src/blockstore/loader.ts
1267
1141
  var import_p_limit = __toESM(require("p-limit"), 1);
1268
1142
  var import_car = require("@ipld/car");
1269
- var import_cement4 = require("@adviser/cement");
1270
-
1271
- // src/blockstore/types.ts
1272
- function toCIDBlock(block) {
1273
- return block;
1274
- }
1143
+ var import_cement6 = require("@adviser/cement");
1275
1144
 
1276
1145
  // src/blockstore/loader-helpers.ts
1277
- var import_block2 = require("multiformats/block");
1278
1146
  var import_sha2 = require("multiformats/hashes/sha2");
1279
- var raw2 = __toESM(require("multiformats/codecs/raw"), 1);
1280
- var CBW = __toESM(require("@ipld/car/buffer-writer"), 1);
1281
- var codec = __toESM(require("@ipld/dag-cbor"), 1);
1282
- async function encodeCarFile(roots, t) {
1283
- let size = 0;
1284
- const headerSize = CBW.headerLength({ roots });
1285
- size += headerSize;
1286
- for (const { cid, bytes } of t.entries()) {
1287
- size += CBW.blockLength({ cid, bytes });
1288
- }
1289
- const buffer = new Uint8Array(size);
1290
- const writer = CBW.createWriter(buffer, { headerSize });
1291
- for (const r of roots) {
1292
- writer.addRoot(r);
1293
- }
1294
- for (const { cid, bytes } of t.entries()) {
1295
- writer.write({ cid, bytes });
1296
- }
1297
- writer.close();
1298
- return await (0, import_block2.encode)({ value: writer.bytes, hasher: import_sha2.sha256, codec: raw2 });
1299
- }
1300
- async function encodeCarHeader(fp) {
1301
- return await (0, import_block2.encode)({
1302
- value: { fp },
1303
- hasher: import_sha2.sha256,
1304
- codec
1305
- });
1306
- }
1147
+ var dagCodec = __toESM(require("@ipld/dag-cbor"), 1);
1307
1148
  async function parseCarFile(reader, logger) {
1308
1149
  const roots = await reader.getRoots();
1309
1150
  const header = await reader.get(roots[0]);
1310
1151
  if (!header) throw logger.Error().Msg("missing header block").AsError();
1311
- const { value } = await (0, import_block2.decode)({ bytes: header.bytes, hasher: import_sha2.sha256, codec });
1312
- const fpvalue = value;
1152
+ const dec = await decode({ bytes: header.bytes, hasher: import_sha2.sha256, codec: dagCodec });
1153
+ const fpvalue = dec.value;
1313
1154
  if (fpvalue && !fpvalue.fp) {
1314
1155
  throw logger.Error().Msg("missing fp").AsError();
1315
1156
  }
1316
1157
  return fpvalue.fp;
1317
1158
  }
1318
1159
 
1319
- // src/blockstore/encrypt-helpers.ts
1320
- var import_sha22 = require("multiformats/hashes/sha2");
1321
- var import_multiformats2 = require("multiformats");
1322
- var import_block3 = require("multiformats/block");
1323
- var dagcbor = __toESM(require("@ipld/dag-cbor"), 1);
1324
- var import_block4 = require("@web3-storage/pail/block");
1325
- var import_utils6 = require("prolly-trees/utils");
1326
- var import_cache = require("prolly-trees/cache");
1327
- var import_cid_set = require("prolly-trees/cid-set");
1328
-
1329
- // src/blockstore/encrypt-codec.ts
1330
- var import_multiformats = require("multiformats");
1331
- init_utils();
1332
- function makeCodec(ilogger, crypto2, randomBytes2) {
1333
- const logger = ensureLogger(ilogger, "makeCodec");
1334
- const enc32 = (value) => {
1335
- value = +value;
1336
- const buff = new Uint8Array(4);
1337
- buff[3] = value >>> 24;
1338
- buff[2] = value >>> 16;
1339
- buff[1] = value >>> 8;
1340
- buff[0] = value & 255;
1341
- return buff;
1342
- };
1343
- const readUInt32LE = (buffer) => {
1344
- const offset = buffer.byteLength - 4;
1345
- return (buffer[offset] | buffer[offset + 1] << 8 | buffer[offset + 2] << 16) + buffer[offset + 3] * 16777216;
1346
- };
1347
- const concat = (buffers) => {
1348
- const uint8Arrays = buffers.map((b) => b instanceof ArrayBuffer ? new Uint8Array(b) : b);
1349
- const totalLength = uint8Arrays.reduce((sum, arr) => sum + arr.length, 0);
1350
- const result = new Uint8Array(totalLength);
1351
- let offset = 0;
1352
- for (const arr of uint8Arrays) {
1353
- result.set(arr, offset);
1354
- offset += arr.length;
1355
- }
1356
- return result;
1357
- };
1358
- const encode4 = ({ iv, bytes }) => concat([iv, bytes]);
1359
- const decode4 = (bytes) => {
1360
- const iv = bytes.subarray(0, 12);
1361
- bytes = bytes.slice(12);
1362
- return { iv, bytes };
1363
- };
1364
- const code = 3145728 + 1337;
1365
- async function subtleKey(key) {
1366
- return await crypto2.importKey(
1367
- "raw",
1368
- // raw or jwk
1369
- key,
1370
- // raw data
1371
- "AES-GCM",
1372
- false,
1373
- // extractable
1374
- ["encrypt", "decrypt"]
1375
- );
1376
- }
1377
- const decrypt = async ({ key, value }) => {
1378
- const { bytes: inBytes, iv } = value;
1379
- const cryKey = await subtleKey(key);
1380
- const deBytes = await crypto2.decrypt(
1381
- {
1382
- name: "AES-GCM",
1383
- iv,
1384
- tagLength: 128
1385
- },
1386
- cryKey,
1387
- inBytes
1388
- );
1389
- const bytes = new Uint8Array(deBytes);
1390
- const len = readUInt32LE(bytes.subarray(0, 4));
1391
- const cid = import_multiformats.CID.decode(bytes.subarray(4, 4 + len));
1392
- return { cid, bytes: bytes.subarray(4 + len) };
1393
- };
1394
- const encrypt = async ({ key, cid, bytes }) => {
1395
- const len = enc32(cid.bytes.byteLength);
1396
- const iv = randomBytes2(12);
1397
- const msg = concat([len, cid.bytes, bytes]);
1398
- try {
1399
- const cryKey = await subtleKey(key);
1400
- const deBytes = await crypto2.encrypt(
1401
- {
1402
- name: "AES-GCM",
1403
- iv,
1404
- tagLength: 128
1405
- },
1406
- cryKey,
1407
- msg
1408
- );
1409
- bytes = new Uint8Array(deBytes);
1410
- } catch (e) {
1411
- throw logger.Error().Err(e).Msg("encrypt failed").AsError();
1412
- }
1413
- return { value: { bytes, iv } };
1414
- };
1415
- const cryptoFn = (key) => {
1416
- return { encrypt: (opts) => encrypt({ ...opts, key }), decrypt: (opts) => decrypt({ ...opts, key }) };
1417
- };
1418
- const name = "jchris@encrypted-block:aes-gcm";
1419
- return { encode: encode4, decode: decode4, code, name, encrypt, decrypt, crypto: cryptoFn };
1420
- }
1421
-
1422
- // src/blockstore/encrypt-helpers.ts
1423
- function carLogIncludesGroup(list, cidMatch) {
1424
- return list.some((cid) => {
1425
- return cid.toString() === cidMatch.toString();
1426
- });
1427
- }
1428
- function makeEncDec(logger, crypto2, randomBytes2) {
1429
- const codec4 = makeCodec(logger, crypto2, randomBytes2);
1430
- const encrypt = async function* ({
1431
- get: get2,
1432
- cids,
1433
- hasher: hasher4,
1434
- key,
1435
- cache: cache3,
1436
- chunker: chunker2,
1437
- root: root3
1438
- }) {
1439
- const set = /* @__PURE__ */ new Set();
1440
- let eroot;
1441
- if (!carLogIncludesGroup(cids, root3)) cids.push(root3);
1442
- for (const cid of cids) {
1443
- const unencrypted = await get2(cid);
1444
- if (!unencrypted) throw logger.Error().Ref("cid", cid).Msg("missing cid block").AsError();
1445
- const encrypted = await codec4.encrypt({ ...unencrypted, key });
1446
- const block2 = await (0, import_block3.encode)({ ...encrypted, codec: codec4, hasher: hasher4 });
1447
- yield block2;
1448
- set.add(block2.cid.toString());
1449
- if (unencrypted.cid.equals(root3)) eroot = block2.cid;
1450
- }
1451
- if (!eroot) throw logger.Error().Msg("cids does not include root").AsError();
1452
- const list = [...set].map((s) => import_multiformats2.CID.parse(s));
1453
- let last;
1454
- for await (const node of (0, import_cid_set.create)({ list, get: get2, cache: cache3, chunker: chunker2, hasher: hasher4, codec: dagcbor })) {
1455
- const block2 = await node.block;
1456
- yield block2;
1457
- last = block2;
1458
- }
1459
- if (!last) throw logger.Error().Msg("missing last block").AsError();
1460
- const head = [eroot, last.cid];
1461
- const block = await (0, import_block3.encode)({ value: head, codec: dagcbor, hasher: hasher4 });
1462
- yield block;
1463
- };
1464
- const decrypt = async function* ({
1465
- root: root3,
1466
- get: get2,
1467
- key,
1468
- cache: cache3,
1469
- chunker: chunker2,
1470
- hasher: hasher4
1471
- }) {
1472
- const getWithDecode = async (cid) => get2(cid).then(async (block) => {
1473
- if (!block) return;
1474
- const decoded = await (0, import_block3.decode)({ ...block, codec: dagcbor, hasher: hasher4 });
1475
- return decoded;
1476
- });
1477
- const getWithDecrypt = async (cid) => get2(cid).then(async (block) => {
1478
- if (!block) return;
1479
- const decoded = await (0, import_block3.decode)({ ...block, codec: codec4, hasher: hasher4 });
1480
- return decoded;
1481
- });
1482
- const decodedRoot = await getWithDecode(root3);
1483
- if (!decodedRoot) throw logger.Error().Msg("missing root").AsError();
1484
- if (!decodedRoot.bytes) throw logger.Error().Msg("missing bytes").AsError();
1485
- const {
1486
- value: [eroot, tree]
1487
- } = decodedRoot;
1488
- const rootBlock = await get2(eroot);
1489
- if (!rootBlock) throw logger.Error().Msg("missing root block").AsError();
1490
- const cidset = await (0, import_cid_set.load)({ cid: tree, get: getWithDecode, cache: cache3, chunker: chunker2, codec: codec4, hasher: hasher4 });
1491
- const { result: nodes } = await cidset.getAllEntries();
1492
- const unwrap = async (eblock) => {
1493
- if (!eblock) throw logger.Error().Msg("missing block").AsError();
1494
- if (!eblock.value) {
1495
- eblock = await (0, import_block3.decode)({ ...eblock, codec: codec4, hasher: hasher4 });
1496
- if (!eblock.value) throw logger.Error().Msg("missing value").AsError();
1497
- }
1498
- const { bytes, cid } = await codec4.decrypt({ ...eblock, key }).catch((e) => {
1499
- throw e;
1500
- });
1501
- const block = await (0, import_block3.create)({ cid, bytes, hasher: hasher4, codec: codec4 });
1502
- return block;
1503
- };
1504
- const promises = [];
1505
- for (const { cid } of nodes) {
1506
- if (!rootBlock.cid.equals(cid)) promises.push(getWithDecrypt(cid).then(unwrap));
1507
- }
1508
- yield* promises;
1509
- yield unwrap(rootBlock);
1510
- };
1511
- return { encrypt, decrypt };
1512
- }
1513
- var chunker = (0, import_utils6.bf)(30);
1514
- function hexStringToUint8Array(hexString) {
1515
- const length = hexString.length;
1516
- const uint8Array = new Uint8Array(length / 2);
1517
- for (let i = 0; i < length; i += 2) {
1518
- uint8Array[i / 2] = parseInt(hexString.substring(i, i + 2), 16);
1519
- }
1520
- return uint8Array;
1521
- }
1522
- async function encryptedEncodeCarFile(logger, crypto2, key, rootCid, t) {
1523
- const encryptionKey = hexStringToUint8Array(key);
1524
- const encryptedBlocks = new import_block4.MemoryBlockstore();
1525
- const cidsToEncrypt = [];
1526
- for (const { cid, bytes } of t.entries()) {
1527
- cidsToEncrypt.push(cid);
1528
- const g = await t.get(cid);
1529
- if (!g) throw logger.Error().Ref("cid", cid).Int("bytes", bytes.length).Msg("missing cid block").AsError();
1530
- }
1531
- let last = null;
1532
- const { encrypt } = makeEncDec(logger, crypto2, crypto2.randomBytes);
1533
- for await (const block of encrypt({
1534
- cids: cidsToEncrypt,
1535
- get: t.get.bind(t),
1536
- key: encryptionKey,
1537
- hasher: import_sha22.sha256,
1538
- chunker,
1539
- cache: import_cache.nocache,
1540
- root: rootCid
1541
- })) {
1542
- await encryptedBlocks.put(block.cid, block.bytes);
1543
- last = block;
1544
- }
1545
- if (!last) throw logger.Error().Msg("no blocks encrypted").AsError();
1546
- const encryptedCar = await encodeCarFile([last.cid], encryptedBlocks);
1547
- return encryptedCar;
1548
- }
1549
- async function decodeEncryptedCar(logger, crypto2, key, reader) {
1550
- const roots = await reader.getRoots();
1551
- const root3 = roots[0];
1552
- return await decodeCarBlocks(logger, crypto2, root3, reader.get.bind(reader), key);
1553
- }
1554
- async function decodeCarBlocks(logger, crypto2, root3, get2, keyMaterial) {
1555
- const decryptionKeyUint8 = hexStringToUint8Array(keyMaterial);
1556
- const decryptionKey = decryptionKeyUint8.buffer.slice(0, decryptionKeyUint8.byteLength);
1557
- const decryptedBlocks = new import_block4.MemoryBlockstore();
1558
- let last = null;
1559
- const { decrypt } = makeEncDec(logger, crypto2, crypto2.randomBytes);
1560
- for await (const block of decrypt({
1561
- root: root3,
1562
- get: get2,
1563
- key: decryptionKey,
1564
- hasher: import_sha22.sha256,
1565
- chunker,
1566
- cache: import_cache.nocache
1567
- })) {
1568
- await decryptedBlocks.put(block.cid, block.bytes);
1569
- last = block;
1570
- }
1571
- if (!last) throw logger.Error().Msg("no blocks decrypted").AsError();
1572
- return { blocks: decryptedBlocks, root: last.cid };
1573
- }
1574
-
1575
1160
  // src/blockstore/transaction.ts
1576
- var import_block5 = require("@web3-storage/pail/block");
1577
- init_types();
1578
- init_crypto();
1161
+ var import_block3 = require("@web3-storage/pail/block");
1162
+ var import_cement2 = require("@adviser/cement");
1579
1163
  init_utils();
1580
- var CarTransaction = class extends import_block5.MemoryBlockstore {
1581
- constructor(parent, opts = { add: true }) {
1164
+ var CarTransaction = class extends import_block3.MemoryBlockstore {
1165
+ constructor(parent, opts = { add: true, noLoader: false }) {
1582
1166
  super();
1583
1167
  if (opts.add) {
1584
1168
  parent.transactions.add(this);
@@ -1592,8 +1176,8 @@ var CarTransaction = class extends import_block5.MemoryBlockstore {
1592
1176
  return super.get(cid);
1593
1177
  }
1594
1178
  };
1595
- function defaultedBlockstoreRuntime(opts, component, ctx) {
1596
- const logger = ensureLogger(opts, component, ctx);
1179
+ function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
1180
+ const logger = ensureLogger(sthis, component, ctx);
1597
1181
  const store = opts.store || {};
1598
1182
  return {
1599
1183
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
@@ -1610,22 +1194,24 @@ function defaultedBlockstoreRuntime(opts, component, ctx) {
1610
1194
  threshold: 1e3 * 1e3,
1611
1195
  ...opts,
1612
1196
  logger,
1613
- crypto: toCryptoOpts(opts.crypto),
1197
+ keyBag: opts.keyBag || {},
1198
+ crypto: (0, import_cement2.toCryptoRuntime)(opts.crypto),
1614
1199
  store,
1615
- storeRuntime: toStoreRuntime(store, logger)
1200
+ storeRuntime: toStoreRuntime(store, sthis)
1616
1201
  };
1617
1202
  }
1618
- var blockstoreFactory = function(opts) {
1203
+ function blockstoreFactory(sthis, opts) {
1619
1204
  if (opts.name) {
1620
- return new EncryptedBlockstore(opts);
1205
+ return new EncryptedBlockstore(sthis, opts);
1621
1206
  } else {
1622
1207
  return new BaseBlockstore(opts);
1623
1208
  }
1624
- };
1209
+ }
1625
1210
  var BaseBlockstore = class {
1626
1211
  constructor(ebOpts = {}) {
1627
1212
  this.transactions = /* @__PURE__ */ new Set();
1628
- this.ebOpts = defaultedBlockstoreRuntime(ebOpts, "BaseBlockstore");
1213
+ this.sthis = ensureSuperThis(ebOpts);
1214
+ this.ebOpts = defaultedBlockstoreRuntime(this.sthis, ebOpts, "BaseBlockstore");
1629
1215
  this.logger = this.ebOpts.logger;
1630
1216
  }
1631
1217
  // ready: Promise<void>;
@@ -1648,8 +1234,8 @@ var BaseBlockstore = class {
1648
1234
  throw this.logger.Error().Msg("use a transaction to put").AsError();
1649
1235
  }
1650
1236
  // TransactionMeta
1651
- async transaction(fn, _opts = {}) {
1652
- const t = new CarTransaction(this);
1237
+ async transaction(fn, _opts) {
1238
+ const t = new CarTransaction(this, _opts);
1653
1239
  const done = await fn(t);
1654
1240
  this.lastTxMeta = done;
1655
1241
  return { t, meta: done };
@@ -1666,16 +1252,16 @@ var BaseBlockstore = class {
1666
1252
  }
1667
1253
  };
1668
1254
  var EncryptedBlockstore = class extends BaseBlockstore {
1669
- constructor(ebOpts) {
1255
+ constructor(sthis, ebOpts) {
1670
1256
  super(ebOpts);
1671
1257
  this.compacting = false;
1672
- this.logger = ensureLogger(ebOpts, "EncryptedBlockstore");
1258
+ this.logger = ensureLogger(this.sthis, "EncryptedBlockstore");
1673
1259
  const { name } = ebOpts;
1674
1260
  if (!name) {
1675
1261
  throw this.logger.Error().Msg("name required").AsError();
1676
1262
  }
1677
1263
  this.name = name;
1678
- this.loader = new Loader(this.name, ebOpts);
1264
+ this.loader = new Loader(this.name, ebOpts, sthis);
1679
1265
  }
1680
1266
  ready() {
1681
1267
  return this.loader.ready();
@@ -1706,10 +1292,13 @@ var EncryptedBlockstore = class extends BaseBlockstore {
1706
1292
  }
1707
1293
  throw this.logger.Error().Msg("failed to commit car files").AsError();
1708
1294
  }
1709
- async getFile(car, cid, isPublic = false) {
1295
+ async getFile(car, cid) {
1710
1296
  await this.ready();
1711
1297
  if (!this.loader) throw this.logger.Error().Msg("loader required to get file, database must be named").AsError();
1712
- const reader = await this.loader.loadFileCar(car, isPublic);
1298
+ const reader = await this.loader.loadFileCar(
1299
+ car
1300
+ /*, isPublic */
1301
+ );
1713
1302
  const block = await reader.get(cid);
1714
1303
  if (!block) throw this.logger.Error().Str("cid", cid.toString()).Msg(`Missing block`).AsError();
1715
1304
  return block.bytes;
@@ -1765,43 +1354,345 @@ var CompactionFetcher = class {
1765
1354
  };
1766
1355
 
1767
1356
  // src/blockstore/commit-queue.ts
1357
+ var import_cement3 = require("@adviser/cement");
1768
1358
  var CommitQueue = class {
1769
1359
  constructor() {
1770
1360
  this.queue = [];
1771
1361
  this.processing = false;
1362
+ this._waitIdleItems = /* @__PURE__ */ new Set();
1363
+ }
1364
+ waitIdle() {
1365
+ if (this.queue.length === 0 && !this.processing) {
1366
+ return Promise.resolve();
1367
+ }
1368
+ const fn = new import_cement3.Future();
1369
+ this._waitIdleItems.add(fn);
1370
+ return fn.asPromise();
1371
+ }
1372
+ async enqueue(fn) {
1373
+ return new Promise((resolve, reject) => {
1374
+ const queueFn = async () => {
1375
+ try {
1376
+ resolve(await fn());
1377
+ } catch (e) {
1378
+ reject(e);
1379
+ } finally {
1380
+ this.processing = false;
1381
+ this.processNext();
1382
+ }
1383
+ };
1384
+ this.queue.push(queueFn);
1385
+ if (!this.processing) {
1386
+ this.processNext();
1387
+ }
1388
+ });
1389
+ }
1390
+ processNext() {
1391
+ if (this.queue.length > 0 && !this.processing) {
1392
+ this.processing = true;
1393
+ const queueFn = this.queue.shift();
1394
+ if (queueFn) {
1395
+ queueFn().finally(() => {
1396
+ });
1397
+ }
1398
+ }
1399
+ if (this.queue.length === 0 && !this.processing) {
1400
+ const toResolve = Array.from(this._waitIdleItems);
1401
+ this._waitIdleItems.clear();
1402
+ toResolve.map((fn) => fn.resolve());
1403
+ }
1404
+ }
1405
+ };
1406
+
1407
+ // src/runtime/key-bag.ts
1408
+ var key_bag_exports = {};
1409
+ __export(key_bag_exports, {
1410
+ KeyBag: () => KeyBag,
1411
+ getKeyBag: () => getKeyBag,
1412
+ registerKeyBagProviderFactory: () => registerKeyBagProviderFactory
1413
+ });
1414
+ var import_cement5 = require("@adviser/cement");
1415
+ init_utils();
1416
+ var import_base582 = require("multiformats/bases/base58");
1417
+ var KeyBag = class {
1418
+ constructor(rt) {
1419
+ this.rt = rt;
1420
+ this._seq = new import_cement5.ResolveSeq();
1421
+ this.logger = ensureLogger(rt.sthis, "KeyBag", {
1422
+ id: rt.id()
1423
+ });
1424
+ this.logger.Debug().Msg("KeyBag created");
1425
+ }
1426
+ async subtleKey(key) {
1427
+ return await this.rt.crypto.importKey(
1428
+ "raw",
1429
+ // raw or jwk
1430
+ import_base582.base58btc.decode(key),
1431
+ // hexStringToUint8Array(key), // raw data
1432
+ "AES-GCM",
1433
+ false,
1434
+ // extractable
1435
+ ["encrypt", "decrypt"]
1436
+ );
1437
+ }
1438
+ async ensureKeyFromUrl(url, keyFactory) {
1439
+ const storeKey = url.getParam("storekey");
1440
+ if (storeKey === "insecure") {
1441
+ return import_cement5.Result.Ok(url);
1442
+ }
1443
+ if (!storeKey) {
1444
+ const keyName = `@${keyFactory()}@`;
1445
+ const ret = await this.getNamedKey(keyName);
1446
+ if (ret.isErr()) {
1447
+ return ret;
1448
+ }
1449
+ const urb = url.build().setParam("storekey", keyName);
1450
+ return import_cement5.Result.Ok(urb.URI());
1451
+ }
1452
+ if (storeKey.startsWith("@") && storeKey.endsWith("@")) {
1453
+ const ret = await this.getNamedKey(storeKey);
1454
+ if (ret.isErr()) {
1455
+ return ret;
1456
+ }
1457
+ }
1458
+ return import_cement5.Result.Ok(url);
1459
+ }
1460
+ async toKeyWithFingerPrint(keyStr) {
1461
+ const material = import_base582.base58btc.decode(keyStr);
1462
+ const key = await this.subtleKey(keyStr);
1463
+ const fpr = await this.rt.crypto.digestSHA256(material);
1464
+ return import_cement5.Result.Ok({
1465
+ key,
1466
+ fingerPrint: import_base582.base58btc.encode(new Uint8Array(fpr))
1467
+ });
1468
+ }
1469
+ async setNamedKey(name, key) {
1470
+ return this._seq.add(() => this._setNamedKey(name, key));
1471
+ }
1472
+ // avoid deadlock
1473
+ async _setNamedKey(name, key) {
1474
+ const item = {
1475
+ name,
1476
+ key
1477
+ };
1478
+ const bag = await this.rt.getBag();
1479
+ this.logger.Debug().Str("name", name).Msg("setNamedKey");
1480
+ await bag.set(name, item);
1481
+ return await this.toKeyWithFingerPrint(item.key);
1482
+ }
1483
+ async getNamedKey(name, failIfNotFound = false) {
1484
+ const id = this.rt.sthis.nextId(4).str;
1485
+ return this._seq.add(async () => {
1486
+ const bag = await this.rt.getBag();
1487
+ const named = await bag.get(name);
1488
+ if (named) {
1489
+ const fpr = await this.toKeyWithFingerPrint(named.key);
1490
+ this.logger.Debug().Str("id", id).Str("name", name).Result("fpr", fpr).Msg("fingerPrint getNamedKey");
1491
+ return fpr;
1492
+ }
1493
+ if (failIfNotFound) {
1494
+ this.logger.Debug().Str("id", id).Str("name", name).Msg("failIfNotFound getNamedKey");
1495
+ return import_cement5.Result.Err(new Error(`Key not found: ${name}`));
1496
+ }
1497
+ const ret = await this._setNamedKey(name, import_base582.base58btc.encode(this.rt.crypto.randomBytes(this.rt.keyLength)));
1498
+ this.logger.Debug().Str("id", id).Str("name", name).Result("fpr", ret).Msg("createKey getNamedKey-post");
1499
+ return ret;
1500
+ });
1501
+ }
1502
+ };
1503
+ var keyBagProviderFactories = new Map(
1504
+ [
1505
+ {
1506
+ protocol: "file:",
1507
+ factory: async (url, sthis) => {
1508
+ const { KeyBagProviderFile: KeyBagProviderFile2 } = await Promise.resolve().then(() => (init_key_bag_file(), key_bag_file_exports));
1509
+ return new KeyBagProviderFile2(url, sthis);
1510
+ }
1511
+ },
1512
+ {
1513
+ protocol: "indexdb:",
1514
+ factory: async (url, sthis) => {
1515
+ const { KeyBagProviderIndexDB: KeyBagProviderIndexDB2 } = await Promise.resolve().then(() => (init_key_bag_indexdb(), key_bag_indexdb_exports));
1516
+ return new KeyBagProviderIndexDB2(url, sthis);
1517
+ }
1518
+ }
1519
+ ].map((i) => [i.protocol, i])
1520
+ );
1521
+ function registerKeyBagProviderFactory(item) {
1522
+ const protocol = item.protocol.endsWith(":") ? item.protocol : item.protocol + ":";
1523
+ keyBagProviderFactories.set(protocol, {
1524
+ ...item,
1525
+ protocol
1526
+ });
1527
+ }
1528
+ function defaultKeyBagOpts(sthis, kbo) {
1529
+ if (kbo.keyRuntime) {
1530
+ return kbo.keyRuntime;
1531
+ }
1532
+ const logger = ensureLogger(sthis, "KeyBag");
1533
+ let url;
1534
+ if (kbo.url) {
1535
+ url = import_cement5.URI.from(kbo.url);
1536
+ logger.Debug().Url(url).Msg("from opts");
1537
+ } else {
1538
+ let bagFnameOrUrl = sthis.env.get("FP_KEYBAG_URL");
1539
+ if ((0, import_cement5.runtimeFn)().isBrowser) {
1540
+ url = import_cement5.URI.from(bagFnameOrUrl || "indexdb://fp-keybag");
1541
+ } else {
1542
+ if (!bagFnameOrUrl) {
1543
+ const home = sthis.env.get("HOME");
1544
+ bagFnameOrUrl = `${home}/.fireproof/keybag`;
1545
+ url = import_cement5.URI.from(`file://${bagFnameOrUrl}`);
1546
+ } else {
1547
+ url = import_cement5.URI.from(bagFnameOrUrl);
1548
+ }
1549
+ }
1550
+ logger.Debug().Url(url).Msg("from env");
1551
+ }
1552
+ let keyProviderFactory;
1553
+ switch (url.protocol) {
1554
+ case "file:":
1555
+ keyProviderFactory = async () => {
1556
+ const { KeyBagProviderFile: KeyBagProviderFile2 } = await Promise.resolve().then(() => (init_key_bag_file(), key_bag_file_exports));
1557
+ return new KeyBagProviderFile2(url, sthis);
1558
+ };
1559
+ break;
1560
+ case "indexdb:":
1561
+ keyProviderFactory = async () => {
1562
+ const { KeyBagProviderIndexDB: KeyBagProviderIndexDB2 } = await Promise.resolve().then(() => (init_key_bag_indexdb(), key_bag_indexdb_exports));
1563
+ return new KeyBagProviderIndexDB2(url, sthis);
1564
+ };
1565
+ break;
1566
+ default:
1567
+ throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
1568
+ }
1569
+ if (url.hasParam("masterkey")) {
1570
+ throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
1571
+ }
1572
+ return {
1573
+ url,
1574
+ crypto: kbo.crypto || (0, import_cement5.toCryptoRuntime)({}),
1575
+ sthis,
1576
+ logger,
1577
+ keyLength: kbo.keyLength || 16,
1578
+ getBag: keyProviderFactory,
1579
+ id: () => {
1580
+ return url.toString();
1581
+ }
1582
+ };
1583
+ }
1584
+ var _keyBags = new import_cement5.KeyedResolvOnce();
1585
+ async function getKeyBag(sthis, kbo = {}) {
1586
+ await sthis.start();
1587
+ const rt = defaultKeyBagOpts(sthis, kbo);
1588
+ return _keyBags.get(rt.id()).once(async () => new KeyBag(rt));
1589
+ }
1590
+
1591
+ // src/blockstore/commitor.ts
1592
+ var CBW = __toESM(require("@ipld/car/buffer-writer"), 1);
1593
+ var import_sha22 = require("multiformats/hashes/sha2");
1594
+ var dagCodec2 = __toESM(require("@ipld/dag-cbor"), 1);
1595
+ async function encodeCarFile(roots, t, codec3) {
1596
+ let size = 0;
1597
+ const headerSize = CBW.headerLength({ roots });
1598
+ size += headerSize;
1599
+ for (const { cid, bytes } of t.entries()) {
1600
+ size += CBW.blockLength({ cid, bytes });
1601
+ }
1602
+ const buffer = new Uint8Array(size);
1603
+ const writer = CBW.createWriter(buffer, { headerSize });
1604
+ for (const r of roots) {
1605
+ writer.addRoot(r);
1772
1606
  }
1773
- async enqueue(fn) {
1774
- return new Promise((resolve, reject) => {
1775
- const queueFn = async () => {
1776
- try {
1777
- resolve(await fn());
1778
- } catch (e) {
1779
- reject(e);
1780
- } finally {
1781
- this.processing = false;
1782
- this.processNext();
1783
- }
1784
- };
1785
- this.queue.push(queueFn);
1786
- if (!this.processing) {
1787
- this.processNext();
1788
- }
1789
- });
1607
+ for (const { cid, bytes } of t.entries()) {
1608
+ writer.write({ cid, bytes });
1790
1609
  }
1791
- processNext() {
1792
- if (this.queue.length > 0 && !this.processing) {
1793
- this.processing = true;
1794
- const queueFn = this.queue.shift();
1795
- if (queueFn) {
1796
- queueFn();
1797
- }
1610
+ writer.close();
1611
+ return await encode({ value: writer.bytes, hasher: import_sha22.sha256, codec: codec3 });
1612
+ }
1613
+ async function createCarFile(encoder, cid, t) {
1614
+ return encodeCarFile([cid], t, encoder);
1615
+ }
1616
+ async function commitFiles(fileStore, walStore, t, done) {
1617
+ const { files: roots } = makeFileCarHeader(done);
1618
+ const cids = [];
1619
+ const codec3 = (await fileStore.keyedCrypto()).codec();
1620
+ const cars = await prepareCarFilesFiles(codec3, roots, t);
1621
+ for (const car of cars) {
1622
+ const { cid, bytes } = car;
1623
+ await fileStore.save({ cid, bytes });
1624
+ await walStore.enqueueFile(
1625
+ cid
1626
+ /*, !!opts.public*/
1627
+ );
1628
+ cids.push(cid);
1629
+ }
1630
+ return cids;
1631
+ }
1632
+ function makeFileCarHeader(result) {
1633
+ const files = [];
1634
+ for (const [, meta] of Object.entries(result.files || {})) {
1635
+ if (meta && typeof meta === "object" && "cid" in meta && meta !== null) {
1636
+ files.push(meta.cid);
1798
1637
  }
1799
1638
  }
1800
- };
1639
+ return { ...result, files };
1640
+ }
1641
+ async function prepareCarFilesFiles(encoder, roots, t) {
1642
+ return [await encodeCarFile(roots, t, encoder)];
1643
+ }
1644
+ function makeCarHeader(meta, cars, compact = false) {
1645
+ const coreHeader = compact ? { cars: [], compact: cars } : { cars, compact: [] };
1646
+ return { ...coreHeader, meta };
1647
+ }
1648
+ async function encodeCarHeader(fp) {
1649
+ return await encode({
1650
+ value: { fp },
1651
+ hasher: import_sha22.sha256,
1652
+ codec: dagCodec2
1653
+ });
1654
+ }
1655
+ async function commit(params, t, done, opts = { noLoader: false, compact: false }) {
1656
+ const fp = makeCarHeader(done, params.carLog, !!opts.compact);
1657
+ const rootBlock = await encodeCarHeader(fp);
1658
+ const cars = await prepareCarFiles(params.encoder, params.threshold, rootBlock, t);
1659
+ const cids = [];
1660
+ for (const car of cars) {
1661
+ const { cid, bytes } = car;
1662
+ await params.carStore.save({ cid, bytes });
1663
+ cids.push(cid);
1664
+ }
1665
+ const newDbMeta = { cars: cids };
1666
+ await params.WALStore.enqueue(newDbMeta, opts);
1667
+ await params.metaStore.save(newDbMeta);
1668
+ return { cgrp: cids, header: fp };
1669
+ }
1670
+ async function prepareCarFiles(encoder, threshold, rootBlock, t) {
1671
+ const carFiles = [];
1672
+ threshold = threshold || 1e3 * 1e3;
1673
+ let clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
1674
+ clonedt.putSync(rootBlock.cid, rootBlock.bytes);
1675
+ let newsize = CBW.blockLength(toCIDBlock(rootBlock));
1676
+ let cidRootBlock = rootBlock;
1677
+ for (const { cid, bytes } of t.entries()) {
1678
+ newsize += CBW.blockLength(toCIDBlock({ cid, bytes }));
1679
+ if (newsize >= threshold) {
1680
+ carFiles.push(await createCarFile(encoder, cidRootBlock.cid, clonedt));
1681
+ clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
1682
+ clonedt.putSync(cid, bytes);
1683
+ cidRootBlock = { cid, bytes };
1684
+ newsize = CBW.blockLength(toCIDBlock({ cid, bytes }));
1685
+ } else {
1686
+ clonedt.putSync(cid, bytes);
1687
+ }
1688
+ }
1689
+ carFiles.push(await createCarFile(encoder, cidRootBlock.cid, clonedt));
1690
+ return carFiles;
1691
+ }
1801
1692
 
1802
1693
  // src/blockstore/loader.ts
1803
- var CBW2 = __toESM(require("@ipld/car/buffer-writer"), 1);
1804
- function carLogIncludesGroup2(list, cids) {
1694
+ var import_sha23 = require("multiformats/hashes/sha2");
1695
+ function carLogIncludesGroup(list, cids) {
1805
1696
  return list.some((arr) => {
1806
1697
  return arr.toString() === cids.toString();
1807
1698
  });
@@ -1814,17 +1705,8 @@ function uniqueCids(list, remove = /* @__PURE__ */ new Set()) {
1814
1705
  }
1815
1706
  return [...byString.values()];
1816
1707
  }
1817
- function toHexString(byteArray) {
1818
- return Array.from(byteArray).map((byte) => byte.toString(16).padStart(2, "0")).join("");
1819
- }
1820
- var Loadable = class {
1821
- constructor() {
1822
- this.name = "";
1823
- this.carLog = new Array();
1824
- }
1825
- };
1826
1708
  var Loader = class {
1827
- constructor(name, ebOpts) {
1709
+ constructor(name, ebOpts, sthis) {
1828
1710
  this.commitQueue = new CommitQueue();
1829
1711
  this.isCompacting = false;
1830
1712
  this.carReaders = /* @__PURE__ */ new Map();
@@ -1834,9 +1716,11 @@ var Loader = class {
1834
1716
  this.getBlockCache = /* @__PURE__ */ new Map();
1835
1717
  this.seenMeta = /* @__PURE__ */ new Set();
1836
1718
  this.writeLimit = (0, import_p_limit.default)(1);
1837
- this.onceReady = new import_cement4.ResolveOnce();
1719
+ this.onceReady = new import_cement6.ResolveOnce();
1838
1720
  this.name = name;
1721
+ this.sthis = sthis;
1839
1722
  this.ebOpts = defaultedBlockstoreRuntime(
1723
+ sthis,
1840
1724
  {
1841
1725
  ...ebOpts,
1842
1726
  name
@@ -1846,14 +1730,17 @@ var Loader = class {
1846
1730
  this.logger = this.ebOpts.logger;
1847
1731
  }
1848
1732
  // readonly id = uuidv4();
1733
+ async keyBag() {
1734
+ return getKeyBag(this.sthis, this.ebOpts.keyBag);
1735
+ }
1849
1736
  async carStore() {
1850
1737
  return this.ebOpts.storeRuntime.makeDataStore(this);
1851
1738
  }
1852
1739
  async fileStore() {
1853
1740
  return this.ebOpts.storeRuntime.makeDataStore(this);
1854
1741
  }
1855
- async remoteWAL() {
1856
- return this.ebOpts.storeRuntime.makeRemoteWAL(this);
1742
+ async WALStore() {
1743
+ return this.ebOpts.storeRuntime.makeWALStore(this);
1857
1744
  }
1858
1745
  async metaStore() {
1859
1746
  return this.ebOpts.storeRuntime.makeMetaStore(this);
@@ -1867,11 +1754,11 @@ var Loader = class {
1867
1754
  });
1868
1755
  }
1869
1756
  async close() {
1870
- const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.remoteWAL()]);
1757
+ const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
1871
1758
  await Promise.all(toClose.map((store) => store.close()));
1872
1759
  }
1873
1760
  async destroy() {
1874
- const toDestroy = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.remoteWAL()]);
1761
+ const toDestroy = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
1875
1762
  await Promise.all(toDestroy.map((store) => store.destroy()));
1876
1763
  }
1877
1764
  // async snapToCar(carCid: AnyLink | string) {
@@ -1885,6 +1772,7 @@ var Loader = class {
1885
1772
  // await this._applyCarHeader(carHeader, true)
1886
1773
  // }
1887
1774
  async handleDbMetasFromStore(metas) {
1775
+ this.logger.Debug().Any("metas", metas).Msg("handleDbMetasFromStore");
1888
1776
  for (const meta of metas) {
1889
1777
  await this.writeLimit(async () => {
1890
1778
  await this.mergeDbMetaIntoClock(meta);
@@ -1897,10 +1785,7 @@ var Loader = class {
1897
1785
  }
1898
1786
  if (this.seenMeta.has(meta.cars.toString())) return;
1899
1787
  this.seenMeta.add(meta.cars.toString());
1900
- if (meta.key) {
1901
- await this.setKey(meta.key);
1902
- }
1903
- if (carLogIncludesGroup2(this.carLog, meta.cars)) {
1788
+ if (carLogIncludesGroup(this.carLog, meta.cars)) {
1904
1789
  return;
1905
1790
  }
1906
1791
  const carHeader = await this.loadCarHeaderFromMeta(meta);
@@ -1909,45 +1794,59 @@ var Loader = class {
1909
1794
  this.carLog = [...uniqueCids([meta.cars, ...this.carLog, ...carHeader.cars], this.seenCompacted)];
1910
1795
  await this.ebOpts.applyMeta?.(carHeader.meta);
1911
1796
  }
1912
- async ingestKeyFromMeta(meta) {
1913
- const { key } = meta;
1914
- if (key) {
1915
- await this.setKey(key);
1916
- }
1917
- }
1797
+ // protected async ingestKeyFromMeta(meta: DbMeta): Promise<void> {
1798
+ // const { key } = meta;
1799
+ // if (key) {
1800
+ // await this.setKey(key);
1801
+ // }
1802
+ // }
1918
1803
  async loadCarHeaderFromMeta({ cars: cids }) {
1919
1804
  const reader = await this.loadCar(cids[0]);
1920
1805
  return await parseCarFile(reader, this.logger);
1921
1806
  }
1922
- async _getKey() {
1923
- if (this.key) return this.key;
1924
- if (!this.ebOpts.public) {
1925
- await this.setKey(toHexString(this.ebOpts.crypto.randomBytes(32)));
1926
- }
1927
- return this.key || void 0;
1928
- }
1929
- async commitFiles(t, done, opts = { noLoader: false, compact: false }) {
1930
- return this.commitQueue.enqueue(() => this._commitInternalFiles(t, done, opts));
1931
- }
1932
- // can these skip the queue? or have a file queue?
1933
- async _commitInternalFiles(t, done, opts = { noLoader: false, compact: false }) {
1807
+ // async _getKey(): Promise<string | undefined> {
1808
+ // if (this.key) return this.key;
1809
+ // // generate a random key
1810
+ // if (!this.ebOpts.public) {
1811
+ // await this.setKey(toHexString(this.ebOpts.crypto.randomBytes(32)));
1812
+ // }
1813
+ // return this.key || undefined;
1814
+ // }
1815
+ async commitFiles(t, done) {
1934
1816
  await this.ready();
1935
- const { files: roots } = this.makeFileCarHeader(done);
1936
- const cids = [];
1937
- const cars = await this.prepareCarFilesFiles(roots, t, !!opts.public);
1938
- for (const car of cars) {
1939
- const { cid, bytes } = car;
1940
- await (await this.fileStore()).save({ cid, bytes });
1941
- await (await this.remoteWAL()).enqueueFile(cid, !!opts.public);
1942
- cids.push(cid);
1943
- }
1944
- return cids;
1817
+ const fstore = await this.fileStore();
1818
+ const wstore = await this.WALStore();
1819
+ return this.commitQueue.enqueue(() => commitFiles(fstore, wstore, t, done));
1945
1820
  }
1946
- async loadFileCar(cid, isPublic = false) {
1947
- return await this.storesLoadCar(cid, await this.fileStore(), this.remoteFileStore, isPublic);
1821
+ async loadFileCar(cid) {
1822
+ return await this.storesLoadCar(cid, await this.fileStore(), this.remoteFileStore);
1948
1823
  }
1949
1824
  async commit(t, done, opts = { noLoader: false, compact: false }) {
1950
- return this.commitQueue.enqueue(() => this._commitInternal(t, done, opts));
1825
+ await this.ready();
1826
+ const fstore = await this.fileStore();
1827
+ const params = {
1828
+ encoder: (await fstore.keyedCrypto()).codec(),
1829
+ carLog: this.carLog,
1830
+ carStore: fstore,
1831
+ WALStore: await this.WALStore(),
1832
+ metaStore: await this.metaStore()
1833
+ };
1834
+ return this.commitQueue.enqueue(async () => {
1835
+ await this.cacheTransaction(t);
1836
+ const ret = await commit(params, t, done, opts);
1837
+ await this.updateCarLog(ret.cgrp, ret.header, !!opts.compact);
1838
+ return ret.cgrp;
1839
+ });
1840
+ }
1841
+ async updateCarLog(cids, fp, compact) {
1842
+ if (compact) {
1843
+ const previousCompactCid = fp.compact[fp.compact.length - 1];
1844
+ fp.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
1845
+ this.carLog = [...uniqueCids([...this.carLog, ...fp.cars, cids], this.seenCompacted)];
1846
+ await this.removeCidsForCompact(previousCompactCid[0]).catch((e) => e);
1847
+ } else {
1848
+ this.carLog.unshift(cids);
1849
+ }
1951
1850
  }
1952
1851
  async cacheTransaction(t) {
1953
1852
  for await (const block of t.entries()) {
@@ -1967,79 +1866,6 @@ var Loader = class {
1967
1866
  }
1968
1867
  }
1969
1868
  }
1970
- async _commitInternal(t, done, opts = { noLoader: false, compact: false }) {
1971
- await this.ready();
1972
- const fp = this.makeCarHeader(done, this.carLog, !!opts.compact);
1973
- const rootBlock = await encodeCarHeader(fp);
1974
- const cars = await this.prepareCarFiles(rootBlock, t, !!opts.public);
1975
- const cids = [];
1976
- for (const car of cars) {
1977
- const { cid, bytes } = car;
1978
- await (await this.carStore()).save({ cid, bytes });
1979
- cids.push(cid);
1980
- }
1981
- await this.cacheTransaction(t);
1982
- const newDbMeta = { cars: cids, key: this.key || null };
1983
- await (await this.remoteWAL()).enqueue(newDbMeta, opts);
1984
- await (await this.metaStore()).save(newDbMeta);
1985
- await this.updateCarLog(cids, fp, !!opts.compact);
1986
- return cids;
1987
- }
1988
- async prepareCarFilesFiles(roots, t, isPublic) {
1989
- const theKey = isPublic ? null : await this._getKey();
1990
- const car = theKey && this.ebOpts.crypto ? await encryptedEncodeCarFile(this.logger, this.ebOpts.crypto, theKey, roots[0], t) : await encodeCarFile(roots, t);
1991
- return [car];
1992
- }
1993
- async prepareCarFiles(rootBlock, t, isPublic) {
1994
- const theKey = isPublic ? void 0 : await this._getKey();
1995
- const carFiles = [];
1996
- const threshold = this.ebOpts.threshold || 1e3 * 1e3;
1997
- let clonedt = new CarTransaction(t.parent, { add: false });
1998
- clonedt.putSync(rootBlock.cid, rootBlock.bytes);
1999
- let newsize = CBW2.blockLength(toCIDBlock(rootBlock));
2000
- let cidRootBlock = rootBlock;
2001
- for (const { cid, bytes } of t.entries()) {
2002
- newsize += CBW2.blockLength(toCIDBlock({ cid, bytes }));
2003
- if (newsize >= threshold) {
2004
- carFiles.push(await this.createCarFile(theKey, cidRootBlock.cid, clonedt));
2005
- clonedt = new CarTransaction(t.parent, { add: false });
2006
- clonedt.putSync(cid, bytes);
2007
- cidRootBlock = { cid, bytes };
2008
- newsize = CBW2.blockLength(toCIDBlock({ cid, bytes }));
2009
- } else {
2010
- clonedt.putSync(cid, bytes);
2011
- }
2012
- }
2013
- carFiles.push(await this.createCarFile(theKey, cidRootBlock.cid, clonedt));
2014
- return carFiles;
2015
- }
2016
- async createCarFile(theKey, cid, t) {
2017
- try {
2018
- return theKey && this.ebOpts.crypto ? await encryptedEncodeCarFile(this.logger, this.ebOpts.crypto, theKey, cid, t) : await encodeCarFile([cid], t);
2019
- } catch (e) {
2020
- console.error("error creating car file", e);
2021
- throw e;
2022
- }
2023
- }
2024
- makeFileCarHeader(result) {
2025
- const files = [];
2026
- for (const [, meta] of Object.entries(result.files || {})) {
2027
- if (meta && typeof meta === "object" && "cid" in meta && meta !== null) {
2028
- files.push(meta.cid);
2029
- }
2030
- }
2031
- return { ...result, files };
2032
- }
2033
- async updateCarLog(cids, fp, compact) {
2034
- if (compact) {
2035
- const previousCompactCid = fp.compact[fp.compact.length - 1];
2036
- fp.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
2037
- this.carLog = [...uniqueCids([...this.carLog, ...fp.cars, cids], this.seenCompacted)];
2038
- await this.removeCidsForCompact(previousCompactCid[0]);
2039
- } else {
2040
- this.carLog.unshift(cids);
2041
- }
2042
- }
2043
1869
  async removeCidsForCompact(cid) {
2044
1870
  const carHeader = await this.loadCarHeaderFromMeta({
2045
1871
  cars: [cid]
@@ -2058,9 +1884,9 @@ var Loader = class {
2058
1884
  // await this.remoteWAL!.enqueue(dbMeta, { public: false })
2059
1885
  // }
2060
1886
  // }
2061
- async *entries(cache3 = true) {
1887
+ async *entries(cache2 = true) {
2062
1888
  await this.ready();
2063
- if (cache3) {
1889
+ if (cache2) {
2064
1890
  for (const [, block] of this.getBlockCache) {
2065
1891
  yield block;
2066
1892
  }
@@ -2142,10 +1968,6 @@ var Loader = class {
2142
1968
  }
2143
1969
  return got;
2144
1970
  }
2145
- makeCarHeader(meta, cars, compact = false) {
2146
- const coreHeader = compact ? { cars: [], compact: cars } : { cars, compact: [] };
2147
- return { ...coreHeader, meta };
2148
- }
2149
1971
  async loadCar(cid) {
2150
1972
  if (!this.carStore) {
2151
1973
  throw this.logger.Error().Msg("car store not initialized").AsError();
@@ -2153,72 +1975,52 @@ var Loader = class {
2153
1975
  const loaded = await this.storesLoadCar(cid, await this.carStore(), this.remoteCarStore);
2154
1976
  return loaded;
2155
1977
  }
2156
- //What if instead it returns an Array of CarHeader
2157
- async storesLoadCar(cid, local, remote, publicFiles) {
1978
+ async makeDecoderAndCarReader(cid, local, remote) {
2158
1979
  const cidsString = cid.toString();
2159
- if (!this.carReaders.has(cidsString)) {
2160
- this.carReaders.set(
2161
- cidsString,
2162
- (async () => {
2163
- let loadedCar = void 0;
2164
- try {
2165
- this.logger.Debug().Str("cid", cidsString).Msg("loading car");
2166
- loadedCar = await local.load(cid);
2167
- this.logger.Debug().Bool("loadedCar", loadedCar).Msg("loaded");
2168
- } catch (e) {
2169
- if (remote) {
2170
- const remoteCar = await remote.load(cid);
2171
- if (remoteCar) {
2172
- this.logger.Debug().Ref("cid", remoteCar.cid).Msg("saving remote car locally");
2173
- await local.save(remoteCar);
2174
- loadedCar = remoteCar;
2175
- }
2176
- } else {
2177
- this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
2178
- }
2179
- }
2180
- if (!loadedCar) {
2181
- throw this.logger.Error().Url(local.url).Str("cid", cidsString).Msg("missing car files").AsError();
2182
- }
2183
- const rawReader = await import_car.CarReader.fromBytes(loadedCar.bytes);
2184
- const readerP = publicFiles ? Promise.resolve(rawReader) : this.ensureDecryptedReader(rawReader);
2185
- const cachedReaderP = readerP.then(async (reader) => {
2186
- await this.cacheCarReader(cidsString, reader).catch(() => {
2187
- return;
2188
- });
2189
- return reader;
2190
- });
2191
- this.carReaders.set(cidsString, cachedReaderP);
2192
- return readerP;
2193
- })().catch((e) => {
2194
- this.carReaders.delete(cidsString);
2195
- throw e;
2196
- })
2197
- );
1980
+ let loadedCar = void 0;
1981
+ let activeStore = local;
1982
+ try {
1983
+ this.logger.Debug().Str("cid", cidsString).Msg("loading car");
1984
+ loadedCar = await local.load(cid);
1985
+ this.logger.Debug().Bool("loadedCar", loadedCar).Msg("loaded");
1986
+ } catch (e) {
1987
+ if (remote) {
1988
+ const remoteCar = await remote.load(cid);
1989
+ if (remoteCar) {
1990
+ this.logger.Debug().Ref("cid", remoteCar.cid).Msg("saving remote car locally");
1991
+ await local.save(remoteCar);
1992
+ loadedCar = remoteCar;
1993
+ activeStore = remote;
1994
+ }
1995
+ } else {
1996
+ this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
1997
+ }
2198
1998
  }
2199
- return this.carReaders.get(cidsString);
2200
- }
2201
- async ensureDecryptedReader(reader) {
2202
- const theKey = await this._getKey();
2203
- if (this.ebOpts.public || !(theKey && this.ebOpts.crypto)) {
2204
- return reader;
1999
+ if (!loadedCar) {
2000
+ throw this.logger.Error().Url(local.url()).Str("cid", cidsString).Msg("missing car files").AsError();
2205
2001
  }
2206
- const { blocks, root: root3 } = await decodeEncryptedCar(this.logger, this.ebOpts.crypto, theKey, reader);
2207
- return {
2208
- getRoots: () => [root3],
2209
- get: blocks.get.bind(blocks),
2210
- blocks: blocks.entries.bind(blocks)
2211
- };
2002
+ const bytes = await decode({ bytes: loadedCar.bytes, hasher: import_sha23.sha256, codec: (await activeStore.keyedCrypto()).codec() });
2003
+ const rawReader = await import_car.CarReader.fromBytes(bytes.value);
2004
+ const readerP = Promise.resolve(rawReader);
2005
+ const cachedReaderP = readerP.then(async (reader) => {
2006
+ await this.cacheCarReader(cidsString, reader).catch((e) => {
2007
+ this.logger.Error().Err(e).Str("cid", cidsString).Msg("error caching car reader");
2008
+ return;
2009
+ });
2010
+ return reader;
2011
+ });
2012
+ this.carReaders.set(cidsString, cachedReaderP);
2013
+ return readerP;
2212
2014
  }
2213
- async setKey(key) {
2214
- if (this.key && this.key !== key)
2215
- throw this.logger.Error().Str("this.key", this.key).Str("key", key).Msg("setting key").AsError();
2216
- this.key = key;
2217
- const encoder = new TextEncoder();
2218
- const data = encoder.encode(key);
2219
- const hashBuffer = await this.ebOpts.crypto.digestSHA256(data);
2220
- const hashArray = Array.from(new Uint8Array(hashBuffer));
2221
- this.keyId = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
2015
+ //What if instead it returns an Array of CarHeader
2016
+ async storesLoadCar(cid, local, remote) {
2017
+ const cidsString = cid.toString();
2018
+ let dacr = this.carReaders.get(cidsString);
2019
+ if (!dacr) {
2020
+ dacr = this.makeDecoderAndCarReader(cid, local, remote);
2021
+ this.carReaders.set(cidsString, dacr);
2022
+ }
2023
+ return dacr;
2222
2024
  }
2223
2025
  async getMoreReaders(cids) {
2224
2026
  const limit = (0, import_p_limit.default)(5);
@@ -2227,20 +2029,345 @@ var Loader = class {
2227
2029
  }
2228
2030
  };
2229
2031
 
2032
+ // src/runtime/keyed-crypto.ts
2033
+ var keyed_crypto_exports = {};
2034
+ __export(keyed_crypto_exports, {
2035
+ BlockIvKeyIdCodec: () => BlockIvKeyIdCodec,
2036
+ keyedCryptoFactory: () => keyedCryptoFactory
2037
+ });
2038
+ init_utils();
2039
+ var import_base583 = require("multiformats/bases/base58");
2040
+ var import_sha24 = require("multiformats/hashes/sha2");
2041
+ var CBOR = __toESM(require("cborg"), 1);
2042
+ var generateIV = {
2043
+ random: {
2044
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2045
+ calc: async (ko, crypto, data) => {
2046
+ return crypto.randomBytes(ko.ivLength);
2047
+ },
2048
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2049
+ verify: async (ko, crypto, iv, data) => {
2050
+ return true;
2051
+ }
2052
+ },
2053
+ hash: {
2054
+ calc: async (ko, crypto, data) => {
2055
+ const hash = await import_sha24.sha256.digest(data);
2056
+ const hashBytes = new Uint8Array(hash.bytes);
2057
+ const hashArray = new Uint8Array(ko.ivLength * 8);
2058
+ for (let i = 0; i < hashBytes.length; i++) {
2059
+ hashArray[i % ko.ivLength] ^= hashBytes[i];
2060
+ }
2061
+ return hashArray;
2062
+ },
2063
+ verify: async function(ko, crypto, iv, data) {
2064
+ return ko.url.getParam("ivverify") !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
2065
+ }
2066
+ }
2067
+ };
2068
+ function getGenerateIVFn(url, opts) {
2069
+ const ivhash = opts.ivCalc || url.getParam("ivhash") || "hash";
2070
+ return generateIV[ivhash] || generateIV["hash"];
2071
+ }
2072
+ var BlockIvKeyIdCodec = class {
2073
+ constructor(ko, iv, opts) {
2074
+ this.code = 3147065;
2075
+ this.name = "Fireproof@encrypted-block:aes-gcm";
2076
+ this.ko = ko;
2077
+ this.iv = iv;
2078
+ this.opts = opts || {};
2079
+ }
2080
+ async encode(data) {
2081
+ const calcIv = this.iv || await getGenerateIVFn(this.ko.url, this.opts).calc(this.ko, this.ko.crypto, data);
2082
+ const { iv } = this.ko.algo(calcIv);
2083
+ const fprt = await this.ko.fingerPrint();
2084
+ const keyId = import_base583.base58btc.decode(fprt);
2085
+ this.ko.logger.Debug().Str("fp", fprt).Msg("encode");
2086
+ return CBOR.encode({
2087
+ iv,
2088
+ keyId,
2089
+ data: await this.ko._encrypt({ iv, bytes: data })
2090
+ });
2091
+ }
2092
+ async decode(abytes) {
2093
+ let bytes;
2094
+ if (abytes instanceof Uint8Array) {
2095
+ bytes = abytes;
2096
+ } else {
2097
+ bytes = new Uint8Array(abytes);
2098
+ }
2099
+ const { iv, keyId, data } = CBOR.decode(bytes);
2100
+ const fprt = await this.ko.fingerPrint();
2101
+ this.ko.logger.Debug().Str("fp", import_base583.base58btc.encode(keyId)).Msg("decode");
2102
+ if (import_base583.base58btc.encode(keyId) !== fprt) {
2103
+ throw this.ko.logger.Error().Str("fp", fprt).Str("keyId", import_base583.base58btc.encode(keyId)).Msg("keyId mismatch").AsError();
2104
+ }
2105
+ const result = await this.ko._decrypt({ iv, bytes: data });
2106
+ if (!this.opts?.noIVVerify && !await getGenerateIVFn(this.ko.url, this.opts).verify(this.ko, this.ko.crypto, iv, result)) {
2107
+ throw this.ko.logger.Error().Msg("iv missmatch").AsError();
2108
+ }
2109
+ return result;
2110
+ }
2111
+ };
2112
+ var keyedCrypto = class {
2113
+ constructor(url, key, cyopt, sthis) {
2114
+ this.ivLength = 12;
2115
+ this.isEncrypting = true;
2116
+ this.logger = ensureLogger(sthis, "keyedCrypto");
2117
+ this.crypto = cyopt;
2118
+ this.key = key;
2119
+ this.url = url;
2120
+ }
2121
+ fingerPrint() {
2122
+ return Promise.resolve(this.key.fingerPrint);
2123
+ }
2124
+ codec(iv, opts) {
2125
+ return new BlockIvKeyIdCodec(this, iv, opts);
2126
+ }
2127
+ algo(iv) {
2128
+ return {
2129
+ name: "AES-GCM",
2130
+ iv: iv || this.crypto.randomBytes(this.ivLength),
2131
+ tagLength: 128
2132
+ };
2133
+ }
2134
+ async _decrypt(data) {
2135
+ this.logger.Debug().Len(data.bytes).Str("fp", this.key.fingerPrint).Msg("decrypting");
2136
+ return new Uint8Array(await this.crypto.decrypt(this.algo(data.iv), this.key.key, data.bytes));
2137
+ }
2138
+ async _encrypt(data) {
2139
+ this.logger.Debug().Len(data.bytes).Str("fp", this.key.fingerPrint).Msg("encrypting");
2140
+ const a = this.algo(data.iv);
2141
+ return new Uint8Array(await this.crypto.encrypt(a, this.key.key, data.bytes));
2142
+ }
2143
+ };
2144
+ var nullCodec = class {
2145
+ constructor() {
2146
+ this.code = 0;
2147
+ this.name = "Fireproof@unencrypted-block";
2148
+ }
2149
+ encode(data) {
2150
+ return data;
2151
+ }
2152
+ decode(data) {
2153
+ return data;
2154
+ }
2155
+ };
2156
+ var noCrypto = class {
2157
+ constructor(url, cyrt, sthis) {
2158
+ this.ivLength = 0;
2159
+ this.code = 0;
2160
+ this.name = "Fireproof@unencrypted-block";
2161
+ this.isEncrypting = false;
2162
+ this._fingerPrint = "noCrypto:" + Math.random();
2163
+ this.logger = ensureLogger(sthis, "noCrypto");
2164
+ this.crypto = cyrt;
2165
+ this.url = url;
2166
+ }
2167
+ fingerPrint() {
2168
+ return Promise.resolve(this._fingerPrint);
2169
+ }
2170
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2171
+ codec(iv) {
2172
+ return new nullCodec();
2173
+ }
2174
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2175
+ algo(iv) {
2176
+ return {
2177
+ name: "noCrypto",
2178
+ iv: new Uint8Array(),
2179
+ tagLength: 0
2180
+ };
2181
+ }
2182
+ _decrypt() {
2183
+ throw this.logger.Error().Msg("noCrypto.decrypt not implemented").AsError();
2184
+ }
2185
+ _encrypt() {
2186
+ throw this.logger.Error().Msg("noCrypto.decrypt not implemented").AsError();
2187
+ }
2188
+ };
2189
+ async function keyedCryptoFactory(url, kb, sthis) {
2190
+ const storekey = url.getParam("storekey");
2191
+ if (storekey && storekey !== "insecure") {
2192
+ let rkey = await kb.getNamedKey(storekey, true);
2193
+ if (rkey.isErr()) {
2194
+ try {
2195
+ rkey = await kb.toKeyWithFingerPrint(storekey);
2196
+ } catch (e) {
2197
+ throw sthis.logger.Error().Err(e).Str("keybag", kb.rt.id()).Str("name", storekey).Msg("getNamedKey failed").AsError();
2198
+ }
2199
+ }
2200
+ return new keyedCrypto(url, rkey.Ok(), kb.rt.crypto, sthis);
2201
+ }
2202
+ return new noCrypto(url, kb.rt.crypto, sthis);
2203
+ }
2204
+
2205
+ // src/blockstore/fragment-gateway.ts
2206
+ var import_base584 = require("multiformats/bases/base58");
2207
+ var import_cborg = require("cborg");
2208
+ function getFragSize(url) {
2209
+ const fragSize = url.getParam("fragSize");
2210
+ let ret = 0;
2211
+ if (fragSize) {
2212
+ ret = parseInt(fragSize);
2213
+ }
2214
+ if (isNaN(ret) || ret <= 0) {
2215
+ ret = 0;
2216
+ }
2217
+ return ret;
2218
+ }
2219
+ async function getFrags(url, innerGW, headerSize, logger) {
2220
+ const fragSize = getFragSize(url);
2221
+ if (!fragSize) {
2222
+ const res = await innerGW.get(url);
2223
+ if (res.isErr()) {
2224
+ return [res];
2225
+ }
2226
+ const data = res.unwrap();
2227
+ return [
2228
+ import_cement.Result.Ok({
2229
+ fid: new Uint8Array(0),
2230
+ ofs: 0,
2231
+ len: data.length,
2232
+ data
2233
+ })
2234
+ ];
2235
+ }
2236
+ const firstRaw = await innerGW.get(url.build().setParam("ofs", "0").URI());
2237
+ if (firstRaw.isErr()) {
2238
+ return [firstRaw];
2239
+ }
2240
+ const firstFragment = (0, import_cborg.decode)(firstRaw.unwrap());
2241
+ const blockSize = firstFragment.data.length;
2242
+ const ops = [Promise.resolve(import_cement.Result.Ok(firstFragment))];
2243
+ const fidStr = import_base584.base58btc.encode(firstFragment.fid);
2244
+ const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
2245
+ for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
2246
+ ops.push(
2247
+ (async (furl, ofs2) => {
2248
+ const raw2 = await innerGW.get(furl);
2249
+ if (raw2.isErr()) {
2250
+ return raw2;
2251
+ }
2252
+ const fragment = (0, import_cborg.decode)(raw2.unwrap());
2253
+ if (import_base584.base58btc.encode(fragment.fid) !== fidStr) {
2254
+ return import_cement.Result.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
2255
+ }
2256
+ if (fragment.ofs !== ofs2) {
2257
+ return import_cement.Result.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
2258
+ }
2259
+ return import_cement.Result.Ok(fragment);
2260
+ })(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
2261
+ );
2262
+ }
2263
+ return Promise.all(ops);
2264
+ }
2265
+ var FragmentGateway = class {
2266
+ constructor(sthis, innerGW) {
2267
+ this.fidLength = 4;
2268
+ this.headerSize = 32;
2269
+ this.sthis = ensureSuperLog(sthis, "FragmentGateway");
2270
+ this.logger = this.sthis.logger;
2271
+ this.innerGW = innerGW;
2272
+ }
2273
+ slicer(url, body) {
2274
+ const fragSize = getFragSize(url);
2275
+ if (!fragSize) {
2276
+ return [this.innerGW.put(url, body)];
2277
+ }
2278
+ const blocksize = fragSize - this.headerSize;
2279
+ if (blocksize <= 0) {
2280
+ throw this.logger.Error().Uint64("fragSize", fragSize).Uint64("headerSize", this.headerSize).Msg("Fragment size is too small").AsError();
2281
+ }
2282
+ const ops = [];
2283
+ const fid = this.sthis.nextId(this.fidLength);
2284
+ const fragUrl = url.build().setParam("fid", fid.str).setParam("len", body.length.toString()).setParam("headerSize", this.headerSize.toString());
2285
+ for (let ofs = 0; ofs < body.length; ofs += blocksize) {
2286
+ const block = (0, import_cborg.encode)({
2287
+ fid: fid.bin,
2288
+ ofs,
2289
+ len: body.length,
2290
+ data: body.slice(ofs, ofs + blocksize)
2291
+ });
2292
+ if (block.length > fragSize) {
2293
+ throw this.logger.Error().Uint64("block", block.length).Uint64("fragSize", fragSize).Msg("Block size to big").AsError();
2294
+ }
2295
+ ops.push(this.innerGW.put(fragUrl.setParam("ofs", ofs.toString()).URI(), block));
2296
+ }
2297
+ return ops;
2298
+ }
2299
+ buildUrl(baseUrl, key) {
2300
+ return this.innerGW.buildUrl(baseUrl, key);
2301
+ }
2302
+ async destroy(iurl) {
2303
+ return this.innerGW.destroy(iurl);
2304
+ }
2305
+ async start(url) {
2306
+ this.headerSize = (0, import_cborg.encode)({
2307
+ fid: this.sthis.nextId(this.fidLength).bin,
2308
+ ofs: 1024 * 1024,
2309
+ // 32bit
2310
+ len: 16 * 1024 * 1024,
2311
+ // 32bit
2312
+ data: new Uint8Array(1024)
2313
+ }).length - 1024;
2314
+ return this.innerGW.start(url);
2315
+ }
2316
+ async close(url) {
2317
+ return this.innerGW.close(url);
2318
+ }
2319
+ async put(url, body) {
2320
+ await Promise.all(this.slicer(url, body));
2321
+ return import_cement.Result.Ok(void 0);
2322
+ }
2323
+ async get(url) {
2324
+ const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
2325
+ let buffer = void 0;
2326
+ for (const rfrag of rfrags) {
2327
+ if (rfrag.isErr()) {
2328
+ return import_cement.Result.Err(rfrag.Err());
2329
+ }
2330
+ const frag = rfrag.Ok();
2331
+ buffer = buffer || new Uint8Array(frag.len);
2332
+ buffer.set(frag.data, frag.ofs);
2333
+ }
2334
+ return import_cement.Result.Ok(buffer || new Uint8Array(0));
2335
+ }
2336
+ async delete(url) {
2337
+ const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
2338
+ for (const rfrag of rfrags) {
2339
+ if (rfrag.isErr()) {
2340
+ return import_cement.Result.Err(rfrag.Err());
2341
+ }
2342
+ const frag = rfrag.Ok();
2343
+ const fidStr = import_base584.base58btc.encode(frag.fid);
2344
+ const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
2345
+ await this.innerGW.delete(fragUrl);
2346
+ }
2347
+ return import_cement.Result.Ok(void 0);
2348
+ }
2349
+ };
2350
+
2230
2351
  // src/blockstore/store.ts
2231
- function guardVersion(url2) {
2232
- if (!url2.searchParams.has("version")) {
2233
- return import_cement5.Result.Err(`missing version: ${url2.toString()}`);
2352
+ function guardVersion(url) {
2353
+ if (!url.hasParam("version")) {
2354
+ return import_cement7.Result.Err(`missing version: ${url.toString()}`);
2234
2355
  }
2235
- return import_cement5.Result.Ok(url2);
2356
+ return import_cement7.Result.Ok(url);
2236
2357
  }
2237
- var VersionedStore = class {
2238
- constructor(name, url2, logger) {
2358
+ var BaseStoreImpl = class {
2359
+ constructor(name, url, opts, sthis, logger) {
2239
2360
  this._onStarted = [];
2240
2361
  this._onClosed = [];
2241
2362
  this.name = name;
2242
- this.url = url2;
2243
- this.logger = logger;
2363
+ this._url = url;
2364
+ this.keybag = opts.keybag;
2365
+ this.sthis = sthis;
2366
+ this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
2367
+ this.gateway = new FragmentGateway(this.sthis, opts.gateway);
2368
+ }
2369
+ url() {
2370
+ return this._url;
2244
2371
  }
2245
2372
  onStarted(fn) {
2246
2373
  this._onStarted.push(fn);
@@ -2248,110 +2375,168 @@ var VersionedStore = class {
2248
2375
  onClosed(fn) {
2249
2376
  this._onClosed.push(fn);
2250
2377
  }
2378
+ async keyedCrypto() {
2379
+ return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
2380
+ }
2381
+ async start() {
2382
+ this.logger.Debug().Str("storeType", this.storeType).Msg("starting-gateway-pre");
2383
+ this._url = this._url.build().setParam("store", this.storeType).URI();
2384
+ const res = await this.gateway.start(this._url);
2385
+ if (res.isErr()) {
2386
+ this.logger.Error().Result("gw-start", res).Msg("started-gateway");
2387
+ return res;
2388
+ }
2389
+ this._url = res.Ok();
2390
+ const kb = await this.keybag();
2391
+ const skRes = await kb.ensureKeyFromUrl(this._url, () => {
2392
+ const idx = this._url.getParam("index");
2393
+ const storeKeyName = [this.name];
2394
+ if (idx) {
2395
+ storeKeyName.push(idx);
2396
+ }
2397
+ storeKeyName.push(this.storeType);
2398
+ return storeKeyName.join(":");
2399
+ });
2400
+ if (skRes.isErr()) {
2401
+ return skRes;
2402
+ }
2403
+ this._url = skRes.Ok();
2404
+ const version = guardVersion(this._url);
2405
+ if (version.isErr()) {
2406
+ this.logger.Error().Result("version", version).Msg("guardVersion");
2407
+ await this.close();
2408
+ return version;
2409
+ }
2410
+ if (this.ready) {
2411
+ const fn = this.ready.bind(this);
2412
+ const ready = await exception2Result(fn);
2413
+ if (ready.isErr()) {
2414
+ await this.close();
2415
+ return ready;
2416
+ }
2417
+ }
2418
+ this._onStarted.forEach((fn) => fn());
2419
+ this.logger.Debug().Msg("started");
2420
+ return version;
2421
+ }
2251
2422
  };
2252
- var textEncoder = new TextEncoder();
2253
- var textDecoder = new TextDecoder();
2254
- var MetaStore = class extends VersionedStore {
2255
- constructor(name, url2, logger, gateway) {
2256
- super(name, url2, ensureLogger(logger, "MetaStore", {}));
2257
- this.tag = "header-base";
2258
- this.gateway = gateway;
2259
- }
2260
- makeHeader({ cars, key }) {
2423
+ var MetaStoreImpl = class extends BaseStoreImpl {
2424
+ constructor(sthis, name, url, opts) {
2425
+ super(
2426
+ name,
2427
+ url,
2428
+ {
2429
+ ...opts
2430
+ },
2431
+ sthis,
2432
+ ensureLogger(sthis, "MetaStoreImpl")
2433
+ );
2434
+ this.storeType = "meta";
2435
+ this.subscribers = /* @__PURE__ */ new Map();
2436
+ }
2437
+ onLoad(branch, loadHandler) {
2438
+ const subscribers = this.subscribers.get(branch) || [];
2439
+ subscribers.push(loadHandler);
2440
+ this.subscribers.set(branch, subscribers);
2441
+ return () => {
2442
+ const subscribers2 = this.subscribers.get(branch) || [];
2443
+ const idx = subscribers2.indexOf(loadHandler);
2444
+ if (idx > -1) subscribers2.splice(idx, 1);
2445
+ };
2446
+ }
2447
+ makeHeader({ cars }) {
2261
2448
  const toEncode = { cars };
2262
- if (key) toEncode.key = key;
2263
2449
  return (0, import_dag_json.format)(toEncode);
2264
2450
  }
2265
2451
  parseHeader(headerData) {
2266
2452
  const got = (0, import_dag_json.parse)(headerData);
2267
2453
  return got;
2268
2454
  }
2269
- async start() {
2270
- this.logger.Debug().Msg("starting");
2271
- const res = await this.gateway.start(this.url);
2272
- if (res.isErr()) {
2273
- return res;
2455
+ async handleSubscribers(dbMetas, branch) {
2456
+ try {
2457
+ const subscribers = this.subscribers.get(branch) || [];
2458
+ await Promise.all(subscribers.map((subscriber) => subscriber(dbMetas)));
2459
+ } catch (e) {
2460
+ this.logger.Error().Err(e).Msg("handleSubscribers").AsError();
2274
2461
  }
2275
- this._onStarted.forEach((fn) => fn());
2276
- return guardVersion(this.url);
2462
+ }
2463
+ async handleByteHeads(byteHeads, branch = "main") {
2464
+ let dbMetas;
2465
+ try {
2466
+ dbMetas = this.dbMetasForByteHeads(byteHeads);
2467
+ } catch (e) {
2468
+ throw this.logger.Error().Err(e).Msg("parseHeader").AsError();
2469
+ }
2470
+ await this.handleSubscribers(dbMetas, branch);
2471
+ return dbMetas;
2472
+ }
2473
+ dbMetasForByteHeads(byteHeads) {
2474
+ return byteHeads.map((bytes) => {
2475
+ const txt = this.sthis.txt.decode(bytes);
2476
+ return this.parseHeader(txt);
2477
+ });
2277
2478
  }
2278
2479
  async load(branch) {
2279
- this.logger.Debug().Str("branch", branch || "").Msg("loading");
2280
- const url2 = await this.gateway.buildUrl(this.url, branch || "main");
2281
- if (url2.isErr()) {
2282
- throw this.logger.Error().Result("buidUrl", url2).Str("branch", branch || "").Url(this.url).Msg("got error from gateway.buildUrl").AsError();
2480
+ branch = branch || "main";
2481
+ this.logger.Debug().Str("branch", branch).Msg("loading");
2482
+ const url = await this.gateway.buildUrl(this.url(), branch);
2483
+ if (url.isErr()) {
2484
+ throw this.logger.Error().Result("buidUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
2283
2485
  }
2284
- const bytes = await this.gateway.get(url2.Ok());
2486
+ const bytes = await this.gateway.get(url.Ok());
2285
2487
  if (bytes.isErr()) {
2286
2488
  if (isNotFoundError(bytes)) {
2287
2489
  return void 0;
2288
2490
  }
2289
- throw this.logger.Error().Url(url2.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
2290
- }
2291
- try {
2292
- return [this.parseHeader(textDecoder.decode(bytes.Ok()))];
2293
- } catch (e) {
2294
- throw this.logger.Error().Err(e).Msg("parseHeader").AsError();
2491
+ throw this.logger.Error().Url(url.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
2295
2492
  }
2493
+ return this.handleByteHeads([bytes.Ok()], branch);
2296
2494
  }
2297
- async save(meta, branch = "main") {
2495
+ async save(meta, branch) {
2496
+ branch = branch || "main";
2298
2497
  this.logger.Debug().Str("branch", branch).Any("meta", meta).Msg("saving meta");
2299
2498
  const bytes = this.makeHeader(meta);
2300
- const url2 = await this.gateway.buildUrl(this.url, branch);
2301
- if (url2.isErr()) {
2302
- throw this.logger.Error().Err(url2.Err()).Str("branch", branch).Url(this.url).Msg("got error from gateway.buildUrl").AsError();
2499
+ const url = await this.gateway.buildUrl(this.url(), branch);
2500
+ if (url.isErr()) {
2501
+ throw this.logger.Error().Err(url.Err()).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
2303
2502
  }
2304
- const res = await this.gateway.put(url2.Ok(), textEncoder.encode(bytes));
2503
+ const res = await this.gateway.put(url.Ok(), this.sthis.txt.encode(bytes));
2305
2504
  if (res.isErr()) {
2306
2505
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
2307
2506
  }
2308
- return res.Ok();
2507
+ await this.handleSubscribers([meta], branch);
2508
+ return res;
2309
2509
  }
2310
2510
  async close() {
2311
- await this.gateway.close(this.url);
2511
+ await this.gateway.close(this.url());
2312
2512
  this._onClosed.forEach((fn) => fn());
2313
- return import_cement5.Result.Ok(void 0);
2513
+ return import_cement7.Result.Ok(void 0);
2314
2514
  }
2315
2515
  async destroy() {
2316
- return this.gateway.destroy(this.url);
2516
+ return this.gateway.destroy(this.url());
2317
2517
  }
2318
2518
  };
2319
- var DataStore = class extends VersionedStore {
2320
- constructor(name, url2, logger, gateway) {
2519
+ var DataStoreImpl = class extends BaseStoreImpl {
2520
+ // readonly tag: string = "car-base";
2521
+ constructor(sthis, name, url, opts) {
2321
2522
  super(
2322
2523
  name,
2323
- url2,
2324
- ensureLogger(logger, "DataStore", {
2325
- url: () => url2.toString()
2326
- })
2524
+ url,
2525
+ {
2526
+ ...opts
2527
+ },
2528
+ sthis,
2529
+ ensureLogger(sthis, "DataStoreImpl")
2327
2530
  );
2328
- this.tag = "car-base";
2329
- this.gateway = gateway;
2330
- }
2331
- async start() {
2332
- this.logger.Debug().Msg("starting-gateway");
2333
- const res = await this.gateway.start(this.url);
2334
- if (res.isErr()) {
2335
- this.logger.Error().Result("gw-start", res).Msg("started-gateway");
2336
- return res;
2337
- }
2338
- this._onStarted.forEach((fn) => fn());
2339
- const version = guardVersion(this.url);
2340
- if (version.isErr()) {
2341
- this.logger.Error().Result("version", version).Msg("guardVersion");
2342
- await this.close();
2343
- return version;
2344
- }
2345
- this.logger.Debug().Msg("started");
2346
- return version;
2531
+ this.storeType = "data";
2347
2532
  }
2348
2533
  async load(cid) {
2349
2534
  this.logger.Debug().Any("cid", cid).Msg("loading");
2350
- const url2 = await this.gateway.buildUrl(this.url, cid.toString());
2351
- if (url2.isErr()) {
2352
- throw this.logger.Error().Err(url2.Err()).Str("cid", cid.toString()).Msg("got error from gateway.buildUrl").AsError();
2535
+ const url = await this.gateway.buildUrl(this.url(), cid.toString());
2536
+ if (url.isErr()) {
2537
+ throw this.logger.Error().Err(url.Err()).Str("cid", cid.toString()).Msg("got error from gateway.buildUrl").AsError();
2353
2538
  }
2354
- const res = await this.gateway.get(url2.Ok());
2539
+ const res = await this.gateway.get(url.Ok());
2355
2540
  if (res.isErr()) {
2356
2541
  throw res.Err();
2357
2542
  }
@@ -2360,57 +2545,64 @@ var DataStore = class extends VersionedStore {
2360
2545
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
2361
2546
  async save(car, opts) {
2362
2547
  this.logger.Debug().Any("cid", car.cid.toString()).Msg("saving");
2363
- const url2 = await this.gateway.buildUrl(this.url, car.cid.toString());
2364
- if (url2.isErr()) {
2365
- throw this.logger.Error().Err(url2.Err()).Ref("cid", car.cid).Msg("got error from gateway.buildUrl").AsError();
2548
+ const url = await this.gateway.buildUrl(this.url(), car.cid.toString());
2549
+ if (url.isErr()) {
2550
+ throw this.logger.Error().Err(url.Err()).Ref("cid", car.cid).Msg("got error from gateway.buildUrl").AsError();
2366
2551
  }
2367
- const res = await this.gateway.put(url2.Ok(), car.bytes);
2552
+ const res = await this.gateway.put(url.Ok(), car.bytes);
2368
2553
  if (res.isErr()) {
2369
2554
  throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
2370
2555
  }
2371
2556
  return res.Ok();
2372
2557
  }
2373
2558
  async remove(cid) {
2374
- const url2 = await this.gateway.buildUrl(this.url, cid.toString());
2375
- if (url2.isErr()) {
2376
- return url2;
2559
+ const url = await this.gateway.buildUrl(this.url(), cid.toString());
2560
+ if (url.isErr()) {
2561
+ return url;
2377
2562
  }
2378
- return this.gateway.delete(url2.Ok());
2563
+ return this.gateway.delete(url.Ok());
2379
2564
  }
2380
2565
  async close() {
2381
- await this.gateway.close(this.url);
2566
+ await this.gateway.close(this.url());
2382
2567
  this._onClosed.forEach((fn) => fn());
2383
- return import_cement5.Result.Ok(void 0);
2568
+ return import_cement7.Result.Ok(void 0);
2384
2569
  }
2385
2570
  destroy() {
2386
- return this.gateway.destroy(this.url);
2571
+ return this.gateway.destroy(this.url());
2387
2572
  }
2388
2573
  };
2389
- var RemoteWAL = class extends VersionedStore {
2390
- constructor(loader, url2, logger, gateway) {
2391
- super(loader.name, url2, ensureLogger(logger, "RemoteWAL"));
2392
- this.tag = "rwal-base";
2393
- this._ready = new import_cement5.ResolveOnce();
2574
+ var WALStoreImpl = class extends BaseStoreImpl {
2575
+ constructor(loader, url, opts) {
2576
+ super(
2577
+ loader.name,
2578
+ url,
2579
+ {
2580
+ ...opts
2581
+ },
2582
+ loader.sthis,
2583
+ ensureLogger(loader.sthis, "WALStoreImpl")
2584
+ );
2585
+ this.storeType = "wal";
2586
+ this._ready = new import_cement7.ResolveOnce();
2394
2587
  this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
2395
2588
  this.processing = void 0;
2396
2589
  this.processQueue = new CommitQueue();
2397
- this.loader = loader;
2398
- this.gateway = gateway;
2399
- }
2400
- async ready() {
2401
- return this._ready.once(async () => {
2402
- const walState = await this.load().catch((e) => {
2403
- this.logger.Error().Any("error", e).Msg("error loading wal");
2404
- return void 0;
2590
+ this.ready = async () => {
2591
+ return this._ready.once(async () => {
2592
+ const walState = await this.load().catch((e) => {
2593
+ this.logger.Error().Any("error", e).Msg("error loading wal");
2594
+ return void 0;
2595
+ });
2596
+ if (!walState) {
2597
+ this.walState.operations = [];
2598
+ this.walState.fileOperations = [];
2599
+ } else {
2600
+ this.walState.operations = walState.operations || [];
2601
+ this.walState.fileOperations = walState.fileOperations || [];
2602
+ }
2405
2603
  });
2406
- if (!walState) {
2407
- this.walState.operations = [];
2408
- this.walState.fileOperations = [];
2409
- } else {
2410
- this.walState.operations = walState.operations || [];
2411
- this.walState.fileOperations = walState.fileOperations || [];
2412
- }
2413
- });
2604
+ };
2605
+ this.loader = loader;
2414
2606
  }
2415
2607
  async enqueue(dbMeta, opts) {
2416
2608
  await this.ready();
@@ -2420,19 +2612,23 @@ var RemoteWAL = class extends VersionedStore {
2420
2612
  this.walState.operations.push(dbMeta);
2421
2613
  }
2422
2614
  await this.save(this.walState);
2423
- void this._process();
2615
+ void this.process();
2424
2616
  }
2425
2617
  async enqueueFile(fileCid, publicFile = false) {
2426
2618
  await this.ready();
2427
2619
  this.walState.fileOperations.push({ cid: fileCid, public: publicFile });
2428
2620
  }
2429
- async _process() {
2621
+ async process() {
2430
2622
  await this.ready();
2431
2623
  if (!this.loader.remoteCarStore) return;
2432
2624
  await this.processQueue.enqueue(async () => {
2433
- await this._doProcess();
2625
+ try {
2626
+ await this._doProcess();
2627
+ } catch (e) {
2628
+ this.logger.Error().Any("error", e).Msg("error processing wal");
2629
+ }
2434
2630
  if (this.walState.operations.length || this.walState.fileOperations.length || this.walState.noLoaderOps.length) {
2435
- setTimeout(() => void this._process(), 0);
2631
+ setTimeout(() => void this.process(), 0);
2436
2632
  }
2437
2633
  });
2438
2634
  }
@@ -2450,7 +2646,7 @@ var RemoteWAL = class extends VersionedStore {
2450
2646
  for (const cid of dbMeta.cars) {
2451
2647
  const car = await (await this.loader.carStore()).load(cid);
2452
2648
  if (!car) {
2453
- if (carLogIncludesGroup2(this.loader.carLog, dbMeta.cars))
2649
+ if (carLogIncludesGroup(this.loader.carLog, dbMeta.cars))
2454
2650
  throw this.logger.Error().Ref("cid", cid).Msg("missing local car").AsError();
2455
2651
  } else {
2456
2652
  await throwFalsy(this.loader.remoteCarStore).save(car);
@@ -2465,7 +2661,7 @@ var RemoteWAL = class extends VersionedStore {
2465
2661
  for (const cid of dbMeta.cars) {
2466
2662
  const car = await (await this.loader.carStore()).load(cid).catch(() => null);
2467
2663
  if (!car) {
2468
- if (carLogIncludesGroup2(this.loader.carLog, dbMeta.cars))
2664
+ if (carLogIncludesGroup(this.loader.carLog, dbMeta.cars))
2469
2665
  throw this.logger.Error().Ref("cid", cid).Msg(`missing local car`).AsError();
2470
2666
  } else {
2471
2667
  await throwFalsy(this.loader.remoteCarStore).save(car);
@@ -2490,11 +2686,7 @@ var RemoteWAL = class extends VersionedStore {
2490
2686
  const res = await Promise.allSettled(uploads);
2491
2687
  const errors = res.filter((r) => r.status === "rejected");
2492
2688
  if (errors.length) {
2493
- throw this.logger.Error().Any(
2494
- "errors",
2495
- errors.map((e) => e.reason)
2496
- ).Msg("error uploading").AsError();
2497
- errors[0].reason;
2689
+ throw this.logger.Error().Any("errors", errors).Msg("error uploading").AsError();
2498
2690
  }
2499
2691
  if (operations.length) {
2500
2692
  const lastOp = operations[operations.length - 1];
@@ -2509,29 +2701,11 @@ var RemoteWAL = class extends VersionedStore {
2509
2701
  })();
2510
2702
  await rmlp;
2511
2703
  }
2512
- async start() {
2513
- const res = await this.gateway.start(this.url);
2514
- if (res.isErr()) {
2515
- return res;
2516
- }
2517
- const ver = guardVersion(this.url);
2518
- if (ver.isErr()) {
2519
- await this.close();
2520
- return ver;
2521
- }
2522
- const ready = await exception2Result(() => this.ready());
2523
- this._onStarted.forEach((fn) => fn());
2524
- if (ready.isErr()) {
2525
- await this.close();
2526
- return ready;
2527
- }
2528
- return ready;
2529
- }
2530
2704
  async load() {
2531
2705
  this.logger.Debug().Msg("loading");
2532
- const filepath = await this.gateway.buildUrl(this.url, "main");
2706
+ const filepath = await this.gateway.buildUrl(this.url(), "main");
2533
2707
  if (filepath.isErr()) {
2534
- throw this.logger.Error().Err(filepath.Err()).Str("url", this.url.toString()).Msg("error building url").AsError();
2708
+ throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2535
2709
  }
2536
2710
  const bytes = await this.gateway.get(filepath.Ok());
2537
2711
  if (bytes.isErr()) {
@@ -2541,15 +2715,15 @@ var RemoteWAL = class extends VersionedStore {
2541
2715
  throw this.logger.Error().Err(bytes.Err()).Msg("error get").AsError();
2542
2716
  }
2543
2717
  try {
2544
- return bytes && (0, import_dag_json.parse)(textDecoder.decode(bytes.Ok()));
2718
+ return bytes && (0, import_dag_json.parse)(this.sthis.txt.decode(bytes.Ok()));
2545
2719
  } catch (e) {
2546
2720
  throw this.logger.Error().Err(e).Msg("error parse").AsError();
2547
2721
  }
2548
2722
  }
2549
2723
  async save(state) {
2550
- const filepath = await this.gateway.buildUrl(this.url, "main");
2724
+ const filepath = await this.gateway.buildUrl(this.url(), "main");
2551
2725
  if (filepath.isErr()) {
2552
- throw this.logger.Error().Err(filepath.Err()).Str("url", this.url.toString()).Msg("error building url").AsError();
2726
+ throw this.logger.Error().Err(filepath.Err()).Url(this.url()).Msg("error building url").AsError();
2553
2727
  }
2554
2728
  let encoded;
2555
2729
  try {
@@ -2557,56 +2731,68 @@ var RemoteWAL = class extends VersionedStore {
2557
2731
  } catch (e) {
2558
2732
  throw this.logger.Error().Err(e).Any("state", state).Msg("error format").AsError();
2559
2733
  }
2560
- const res = await this.gateway.put(filepath.Ok(), textEncoder.encode(encoded));
2734
+ const res = await this.gateway.put(filepath.Ok(), this.sthis.txt.encode(encoded));
2561
2735
  if (res.isErr()) {
2562
2736
  throw this.logger.Error().Err(res.Err()).Str("filePath", filepath.Ok().toString()).Msg("error saving").AsError();
2563
2737
  }
2564
2738
  }
2565
2739
  async close() {
2566
- await this.gateway.close(this.url);
2740
+ await this.gateway.close(this.url());
2567
2741
  this._onClosed.forEach((fn) => fn());
2568
- return import_cement5.Result.Ok(void 0);
2742
+ return import_cement7.Result.Ok(void 0);
2569
2743
  }
2570
2744
  destroy() {
2571
- return this.gateway.destroy(this.url);
2745
+ return this.gateway.destroy(this.url());
2572
2746
  }
2573
2747
  };
2574
2748
 
2575
2749
  // src/blockstore/store-factory.ts
2576
2750
  init_utils();
2577
- function ensureIsIndex(url2, isIndex) {
2751
+ function ensureIsIndex(url, isIndex) {
2578
2752
  if (isIndex) {
2579
- url2.searchParams.set("index", isIndex);
2580
- return url2;
2581
- } else {
2582
- url2.searchParams.delete("index");
2583
- return url2;
2753
+ return url.build().setParam("index", isIndex).URI();
2584
2754
  }
2755
+ return url.build().delParam("index").URI();
2585
2756
  }
2586
- function toURL(pathOrUrl, isIndex) {
2587
- if (pathOrUrl instanceof URL) return ensureIsIndex(pathOrUrl, isIndex);
2588
- try {
2589
- const url2 = new URL(pathOrUrl);
2590
- return ensureIsIndex(url2, isIndex);
2591
- } catch (e) {
2592
- const url2 = new URL(`file://${pathOrUrl}`);
2593
- return ensureIsIndex(url2, isIndex);
2757
+ function ensureName(name, url) {
2758
+ if (!url.hasParam("name")) {
2759
+ return url.build().setParam("name", name).URI();
2594
2760
  }
2761
+ return url;
2595
2762
  }
2596
2763
  var storeFactory = /* @__PURE__ */ new Map();
2597
- function ensureName(name, url2) {
2598
- if (!url2.searchParams.has("name")) {
2599
- url2.searchParams.set("name", name);
2600
- }
2601
- }
2602
2764
  function buildURL(optURL, loader) {
2603
2765
  const storeOpts = loader.ebOpts.store;
2604
2766
  const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
2605
2767
  let obuUrl;
2606
2768
  if (obuItem && obuItem.overrideBaseURL) {
2607
- obuUrl = new URL(obuItem.overrideBaseURL);
2769
+ obuUrl = import_cement10.URI.from(obuItem.overrideBaseURL);
2608
2770
  }
2609
- return toURL(optURL || obuUrl || dataDir(loader.name, storeOpts.stores?.base), storeOpts.isIndex);
2771
+ const ret = ensureIsIndex(
2772
+ import_cement10.URI.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
2773
+ storeOpts.isIndex
2774
+ );
2775
+ return ret;
2776
+ }
2777
+ var onceGateway = new import_cement10.KeyedResolvOnce();
2778
+ async function getGatewayFromURL(url, sthis) {
2779
+ return onceGateway.get(url.toString()).once(async () => {
2780
+ const item = storeFactory.get(url.protocol);
2781
+ if (item) {
2782
+ const ret = {
2783
+ gateway: await item.gateway(sthis),
2784
+ test: await item.test(sthis)
2785
+ };
2786
+ const res = await ret.gateway.start(url);
2787
+ if (res.isErr()) {
2788
+ sthis.logger.Error().Result("start", res).Msg("start failed");
2789
+ return void 0;
2790
+ }
2791
+ return ret;
2792
+ }
2793
+ sthis.logger.Warn().Url(url).Msg("unsupported protocol");
2794
+ return void 0;
2795
+ });
2610
2796
  }
2611
2797
  function registerStoreProtocol(item) {
2612
2798
  let protocol = item.protocol;
@@ -2615,8 +2801,7 @@ function registerStoreProtocol(item) {
2615
2801
  }
2616
2802
  if (storeFactory.has(protocol)) {
2617
2803
  if (!item.overrideBaseURL && storeFactory.get(protocol) !== item) {
2618
- const logger = ensureLogger({}, "registerStoreProtocol", { protocol });
2619
- logger.Warn().Msg(`protocol ${protocol} already registered`);
2804
+ throw new Error(`we need a logger here`);
2620
2805
  return () => {
2621
2806
  };
2622
2807
  }
@@ -2631,106 +2816,83 @@ function registerStoreProtocol(item) {
2631
2816
  storeFactory.delete(protocol);
2632
2817
  };
2633
2818
  }
2634
- function runStoreFactory(url2, logger, run) {
2635
- const item = storeFactory.get(url2.protocol);
2636
- if (!item) {
2637
- throw logger.Error().Url(url2).Str("protocol", url2.protocol).Any("keys", Array(storeFactory.keys())).Msg(`unsupported protocol`).AsError();
2638
- }
2639
- logger.Debug().Str("protocol", url2.protocol).Msg("run");
2640
- return run(item);
2641
- }
2642
- var onceLoadDataGateway = new import_cement8.KeyedResolvOnce();
2643
- function loadDataGateway(url2, logger) {
2644
- return onceLoadDataGateway.get(url2.protocol).once(async () => {
2645
- return runStoreFactory(url2, logger, async (item) => item.data(logger));
2646
- });
2647
- }
2648
- var onceDataStoreFactory = new import_cement8.KeyedResolvOnce();
2649
2819
  async function dataStoreFactory(loader) {
2650
- const url2 = buildURL(loader.ebOpts.store.stores?.data, loader);
2651
- ensureName(loader.name, url2);
2652
- const logger = ensureLogger(loader.logger, "dataStoreFactory", { url: url2.toString() });
2653
- url2.searchParams.set("store", "data");
2654
- return onceDataStoreFactory.get(url2.toString()).once(async () => {
2655
- const gateway = await loadDataGateway(url2, logger);
2656
- const store = new DataStore(loader.name, url2, loader.logger, gateway);
2657
- const ret = await store.start();
2658
- if (ret.isErr()) {
2659
- throw logger.Error().Result("start", ret).Msg("start failed").AsError();
2660
- }
2661
- logger.Debug().Str("prepared", store.url.toString()).Msg("produced");
2662
- return store;
2663
- });
2664
- }
2665
- var onceLoadMetaGateway = new import_cement8.KeyedResolvOnce();
2666
- function loadMetaGateway(url2, logger) {
2667
- return onceLoadMetaGateway.get(url2.protocol).once(async () => {
2668
- return runStoreFactory(url2, logger, async (item) => item.meta(logger));
2820
+ const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
2821
+ const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
2822
+ const gateway = await getGatewayFromURL(url, sthis);
2823
+ if (!gateway) {
2824
+ throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2825
+ }
2826
+ const store = new DataStoreImpl(sthis, loader.name, url, {
2827
+ gateway: gateway.gateway,
2828
+ keybag: () => getKeyBag(loader.sthis, {
2829
+ ...loader.ebOpts.keyBag
2830
+ })
2669
2831
  });
2832
+ return store;
2670
2833
  }
2671
- var onceMetaStoreFactory = new import_cement8.KeyedResolvOnce();
2672
2834
  async function metaStoreFactory(loader) {
2673
- const url2 = buildURL(loader.ebOpts.store.stores?.meta, loader);
2674
- ensureName(loader.name, url2);
2675
- const logger = ensureLogger(loader.logger, "metaStoreFactory", { url: () => url2.toString() });
2676
- url2.searchParams.set("store", "meta");
2677
- return onceMetaStoreFactory.get(url2.toString()).once(async () => {
2678
- logger.Debug().Str("protocol", url2.protocol).Msg("pre-protocol switch");
2679
- const gateway = await loadMetaGateway(url2, logger);
2680
- const store = new MetaStore(loader.name, url2, loader.logger, gateway);
2681
- const ret = await store.start();
2682
- if (ret.isErr()) {
2683
- throw logger.Error().Result("start", ret).Msg("start failed").AsError();
2684
- }
2685
- return store;
2686
- });
2687
- }
2688
- var onceWalGateway = new import_cement8.KeyedResolvOnce();
2689
- function loadWalGateway(url2, logger) {
2690
- return onceWalGateway.get(url2.protocol).once(async () => {
2691
- return runStoreFactory(url2, logger, async (item) => item.wal(logger));
2835
+ const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
2836
+ const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
2837
+ sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
2838
+ const gateway = await getGatewayFromURL(url, sthis);
2839
+ if (!gateway) {
2840
+ throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2841
+ }
2842
+ const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
2843
+ gateway: gateway.gateway,
2844
+ keybag: () => getKeyBag(loader.sthis, {
2845
+ ...loader.ebOpts.keyBag
2846
+ })
2692
2847
  });
2848
+ return store;
2693
2849
  }
2694
- var onceRemoteWalFactory = new import_cement8.KeyedResolvOnce();
2695
2850
  async function remoteWalFactory(loader) {
2696
- const url2 = buildURL(loader.ebOpts.store.stores?.meta, loader);
2697
- ensureName(loader.name, url2);
2698
- const logger = ensureLogger(loader.logger, "remoteWalFactory", { url: url2.toString() });
2699
- url2.searchParams.set("store", "wal");
2700
- return onceRemoteWalFactory.get(url2.toString()).once(async () => {
2701
- const gateway = await loadWalGateway(url2, logger);
2702
- logger.Debug().Str("prepared", url2.toString()).Msg("produced");
2703
- const store = new RemoteWAL(loader, url2, loader.logger, gateway);
2704
- const ret = await store.start();
2705
- if (ret.isErr()) {
2706
- throw logger.Error().Result("start", ret).Msg("start failed").AsError();
2707
- }
2708
- return store;
2851
+ const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
2852
+ const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
2853
+ const gateway = await getGatewayFromURL(url, sthis);
2854
+ if (!gateway) {
2855
+ throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2856
+ }
2857
+ sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
2858
+ const store = new WALStoreImpl(loader, url, {
2859
+ gateway: gateway.gateway,
2860
+ keybag: () => getKeyBag(loader.sthis, {
2861
+ ...loader.ebOpts.keyBag
2862
+ })
2709
2863
  });
2864
+ return store;
2710
2865
  }
2711
- async function testStoreFactory(url2, ilogger) {
2712
- const logger = ensureLogger(
2713
- {
2714
- logger: ilogger
2715
- },
2716
- "testStoreFactory"
2717
- );
2718
- return runStoreFactory(url2, logger, async (item) => item.test(logger));
2866
+ async function testStoreFactory(url, sthis) {
2867
+ sthis = ensureSuperLog(sthis, "testStoreFactory");
2868
+ const gateway = await getGatewayFromURL(url, sthis);
2869
+ if (!gateway) {
2870
+ throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
2871
+ }
2872
+ return gateway.test;
2873
+ }
2874
+ async function ensureStart(store, logger) {
2875
+ const ret = await store.start();
2876
+ if (ret.isErr()) {
2877
+ throw logger.Error().Result("start", ret).Msg("start failed").AsError();
2878
+ }
2879
+ logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
2880
+ return store;
2719
2881
  }
2720
- function toStoreRuntime(opts, ilogger) {
2721
- const logger = ensureLogger(ilogger, "toStoreRuntime", {});
2882
+ function toStoreRuntime(opts, sthis) {
2883
+ const logger = ensureLogger(sthis, "toStoreRuntime", {});
2722
2884
  return {
2723
- makeMetaStore: (loader) => {
2885
+ makeMetaStore: async (loader) => {
2724
2886
  logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeMetaStore).Msg("makeMetaStore");
2725
- return (loader.ebOpts.store.makeMetaStore || metaStoreFactory)(loader);
2887
+ return ensureStart(await (loader.ebOpts.store.makeMetaStore || metaStoreFactory)(loader), logger);
2726
2888
  },
2727
- makeDataStore: (loader) => {
2889
+ makeDataStore: async (loader) => {
2728
2890
  logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeDataStore).Msg("makeDataStore");
2729
- return (loader.ebOpts.store.makeDataStore || dataStoreFactory)(loader);
2891
+ return ensureStart(await (loader.ebOpts.store.makeDataStore || dataStoreFactory)(loader), logger);
2730
2892
  },
2731
- makeRemoteWAL: (loader) => {
2732
- logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeRemoteWAL).Msg("makeRemoteWAL");
2733
- return (loader.ebOpts.store.makeRemoteWAL || remoteWalFactory)(loader);
2893
+ makeWALStore: async (loader) => {
2894
+ logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeWALStore).Msg("makeRemoteWAL");
2895
+ return ensureStart(await (loader.ebOpts.store.makeWALStore || remoteWalFactory)(loader), logger);
2734
2896
  },
2735
2897
  encodeFile: opts.encodeFile || encodeFile,
2736
2898
  decodeFile: opts.decodeFile || decodeFile
@@ -2738,48 +2900,202 @@ function toStoreRuntime(opts, ilogger) {
2738
2900
  }
2739
2901
  registerStoreProtocol({
2740
2902
  protocol: "file:",
2741
- data: async (logger) => {
2742
- const { FileDataGateway: FileDataGateway2 } = await Promise.resolve().then(() => (init_store_file(), store_file_exports));
2743
- return new FileDataGateway2(logger);
2744
- },
2745
- meta: async (logger) => {
2746
- const { FileMetaGateway: FileMetaGateway2 } = await Promise.resolve().then(() => (init_store_file(), store_file_exports));
2747
- return new FileMetaGateway2(logger);
2748
- },
2749
- wal: async (logger) => {
2750
- const { FileWALGateway: FileWALGateway2 } = await Promise.resolve().then(() => (init_store_file(), store_file_exports));
2751
- return new FileWALGateway2(logger);
2903
+ gateway: async (logger) => {
2904
+ const { FileGateway: FileGateway2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
2905
+ return new FileGateway2(logger);
2752
2906
  },
2753
2907
  test: async (logger) => {
2754
- const { FileTestStore: FileTestStore2 } = await Promise.resolve().then(() => (init_store_file(), store_file_exports));
2908
+ const { FileTestStore: FileTestStore2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
2755
2909
  return new FileTestStore2(logger);
2756
2910
  }
2757
2911
  });
2758
2912
  registerStoreProtocol({
2759
2913
  protocol: "indexdb:",
2760
- data: async (logger) => {
2761
- const { IndexDBDataGateway: IndexDBDataGateway2 } = await Promise.resolve().then(() => (init_store_indexdb(), store_indexdb_exports));
2762
- return new IndexDBDataGateway2(logger);
2763
- },
2764
- meta: async (logger) => {
2765
- const { IndexDBMetaGateway: IndexDBMetaGateway2 } = await Promise.resolve().then(() => (init_store_indexdb(), store_indexdb_exports));
2766
- return new IndexDBMetaGateway2(logger);
2767
- },
2768
- wal: async (logger) => {
2769
- const { IndexDBMetaGateway: IndexDBMetaGateway2 } = await Promise.resolve().then(() => (init_store_indexdb(), store_indexdb_exports));
2770
- return new IndexDBMetaGateway2(logger);
2914
+ gateway: async (logger) => {
2915
+ const { IndexDBGateway: IndexDBGateway2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
2916
+ return new IndexDBGateway2(logger);
2771
2917
  },
2772
2918
  test: async (logger) => {
2773
- const { IndexDBTestStore: IndexDBTestStore2 } = await Promise.resolve().then(() => (init_store_indexdb(), store_indexdb_exports));
2919
+ const { IndexDBTestStore: IndexDBTestStore2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
2774
2920
  return new IndexDBTestStore2(logger);
2775
2921
  }
2776
2922
  });
2777
2923
 
2778
- // src/blockstore/index.ts
2779
- init_gateway();
2924
+ // src/blockstore/connection-base.ts
2925
+ var import_clock = require("@web3-storage/pail/clock");
2926
+ var import_block6 = require("@web3-storage/pail/block");
2927
+
2928
+ // src/blockstore/task-manager.ts
2929
+ init_utils();
2930
+ var TaskManager = class {
2931
+ constructor(loader) {
2932
+ this.eventsWeHandled = /* @__PURE__ */ new Set();
2933
+ this.queue = [];
2934
+ this.isProcessing = false;
2935
+ this.loader = loader;
2936
+ this.logger = ensureLogger(loader.sthis, "TaskManager");
2937
+ }
2938
+ async handleEvent(eventBlock) {
2939
+ const cid = eventBlock.cid.toString();
2940
+ const parents = eventBlock.value.parents.map((cid2) => cid2.toString());
2941
+ for (const parent of parents) {
2942
+ this.eventsWeHandled.add(parent);
2943
+ }
2944
+ this.queue.push({ cid, eventBlock, retries: 0 });
2945
+ this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
2946
+ void this.processQueue();
2947
+ }
2948
+ async processQueue() {
2949
+ if (this.isProcessing) return;
2950
+ this.isProcessing = true;
2951
+ const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
2952
+ const first = filteredQueue[0];
2953
+ if (!first) {
2954
+ return;
2955
+ }
2956
+ try {
2957
+ this.loader?.remoteMetaStore?.handleByteHeads([first.eventBlock.value.data.dbMeta]);
2958
+ this.eventsWeHandled.add(first.cid);
2959
+ this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
2960
+ } catch (err) {
2961
+ if (first.retries++ > 3) {
2962
+ this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
2963
+ this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
2964
+ }
2965
+ await new Promise((resolve) => setTimeout(resolve, 50));
2966
+ throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
2967
+ } finally {
2968
+ this.isProcessing = false;
2969
+ if (this.queue.length > 0) {
2970
+ void this.processQueue();
2971
+ }
2972
+ }
2973
+ }
2974
+ };
2975
+
2976
+ // src/blockstore/store-remote.ts
2977
+ async function RemoteDataStore(sthis, name, url, opts) {
2978
+ const ds = new DataStoreImpl(sthis, name, url, opts);
2979
+ await ds.start();
2980
+ return ds;
2981
+ }
2982
+ async function RemoteMetaStore(sthis, name, url, opts) {
2983
+ const ms = new MetaStoreImpl(sthis, name, url, opts);
2984
+ await ms.start();
2985
+ return ms;
2986
+ }
2987
+
2988
+ // src/blockstore/connection-base.ts
2989
+ var ConnectionBase = class {
2990
+ constructor(url, logger) {
2991
+ // readonly ready: Promise<unknown>;
2992
+ // todo move to LRU blockstore https://github.com/web3-storage/w3clock/blob/main/src/worker/block.js
2993
+ this.eventBlocks = new import_block6.MemoryBlockstore();
2994
+ this.parents = [];
2995
+ this.loaded = Promise.resolve();
2996
+ this.logger = logger;
2997
+ this.url = url;
2998
+ }
2999
+ async refresh() {
3000
+ await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load("main");
3001
+ await (await throwFalsy(this.loader).WALStore()).process();
3002
+ }
3003
+ async connect_X({ loader }) {
3004
+ if (!loader) throw this.logger.Error().Msg("loader is required").AsError();
3005
+ await this.connectMeta_X({ loader });
3006
+ await this.connectStorage_X({ loader });
3007
+ }
3008
+ async connectMeta_X({ loader }) {
3009
+ if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
3010
+ this.loader = loader;
3011
+ this.taskManager = new TaskManager(loader);
3012
+ await this.onConnect();
3013
+ const metaUrl = this.url.build().defParam("store", "meta").URI();
3014
+ const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
3015
+ if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
3016
+ const name = metaUrl.toString();
3017
+ const remote = await RemoteMetaStore(loader.sthis, name, metaUrl, {
3018
+ gateway: gateway.gateway,
3019
+ keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag)
3020
+ });
3021
+ remote.onLoad("main", async (metas) => {
3022
+ if (metas) {
3023
+ this.logger.Debug().Any("metas", metas).Bool("loader", this.loader).Msg("connectMeta_X: handleDbMetasFromStore pre");
3024
+ await throwFalsy(this.loader).handleDbMetasFromStore(metas);
3025
+ this.logger.Debug().Any("metas", metas).Msg("connectMeta_X: handleDbMetasFromStore post");
3026
+ }
3027
+ });
3028
+ this.loader.remoteMetaStore = remote;
3029
+ this.loaded = this.loader.ready().then(async () => {
3030
+ remote.load("main").then(async () => {
3031
+ (await throwFalsy(this.loader).WALStore()).process();
3032
+ });
3033
+ });
3034
+ }
3035
+ async connectStorage_X({ loader }) {
3036
+ if (!loader) throw this.logger.Error().Msg("connectStorage_X: loader is required").AsError();
3037
+ this.loader = loader;
3038
+ const dataUrl = this.url.build().defParam("store", "data").URI();
3039
+ const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
3040
+ if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
3041
+ const name = dataUrl.toString();
3042
+ loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
3043
+ gateway: gateway.gateway,
3044
+ keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
3045
+ });
3046
+ loader.remoteFileStore = loader.remoteCarStore;
3047
+ }
3048
+ async createEventBlock(bytes) {
3049
+ const data = {
3050
+ dbMeta: bytes
3051
+ };
3052
+ const event = await import_clock.EventBlock.create(
3053
+ data,
3054
+ this.parents
3055
+ );
3056
+ await this.eventBlocks.put(event.cid, event.bytes);
3057
+ return event;
3058
+ }
3059
+ async decodeEventBlock(bytes) {
3060
+ const event = await (0, import_clock.decodeEventBlock)(bytes);
3061
+ return event;
3062
+ }
3063
+ // move this stuff to connect
3064
+ // async getDashboardURL(compact = true) {
3065
+ // const baseUrl = 'https://dashboard.fireproof.storage/'
3066
+ // if (!this.loader?.remoteCarStore) return new URL('/howto', baseUrl)
3067
+ // // if (compact) {
3068
+ // // await this.compact()
3069
+ // // }
3070
+ // const currents = await this.loader?.metaStore?.load()
3071
+ // if (!currents) throw new Error("Can't sync empty database: save data first")
3072
+ // if (currents.length > 1)
3073
+ // throw new Error("Can't sync database with split heads: make an update first")
3074
+ // const current = currents[0]
3075
+ // const params = {
3076
+ // car: current.car.toString()
3077
+ // }
3078
+ // if (current.key) {
3079
+ // // @ts-ignore
3080
+ // params.key = current.key.toString()
3081
+ // }
3082
+ // // @ts-ignore
3083
+ // if (this.name) {
3084
+ // // @ts-ignore
3085
+ // params.name = this.name
3086
+ // }
3087
+ // const url = new URL('/import#' + new URLSearchParams(params).toString(), baseUrl)
3088
+ // console.log('Import to dashboard: ' + url.toString())
3089
+ // return url
3090
+ // }
3091
+ // openDashboard() {
3092
+ // void this.getDashboardURL().then(url => {
3093
+ // if (url) window.open(url.toString(), '_blank')
3094
+ // })
3095
+ // }
3096
+ };
2780
3097
 
2781
3098
  // src/crdt-helpers.ts
2782
- init_types();
2783
3099
  function time(tag) {
2784
3100
  }
2785
3101
  function timeEnd(tag) {
@@ -2827,7 +3143,7 @@ async function writeDocContent(store, blocks, update, logger) {
2827
3143
  await processFiles(store, blocks, update.value, logger);
2828
3144
  value = { doc: update.value };
2829
3145
  }
2830
- const block = await (0, import_block6.encode)({ value, hasher: import_sha23.sha256, codec: codec2 });
3146
+ const block = await encode({ value, hasher: import_sha25.sha256, codec });
2831
3147
  blocks.putSync(block.cid, block.bytes);
2832
3148
  return block.cid;
2833
3149
  }
@@ -2836,10 +3152,16 @@ async function processFiles(store, blocks, doc, logger) {
2836
3152
  await processFileset(logger, store, blocks, doc._files);
2837
3153
  }
2838
3154
  if (doc._publicFiles) {
2839
- await processFileset(logger, store, blocks, doc._publicFiles, true);
3155
+ await processFileset(
3156
+ logger,
3157
+ store,
3158
+ blocks,
3159
+ doc._publicFiles
3160
+ /*, true*/
3161
+ );
2840
3162
  }
2841
3163
  }
2842
- async function processFileset(logger, store, blocks, files, publicFiles = false) {
3164
+ async function processFileset(logger, store, blocks, files) {
2843
3165
  const dbBlockstore = blocks.parent;
2844
3166
  if (!dbBlockstore.loader) throw logger.Error().Msg("Missing loader, database name is required").AsError();
2845
3167
  const t = new CarTransaction(dbBlockstore);
@@ -2861,9 +3183,10 @@ async function processFileset(logger, store, blocks, files, publicFiles = false)
2861
3183
  }
2862
3184
  }
2863
3185
  if (didPut.length) {
2864
- const car = await dbBlockstore.loader.commitFiles(t, { files }, {
2865
- public: publicFiles
2866
- });
3186
+ const car = await dbBlockstore.loader.commitFiles(
3187
+ t,
3188
+ { files }
3189
+ );
2867
3190
  if (car) {
2868
3191
  for (const name of didPut) {
2869
3192
  files[name] = { car, ...files[name] };
@@ -2897,7 +3220,7 @@ function readFileset(blocks, files, isPublic = false) {
2897
3220
  fileMeta.file = async () => await blocks.ebOpts.storeRuntime.decodeFile(
2898
3221
  {
2899
3222
  get: async (cid) => {
2900
- return await blocks.getFile(throwFalsy(fileMeta.car), cid, isPublic);
3223
+ return await blocks.getFile(throwFalsy(fileMeta.car), cid);
2901
3224
  }
2902
3225
  },
2903
3226
  fileMeta.cid,
@@ -2911,7 +3234,7 @@ function readFileset(blocks, files, isPublic = false) {
2911
3234
  async function getValueFromLink(blocks, link, logger) {
2912
3235
  const block = await blocks.get(link);
2913
3236
  if (!block) throw logger.Error().Str("link", link.toString()).Msg(`Missing linked block`).AsError();
2914
- const { value } = await (0, import_block6.decode)({ bytes: block.bytes, hasher: import_sha23.sha256, codec: codec2 });
3237
+ const { value } = await decode({ bytes: block.bytes, hasher: import_sha25.sha256, codec });
2915
3238
  const cvalue = {
2916
3239
  ...value,
2917
3240
  cid: link
@@ -2920,17 +3243,21 @@ async function getValueFromLink(blocks, link, logger) {
2920
3243
  return cvalue;
2921
3244
  }
2922
3245
  var DirtyEventFetcher = class extends import_clock2.EventFetcher {
3246
+ constructor(logger, blocks) {
3247
+ super(blocks);
3248
+ this.logger = logger;
3249
+ }
2923
3250
  async get(link) {
2924
3251
  try {
2925
3252
  return super.get(link);
2926
3253
  } catch (e) {
2927
- console.error("missing event", link.toString(), e);
3254
+ this.logger.Error().Ref("link", link.toString()).Err(e).Msg("Missing event");
2928
3255
  return { value: void 0 };
2929
3256
  }
2930
3257
  }
2931
3258
  };
2932
3259
  async function clockChangesSince(blocks, head, since, opts, logger) {
2933
- const eventsFetcher = opts.dirty ? new DirtyEventFetcher(blocks) : new import_clock2.EventFetcher(blocks);
3260
+ const eventsFetcher = opts.dirty ? new DirtyEventFetcher(logger, blocks) : new import_clock2.EventFetcher(blocks);
2934
3261
  const keys = /* @__PURE__ */ new Set();
2935
3262
  const updates = await gatherUpdates(
2936
3263
  blocks,
@@ -3028,38 +3355,34 @@ async function doCompact(blockLog, head, logger) {
3028
3355
  async function getBlock(blocks, cidString) {
3029
3356
  const block = await blocks.get((0, import_link.parse)(cidString));
3030
3357
  if (!block) throw new Error(`Missing block ${cidString}`);
3031
- const { cid, value } = await (0, import_block6.decode)({ bytes: block.bytes, codec: codec2, hasher: import_sha23.sha256 });
3032
- return new import_block6.Block({ cid, value, bytes: block.bytes });
3358
+ const { cid, value } = await decode({ bytes: block.bytes, codec, hasher: import_sha25.sha256 });
3359
+ return new Block({ cid, value, bytes: block.bytes });
3033
3360
  }
3034
3361
 
3035
- // src/indexer.ts
3036
- init_types();
3037
-
3038
3362
  // src/indexer-helpers.ts
3039
- var import_block7 = require("multiformats/block");
3040
- var import_sha24 = require("multiformats/hashes/sha2");
3041
- var codec3 = __toESM(require("@ipld/dag-cbor"), 1);
3363
+ var import_sha26 = require("multiformats/hashes/sha2");
3364
+ var codec2 = __toESM(require("@ipld/dag-cbor"), 1);
3042
3365
  var import_charwise = __toESM(require("charwise"), 1);
3043
3366
  var DbIndex = __toESM(require("prolly-trees/db-index"), 1);
3044
- var import_utils12 = require("prolly-trees/utils");
3045
- var import_cache2 = require("prolly-trees/cache");
3367
+ var import_utils15 = require("prolly-trees/utils");
3368
+ var import_cache = require("prolly-trees/cache");
3046
3369
  var IndexTree = class {
3047
3370
  };
3048
3371
  function refCompare(aRef, bRef) {
3049
3372
  if (Number.isNaN(aRef)) return -1;
3050
3373
  if (Number.isNaN(bRef)) throw new Error("ref may not be Infinity or NaN");
3051
3374
  if (aRef === Infinity) return 1;
3052
- return (0, import_utils12.simpleCompare)(aRef, bRef);
3375
+ return (0, import_utils15.simpleCompare)(aRef, bRef);
3053
3376
  }
3054
3377
  function compare(a, b) {
3055
3378
  const [aKey, aRef] = a;
3056
3379
  const [bKey, bRef] = b;
3057
- const comp = (0, import_utils12.simpleCompare)(aKey, bKey);
3380
+ const comp = (0, import_utils15.simpleCompare)(aKey, bKey);
3058
3381
  if (comp !== 0) return comp;
3059
3382
  return refCompare(aRef, bRef);
3060
3383
  }
3061
- var byKeyOpts = { cache: import_cache2.nocache, chunker: (0, import_utils12.bf)(30), codec: codec3, hasher: import_sha24.sha256, compare };
3062
- var byIdOpts = { cache: import_cache2.nocache, chunker: (0, import_utils12.bf)(30), codec: codec3, hasher: import_sha24.sha256, compare: import_utils12.simpleCompare };
3384
+ var byKeyOpts = { cache: import_cache.nocache, chunker: (0, import_utils15.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare };
3385
+ var byIdOpts = { cache: import_cache.nocache, chunker: (0, import_utils15.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare: import_utils15.simpleCompare };
3063
3386
  function indexEntriesForChanges(changes, mapFn) {
3064
3387
  const indexEntries = [];
3065
3388
  changes.forEach(({ id: key, value, del }) => {
@@ -3087,7 +3410,7 @@ function makeProllyGetBlock(blocks) {
3087
3410
  const block = await blocks.get(address);
3088
3411
  if (!block) throw new Error(`Missing block ${address.toString()}`);
3089
3412
  const { cid, bytes } = block;
3090
- return (0, import_block7.create)({ cid, bytes, hasher: import_sha24.sha256, codec: codec3 });
3413
+ return create({ cid, bytes, hasher: import_sha26.sha256, codec: codec2 });
3091
3414
  };
3092
3415
  }
3093
3416
  async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
@@ -3159,25 +3482,25 @@ function encodeKey(key) {
3159
3482
 
3160
3483
  // src/indexer.ts
3161
3484
  init_utils();
3162
- function index({ _crdt }, name, mapFn, meta) {
3485
+ function index(sthis, { _crdt }, name, mapFn, meta) {
3163
3486
  if (mapFn && meta) throw _crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
3164
3487
  if (mapFn && mapFn.constructor.name !== "Function") throw _crdt.logger.Error().Msg("mapFn must be a function").AsError();
3165
3488
  if (_crdt.indexers.has(name)) {
3166
3489
  const idx = _crdt.indexers.get(name);
3167
3490
  idx.applyMapFn(name, mapFn, meta);
3168
3491
  } else {
3169
- const idx = new Index(_crdt, name, mapFn, meta);
3492
+ const idx = new Index(sthis, _crdt, name, mapFn, meta);
3170
3493
  _crdt.indexers.set(name, idx);
3171
3494
  }
3172
3495
  return _crdt.indexers.get(name);
3173
3496
  }
3174
3497
  var Index = class {
3175
- constructor(crdt, name, mapFn, meta) {
3498
+ constructor(sthis, crdt, name, mapFn, meta) {
3176
3499
  this.mapFnString = "";
3177
3500
  this.byKey = new IndexTree();
3178
3501
  this.byId = new IndexTree();
3179
3502
  this.includeDocsDefault = false;
3180
- this.logger = ensureLogger(crdt.logger, "Index");
3503
+ this.logger = ensureLogger(sthis, "Index");
3181
3504
  this.blockstore = crdt.indexBlockstore;
3182
3505
  this.crdt = crdt;
3183
3506
  this.applyMapFn(name, mapFn, meta);
@@ -3232,7 +3555,7 @@ var Index = class {
3232
3555
  }
3233
3556
  if (this.mapFnString) {
3234
3557
  if (this.mapFnString !== mapFn.toString()) {
3235
- throw this.logger.Error().Msg("cannot apply different mapFn app").AsError();
3558
+ throw this.logger.Error().Str("mapFnString", this.mapFnString).Str("mapFn", mapFn.toString()).Msg("cannot apply different mapFn app").AsError();
3236
3559
  }
3237
3560
  } else {
3238
3561
  this.mapFnString = mapFn.toString();
@@ -3367,8 +3690,7 @@ var Index = class {
3367
3690
  // src/crdt-clock.ts
3368
3691
  var import_clock3 = require("@web3-storage/pail/clock");
3369
3692
  var import_crdt2 = require("@web3-storage/pail/crdt");
3370
- var import_cement9 = require("@adviser/cement");
3371
- init_types();
3693
+ var import_cement11 = require("@adviser/cement");
3372
3694
 
3373
3695
  // src/apply-head-queue.ts
3374
3696
  function applyHeadQueue(worker, logger) {
@@ -3426,9 +3748,9 @@ var CRDTClock = class {
3426
3748
  this.zoomers = /* @__PURE__ */ new Set();
3427
3749
  this.watchers = /* @__PURE__ */ new Set();
3428
3750
  this.emptyWatchers = /* @__PURE__ */ new Set();
3429
- this._ready = new import_cement9.ResolveOnce();
3751
+ this._ready = new import_cement11.ResolveOnce();
3430
3752
  this.blockstore = blockstore;
3431
- this.logger = ensureLogger(blockstore.logger, "CRDTClock");
3753
+ this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
3432
3754
  this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
3433
3755
  }
3434
3756
  async ready() {
@@ -3501,7 +3823,7 @@ var CRDTClock = class {
3501
3823
  }
3502
3824
  return { head: advancedHead };
3503
3825
  },
3504
- { noLoader }
3826
+ { noLoader, add: false }
3505
3827
  );
3506
3828
  this.setHead(meta.head);
3507
3829
  }
@@ -3536,13 +3858,14 @@ async function advanceBlocks(logger, newHead, tblocks, head) {
3536
3858
  // src/crdt.ts
3537
3859
  init_utils();
3538
3860
  var CRDT = class {
3539
- constructor(name, opts = {}) {
3540
- this.onceReady = new import_cement10.ResolveOnce();
3861
+ constructor(sthis, name, opts = {}) {
3541
3862
  this.indexers = /* @__PURE__ */ new Map();
3863
+ this.onceReady = new import_cement12.ResolveOnce();
3864
+ this.sthis = sthis;
3542
3865
  this.name = name;
3543
- this.logger = ensureLogger(opts, "CRDT");
3866
+ this.logger = ensureLogger(sthis, "CRDT");
3544
3867
  this.opts = opts;
3545
- this.blockstore = blockstoreFactory({
3868
+ this.blockstore = blockstoreFactory(sthis, {
3546
3869
  name,
3547
3870
  applyMeta: async (meta) => {
3548
3871
  const crdtMeta = meta;
@@ -3554,22 +3877,20 @@ var CRDT = class {
3554
3877
  return { head: this.clock.head };
3555
3878
  },
3556
3879
  autoCompact: this.opts.autoCompact || 100,
3557
- crypto: this.opts.crypto,
3558
3880
  store: { ...this.opts.store, isIndex: void 0 },
3559
3881
  public: this.opts.public,
3560
3882
  meta: this.opts.meta,
3561
3883
  threshold: this.opts.threshold
3562
3884
  });
3563
- this.indexBlockstore = blockstoreFactory({
3885
+ this.indexBlockstore = blockstoreFactory(sthis, {
3564
3886
  name,
3565
3887
  applyMeta: async (meta) => {
3566
3888
  const idxCarMeta = meta;
3567
3889
  if (!idxCarMeta.indexes) throw this.logger.Error().Msg("missing indexes").AsError();
3568
3890
  for (const [name2, idx] of Object.entries(idxCarMeta.indexes)) {
3569
- index({ _crdt: this }, name2, void 0, idx);
3891
+ index(this.sthis, { _crdt: this }, name2, void 0, idx);
3570
3892
  }
3571
3893
  },
3572
- crypto: this.opts.crypto,
3573
3894
  store: { ...this.opts.store, isIndex: this.opts.store?.isIndex || "idx" },
3574
3895
  public: this.opts.public
3575
3896
  });
@@ -3580,17 +3901,6 @@ var CRDT = class {
3580
3901
  }
3581
3902
  });
3582
3903
  }
3583
- async ready() {
3584
- return this.onceReady.once(async () => {
3585
- await Promise.all([this.blockstore.ready(), this.indexBlockstore.ready(), this.clock.ready()]);
3586
- });
3587
- }
3588
- async close() {
3589
- await Promise.all([this.blockstore.close(), this.indexBlockstore.close(), this.clock.close()]);
3590
- }
3591
- async destroy() {
3592
- await Promise.all([this.blockstore.destroy(), this.indexBlockstore.destroy()]);
3593
- }
3594
3904
  async bulk(updates) {
3595
3905
  await this.ready();
3596
3906
  const prevHead = [...this.clock.head];
@@ -3611,6 +3921,21 @@ var CRDT = class {
3611
3921
  await this.clock.applyHead(done.meta.head, prevHead, updates);
3612
3922
  return done.meta;
3613
3923
  }
3924
+ async ready() {
3925
+ return this.onceReady.once(async () => {
3926
+ try {
3927
+ await Promise.all([this.blockstore.ready(), this.indexBlockstore.ready(), this.clock.ready()]);
3928
+ } catch (e) {
3929
+ throw this.logger.Error().Err(e).Msg("CRDT not ready").AsError();
3930
+ }
3931
+ });
3932
+ }
3933
+ async close() {
3934
+ await Promise.all([this.blockstore.close(), this.indexBlockstore.close(), this.clock.close()]);
3935
+ }
3936
+ async destroy() {
3937
+ await Promise.all([this.blockstore.destroy(), this.indexBlockstore.destroy()]);
3938
+ }
3614
3939
  // if (snap) await this.clock.applyHead(crdtMeta.head, this.clock.head)
3615
3940
  async allDocs() {
3616
3941
  await this.ready();
@@ -3649,20 +3974,19 @@ var CRDT = class {
3649
3974
  };
3650
3975
 
3651
3976
  // src/database.ts
3652
- init_sys_container();
3653
3977
  init_utils();
3654
- init_gateway();
3655
3978
  var Database = class {
3656
3979
  constructor(name, opts) {
3657
3980
  this.opts = {};
3658
3981
  this._listening = false;
3659
3982
  this._listeners = /* @__PURE__ */ new Set();
3660
3983
  this._noupdate_listeners = /* @__PURE__ */ new Set();
3661
- this._ready = new import_cement11.ResolveOnce();
3984
+ this._ready = new import_cement13.ResolveOnce();
3662
3985
  this.name = name;
3663
3986
  this.opts = opts || this.opts;
3664
- this.logger = ensureLogger(this.opts, "Database");
3665
- this._crdt = new CRDT(name, this.opts);
3987
+ this.sthis = ensureSuperThis(this.opts);
3988
+ this.logger = ensureLogger(this.sthis, "Database");
3989
+ this._crdt = new CRDT(this.sthis, name, this.opts);
3666
3990
  this.blockstore = this._crdt.blockstore;
3667
3991
  this._writeQueue = writeQueue(async (updates) => {
3668
3992
  return await this._crdt.bulk(updates);
@@ -3686,7 +4010,7 @@ var Database = class {
3686
4010
  }
3687
4011
  async ready() {
3688
4012
  return this._ready.once(async () => {
3689
- await SysContainer.start();
4013
+ await this.sthis.start();
3690
4014
  await this._crdt.ready();
3691
4015
  await this.blockstore.ready();
3692
4016
  });
@@ -3706,7 +4030,7 @@ var Database = class {
3706
4030
  await this.ready();
3707
4031
  this.logger.Debug().Str("id", doc._id).Msg("put");
3708
4032
  const { _id, ...value } = doc;
3709
- const docId = _id || (0, import_uuidv73.uuidv7)();
4033
+ const docId = _id || this.sthis.nextId().str;
3710
4034
  const result = await this._writeQueue.push({
3711
4035
  id: docId,
3712
4036
  value: {
@@ -3771,7 +4095,7 @@ var Database = class {
3771
4095
  await this.ready();
3772
4096
  this.logger.Debug().Any("field", field).Any("opts", opts).Msg("query");
3773
4097
  const _crdt = this._crdt;
3774
- const idx = typeof field === "string" ? index({ _crdt }, field) : index({ _crdt }, makeName(field.toString()), field);
4098
+ const idx = typeof field === "string" ? index(this.sthis, { _crdt }, field) : index(this.sthis, { _crdt }, makeName(field.toString()), field);
3775
4099
  return await idx.query(opts);
3776
4100
  }
3777
4101
  async compact() {
@@ -3808,12 +4132,7 @@ function fireproof(name, opts) {
3808
4132
  const key = JSON.stringify(
3809
4133
  toSortedArray({
3810
4134
  name,
3811
- stores: toSortedArray(opts?.store?.stores),
3812
- makeMetaStore: !!opts?.store?.makeMetaStore,
3813
- makeDataStore: !!opts?.store?.makeDataStore,
3814
- makeRemoteWAL: !!opts?.store?.makeRemoteWAL,
3815
- encodeFile: !!opts?.store?.encodeFile,
3816
- decodeFile: !!opts?.store?.decodeFile
4135
+ stores: toSortedArray(opts?.store?.stores)
3817
4136
  })
3818
4137
  );
3819
4138
  let db = Database.databases.get(key);
@@ -3828,7 +4147,10 @@ function makeName(fnString) {
3828
4147
  let found = null;
3829
4148
  const matches = Array.from(fnString.matchAll(regex), (match) => match[1].trim());
3830
4149
  if (matches.length === 0) {
3831
- found = /=>\s*(.*)/.exec(fnString);
4150
+ found = /=>\s*{?\s*([^{}]+)\s*}?/.exec(fnString);
4151
+ if (found && found[1].includes("return")) {
4152
+ found = null;
4153
+ }
3832
4154
  }
3833
4155
  if (!found) {
3834
4156
  return fnString;
@@ -3837,14 +4159,41 @@ function makeName(fnString) {
3837
4159
  }
3838
4160
  }
3839
4161
 
4162
+ // src/runtime/index.ts
4163
+ var runtime_exports = {};
4164
+ __export(runtime_exports, {
4165
+ FILESTORE_VERSION: () => FILESTORE_VERSION,
4166
+ INDEXDB_VERSION: () => INDEXDB_VERSION,
4167
+ files: () => files_exports,
4168
+ getFileName: () => getFileName,
4169
+ getFileSystem: () => getFileSystem,
4170
+ getPath: () => getPath,
4171
+ kb: () => key_bag_exports,
4172
+ kc: () => keyed_crypto_exports,
4173
+ mf: () => wait_pr_multiformats_exports,
4174
+ toArrayBuffer: () => toArrayBuffer
4175
+ });
4176
+ init_utils2();
4177
+
4178
+ // src/runtime/wait-pr-multiformats/index.ts
4179
+ var wait_pr_multiformats_exports = {};
4180
+ __export(wait_pr_multiformats_exports, {
4181
+ block: () => block_exports,
4182
+ codec: () => codec_interface_exports
4183
+ });
4184
+
4185
+ // src/runtime/wait-pr-multiformats/codec-interface.ts
4186
+ var codec_interface_exports = {};
4187
+
4188
+ // src/runtime/index.ts
4189
+ init_version();
4190
+ init_version2();
4191
+
3840
4192
  // src/index.ts
3841
- init_types();
3842
- init_runtime();
3843
- init_runtime();
3844
4193
  init_utils();
3845
4194
 
3846
4195
  // src/version.ts
3847
4196
  var PACKAGE_VERSION = Object.keys({
3848
- "0.19.8-dev-global": "xxxx"
4197
+ "0.19.9-dev-frag": "xxxx"
3849
4198
  })[0];
3850
4199
  //# sourceMappingURL=index.cjs.map