@fireproof/core 0.19.101 → 0.19.103
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{chunk-3EB3ENHT.js → chunk-OFGPKRCM.js} +25 -54
- package/chunk-OFGPKRCM.js.map +1 -0
- package/chunk-WS3YRPIA.js +75 -0
- package/chunk-WS3YRPIA.js.map +1 -0
- package/{gateway-GK5QZ6KP.js → gateway-5FCWPX5W.js} +12 -13
- package/gateway-5FCWPX5W.js.map +1 -0
- package/{gateway-TQTGDRCN.js → gateway-H7UD6TNB.js} +8 -9
- package/gateway-H7UD6TNB.js.map +1 -0
- package/index.cjs +1571 -1992
- package/index.cjs.map +1 -1
- package/index.d.cts +117 -257
- package/index.d.ts +117 -257
- package/index.global.js +12280 -12741
- package/index.global.js.map +1 -1
- package/index.js +1463 -1790
- package/index.js.map +1 -1
- package/{key-bag-file-VOSSK46F.js → key-bag-file-WADZBHYG.js} +3 -4
- package/{key-bag-file-VOSSK46F.js.map → key-bag-file-WADZBHYG.js.map} +1 -1
- package/{key-bag-indexdb-AXTQOSMC.js → key-bag-indexdb-PGVAI3FJ.js} +3 -4
- package/{key-bag-indexdb-AXTQOSMC.js.map → key-bag-indexdb-PGVAI3FJ.js.map} +1 -1
- package/mem-filesystem-YPPJV7Q2.js +41 -0
- package/mem-filesystem-YPPJV7Q2.js.map +1 -0
- package/metafile-cjs.json +1 -1
- package/metafile-esm.json +1 -1
- package/metafile-iife.json +1 -1
- package/{node-filesystem-CFRXFSO7.js → node-filesystem-INX4ZTHE.js} +9 -6
- package/node-filesystem-INX4ZTHE.js.map +1 -0
- package/package.json +1 -1
- package/tests/blockstore/keyed-crypto.test.ts +227 -63
- package/tests/blockstore/loader.test.ts +11 -19
- package/tests/blockstore/store.test.ts +19 -23
- package/tests/blockstore/transaction.test.ts +12 -12
- package/tests/fireproof/all-gateway.test.ts +193 -201
- package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.ts +316 -324
- package/tests/fireproof/config.test.ts +172 -0
- package/tests/fireproof/crdt.test.ts +16 -67
- package/tests/fireproof/database.test.ts +21 -183
- package/tests/fireproof/fireproof.test.ts +74 -83
- package/tests/fireproof/hello.test.ts +14 -18
- package/tests/fireproof/indexer.test.ts +43 -53
- package/tests/fireproof/utils.test.ts +6 -18
- package/tests/helpers.ts +9 -27
- package/tests/react/useFireproof.test.tsx +1 -1
- package/{utils-STA2C35G.js → utils-QO2HIWGI.js} +3 -4
- package/chunk-3EB3ENHT.js.map +0 -1
- package/chunk-HQ7D3PEU.js +0 -61
- package/chunk-HQ7D3PEU.js.map +0 -1
- package/chunk-PZ5AY32C.js +0 -10
- package/deno-filesystem-Q2IJ7YDR.js +0 -57
- package/deno-filesystem-Q2IJ7YDR.js.map +0 -1
- package/gateway-GK5QZ6KP.js.map +0 -1
- package/gateway-TQTGDRCN.js.map +0 -1
- package/key-bag-memory-LWE6ARPX.js +0 -29
- package/key-bag-memory-LWE6ARPX.js.map +0 -1
- package/node-filesystem-CFRXFSO7.js.map +0 -1
- package/tests/blockstore/keyed-crypto-indexdb-file.test.ts +0 -129
- package/tests/gateway/file/loader-config.test.ts +0 -303
- package/tests/gateway/indexdb/loader-config.test.ts +0 -75
- package/utils-STA2C35G.js.map +0 -1
- /package/tests/fireproof/{fireproof.fixture.ts → fireproof.test.fixture.ts} +0 -0
- /package/{chunk-PZ5AY32C.js.map → utils-QO2HIWGI.js.map} +0 -0
package/index.cjs
CHANGED
@@ -30,47 +30,6 @@ 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 PARAM;
|
50
|
-
var init_types = __esm({
|
51
|
-
"src/types.ts"() {
|
52
|
-
"use strict";
|
53
|
-
PARAM = /* @__PURE__ */ ((PARAM2) => {
|
54
|
-
PARAM2["SUFFIX"] = "suffix";
|
55
|
-
PARAM2["URL_GEN"] = "urlGen";
|
56
|
-
PARAM2["STORE_KEY"] = "storekey";
|
57
|
-
PARAM2["STORE"] = "store";
|
58
|
-
PARAM2["KEY"] = "key";
|
59
|
-
PARAM2["INDEX"] = "index";
|
60
|
-
PARAM2["NAME"] = "name";
|
61
|
-
PARAM2["VERSION"] = "version";
|
62
|
-
PARAM2["FRAG_SIZE"] = "fragSize";
|
63
|
-
PARAM2["IV_VERIFY"] = "ivVerify";
|
64
|
-
PARAM2["IV_HASH"] = "ivHash";
|
65
|
-
PARAM2["FRAG_FID"] = "fid";
|
66
|
-
PARAM2["FRAG_OFS"] = "ofs";
|
67
|
-
PARAM2["FRAG_LEN"] = "len";
|
68
|
-
PARAM2["FRAG_HEAD"] = "headerSize";
|
69
|
-
return PARAM2;
|
70
|
-
})(PARAM || {});
|
71
|
-
}
|
72
|
-
});
|
73
|
-
|
74
33
|
// src/utils.ts
|
75
34
|
function presetEnv() {
|
76
35
|
const penv = new Map([
|
@@ -128,10 +87,6 @@ function ensureLogger(sthis, componentName, ctx) {
|
|
128
87
|
exposeStack = true;
|
129
88
|
delete ctx.exposeStack;
|
130
89
|
}
|
131
|
-
if ("exposeStack" in ctx) {
|
132
|
-
exposeStack = true;
|
133
|
-
delete ctx.exposeStack;
|
134
|
-
}
|
135
90
|
if ("this" in ctx) {
|
136
91
|
cLogger.Str("this", sthis.nextId(4).str);
|
137
92
|
delete ctx.this;
|
@@ -198,13 +153,10 @@ function ensureLogger(sthis, componentName, ctx) {
|
|
198
153
|
logger.SetExposeStack(true);
|
199
154
|
}
|
200
155
|
const out = cLogger.Logger();
|
201
|
-
if (sthis.env.get("FP_CONSTRUCTOR_DEBUG")) {
|
202
|
-
out.Debug().Msg("constructor");
|
203
|
-
}
|
204
156
|
return out;
|
205
157
|
}
|
206
158
|
function getStore(url, sthis, joiner) {
|
207
|
-
const store = url.getParam("store"
|
159
|
+
const store = url.getParam("store");
|
208
160
|
switch (store) {
|
209
161
|
case "data":
|
210
162
|
case "wal":
|
@@ -212,21 +164,20 @@ function getStore(url, sthis, joiner) {
|
|
212
164
|
break;
|
213
165
|
default:
|
214
166
|
throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
|
215
|
-
throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
|
216
167
|
}
|
217
168
|
let name = store;
|
218
169
|
if (url.hasParam("index")) {
|
219
|
-
name = joiner(url.getParam("index"
|
170
|
+
name = joiner(url.getParam("index") || "idx", name);
|
220
171
|
}
|
221
172
|
return { store, name };
|
222
173
|
}
|
223
174
|
function getKey(url, logger) {
|
224
|
-
const result = url.getParam("key"
|
175
|
+
const result = url.getParam("key");
|
225
176
|
if (!result) throw logger.Error().Str("url", url.toString()).Msg(`key not found`).AsError();
|
226
177
|
return result;
|
227
178
|
}
|
228
179
|
function getName(sthis, url) {
|
229
|
-
let result = url.getParam("name"
|
180
|
+
let result = url.getParam("name");
|
230
181
|
if (!result) {
|
231
182
|
result = sthis.pathOps.dirname(url.pathname);
|
232
183
|
if (result.length === 0) {
|
@@ -246,6 +197,17 @@ function isNotFoundError(e) {
|
|
246
197
|
if (e.code === "ENOENT") return true;
|
247
198
|
return false;
|
248
199
|
}
|
200
|
+
function dataDir(sthis, name, base) {
|
201
|
+
if (!base) {
|
202
|
+
if (!(0, import_cement.runtimeFn)().isBrowser) {
|
203
|
+
const home = sthis.env.get("HOME") || "./";
|
204
|
+
base = sthis.env.get("FP_STORAGE_URL") || `file://${sthis.pathOps.join(home, ".fireproof")}`;
|
205
|
+
} else {
|
206
|
+
base = sthis.env.get("FP_STORAGE_URL") || `indexdb://fp`;
|
207
|
+
}
|
208
|
+
}
|
209
|
+
return import_cement.URI.from(base.toString()).build().setParam("name", name || "").URI();
|
210
|
+
}
|
249
211
|
function UInt8ArrayEqual(a, b) {
|
250
212
|
if (a.length !== b.length) {
|
251
213
|
return false;
|
@@ -262,7 +224,6 @@ var init_utils = __esm({
|
|
262
224
|
"src/utils.ts"() {
|
263
225
|
"use strict";
|
264
226
|
import_cement = require("@adviser/cement");
|
265
|
-
init_types();
|
266
227
|
import_base58 = require("multiformats/bases/base58");
|
267
228
|
globalLogger = new import_cement.LoggerImpl();
|
268
229
|
registerFP_DEBUG = new import_cement.ResolveOnce();
|
@@ -313,9 +274,6 @@ var init_utils = __esm({
|
|
313
274
|
dirname(path) {
|
314
275
|
return path.split("/").slice(0, -1).join("/");
|
315
276
|
}
|
316
|
-
basename(path) {
|
317
|
-
return path.split("/").pop() || "";
|
318
|
-
}
|
319
277
|
// homedir() {
|
320
278
|
// throw new Error("SysContainer:homedir is not available in seeded state");
|
321
279
|
// }
|
@@ -334,63 +292,45 @@ var init_utils = __esm({
|
|
334
292
|
}
|
335
293
|
});
|
336
294
|
|
337
|
-
// src/runtime/gateways/file/
|
338
|
-
var
|
339
|
-
__export(
|
340
|
-
|
295
|
+
// src/runtime/gateways/file/mem-filesystem.ts
|
296
|
+
var mem_filesystem_exports = {};
|
297
|
+
__export(mem_filesystem_exports, {
|
298
|
+
MemFileSystem: () => MemFileSystem
|
341
299
|
});
|
342
|
-
var
|
343
|
-
var
|
344
|
-
"src/runtime/gateways/file/
|
300
|
+
var import_memfs, MemFileSystem;
|
301
|
+
var init_mem_filesystem = __esm({
|
302
|
+
"src/runtime/gateways/file/mem-filesystem.ts"() {
|
345
303
|
"use strict";
|
346
|
-
|
304
|
+
import_memfs = require("memfs");
|
305
|
+
init_utils2();
|
306
|
+
MemFileSystem = class {
|
347
307
|
async start() {
|
348
|
-
this.fs = Deno;
|
349
308
|
return this;
|
350
309
|
}
|
351
|
-
|
352
|
-
return
|
310
|
+
mkdir(path, options) {
|
311
|
+
return import_memfs.fs.promises.mkdir(path, options);
|
353
312
|
}
|
354
|
-
|
355
|
-
|
356
|
-
for await (const dirEntry of this.fs.readdir(path)) {
|
357
|
-
ret.push(dirEntry.name);
|
358
|
-
}
|
359
|
-
return ret;
|
313
|
+
readdir(path, options) {
|
314
|
+
return import_memfs.fs.promises.readdir(path, options);
|
360
315
|
}
|
361
|
-
|
362
|
-
return
|
316
|
+
rm(path, options) {
|
317
|
+
return import_memfs.fs.promises.rm(path, options);
|
363
318
|
}
|
364
|
-
|
365
|
-
return
|
319
|
+
copyFile(source, destination) {
|
320
|
+
return import_memfs.fs.promises.copyFile(source, destination);
|
366
321
|
}
|
367
|
-
async readfile(path) {
|
368
|
-
|
322
|
+
async readfile(path, options) {
|
323
|
+
const ret = await import_memfs.fs.promises.readFile(path, options);
|
324
|
+
return toArrayBuffer(ret);
|
369
325
|
}
|
370
|
-
|
371
|
-
|
372
|
-
return {
|
373
|
-
isFile: () => x.isFile,
|
374
|
-
isDirectory: () => x.isDirectory,
|
375
|
-
isBlockDevice: () => !!x.isBlockDevice,
|
376
|
-
isCharacterDevice: () => !!x.isCharDevice,
|
377
|
-
isSymbolicLink: () => !!x.isSymlink,
|
378
|
-
isFIFO: () => !!x.isFifo,
|
379
|
-
isSocket: () => !!x.isSocket,
|
380
|
-
uid: x.uid,
|
381
|
-
gid: x.gid,
|
382
|
-
size: x.size,
|
383
|
-
atime: x.atime,
|
384
|
-
mtime: x.mtime,
|
385
|
-
ctime: x.birthtime,
|
386
|
-
birthtime: x.birthtime
|
387
|
-
};
|
326
|
+
stat(path) {
|
327
|
+
return import_memfs.fs.promises.stat(path);
|
388
328
|
}
|
389
|
-
|
390
|
-
return
|
329
|
+
unlink(path) {
|
330
|
+
return import_memfs.fs.promises.unlink(path);
|
391
331
|
}
|
392
|
-
|
393
|
-
return
|
332
|
+
writefile(path, data) {
|
333
|
+
return import_memfs.fs.promises.writeFile(path, Buffer.from(data));
|
394
334
|
}
|
395
335
|
};
|
396
336
|
}
|
@@ -401,11 +341,12 @@ var node_filesystem_exports = {};
|
|
401
341
|
__export(node_filesystem_exports, {
|
402
342
|
NodeFileSystem: () => NodeFileSystem
|
403
343
|
});
|
404
|
-
var NodeFileSystem;
|
344
|
+
var import_cement4, NodeFileSystem;
|
405
345
|
var init_node_filesystem = __esm({
|
406
346
|
"src/runtime/gateways/file/node-filesystem.ts"() {
|
407
347
|
"use strict";
|
408
348
|
init_utils2();
|
349
|
+
import_cement4 = require("@adviser/cement");
|
409
350
|
NodeFileSystem = class {
|
410
351
|
async start() {
|
411
352
|
this.fs = await import("fs/promises");
|
@@ -428,12 +369,15 @@ var init_node_filesystem = __esm({
|
|
428
369
|
return toArrayBuffer(ret);
|
429
370
|
}
|
430
371
|
stat(path) {
|
431
|
-
return this.fs
|
372
|
+
return this.fs?.stat(path);
|
432
373
|
}
|
433
374
|
async unlink(path) {
|
434
375
|
return this.fs?.unlink(path);
|
435
376
|
}
|
436
377
|
async writefile(path, data) {
|
378
|
+
if ((0, import_cement4.runtimeFn)().isDeno) {
|
379
|
+
return this.fs?.writeFile(path, data);
|
380
|
+
}
|
437
381
|
return this.fs?.writeFile(path, Buffer.from(data));
|
438
382
|
}
|
439
383
|
};
|
@@ -449,34 +393,49 @@ __export(utils_exports, {
|
|
449
393
|
toArrayBuffer: () => toArrayBuffer
|
450
394
|
});
|
451
395
|
async function getFileSystem(url) {
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
396
|
+
const name = url.getParam("fs");
|
397
|
+
let fs2;
|
398
|
+
switch (name) {
|
399
|
+
case "mem":
|
400
|
+
{
|
401
|
+
const { MemFileSystem: MemFileSystem2 } = await Promise.resolve().then(() => (init_mem_filesystem(), mem_filesystem_exports));
|
402
|
+
fs2 = new MemFileSystem2();
|
403
|
+
}
|
404
|
+
break;
|
405
|
+
// case 'deno': {
|
406
|
+
// const { DenoFileSystem } = await import("./deno-filesystem.js");
|
407
|
+
// fs = new DenoFileSystem();
|
408
|
+
// break;
|
409
|
+
// }
|
410
|
+
case "node": {
|
411
|
+
const { NodeFileSystem: NodeFileSystem2 } = await Promise.resolve().then(() => (init_node_filesystem(), node_filesystem_exports));
|
412
|
+
fs2 = new NodeFileSystem2();
|
413
|
+
break;
|
414
|
+
}
|
415
|
+
case "sys":
|
416
|
+
default: {
|
417
|
+
return getFileSystem(url.build().setParam("fs", "node").URI());
|
418
|
+
}
|
461
419
|
}
|
462
|
-
return
|
420
|
+
return fs2.start();
|
463
421
|
}
|
464
422
|
function getPath(url, sthis) {
|
465
423
|
const basePath = url.pathname;
|
466
|
-
const name = url.getParam("name"
|
424
|
+
const name = url.getParam("name");
|
467
425
|
if (name) {
|
468
|
-
|
426
|
+
const version = url.getParam("version");
|
427
|
+
if (!version) throw sthis.logger.Error().Url(url).Msg(`version not found`).AsError();
|
428
|
+
return sthis.pathOps.join(basePath, version, name);
|
469
429
|
}
|
470
430
|
return sthis.pathOps.join(basePath);
|
471
431
|
}
|
472
432
|
function getFileName(url, sthis) {
|
473
|
-
const key = url.getParam("key"
|
433
|
+
const key = url.getParam("key");
|
474
434
|
if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
|
475
435
|
const res = getStore(url, sthis, (...a) => a.join("-"));
|
476
436
|
switch (res.store) {
|
477
|
-
case "data":
|
478
|
-
return sthis.pathOps.join(res.name, key +
|
479
|
-
}
|
437
|
+
case "data":
|
438
|
+
return sthis.pathOps.join(res.name, key + ".car");
|
480
439
|
case "wal":
|
481
440
|
case "meta":
|
482
441
|
return sthis.pathOps.join(res.name, key + ".json");
|
@@ -495,13 +454,10 @@ function toArrayBuffer(buffer) {
|
|
495
454
|
}
|
496
455
|
return view;
|
497
456
|
}
|
498
|
-
var import_cement4;
|
499
457
|
var init_utils2 = __esm({
|
500
458
|
"src/runtime/gateways/file/utils.ts"() {
|
501
459
|
"use strict";
|
502
|
-
import_cement4 = require("@adviser/cement");
|
503
460
|
init_utils();
|
504
|
-
init_types();
|
505
461
|
}
|
506
462
|
});
|
507
463
|
|
@@ -616,40 +572,6 @@ var init_key_bag_indexdb = __esm({
|
|
616
572
|
}
|
617
573
|
});
|
618
574
|
|
619
|
-
// src/runtime/key-bag-memory.ts
|
620
|
-
var key_bag_memory_exports = {};
|
621
|
-
__export(key_bag_memory_exports, {
|
622
|
-
KeyBagProviderMemory: () => KeyBagProviderMemory
|
623
|
-
});
|
624
|
-
var memoryKeyBag, KeyBagProviderMemory;
|
625
|
-
var init_key_bag_memory = __esm({
|
626
|
-
"src/runtime/key-bag-memory.ts"() {
|
627
|
-
"use strict";
|
628
|
-
memoryKeyBag = /* @__PURE__ */ new Map();
|
629
|
-
KeyBagProviderMemory = class {
|
630
|
-
constructor(url, sthis) {
|
631
|
-
this.url = url;
|
632
|
-
this.sthis = sthis;
|
633
|
-
}
|
634
|
-
key(id) {
|
635
|
-
return `${this.url.pathname}/${id}`;
|
636
|
-
}
|
637
|
-
async get(id) {
|
638
|
-
const binKeyItem = memoryKeyBag.get(this.key(id));
|
639
|
-
if (binKeyItem) {
|
640
|
-
const ki = JSON.parse(this.sthis.txt.decode(binKeyItem));
|
641
|
-
return ki;
|
642
|
-
}
|
643
|
-
return void 0;
|
644
|
-
}
|
645
|
-
async set(id, item) {
|
646
|
-
const p = this.sthis.txt.encode(JSON.stringify(item, null, 2));
|
647
|
-
memoryKeyBag.set(this.key(id), p);
|
648
|
-
}
|
649
|
-
};
|
650
|
-
}
|
651
|
-
});
|
652
|
-
|
653
575
|
// src/runtime/gateways/file/version.ts
|
654
576
|
var FILESTORE_VERSION;
|
655
577
|
var init_version = __esm({
|
@@ -665,24 +587,23 @@ __export(gateway_exports, {
|
|
665
587
|
FileGateway: () => FileGateway,
|
666
588
|
FileTestStore: () => FileTestStore
|
667
589
|
});
|
668
|
-
var
|
590
|
+
var import_cement11, versionFiles, FileGateway, FileTestStore;
|
669
591
|
var init_gateway = __esm({
|
670
592
|
"src/runtime/gateways/file/gateway.ts"() {
|
671
593
|
"use strict";
|
672
594
|
init_version();
|
673
|
-
|
595
|
+
import_cement11 = require("@adviser/cement");
|
674
596
|
init_utils();
|
675
597
|
init_utils2();
|
676
|
-
|
677
|
-
versionFiles = new import_cement12.KeyedResolvOnce();
|
598
|
+
versionFiles = new import_cement11.KeyedResolvOnce();
|
678
599
|
FileGateway = class {
|
679
600
|
get fs() {
|
680
601
|
if (!this._fs) throw this.logger.Error().Msg("fs not initialized").AsError();
|
681
602
|
return this._fs;
|
682
603
|
}
|
683
604
|
constructor(sthis) {
|
684
|
-
this.sthis =
|
685
|
-
this.logger =
|
605
|
+
this.sthis = sthis;
|
606
|
+
this.logger = sthis.logger;
|
686
607
|
}
|
687
608
|
async getVersionFromFile(path, logger) {
|
688
609
|
return versionFiles.get(path).once(async () => {
|
@@ -704,33 +625,34 @@ var init_gateway = __esm({
|
|
704
625
|
});
|
705
626
|
}
|
706
627
|
start(baseURL) {
|
707
|
-
return (0,
|
628
|
+
return (0, import_cement11.exception2Result)(async () => {
|
708
629
|
this._fs = await getFileSystem(baseURL);
|
630
|
+
await this.fs.start();
|
709
631
|
const url = baseURL.build();
|
710
|
-
url.defParam("version"
|
632
|
+
url.defParam("version", FILESTORE_VERSION);
|
711
633
|
const dbUrl = await this.buildUrl(url.URI(), "dummy");
|
712
634
|
const dbdirFile = this.getFilePath(dbUrl.Ok());
|
713
635
|
await this.fs.mkdir(this.sthis.pathOps.dirname(dbdirFile), { recursive: true });
|
714
636
|
const dbroot = this.sthis.pathOps.dirname(dbdirFile);
|
715
637
|
this.logger.Debug().Url(url.URI()).Str("dbroot", dbroot).Msg("start");
|
716
|
-
url.setParam("version"
|
638
|
+
url.setParam("version", await this.getVersionFromFile(dbroot, this.logger));
|
717
639
|
return url.URI();
|
718
640
|
});
|
719
641
|
}
|
720
642
|
async buildUrl(baseUrl, key) {
|
721
|
-
return
|
643
|
+
return import_cement11.Result.Ok(baseUrl.build().setParam("key", key).URI());
|
722
644
|
}
|
723
645
|
async close() {
|
724
|
-
return
|
646
|
+
return import_cement11.Result.Ok(void 0);
|
725
647
|
}
|
726
648
|
// abstract buildUrl(baseUrl: URL, key: string): Promise<Result<URL>>;
|
727
649
|
getFilePath(url) {
|
728
|
-
const key = url.getParam("key"
|
650
|
+
const key = url.getParam("key");
|
729
651
|
if (!key) throw this.logger.Error().Url(url).Msg(`key not found`).AsError();
|
730
652
|
return this.sthis.pathOps.join(getPath(url, this.sthis), getFileName(url, this.sthis));
|
731
653
|
}
|
732
654
|
async put(url, body) {
|
733
|
-
return (0,
|
655
|
+
return (0, import_cement11.exception2Result)(async () => {
|
734
656
|
const file = await this.getFilePath(url);
|
735
657
|
this.logger.Debug().Str("url", url.toString()).Str("file", file).Msg("put");
|
736
658
|
await this.fs.writefile(file, body);
|
@@ -740,19 +662,19 @@ var init_gateway = __esm({
|
|
740
662
|
return exceptionWrapper(async () => {
|
741
663
|
const file = this.getFilePath(url);
|
742
664
|
try {
|
743
|
-
this.logger.Debug().Url(url).Str("file", file).Msg("get");
|
744
665
|
const res = await this.fs.readfile(file);
|
745
|
-
|
666
|
+
this.logger.Debug().Url(url.asURL()).Str("file", file).Msg("get");
|
667
|
+
return import_cement11.Result.Ok(new Uint8Array(res));
|
746
668
|
} catch (e) {
|
747
669
|
if (isNotFoundError(e)) {
|
748
|
-
return
|
670
|
+
return import_cement11.Result.Err(new NotFoundError(`file not found: ${file}`));
|
749
671
|
}
|
750
|
-
return
|
672
|
+
return import_cement11.Result.Err(e);
|
751
673
|
}
|
752
674
|
});
|
753
675
|
}
|
754
676
|
async delete(url) {
|
755
|
-
return (0,
|
677
|
+
return (0, import_cement11.exception2Result)(async () => {
|
756
678
|
await this.fs.unlink(this.getFilePath(url));
|
757
679
|
});
|
758
680
|
}
|
@@ -778,7 +700,7 @@ var init_gateway = __esm({
|
|
778
700
|
}
|
779
701
|
}
|
780
702
|
}
|
781
|
-
return
|
703
|
+
return import_cement11.Result.Ok(void 0);
|
782
704
|
}
|
783
705
|
};
|
784
706
|
FileTestStore = class {
|
@@ -787,7 +709,7 @@ var init_gateway = __esm({
|
|
787
709
|
this.sthis = sthis;
|
788
710
|
}
|
789
711
|
async get(iurl, key) {
|
790
|
-
const url = iurl.build().setParam("key"
|
712
|
+
const url = iurl.build().setParam("key", key).URI();
|
791
713
|
const dbFile = this.sthis.pathOps.join(getPath(url, this.sthis), getFileName(url, this.sthis));
|
792
714
|
this.logger.Debug().Url(url).Str("dbFile", dbFile).Msg("get");
|
793
715
|
const buffer = await (await getFileSystem(url)).readfile(dbFile);
|
@@ -815,7 +737,7 @@ __export(gateway_exports2, {
|
|
815
737
|
getIndexDBName: () => getIndexDBName
|
816
738
|
});
|
817
739
|
function ensureVersion(url) {
|
818
|
-
return url.build().defParam("version"
|
740
|
+
return url.build().defParam("version", INDEXDB_VERSION).URI();
|
819
741
|
}
|
820
742
|
function sanitzeKey(key) {
|
821
743
|
if (key.length === 1) {
|
@@ -836,17 +758,17 @@ async function connectIdb(url, sthis) {
|
|
836
758
|
}
|
837
759
|
});
|
838
760
|
const found = await db.get("version", "version");
|
839
|
-
const version = ensureVersion(url).getParam("version"
|
761
|
+
const version = ensureVersion(url).getParam("version");
|
840
762
|
if (!found) {
|
841
763
|
await db.put("version", { version }, "version");
|
842
764
|
} else if (found.version !== version) {
|
843
|
-
sthis.logger.Warn().
|
765
|
+
sthis.logger.Warn().Str("url", url.toString()).Str("version", version).Str("found", found.version).Msg("version mismatch");
|
844
766
|
}
|
845
767
|
return { db, dbName, version, url };
|
846
768
|
});
|
847
769
|
return {
|
848
770
|
...once,
|
849
|
-
url: url.build().setParam("version"
|
771
|
+
url: url.build().setParam("version", once.version).URI()
|
850
772
|
};
|
851
773
|
}
|
852
774
|
function joinDBName(...names) {
|
@@ -855,7 +777,7 @@ function joinDBName(...names) {
|
|
855
777
|
function getIndexDBName(iurl, sthis) {
|
856
778
|
const url = ensureVersion(iurl);
|
857
779
|
const fullDb = url.pathname.replace(/^\/+/, "").replace(/\?.*$/, "");
|
858
|
-
const dbName = url.getParam("name"
|
780
|
+
const dbName = url.getParam("name");
|
859
781
|
if (!dbName) throw sthis.logger.Error().Str("url", url.toString()).Msg(`name not found`).AsError();
|
860
782
|
const result = joinDBName(fullDb, dbName);
|
861
783
|
const objStore = getStore(url, sthis, joinDBName).name;
|
@@ -867,16 +789,15 @@ function getIndexDBName(iurl, sthis) {
|
|
867
789
|
dbName
|
868
790
|
};
|
869
791
|
}
|
870
|
-
var import_idb2,
|
792
|
+
var import_idb2, import_cement12, onceIndexDB, IndexDBGateway, IndexDBTestStore;
|
871
793
|
var init_gateway2 = __esm({
|
872
794
|
"src/runtime/gateways/indexdb/gateway.ts"() {
|
873
795
|
"use strict";
|
874
796
|
import_idb2 = require("idb");
|
875
|
-
|
797
|
+
import_cement12 = require("@adviser/cement");
|
876
798
|
init_version2();
|
877
799
|
init_utils();
|
878
|
-
|
879
|
-
onceIndexDB = new import_cement13.KeyedResolvOnce();
|
800
|
+
onceIndexDB = new import_cement12.KeyedResolvOnce();
|
880
801
|
IndexDBGateway = class {
|
881
802
|
constructor(sthis) {
|
882
803
|
this._db = {};
|
@@ -884,7 +805,7 @@ var init_gateway2 = __esm({
|
|
884
805
|
this.sthis = sthis;
|
885
806
|
}
|
886
807
|
async start(baseURL) {
|
887
|
-
return (0,
|
808
|
+
return (0, import_cement12.exception2Result)(async () => {
|
888
809
|
this.logger.Debug().Url(baseURL).Msg("starting");
|
889
810
|
await this.sthis.start();
|
890
811
|
const ic = await connectIdb(baseURL, this.sthis);
|
@@ -894,10 +815,10 @@ var init_gateway2 = __esm({
|
|
894
815
|
});
|
895
816
|
}
|
896
817
|
async close() {
|
897
|
-
return
|
818
|
+
return import_cement12.Result.Ok(void 0);
|
898
819
|
}
|
899
820
|
async destroy(baseUrl) {
|
900
|
-
return (0,
|
821
|
+
return (0, import_cement12.exception2Result)(async () => {
|
901
822
|
const type = getStore(baseUrl, this.sthis, joinDBName).name;
|
902
823
|
const idb = this._db;
|
903
824
|
const trans = idb.transaction(type, "readwrite");
|
@@ -913,7 +834,7 @@ var init_gateway2 = __esm({
|
|
913
834
|
});
|
914
835
|
}
|
915
836
|
buildUrl(baseUrl, key) {
|
916
|
-
return Promise.resolve(
|
837
|
+
return Promise.resolve(import_cement12.Result.Ok(baseUrl.build().setParam("key", key).URI()));
|
917
838
|
}
|
918
839
|
async get(url) {
|
919
840
|
return exceptionWrapper(async () => {
|
@@ -924,13 +845,13 @@ var init_gateway2 = __esm({
|
|
924
845
|
const bytes = await tx.objectStore(store).get(sanitzeKey(key));
|
925
846
|
await tx.done;
|
926
847
|
if (!bytes) {
|
927
|
-
return
|
848
|
+
return import_cement12.Result.Err(new NotFoundError(`missing ${key}`));
|
928
849
|
}
|
929
|
-
return
|
850
|
+
return import_cement12.Result.Ok(bytes);
|
930
851
|
});
|
931
852
|
}
|
932
853
|
async put(url, value) {
|
933
|
-
return (0,
|
854
|
+
return (0, import_cement12.exception2Result)(async () => {
|
934
855
|
const key = getKey(url, this.logger);
|
935
856
|
const store = getStore(url, this.sthis, joinDBName).name;
|
936
857
|
this.logger.Debug().Url(url).Str("key", key).Str("store", store).Msg("putting");
|
@@ -940,14 +861,14 @@ var init_gateway2 = __esm({
|
|
940
861
|
});
|
941
862
|
}
|
942
863
|
async delete(url) {
|
943
|
-
return (0,
|
864
|
+
return (0, import_cement12.exception2Result)(async () => {
|
944
865
|
const key = getKey(url, this.logger);
|
945
866
|
const store = getStore(url, this.sthis, joinDBName).name;
|
946
867
|
this.logger.Debug().Url(url).Str("key", key).Str("store", store).Msg("deleting");
|
947
868
|
const tx = this._db.transaction([store], "readwrite");
|
948
869
|
await tx.objectStore(store).delete(sanitzeKey(key));
|
949
870
|
await tx.done;
|
950
|
-
return
|
871
|
+
return import_cement12.Result.Ok(void 0);
|
951
872
|
});
|
952
873
|
}
|
953
874
|
};
|
@@ -975,16 +896,15 @@ var init_gateway2 = __esm({
|
|
975
896
|
var src_exports = {};
|
976
897
|
__export(src_exports, {
|
977
898
|
CRDT: () => CRDT,
|
978
|
-
|
979
|
-
DatabaseShell: () => DatabaseShell,
|
899
|
+
Database: () => Database,
|
980
900
|
Index: () => Index,
|
981
901
|
NotFoundError: () => NotFoundError,
|
982
902
|
PACKAGE_VERSION: () => PACKAGE_VERSION,
|
983
|
-
PARAM: () => PARAM,
|
984
903
|
Result: () => import_cement.Result,
|
985
904
|
UInt8ArrayEqual: () => UInt8ArrayEqual,
|
986
905
|
blockstore: () => blockstore_exports,
|
987
906
|
bs: () => blockstore_exports,
|
907
|
+
dataDir: () => dataDir,
|
988
908
|
ensureLogger: () => ensureLogger,
|
989
909
|
ensureSuperLog: () => ensureSuperLog,
|
990
910
|
ensureSuperThis: () => ensureSuperThis,
|
@@ -995,19 +915,16 @@ __export(src_exports, {
|
|
995
915
|
getName: () => getName,
|
996
916
|
getStore: () => getStore,
|
997
917
|
index: () => index,
|
998
|
-
isDatabase: () => isDatabase,
|
999
918
|
isFalsy: () => isFalsy,
|
1000
919
|
isNotFoundError: () => isNotFoundError,
|
1001
|
-
keyConfigOpts: () => keyConfigOpts,
|
1002
920
|
rt: () => runtime_exports,
|
1003
921
|
runtime: () => runtime_exports,
|
1004
|
-
throwFalsy: () => throwFalsy
|
1005
|
-
toStoreURIRuntime: () => toStoreURIRuntime
|
922
|
+
throwFalsy: () => throwFalsy
|
1006
923
|
});
|
1007
924
|
module.exports = __toCommonJS(src_exports);
|
1008
925
|
|
1009
926
|
// src/database.ts
|
1010
|
-
var
|
927
|
+
var import_cement16 = require("@adviser/cement");
|
1011
928
|
|
1012
929
|
// src/write-queue.ts
|
1013
930
|
function writeQueue(worker, payload = Infinity, unbounded = false) {
|
@@ -1050,7 +967,86 @@ function writeQueue(worker, payload = Infinity, unbounded = false) {
|
|
1050
967
|
}
|
1051
968
|
|
1052
969
|
// src/crdt.ts
|
1053
|
-
var
|
970
|
+
var import_cement15 = require("@adviser/cement");
|
971
|
+
|
972
|
+
// src/runtime/wait-pr-multiformats/block.ts
|
973
|
+
var block_exports = {};
|
974
|
+
__export(block_exports, {
|
975
|
+
Block: () => Block,
|
976
|
+
create: () => create,
|
977
|
+
createUnsafe: () => createUnsafe,
|
978
|
+
decode: () => decode,
|
979
|
+
encode: () => encode
|
980
|
+
});
|
981
|
+
var import_multiformats = require("multiformats");
|
982
|
+
var import_block = require("multiformats/block");
|
983
|
+
var Block = import_block.Block;
|
984
|
+
async function decode({
|
985
|
+
bytes,
|
986
|
+
codec: codec3,
|
987
|
+
hasher: hasher7
|
988
|
+
}) {
|
989
|
+
if (bytes == null) throw new Error('Missing required argument "bytes"');
|
990
|
+
if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
|
991
|
+
const value = await Promise.resolve(codec3.decode(bytes));
|
992
|
+
const hash = await hasher7.digest(bytes);
|
993
|
+
const cid = import_multiformats.CID.create(1, codec3.code, hash);
|
994
|
+
return new import_block.Block({ value, bytes, cid });
|
995
|
+
}
|
996
|
+
async function encode({
|
997
|
+
value,
|
998
|
+
codec: codec3,
|
999
|
+
hasher: hasher7
|
1000
|
+
}) {
|
1001
|
+
if (typeof value === "undefined") throw new Error('Missing required argument "value"');
|
1002
|
+
if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
|
1003
|
+
const bytes = await Promise.resolve(codec3.encode(value));
|
1004
|
+
const hash = await hasher7.digest(bytes);
|
1005
|
+
const cid = import_multiformats.CID.create(1, codec3.code, hash);
|
1006
|
+
return new import_block.Block({ value, bytes, cid });
|
1007
|
+
}
|
1008
|
+
async function create({
|
1009
|
+
bytes,
|
1010
|
+
cid,
|
1011
|
+
hasher: hasher7,
|
1012
|
+
codec: codec3
|
1013
|
+
}) {
|
1014
|
+
if (bytes == null) throw new Error('Missing required argument "bytes"');
|
1015
|
+
if (hasher7 == null) throw new Error('Missing required argument "hasher"');
|
1016
|
+
const value = await Promise.resolve(codec3.decode(bytes));
|
1017
|
+
const hash = await hasher7.digest(bytes);
|
1018
|
+
if (!import_multiformats.bytes.equals(cid.multihash.bytes, hash.bytes)) {
|
1019
|
+
throw new Error("CID hash does not match bytes");
|
1020
|
+
}
|
1021
|
+
return createUnsafe({
|
1022
|
+
bytes,
|
1023
|
+
cid,
|
1024
|
+
value,
|
1025
|
+
codec: codec3
|
1026
|
+
});
|
1027
|
+
}
|
1028
|
+
async function createUnsafe({
|
1029
|
+
bytes,
|
1030
|
+
cid,
|
1031
|
+
value: maybeValue,
|
1032
|
+
codec: codec3
|
1033
|
+
}) {
|
1034
|
+
const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
|
1035
|
+
if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
|
1036
|
+
return new Block({
|
1037
|
+
cid,
|
1038
|
+
bytes,
|
1039
|
+
value
|
1040
|
+
});
|
1041
|
+
}
|
1042
|
+
|
1043
|
+
// src/crdt-helpers.ts
|
1044
|
+
var import_link = require("multiformats/link");
|
1045
|
+
var import_sha25 = require("multiformats/hashes/sha2");
|
1046
|
+
var codec = __toESM(require("@ipld/dag-cbor"), 1);
|
1047
|
+
var import_crdt = require("@web3-storage/pail/crdt");
|
1048
|
+
var import_clock2 = require("@web3-storage/pail/clock");
|
1049
|
+
var Batch = __toESM(require("@web3-storage/pail/crdt/batch"), 1);
|
1054
1050
|
|
1055
1051
|
// src/blockstore/index.ts
|
1056
1052
|
var blockstore_exports = {};
|
@@ -1063,11 +1059,8 @@ __export(blockstore_exports, {
|
|
1063
1059
|
FragmentGateway: () => FragmentGateway,
|
1064
1060
|
Loader: () => Loader,
|
1065
1061
|
addCryptoKeyToGatewayMetaPayload: () => addCryptoKeyToGatewayMetaPayload,
|
1066
|
-
|
1067
|
-
|
1068
|
-
getDefaultURI: () => getDefaultURI,
|
1069
|
-
getGatewayFactoryItem: () => getGatewayFactoryItem,
|
1070
|
-
getStartedGateway: () => getStartedGateway,
|
1062
|
+
ensureStart: () => ensureStart,
|
1063
|
+
getGatewayFromURL: () => getGatewayFromURL,
|
1071
1064
|
parseCarFile: () => parseCarFile,
|
1072
1065
|
registerStoreProtocol: () => registerStoreProtocol,
|
1073
1066
|
setCryptoKeyFromGatewayMetaPayload: () => setCryptoKeyFromGatewayMetaPayload,
|
@@ -1082,7 +1075,7 @@ function toCIDBlock(block) {
|
|
1082
1075
|
}
|
1083
1076
|
|
1084
1077
|
// src/blockstore/store-factory.ts
|
1085
|
-
var
|
1078
|
+
var import_cement13 = require("@adviser/cement");
|
1086
1079
|
|
1087
1080
|
// src/runtime/files.ts
|
1088
1081
|
var files_exports = {};
|
@@ -1158,422 +1151,327 @@ var UnixFSFileBuilder = class {
|
|
1158
1151
|
// src/blockstore/store.ts
|
1159
1152
|
var import_dag_json2 = require("@ipld/dag-json");
|
1160
1153
|
var import_cement10 = require("@adviser/cement");
|
1161
|
-
init_types();
|
1162
|
-
init_utils();
|
1163
1154
|
|
1164
|
-
// src/
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
}
|
1172
|
-
waitIdle() {
|
1173
|
-
if (this.queue.length === 0 && !this.processing) {
|
1174
|
-
return Promise.resolve();
|
1175
|
-
}
|
1176
|
-
const fn = new import_cement2.Future();
|
1177
|
-
this._waitIdleItems.add(fn);
|
1178
|
-
return fn.asPromise();
|
1179
|
-
}
|
1180
|
-
async enqueue(fn) {
|
1181
|
-
return new Promise((resolve, reject) => {
|
1182
|
-
const queueFn = async () => {
|
1183
|
-
try {
|
1184
|
-
resolve(await fn());
|
1185
|
-
} catch (e) {
|
1186
|
-
reject(e);
|
1187
|
-
} finally {
|
1188
|
-
this.processing = false;
|
1189
|
-
this.processNext();
|
1190
|
-
}
|
1191
|
-
};
|
1192
|
-
this.queue.push(queueFn);
|
1193
|
-
if (!this.processing) {
|
1194
|
-
this.processNext();
|
1195
|
-
}
|
1196
|
-
});
|
1155
|
+
// src/types.ts
|
1156
|
+
function isFalsy(value) {
|
1157
|
+
return value === false && value === null && value === void 0;
|
1158
|
+
}
|
1159
|
+
function throwFalsy(value) {
|
1160
|
+
if (isFalsy(value)) {
|
1161
|
+
throw new Error("value is Falsy");
|
1197
1162
|
}
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
queueFn().finally(() => {
|
1204
|
-
});
|
1205
|
-
}
|
1206
|
-
}
|
1207
|
-
if (this.queue.length === 0 && !this.processing) {
|
1208
|
-
const toResolve = Array.from(this._waitIdleItems);
|
1209
|
-
this._waitIdleItems.clear();
|
1210
|
-
toResolve.map((fn) => fn.resolve());
|
1211
|
-
}
|
1163
|
+
return value;
|
1164
|
+
}
|
1165
|
+
function falsyToUndef(value) {
|
1166
|
+
if (isFalsy(value)) {
|
1167
|
+
return void 0;
|
1212
1168
|
}
|
1213
|
-
|
1169
|
+
return value;
|
1170
|
+
}
|
1214
1171
|
|
1215
|
-
// src/
|
1216
|
-
var keyed_crypto_exports = {};
|
1217
|
-
__export(keyed_crypto_exports, {
|
1218
|
-
BlockIvKeyIdCodec: () => BlockIvKeyIdCodec,
|
1219
|
-
keyedCryptoFactory: () => keyedCryptoFactory
|
1220
|
-
});
|
1172
|
+
// src/blockstore/store.ts
|
1221
1173
|
init_utils();
|
1222
|
-
|
1174
|
+
|
1175
|
+
// src/blockstore/loader.ts
|
1176
|
+
var import_p_limit = __toESM(require("p-limit"), 1);
|
1177
|
+
var import_car = require("@ipld/car");
|
1178
|
+
var import_cement7 = require("@adviser/cement");
|
1179
|
+
|
1180
|
+
// src/blockstore/loader-helpers.ts
|
1223
1181
|
var import_sha2 = require("multiformats/hashes/sha2");
|
1224
|
-
var
|
1225
|
-
|
1226
|
-
|
1227
|
-
|
1228
|
-
|
1229
|
-
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1233
|
-
|
1234
|
-
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
|
1242
|
-
|
1243
|
-
|
1244
|
-
|
1245
|
-
|
1246
|
-
},
|
1247
|
-
verify: async function(ko, crypto, iv, data) {
|
1248
|
-
return ko.url.getParam("ivVerify" /* IV_VERIFY */) !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
|
1182
|
+
var dagCodec = __toESM(require("@ipld/dag-cbor"), 1);
|
1183
|
+
async function parseCarFile(reader, logger) {
|
1184
|
+
const roots = await reader.getRoots();
|
1185
|
+
const header = await reader.get(roots[0]);
|
1186
|
+
if (!header) throw logger.Error().Msg("missing header block").AsError();
|
1187
|
+
const dec = await decode({ bytes: header.bytes, hasher: import_sha2.sha256, codec: dagCodec });
|
1188
|
+
const fpvalue = dec.value;
|
1189
|
+
if (fpvalue && !fpvalue.fp) {
|
1190
|
+
throw logger.Error().Msg("missing fp").AsError();
|
1191
|
+
}
|
1192
|
+
return fpvalue.fp;
|
1193
|
+
}
|
1194
|
+
|
1195
|
+
// src/blockstore/transaction.ts
|
1196
|
+
var import_block3 = require("@web3-storage/pail/block");
|
1197
|
+
var import_cement2 = require("@adviser/cement");
|
1198
|
+
init_utils();
|
1199
|
+
var CarTransaction = class extends import_block3.MemoryBlockstore {
|
1200
|
+
constructor(parent, opts = { add: true, noLoader: false }) {
|
1201
|
+
super();
|
1202
|
+
if (opts.add) {
|
1203
|
+
parent.transactions.add(this);
|
1249
1204
|
}
|
1205
|
+
this.parent = parent;
|
1206
|
+
}
|
1207
|
+
async get(cid) {
|
1208
|
+
return await this.superGet(cid) || falsyToUndef(await this.parent.get(cid));
|
1209
|
+
}
|
1210
|
+
async superGet(cid) {
|
1211
|
+
return super.get(cid);
|
1250
1212
|
}
|
1251
1213
|
};
|
1252
|
-
function
|
1253
|
-
const
|
1254
|
-
|
1214
|
+
function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
|
1215
|
+
const logger = ensureLogger(sthis, component, ctx);
|
1216
|
+
const store = opts.store || {};
|
1217
|
+
return {
|
1218
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
1219
|
+
applyMeta: (meta, snap) => {
|
1220
|
+
return Promise.resolve();
|
1221
|
+
},
|
1222
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
1223
|
+
compact: async (blocks) => {
|
1224
|
+
return {};
|
1225
|
+
},
|
1226
|
+
autoCompact: 100,
|
1227
|
+
public: false,
|
1228
|
+
name: void 0,
|
1229
|
+
threshold: 1e3 * 1e3,
|
1230
|
+
...opts,
|
1231
|
+
logger,
|
1232
|
+
keyBag: opts.keyBag || {},
|
1233
|
+
crypto: (0, import_cement2.toCryptoRuntime)(opts.crypto),
|
1234
|
+
store,
|
1235
|
+
storeRuntime: toStoreRuntime(store, sthis)
|
1236
|
+
};
|
1255
1237
|
}
|
1256
|
-
|
1257
|
-
|
1258
|
-
|
1259
|
-
|
1260
|
-
|
1261
|
-
this.iv = iv;
|
1262
|
-
this.opts = opts || {};
|
1238
|
+
function blockstoreFactory(sthis, opts) {
|
1239
|
+
if (opts.name) {
|
1240
|
+
return new EncryptedBlockstore(sthis, opts);
|
1241
|
+
} else {
|
1242
|
+
return new BaseBlockstore(opts);
|
1263
1243
|
}
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
this.
|
1270
|
-
|
1271
|
-
iv,
|
1272
|
-
keyId,
|
1273
|
-
data: await this.ko._encrypt({ iv, bytes: data })
|
1274
|
-
});
|
1244
|
+
}
|
1245
|
+
var BaseBlockstore = class {
|
1246
|
+
constructor(ebOpts = {}) {
|
1247
|
+
this.transactions = /* @__PURE__ */ new Set();
|
1248
|
+
this.sthis = ensureSuperThis(ebOpts);
|
1249
|
+
this.ebOpts = defaultedBlockstoreRuntime(this.sthis, ebOpts, "BaseBlockstore");
|
1250
|
+
this.logger = this.ebOpts.logger;
|
1275
1251
|
}
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
bytes = abytes;
|
1280
|
-
} else {
|
1281
|
-
bytes = new Uint8Array(abytes);
|
1282
|
-
}
|
1283
|
-
const { iv, keyId, data } = CBOR.decode(bytes);
|
1284
|
-
const fprt = await this.ko.fingerPrint();
|
1285
|
-
this.ko.logger.Debug().Str("fp", import_base582.base58btc.encode(keyId)).Msg("decode");
|
1286
|
-
if (import_base582.base58btc.encode(keyId) !== fprt) {
|
1287
|
-
throw this.ko.logger.Error().Str("fp", fprt).Str("keyId", import_base582.base58btc.encode(keyId)).Msg("keyId mismatch").AsError();
|
1288
|
-
}
|
1289
|
-
const result = await this.ko._decrypt({ iv, bytes: data });
|
1290
|
-
if (!this.opts?.noIVVerify && !await getGenerateIVFn(this.ko.url, this.opts).verify(this.ko, this.ko.crypto, iv, result)) {
|
1291
|
-
throw this.ko.logger.Error().Msg("iv missmatch").AsError();
|
1292
|
-
}
|
1293
|
-
return result;
|
1252
|
+
// ready: Promise<void>;
|
1253
|
+
ready() {
|
1254
|
+
return Promise.resolve();
|
1294
1255
|
}
|
1295
|
-
|
1296
|
-
var keyedCrypto = class {
|
1297
|
-
constructor(url, key, cyopt, sthis) {
|
1298
|
-
this.ivLength = 12;
|
1299
|
-
this.isEncrypting = true;
|
1300
|
-
this.logger = ensureLogger(sthis, "keyedCrypto");
|
1301
|
-
this.crypto = cyopt;
|
1302
|
-
this.key = key;
|
1303
|
-
this.url = url;
|
1256
|
+
async close() {
|
1304
1257
|
}
|
1305
|
-
|
1306
|
-
return Promise.resolve(this.key.fingerPrint);
|
1258
|
+
async destroy() {
|
1307
1259
|
}
|
1308
|
-
|
1309
|
-
return new BlockIvKeyIdCodec(this, iv, opts);
|
1260
|
+
async compact() {
|
1310
1261
|
}
|
1311
|
-
|
1312
|
-
|
1313
|
-
|
1314
|
-
|
1315
|
-
|
1316
|
-
}
|
1262
|
+
async get(cid) {
|
1263
|
+
if (!cid) throw this.logger.Error().Msg("required cid").AsError();
|
1264
|
+
for (const f of this.transactions) {
|
1265
|
+
const v = await f.superGet(cid);
|
1266
|
+
if (v) return v;
|
1267
|
+
}
|
1317
1268
|
}
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1269
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
1270
|
+
async put(cid, block) {
|
1271
|
+
throw this.logger.Error().Msg("use a transaction to put").AsError();
|
1321
1272
|
}
|
1322
|
-
|
1323
|
-
|
1324
|
-
const
|
1325
|
-
|
1273
|
+
// TransactionMeta
|
1274
|
+
async transaction(fn, _opts) {
|
1275
|
+
const t = new CarTransaction(this, _opts);
|
1276
|
+
const done = await fn(t);
|
1277
|
+
this.lastTxMeta = done;
|
1278
|
+
return { t, meta: done };
|
1326
1279
|
}
|
1327
|
-
}
|
1328
|
-
|
1329
|
-
constructor() {
|
1330
|
-
this.code = 0;
|
1331
|
-
this.name = "Fireproof@unencrypted-block";
|
1280
|
+
openTransaction(opts = { add: true, noLoader: false }) {
|
1281
|
+
return new CarTransaction(this, opts);
|
1332
1282
|
}
|
1333
|
-
|
1334
|
-
|
1283
|
+
async commitTransaction(t, done, opts) {
|
1284
|
+
if (!this.loader) throw this.logger.Error().Msg("loader required to commit").AsError();
|
1285
|
+
const cars = await this.loader?.commit(t, done, opts);
|
1286
|
+
if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
|
1287
|
+
setTimeout(() => void this.compact(), 10);
|
1288
|
+
}
|
1289
|
+
if (cars) {
|
1290
|
+
this.transactions.delete(t);
|
1291
|
+
return { meta: done, cars, t };
|
1292
|
+
}
|
1293
|
+
throw this.logger.Error().Msg("failed to commit car files").AsError();
|
1335
1294
|
}
|
1336
|
-
|
1337
|
-
|
1295
|
+
async *entries() {
|
1296
|
+
const seen = /* @__PURE__ */ new Set();
|
1297
|
+
for (const t of this.transactions) {
|
1298
|
+
for await (const blk of t.entries()) {
|
1299
|
+
if (seen.has(blk.cid.toString())) continue;
|
1300
|
+
seen.add(blk.cid.toString());
|
1301
|
+
yield blk;
|
1302
|
+
}
|
1303
|
+
}
|
1338
1304
|
}
|
1339
1305
|
};
|
1340
|
-
var
|
1341
|
-
constructor(
|
1342
|
-
|
1343
|
-
this.
|
1344
|
-
this.
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
this.
|
1350
|
-
|
1351
|
-
fingerPrint() {
|
1352
|
-
return Promise.resolve(this._fingerPrint);
|
1306
|
+
var EncryptedBlockstore = class extends BaseBlockstore {
|
1307
|
+
constructor(sthis, ebOpts) {
|
1308
|
+
super(ebOpts);
|
1309
|
+
this.compacting = false;
|
1310
|
+
this.logger = ensureLogger(this.sthis, "EncryptedBlockstore");
|
1311
|
+
const { name } = ebOpts;
|
1312
|
+
if (!name) {
|
1313
|
+
throw this.logger.Error().Msg("name required").AsError();
|
1314
|
+
}
|
1315
|
+
this.name = name;
|
1316
|
+
this.loader = new Loader(this.name, ebOpts, sthis);
|
1353
1317
|
}
|
1354
|
-
|
1355
|
-
|
1356
|
-
return new nullCodec();
|
1318
|
+
ready() {
|
1319
|
+
return this.loader.ready();
|
1357
1320
|
}
|
1358
|
-
|
1359
|
-
|
1360
|
-
return {
|
1361
|
-
name: "noCrypto",
|
1362
|
-
iv: new Uint8Array(),
|
1363
|
-
tagLength: 0
|
1364
|
-
};
|
1321
|
+
close() {
|
1322
|
+
return this.loader.close();
|
1365
1323
|
}
|
1366
|
-
|
1367
|
-
|
1324
|
+
destroy() {
|
1325
|
+
return this.loader.destroy();
|
1368
1326
|
}
|
1369
|
-
|
1370
|
-
|
1327
|
+
async get(cid) {
|
1328
|
+
const got = await super.get(cid);
|
1329
|
+
if (got) return got;
|
1330
|
+
if (!this.loader) {
|
1331
|
+
return;
|
1332
|
+
}
|
1333
|
+
return falsyToUndef(await this.loader.getBlock(cid));
|
1371
1334
|
}
|
1372
|
-
}
|
1373
|
-
|
1374
|
-
|
1375
|
-
|
1376
|
-
|
1377
|
-
if (rkey.isErr()) {
|
1378
|
-
try {
|
1379
|
-
rkey = await kb.toKeyWithFingerPrint(storekey);
|
1380
|
-
} catch (e) {
|
1381
|
-
throw sthis.logger.Error().Err(e).Str("keybag", kb.rt.id()).Str("name", storekey).Msg("getNamedKey failed").AsError();
|
1382
|
-
}
|
1335
|
+
async transaction(fn, opts = { noLoader: false }) {
|
1336
|
+
const { t, meta: done } = await super.transaction(fn);
|
1337
|
+
const cars = await this.loader.commit(t, done, opts);
|
1338
|
+
if (this.ebOpts.autoCompact && this.loader.carLog.length > this.ebOpts.autoCompact) {
|
1339
|
+
setTimeout(() => void this.compact(), 10);
|
1383
1340
|
}
|
1384
|
-
|
1341
|
+
if (cars) {
|
1342
|
+
this.transactions.delete(t);
|
1343
|
+
return { meta: done, cars, t };
|
1344
|
+
}
|
1345
|
+
throw this.logger.Error().Msg("failed to commit car files").AsError();
|
1385
1346
|
}
|
1386
|
-
|
1387
|
-
|
1388
|
-
|
1389
|
-
|
1390
|
-
|
1391
|
-
|
1392
|
-
var import_cborg = require("cborg");
|
1393
|
-
init_types();
|
1394
|
-
init_utils();
|
1395
|
-
function getFragSize(url) {
|
1396
|
-
const fragSize = url.getParam("fragSize" /* FRAG_SIZE */);
|
1397
|
-
let ret = 0;
|
1398
|
-
if (fragSize) {
|
1399
|
-
ret = parseInt(fragSize);
|
1400
|
-
}
|
1401
|
-
if (isNaN(ret) || ret <= 0) {
|
1402
|
-
ret = 0;
|
1403
|
-
}
|
1404
|
-
return ret;
|
1405
|
-
}
|
1406
|
-
async function getFrags(url, innerGW, headerSize, logger) {
|
1407
|
-
const fragSize = getFragSize(url);
|
1408
|
-
if (!fragSize) {
|
1409
|
-
const res = await innerGW.get(url);
|
1410
|
-
if (res.isErr()) {
|
1411
|
-
return [res];
|
1412
|
-
}
|
1413
|
-
const data = res.unwrap();
|
1414
|
-
return [
|
1415
|
-
import_cement3.Result.Ok({
|
1416
|
-
fid: new Uint8Array(0),
|
1417
|
-
ofs: 0,
|
1418
|
-
len: data.length,
|
1419
|
-
data
|
1420
|
-
})
|
1421
|
-
];
|
1422
|
-
}
|
1423
|
-
const firstRaw = await innerGW.get(url.build().setParam("ofs", "0").URI());
|
1424
|
-
if (firstRaw.isErr()) {
|
1425
|
-
return [firstRaw];
|
1426
|
-
}
|
1427
|
-
const firstFragment = (0, import_cborg.decode)(firstRaw.unwrap());
|
1428
|
-
const blockSize = firstFragment.data.length;
|
1429
|
-
const ops = [Promise.resolve(import_cement3.Result.Ok(firstFragment))];
|
1430
|
-
const fidStr = import_base583.base58btc.encode(firstFragment.fid);
|
1431
|
-
const fragUrl = url.build().setParam("fid" /* FRAG_FID */, fidStr).setParam("len" /* FRAG_LEN */, firstFragment.len.toString()).setParam("headerSize" /* FRAG_HEAD */, headerSize.toString());
|
1432
|
-
for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
|
1433
|
-
ops.push(
|
1434
|
-
(async (furl, ofs2) => {
|
1435
|
-
const raw2 = await innerGW.get(furl);
|
1436
|
-
if (raw2.isErr()) {
|
1437
|
-
return raw2;
|
1438
|
-
}
|
1439
|
-
const fragment = (0, import_cborg.decode)(raw2.unwrap());
|
1440
|
-
if (import_base583.base58btc.encode(fragment.fid) !== fidStr) {
|
1441
|
-
return import_cement3.Result.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
|
1442
|
-
}
|
1443
|
-
if (fragment.ofs !== ofs2) {
|
1444
|
-
return import_cement3.Result.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
|
1445
|
-
}
|
1446
|
-
return import_cement3.Result.Ok(fragment);
|
1447
|
-
})(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
|
1347
|
+
async getFile(car, cid) {
|
1348
|
+
await this.ready();
|
1349
|
+
if (!this.loader) throw this.logger.Error().Msg("loader required to get file, database must be named").AsError();
|
1350
|
+
const reader = await this.loader.loadFileCar(
|
1351
|
+
car
|
1352
|
+
/*, isPublic */
|
1448
1353
|
);
|
1354
|
+
const block = await reader.get(cid);
|
1355
|
+
if (!block) throw this.logger.Error().Str("cid", cid.toString()).Msg(`Missing block`).AsError();
|
1356
|
+
return block.bytes;
|
1449
1357
|
}
|
1450
|
-
|
1451
|
-
|
1452
|
-
|
1453
|
-
|
1454
|
-
this.
|
1455
|
-
this.
|
1456
|
-
|
1457
|
-
this.
|
1458
|
-
|
1358
|
+
async compact() {
|
1359
|
+
await this.ready();
|
1360
|
+
if (!this.loader) throw this.logger.Error().Msg("loader required to compact").AsError();
|
1361
|
+
if (this.loader.carLog.length < 2) return;
|
1362
|
+
const compactFn = this.ebOpts.compact || ((blocks) => this.defaultCompact(blocks, this.logger));
|
1363
|
+
if (!compactFn || this.compacting) return;
|
1364
|
+
const blockLog = new CompactionFetcher(this);
|
1365
|
+
this.compacting = true;
|
1366
|
+
const meta = await compactFn(blockLog);
|
1367
|
+
await this.loader?.commit(blockLog.loggedBlocks, meta, {
|
1368
|
+
compact: true,
|
1369
|
+
noLoader: true
|
1370
|
+
});
|
1371
|
+
this.compacting = false;
|
1459
1372
|
}
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
return [this.innerGW.put(url, body)];
|
1373
|
+
async defaultCompact(blocks, logger) {
|
1374
|
+
if (!this.loader) {
|
1375
|
+
throw logger.Error().Msg("no loader").AsError();
|
1464
1376
|
}
|
1465
|
-
|
1466
|
-
|
1467
|
-
throw this.logger.Error().Uint64("fragSize" /* FRAG_SIZE */, fragSize).Uint64("headerSize" /* FRAG_HEAD */, this.headerSize).Msg("Fragment size is too small").AsError();
|
1377
|
+
if (!this.lastTxMeta) {
|
1378
|
+
throw logger.Error().Msg("no lastTxMeta").AsError();
|
1468
1379
|
}
|
1469
|
-
const
|
1470
|
-
|
1471
|
-
|
1472
|
-
for (
|
1473
|
-
const
|
1474
|
-
|
1475
|
-
ofs,
|
1476
|
-
len: body.length,
|
1477
|
-
data: body.slice(ofs, ofs + blocksize)
|
1478
|
-
});
|
1479
|
-
if (block.length > fragSize) {
|
1480
|
-
throw this.logger.Error().Uint64("block", block.length).Uint64("fragSize", fragSize).Msg("Block size to big").AsError();
|
1380
|
+
for await (const blk of this.loader.entries(false)) {
|
1381
|
+
blocks.loggedBlocks.putSync(blk.cid, blk.bytes);
|
1382
|
+
}
|
1383
|
+
for (const t of this.transactions) {
|
1384
|
+
for await (const blk of t.entries()) {
|
1385
|
+
blocks.loggedBlocks.putSync(blk.cid, blk.bytes);
|
1481
1386
|
}
|
1482
|
-
ops.push(this.innerGW.put(fragUrl.setParam("ofs", ofs.toString()).URI(), block));
|
1483
1387
|
}
|
1484
|
-
return
|
1485
|
-
}
|
1486
|
-
buildUrl(baseUrl, key) {
|
1487
|
-
return this.innerGW.buildUrl(baseUrl, key);
|
1488
|
-
}
|
1489
|
-
async destroy(iurl) {
|
1490
|
-
return this.innerGW.destroy(iurl);
|
1388
|
+
return this.lastTxMeta;
|
1491
1389
|
}
|
1492
|
-
async
|
1493
|
-
|
1494
|
-
|
1495
|
-
|
1496
|
-
// 32bit
|
1497
|
-
len: 16 * 1024 * 1024,
|
1498
|
-
// 32bit
|
1499
|
-
data: new Uint8Array(1024)
|
1500
|
-
}).length - 1024;
|
1501
|
-
return this.innerGW.start(url);
|
1390
|
+
async *entries() {
|
1391
|
+
for await (const blk of this.loader.entries()) {
|
1392
|
+
yield blk;
|
1393
|
+
}
|
1502
1394
|
}
|
1503
|
-
|
1504
|
-
|
1395
|
+
};
|
1396
|
+
var CompactionFetcher = class {
|
1397
|
+
constructor(blocks) {
|
1398
|
+
this.blockstore = blocks;
|
1399
|
+
this.loggedBlocks = new CarTransaction(blocks);
|
1505
1400
|
}
|
1506
|
-
async
|
1507
|
-
await
|
1508
|
-
|
1401
|
+
async get(cid) {
|
1402
|
+
const block = await this.blockstore.get(cid);
|
1403
|
+
if (block) this.loggedBlocks.putSync(cid, block.bytes);
|
1404
|
+
return falsyToUndef(block);
|
1509
1405
|
}
|
1510
|
-
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1517
|
-
|
1518
|
-
|
1519
|
-
buffer.set(frag.data, frag.ofs);
|
1520
|
-
}
|
1521
|
-
return import_cement3.Result.Ok(buffer || new Uint8Array(0));
|
1406
|
+
};
|
1407
|
+
|
1408
|
+
// src/blockstore/commit-queue.ts
|
1409
|
+
var import_cement3 = require("@adviser/cement");
|
1410
|
+
var CommitQueue = class {
|
1411
|
+
constructor() {
|
1412
|
+
this.queue = [];
|
1413
|
+
this.processing = false;
|
1414
|
+
this._waitIdleItems = /* @__PURE__ */ new Set();
|
1522
1415
|
}
|
1523
|
-
|
1524
|
-
if (this.
|
1525
|
-
return
|
1526
|
-
} else {
|
1527
|
-
return import_cement3.Result.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
|
1416
|
+
waitIdle() {
|
1417
|
+
if (this.queue.length === 0 && !this.processing) {
|
1418
|
+
return Promise.resolve();
|
1528
1419
|
}
|
1420
|
+
const fn = new import_cement3.Future();
|
1421
|
+
this._waitIdleItems.add(fn);
|
1422
|
+
return fn.asPromise();
|
1529
1423
|
}
|
1530
|
-
async
|
1531
|
-
|
1532
|
-
|
1533
|
-
|
1534
|
-
|
1424
|
+
async enqueue(fn) {
|
1425
|
+
return new Promise((resolve, reject) => {
|
1426
|
+
const queueFn = async () => {
|
1427
|
+
try {
|
1428
|
+
resolve(await fn());
|
1429
|
+
} catch (e) {
|
1430
|
+
reject(e);
|
1431
|
+
} finally {
|
1432
|
+
this.processing = false;
|
1433
|
+
this.processNext();
|
1434
|
+
}
|
1435
|
+
};
|
1436
|
+
this.queue.push(queueFn);
|
1437
|
+
if (!this.processing) {
|
1438
|
+
this.processNext();
|
1535
1439
|
}
|
1536
|
-
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1440
|
+
});
|
1441
|
+
}
|
1442
|
+
processNext() {
|
1443
|
+
if (this.queue.length > 0 && !this.processing) {
|
1444
|
+
this.processing = true;
|
1445
|
+
const queueFn = this.queue.shift();
|
1446
|
+
if (queueFn) {
|
1447
|
+
queueFn().finally(() => {
|
1448
|
+
});
|
1543
1449
|
}
|
1544
|
-
await this.innerGW.delete(fragUrl);
|
1545
1450
|
}
|
1546
|
-
|
1451
|
+
if (this.queue.length === 0 && !this.processing) {
|
1452
|
+
const toResolve = Array.from(this._waitIdleItems);
|
1453
|
+
this._waitIdleItems.clear();
|
1454
|
+
toResolve.map((fn) => fn.resolve());
|
1455
|
+
}
|
1547
1456
|
}
|
1548
1457
|
};
|
1549
1458
|
|
1550
|
-
// src/blockstore/meta-key-helper.ts
|
1551
|
-
var import_dag_json = require("@ipld/dag-json");
|
1552
|
-
var import_clock = require("@web3-storage/pail/clock");
|
1553
|
-
var import_multiformats = require("multiformats");
|
1554
|
-
var import_base64 = require("multiformats/bases/base64");
|
1555
|
-
var import_cement7 = require("@adviser/cement");
|
1556
|
-
|
1557
1459
|
// src/runtime/key-bag.ts
|
1558
1460
|
var key_bag_exports = {};
|
1559
1461
|
__export(key_bag_exports, {
|
1560
1462
|
KeyBag: () => KeyBag,
|
1561
|
-
defaultKeyBagOpts: () => defaultKeyBagOpts,
|
1562
1463
|
getKeyBag: () => getKeyBag,
|
1563
1464
|
registerKeyBagProviderFactory: () => registerKeyBagProviderFactory
|
1564
1465
|
});
|
1565
1466
|
var import_cement6 = require("@adviser/cement");
|
1566
1467
|
init_utils();
|
1567
|
-
var
|
1568
|
-
init_types();
|
1468
|
+
var import_base582 = require("multiformats/bases/base58");
|
1569
1469
|
var KeyBag = class {
|
1570
1470
|
constructor(rt) {
|
1571
1471
|
this.rt = rt;
|
1572
1472
|
this._warnOnce = new import_cement6.ResolveOnce();
|
1573
1473
|
this._seq = new import_cement6.ResolveSeq();
|
1574
|
-
this.logger = ensureLogger(rt.sthis, "KeyBag"
|
1575
|
-
id: rt.id()
|
1576
|
-
});
|
1474
|
+
this.logger = ensureLogger(rt.sthis, "KeyBag");
|
1577
1475
|
this.logger.Debug().Msg("KeyBag created");
|
1578
1476
|
}
|
1579
1477
|
async subtleKey(key) {
|
@@ -1586,7 +1484,7 @@ var KeyBag = class {
|
|
1586
1484
|
return await this.rt.crypto.importKey(
|
1587
1485
|
"raw",
|
1588
1486
|
// raw or jwk
|
1589
|
-
|
1487
|
+
import_base582.base58btc.decode(key),
|
1590
1488
|
// hexStringToUint8Array(key), // raw data
|
1591
1489
|
"AES-GCM",
|
1592
1490
|
extractable,
|
@@ -1594,7 +1492,7 @@ var KeyBag = class {
|
|
1594
1492
|
);
|
1595
1493
|
}
|
1596
1494
|
async ensureKeyFromUrl(url, keyFactory) {
|
1597
|
-
const storeKey = url.getParam("storekey"
|
1495
|
+
const storeKey = url.getParam("storekey");
|
1598
1496
|
if (storeKey === "insecure") {
|
1599
1497
|
return import_cement6.Result.Ok(url);
|
1600
1498
|
}
|
@@ -1604,7 +1502,7 @@ var KeyBag = class {
|
|
1604
1502
|
if (ret.isErr()) {
|
1605
1503
|
return ret;
|
1606
1504
|
}
|
1607
|
-
const urb = url.build().setParam("storekey"
|
1505
|
+
const urb = url.build().setParam("storekey", keyName);
|
1608
1506
|
return import_cement6.Result.Ok(urb.URI());
|
1609
1507
|
}
|
1610
1508
|
if (storeKey.startsWith("@") && storeKey.endsWith("@")) {
|
@@ -1616,12 +1514,12 @@ var KeyBag = class {
|
|
1616
1514
|
return import_cement6.Result.Ok(url);
|
1617
1515
|
}
|
1618
1516
|
async toKeyWithFingerPrint(keyStr) {
|
1619
|
-
const material =
|
1517
|
+
const material = import_base582.base58btc.decode(keyStr);
|
1620
1518
|
const key = await this.subtleKey(keyStr);
|
1621
1519
|
const fpr = await this.rt.crypto.digestSHA256(material);
|
1622
1520
|
return import_cement6.Result.Ok({
|
1623
1521
|
key,
|
1624
|
-
fingerPrint:
|
1522
|
+
fingerPrint: import_base582.base58btc.encode(new Uint8Array(fpr))
|
1625
1523
|
});
|
1626
1524
|
}
|
1627
1525
|
async setNamedKey(name, key) {
|
@@ -1650,7 +1548,7 @@ var KeyBag = class {
|
|
1650
1548
|
const ext = new Uint8Array(await this.rt.crypto.exportKey("raw", named.key));
|
1651
1549
|
return {
|
1652
1550
|
key: ext,
|
1653
|
-
keyStr:
|
1551
|
+
keyStr: import_base582.base58btc.encode(ext)
|
1654
1552
|
};
|
1655
1553
|
}
|
1656
1554
|
});
|
@@ -1669,7 +1567,7 @@ var KeyBag = class {
|
|
1669
1567
|
this.logger.Debug().Str("id", id).Str("name", name).Msg("failIfNotFound getNamedKey");
|
1670
1568
|
return import_cement6.Result.Err(new Error(`Key not found: ${name}`));
|
1671
1569
|
}
|
1672
|
-
const ret = await this._setNamedKey(name,
|
1570
|
+
const ret = await this._setNamedKey(name, import_base582.base58btc.encode(this.rt.crypto.randomBytes(this.rt.keyLength)));
|
1673
1571
|
this.logger.Debug().Str("id", id).Str("name", name).Result("fpr", ret).Msg("createKey getNamedKey-post");
|
1674
1572
|
return ret;
|
1675
1573
|
});
|
@@ -1701,7 +1599,6 @@ function registerKeyBagProviderFactory(item) {
|
|
1701
1599
|
});
|
1702
1600
|
}
|
1703
1601
|
function defaultKeyBagOpts(sthis, kbo) {
|
1704
|
-
kbo = kbo || {};
|
1705
1602
|
if (kbo.keyRuntime) {
|
1706
1603
|
return kbo.keyRuntime;
|
1707
1604
|
}
|
@@ -1725,29 +1622,11 @@ function defaultKeyBagOpts(sthis, kbo) {
|
|
1725
1622
|
}
|
1726
1623
|
logger.Debug().Url(url).Msg("from env");
|
1727
1624
|
}
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
keyProviderFactory = async () => {
|
1732
|
-
const { KeyBagProviderFile: KeyBagProviderFile2 } = await Promise.resolve().then(() => (init_key_bag_file(), key_bag_file_exports));
|
1733
|
-
return new KeyBagProviderFile2(url, sthis);
|
1734
|
-
};
|
1735
|
-
break;
|
1736
|
-
case "indexdb:":
|
1737
|
-
keyProviderFactory = async () => {
|
1738
|
-
const { KeyBagProviderIndexDB: KeyBagProviderIndexDB2 } = await Promise.resolve().then(() => (init_key_bag_indexdb(), key_bag_indexdb_exports));
|
1739
|
-
return new KeyBagProviderIndexDB2(url, sthis);
|
1740
|
-
};
|
1741
|
-
break;
|
1742
|
-
case "memory:":
|
1743
|
-
keyProviderFactory = async () => {
|
1744
|
-
const { KeyBagProviderMemory: KeyBagProviderMemory2 } = await Promise.resolve().then(() => (init_key_bag_memory(), key_bag_memory_exports));
|
1745
|
-
return new KeyBagProviderMemory2(url, sthis);
|
1746
|
-
};
|
1747
|
-
break;
|
1748
|
-
default:
|
1749
|
-
throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
|
1625
|
+
const kitem = keyBagProviderFactories.get(url.protocol);
|
1626
|
+
if (!kitem) {
|
1627
|
+
throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
|
1750
1628
|
}
|
1629
|
+
const getBag = async () => kitem.factory(url, sthis);
|
1751
1630
|
if (url.hasParam("masterkey")) {
|
1752
1631
|
throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
|
1753
1632
|
}
|
@@ -1757,7 +1636,7 @@ function defaultKeyBagOpts(sthis, kbo) {
|
|
1757
1636
|
sthis,
|
1758
1637
|
logger,
|
1759
1638
|
keyLength: kbo.keyLength || 16,
|
1760
|
-
getBag
|
1639
|
+
getBag,
|
1761
1640
|
id: () => {
|
1762
1641
|
return url.toString();
|
1763
1642
|
}
|
@@ -1770,943 +1649,939 @@ async function getKeyBag(sthis, kbo = {}) {
|
|
1770
1649
|
return _keyBags.get(rt.id()).once(async () => new KeyBag(rt));
|
1771
1650
|
}
|
1772
1651
|
|
1773
|
-
// src/blockstore/
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1652
|
+
// src/blockstore/commitor.ts
|
1653
|
+
var CBW = __toESM(require("@ipld/car/buffer-writer"), 1);
|
1654
|
+
var import_sha22 = require("multiformats/hashes/sha2");
|
1655
|
+
var dagCodec2 = __toESM(require("@ipld/dag-cbor"), 1);
|
1656
|
+
async function encodeCarFile(roots, t, codec3) {
|
1657
|
+
let size = 0;
|
1658
|
+
const headerSize = CBW.headerLength({ roots });
|
1659
|
+
size += headerSize;
|
1660
|
+
for (const { cid, bytes } of t.entries()) {
|
1661
|
+
size += CBW.blockLength({ cid, bytes });
|
1779
1662
|
}
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1663
|
+
const buffer = new Uint8Array(size);
|
1664
|
+
const writer = CBW.createWriter(buffer, { headerSize });
|
1665
|
+
for (const r of roots) {
|
1666
|
+
writer.addRoot(r);
|
1783
1667
|
}
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
eventCid: eventBlock.cid,
|
1790
|
-
parents: crdtEntry.parents,
|
1791
|
-
dbMeta
|
1792
|
-
};
|
1793
|
-
})
|
1794
|
-
);
|
1668
|
+
for (const { cid, bytes } of t.entries()) {
|
1669
|
+
writer.write({ cid, bytes });
|
1670
|
+
}
|
1671
|
+
writer.close();
|
1672
|
+
return await encode({ value: writer.bytes, hasher: import_sha22.sha256, codec: codec3 });
|
1795
1673
|
}
|
1796
|
-
async function
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
return import_cement7.Result.Ok(dbMeta);
|
1813
|
-
}
|
1814
|
-
sthis.logger.Debug().Str("data", new TextDecoder().decode(data)).Msg("No crypto in gateway meta payload");
|
1815
|
-
return import_cement7.Result.Ok(void 0);
|
1816
|
-
} catch (error) {
|
1817
|
-
sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
|
1818
|
-
return import_cement7.Result.Err(error);
|
1674
|
+
async function createCarFile(encoder, cid, t) {
|
1675
|
+
return encodeCarFile([cid], t, encoder);
|
1676
|
+
}
|
1677
|
+
async function commitFiles(fileStore, walStore, t, done) {
|
1678
|
+
const { files: roots } = makeFileCarHeader(done);
|
1679
|
+
const cids = [];
|
1680
|
+
const codec3 = (await fileStore.keyedCrypto()).codec();
|
1681
|
+
const cars = await prepareCarFilesFiles(codec3, roots, t);
|
1682
|
+
for (const car of cars) {
|
1683
|
+
const { cid, bytes } = car;
|
1684
|
+
await fileStore.save({ cid, bytes });
|
1685
|
+
await walStore.enqueueFile(
|
1686
|
+
cid
|
1687
|
+
/*, !!opts.public*/
|
1688
|
+
);
|
1689
|
+
cids.push(cid);
|
1819
1690
|
}
|
1691
|
+
return cids;
|
1820
1692
|
}
|
1821
|
-
|
1822
|
-
|
1823
|
-
|
1824
|
-
|
1825
|
-
|
1826
|
-
const res = await kb.getNamedExtractableKey(keyName, true);
|
1827
|
-
if (res.isErr()) {
|
1828
|
-
sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
|
1829
|
-
throw res.Err();
|
1693
|
+
function makeFileCarHeader(result) {
|
1694
|
+
const files = [];
|
1695
|
+
for (const [, meta] of Object.entries(result.files || {})) {
|
1696
|
+
if (meta && typeof meta === "object" && "cid" in meta && meta !== null) {
|
1697
|
+
files.push(meta.cid);
|
1830
1698
|
}
|
1831
|
-
const keyData = await res.Ok().extract();
|
1832
|
-
const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
|
1833
|
-
const { dbMeta, parents } = dbMetas[0];
|
1834
|
-
const parentLinks = parents.map((p) => import_multiformats.CID.parse(p));
|
1835
|
-
dbMeta.key = keyData.keyStr;
|
1836
|
-
const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
|
1837
|
-
const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
|
1838
|
-
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
|
1839
|
-
return import_cement7.Result.Ok(encoded);
|
1840
|
-
} catch (error) {
|
1841
|
-
sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
|
1842
|
-
return import_cement7.Result.Err(error);
|
1843
1699
|
}
|
1700
|
+
return { ...result, files };
|
1844
1701
|
}
|
1845
|
-
function
|
1846
|
-
|
1847
|
-
const idx = url.getParam("index");
|
1848
|
-
if (idx) {
|
1849
|
-
storeKeyName.push(idx);
|
1850
|
-
}
|
1851
|
-
storeKeyName.push("data");
|
1852
|
-
return `@${storeKeyName.join(":")}@`;
|
1702
|
+
async function prepareCarFilesFiles(encoder, roots, t) {
|
1703
|
+
return [await encodeCarFile(roots, t, encoder)];
|
1853
1704
|
}
|
1854
|
-
|
1855
|
-
const
|
1856
|
-
|
1857
|
-
dbMeta: sthis.txt.encode((0, import_dag_json.format)(dbMeta))
|
1858
|
-
},
|
1859
|
-
parents
|
1860
|
-
);
|
1861
|
-
return event;
|
1705
|
+
function makeCarHeader(meta, cars, compact = false) {
|
1706
|
+
const coreHeader = compact ? { cars: [], compact: cars } : { cars, compact: [] };
|
1707
|
+
return { ...coreHeader, meta };
|
1862
1708
|
}
|
1863
|
-
async function
|
1864
|
-
|
1865
|
-
|
1866
|
-
|
1867
|
-
|
1868
|
-
data: base64String,
|
1869
|
-
parents: parents.map((p) => p.toString())
|
1870
|
-
};
|
1709
|
+
async function encodeCarHeader(fp) {
|
1710
|
+
return await encode({
|
1711
|
+
value: { fp },
|
1712
|
+
hasher: import_sha22.sha256,
|
1713
|
+
codec: dagCodec2
|
1871
1714
|
});
|
1872
|
-
return sthis.txt.encode(JSON.stringify(crdtEntries));
|
1873
|
-
}
|
1874
|
-
|
1875
|
-
// src/blockstore/store.ts
|
1876
|
-
var import_p_retry = __toESM(require("p-retry"), 1);
|
1877
|
-
var import_p_map = __toESM(require("p-map"), 1);
|
1878
|
-
|
1879
|
-
// src/blockstore/loader.ts
|
1880
|
-
var import_p_limit = __toESM(require("p-limit"), 1);
|
1881
|
-
var import_car = require("@ipld/car");
|
1882
|
-
var import_cement9 = require("@adviser/cement");
|
1883
|
-
|
1884
|
-
// src/runtime/wait-pr-multiformats/block.ts
|
1885
|
-
var block_exports = {};
|
1886
|
-
__export(block_exports, {
|
1887
|
-
Block: () => Block,
|
1888
|
-
create: () => create,
|
1889
|
-
createUnsafe: () => createUnsafe,
|
1890
|
-
decode: () => decode3,
|
1891
|
-
encode: () => encode3
|
1892
|
-
});
|
1893
|
-
var import_multiformats2 = require("multiformats");
|
1894
|
-
var import_block = require("multiformats/block");
|
1895
|
-
var Block = import_block.Block;
|
1896
|
-
async function decode3({
|
1897
|
-
bytes,
|
1898
|
-
codec: codec3,
|
1899
|
-
hasher: hasher7
|
1900
|
-
}) {
|
1901
|
-
if (bytes == null) throw new Error('Missing required argument "bytes"');
|
1902
|
-
if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
|
1903
|
-
const value = await Promise.resolve(codec3.decode(bytes));
|
1904
|
-
const hash = await hasher7.digest(bytes);
|
1905
|
-
const cid = import_multiformats2.CID.create(1, codec3.code, hash);
|
1906
|
-
return new import_block.Block({ value, bytes, cid });
|
1907
|
-
}
|
1908
|
-
async function encode3({
|
1909
|
-
value,
|
1910
|
-
codec: codec3,
|
1911
|
-
hasher: hasher7
|
1912
|
-
}) {
|
1913
|
-
if (typeof value === "undefined") throw new Error('Missing required argument "value"');
|
1914
|
-
if (codec3 == null || hasher7 == null) throw new Error("Missing required argument: codec or hasher");
|
1915
|
-
const bytes = await Promise.resolve(codec3.encode(value));
|
1916
|
-
const hash = await hasher7.digest(bytes);
|
1917
|
-
const cid = import_multiformats2.CID.create(1, codec3.code, hash);
|
1918
|
-
return new import_block.Block({ value, bytes, cid });
|
1919
1715
|
}
|
1920
|
-
async function
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
1924
|
-
|
1925
|
-
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
1929
|
-
const hash = await hasher7.digest(bytes);
|
1930
|
-
if (!import_multiformats2.bytes.equals(cid.multihash.bytes, hash.bytes)) {
|
1931
|
-
throw new Error("CID hash does not match bytes");
|
1716
|
+
async function commit(params, t, done, opts = { noLoader: false, compact: false }) {
|
1717
|
+
const fp = makeCarHeader(done, params.carLog, !!opts.compact);
|
1718
|
+
const rootBlock = await encodeCarHeader(fp);
|
1719
|
+
const cars = await prepareCarFiles(params.encoder, params.threshold, rootBlock, t);
|
1720
|
+
const cids = [];
|
1721
|
+
for (const car of cars) {
|
1722
|
+
const { cid, bytes } = car;
|
1723
|
+
await params.carStore.save({ cid, bytes });
|
1724
|
+
cids.push(cid);
|
1932
1725
|
}
|
1933
|
-
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
1937
|
-
codec: codec3
|
1938
|
-
});
|
1939
|
-
}
|
1940
|
-
async function createUnsafe({
|
1941
|
-
bytes,
|
1942
|
-
cid,
|
1943
|
-
value: maybeValue,
|
1944
|
-
codec: codec3
|
1945
|
-
}) {
|
1946
|
-
const value = await Promise.resolve(maybeValue !== void 0 ? maybeValue : codec3?.decode(bytes));
|
1947
|
-
if (value === void 0) throw new Error('Missing required argument, must either provide "value" or "codec"');
|
1948
|
-
return new Block({
|
1949
|
-
cid,
|
1950
|
-
bytes,
|
1951
|
-
value
|
1952
|
-
});
|
1726
|
+
const newDbMeta = { cars: cids };
|
1727
|
+
await params.WALStore.enqueue(newDbMeta, opts);
|
1728
|
+
await params.metaStore.save(newDbMeta);
|
1729
|
+
return { cgrp: cids, header: fp };
|
1953
1730
|
}
|
1954
|
-
|
1955
|
-
|
1956
|
-
|
1957
|
-
|
1958
|
-
|
1959
|
-
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
1963
|
-
|
1964
|
-
|
1965
|
-
|
1731
|
+
async function prepareCarFiles(encoder, threshold, rootBlock, t) {
|
1732
|
+
const carFiles = [];
|
1733
|
+
threshold = threshold || 128e3 * 8;
|
1734
|
+
let clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
|
1735
|
+
clonedt.putSync(rootBlock.cid, rootBlock.bytes);
|
1736
|
+
let newsize = CBW.blockLength(toCIDBlock(rootBlock));
|
1737
|
+
let cidRootBlock = rootBlock;
|
1738
|
+
for (const { cid, bytes } of t.entries()) {
|
1739
|
+
newsize += CBW.blockLength(toCIDBlock({ cid, bytes }));
|
1740
|
+
if (newsize >= threshold) {
|
1741
|
+
carFiles.push(await createCarFile(encoder, cidRootBlock.cid, clonedt));
|
1742
|
+
clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
|
1743
|
+
clonedt.putSync(cid, bytes);
|
1744
|
+
cidRootBlock = { cid, bytes };
|
1745
|
+
newsize = CBW.blockLength(toCIDBlock({ cid, bytes }));
|
1746
|
+
} else {
|
1747
|
+
clonedt.putSync(cid, bytes);
|
1748
|
+
}
|
1966
1749
|
}
|
1967
|
-
|
1750
|
+
carFiles.push(await createCarFile(encoder, cidRootBlock.cid, clonedt));
|
1751
|
+
return carFiles;
|
1968
1752
|
}
|
1969
1753
|
|
1970
|
-
// src/blockstore/
|
1971
|
-
var
|
1972
|
-
|
1973
|
-
|
1754
|
+
// src/blockstore/loader.ts
|
1755
|
+
var import_sha23 = require("multiformats/hashes/sha2");
|
1756
|
+
|
1757
|
+
// src/blockstore/task-manager.ts
|
1974
1758
|
init_utils();
|
1975
|
-
var
|
1976
|
-
constructor(
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
this.
|
1982
|
-
}
|
1983
|
-
async get(cid) {
|
1984
|
-
return await this.superGet(cid) || falsyToUndef(await this.parent.get(cid));
|
1759
|
+
var TaskManager = class {
|
1760
|
+
constructor(sthis, callback) {
|
1761
|
+
this.eventsWeHandled = /* @__PURE__ */ new Set();
|
1762
|
+
this.queue = [];
|
1763
|
+
this.isProcessing = false;
|
1764
|
+
this.logger = ensureLogger(sthis, "TaskManager");
|
1765
|
+
this.callback = callback;
|
1985
1766
|
}
|
1986
|
-
async
|
1987
|
-
|
1767
|
+
async handleEvent(cid, parents, dbMeta) {
|
1768
|
+
for (const parent of parents) {
|
1769
|
+
this.eventsWeHandled.add(parent.toString());
|
1770
|
+
}
|
1771
|
+
this.queue.push({ cid: cid.toString(), dbMeta, retries: 0 });
|
1772
|
+
this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
|
1773
|
+
void this.processQueue();
|
1988
1774
|
}
|
1989
|
-
|
1990
|
-
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
return
|
1996
|
-
}
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2001
|
-
|
2002
|
-
|
2003
|
-
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
1775
|
+
async processQueue() {
|
1776
|
+
if (this.isProcessing) return;
|
1777
|
+
this.isProcessing = true;
|
1778
|
+
const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
1779
|
+
const first = filteredQueue[0];
|
1780
|
+
if (!first) {
|
1781
|
+
return;
|
1782
|
+
}
|
1783
|
+
try {
|
1784
|
+
await this.callback(first.dbMeta);
|
1785
|
+
this.eventsWeHandled.add(first.cid);
|
1786
|
+
this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
1787
|
+
} catch (err) {
|
1788
|
+
if (first.retries++ > 3) {
|
1789
|
+
this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
|
1790
|
+
this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
|
1791
|
+
}
|
1792
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
1793
|
+
throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
|
1794
|
+
} finally {
|
1795
|
+
this.isProcessing = false;
|
1796
|
+
if (this.queue.length > 0) {
|
1797
|
+
void this.processQueue();
|
1798
|
+
}
|
1799
|
+
}
|
1800
|
+
}
|
1801
|
+
};
|
1802
|
+
|
1803
|
+
// src/blockstore/loader.ts
|
1804
|
+
function carLogIncludesGroup(list, cids) {
|
1805
|
+
return list.some((arr) => {
|
1806
|
+
return arr.toString() === cids.toString();
|
1807
|
+
});
|
2014
1808
|
}
|
2015
|
-
function
|
2016
|
-
|
1809
|
+
function uniqueCids(list, remove = /* @__PURE__ */ new Set()) {
|
1810
|
+
const byString = /* @__PURE__ */ new Map();
|
1811
|
+
for (const cid of list) {
|
1812
|
+
if (remove.has(cid.toString())) continue;
|
1813
|
+
byString.set(cid.toString(), cid);
|
1814
|
+
}
|
1815
|
+
return [...byString.values()];
|
2017
1816
|
}
|
2018
|
-
var
|
2019
|
-
constructor(ebOpts) {
|
2020
|
-
this.
|
2021
|
-
this.
|
2022
|
-
this.
|
2023
|
-
this.
|
2024
|
-
this.
|
1817
|
+
var Loader = class {
|
1818
|
+
constructor(name, ebOpts, sthis) {
|
1819
|
+
this.commitQueue = new CommitQueue();
|
1820
|
+
this.isCompacting = false;
|
1821
|
+
this.carReaders = /* @__PURE__ */ new Map();
|
1822
|
+
this.seenCompacted = /* @__PURE__ */ new Set();
|
1823
|
+
this.processedCars = /* @__PURE__ */ new Set();
|
1824
|
+
this.carLog = [];
|
1825
|
+
this.getBlockCache = /* @__PURE__ */ new Map();
|
1826
|
+
this.seenMeta = /* @__PURE__ */ new Set();
|
1827
|
+
this.writeLimit = (0, import_p_limit.default)(1);
|
1828
|
+
this.onceReady = new import_cement7.ResolveOnce();
|
1829
|
+
this.name = name;
|
1830
|
+
this.sthis = sthis;
|
1831
|
+
this.ebOpts = defaultedBlockstoreRuntime(
|
1832
|
+
sthis,
|
1833
|
+
{
|
1834
|
+
...ebOpts,
|
1835
|
+
name
|
1836
|
+
},
|
1837
|
+
"Loader"
|
1838
|
+
);
|
2025
1839
|
this.logger = this.ebOpts.logger;
|
1840
|
+
this.taskManager = new TaskManager(sthis, async (dbMeta) => {
|
1841
|
+
await this.handleDbMetasFromStore([dbMeta]);
|
1842
|
+
});
|
2026
1843
|
}
|
2027
|
-
// readonly
|
2028
|
-
|
2029
|
-
|
2030
|
-
|
1844
|
+
// readonly id = uuidv4();
|
1845
|
+
async keyBag() {
|
1846
|
+
return getKeyBag(this.sthis, this.ebOpts.keyBag);
|
1847
|
+
}
|
1848
|
+
async carStore() {
|
1849
|
+
return this.ebOpts.storeRuntime.makeDataStore(this);
|
1850
|
+
}
|
1851
|
+
async fileStore() {
|
1852
|
+
return this.ebOpts.storeRuntime.makeDataStore(this);
|
1853
|
+
}
|
1854
|
+
async WALStore() {
|
1855
|
+
return this.ebOpts.storeRuntime.makeWALStore(this);
|
1856
|
+
}
|
1857
|
+
async metaStore() {
|
1858
|
+
return this.ebOpts.storeRuntime.makeMetaStore(this);
|
1859
|
+
}
|
1860
|
+
async ready() {
|
1861
|
+
return this.onceReady.once(async () => {
|
1862
|
+
const metas = await (await this.metaStore()).load();
|
1863
|
+
if (this.ebOpts.meta) {
|
1864
|
+
await this.handleDbMetasFromStore([this.ebOpts.meta]);
|
1865
|
+
} else if (metas) {
|
1866
|
+
await this.handleDbMetasFromStore(metas);
|
1867
|
+
}
|
1868
|
+
});
|
2031
1869
|
}
|
2032
1870
|
async close() {
|
1871
|
+
const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
|
1872
|
+
await Promise.all(toClose.map((store) => store.close()));
|
2033
1873
|
}
|
2034
1874
|
async destroy() {
|
1875
|
+
const toDestroy = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
|
1876
|
+
await Promise.all(toDestroy.map((store) => store.destroy()));
|
2035
1877
|
}
|
2036
|
-
async
|
1878
|
+
// async snapToCar(carCid: AnyLink | string) {
|
1879
|
+
// await this.ready
|
1880
|
+
// if (typeof carCid === 'string') {
|
1881
|
+
// carCid = CID.parse(carCid)
|
1882
|
+
// }
|
1883
|
+
// const carHeader = await this.loadCarHeaderFromMeta({ car: carCid, key: this.key || null })
|
1884
|
+
// this.carLog = [carCid, ...carHeader.cars]
|
1885
|
+
// await this.getMoreReaders(carHeader.cars)
|
1886
|
+
// await this._applyCarHeader(carHeader, true)
|
1887
|
+
// }
|
1888
|
+
async handleDbMetasFromStore(metas) {
|
1889
|
+
this.logger.Debug().Any("metas", metas).Msg("handleDbMetasFromStore");
|
1890
|
+
for (const meta of metas) {
|
1891
|
+
await this.writeLimit(async () => {
|
1892
|
+
await this.mergeDbMetaIntoClock(meta);
|
1893
|
+
});
|
1894
|
+
}
|
2037
1895
|
}
|
2038
|
-
async
|
2039
|
-
if (
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
1896
|
+
async mergeDbMetaIntoClock(meta) {
|
1897
|
+
if (this.isCompacting) {
|
1898
|
+
throw this.logger.Error().Msg("cannot merge while compacting").AsError();
|
1899
|
+
}
|
1900
|
+
if (this.seenMeta.has(meta.cars.toString())) return;
|
1901
|
+
this.seenMeta.add(meta.cars.toString());
|
1902
|
+
if (carLogIncludesGroup(this.carLog, meta.cars)) {
|
1903
|
+
return;
|
2043
1904
|
}
|
1905
|
+
const carHeader = await this.loadCarHeaderFromMeta(meta);
|
1906
|
+
carHeader.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
|
1907
|
+
await this.getMoreReaders(carHeader.cars.flat());
|
1908
|
+
this.carLog = [...uniqueCids([meta.cars, ...this.carLog, ...carHeader.cars], this.seenCompacted)];
|
1909
|
+
await this.ebOpts.applyMeta?.(carHeader.meta);
|
2044
1910
|
}
|
2045
|
-
//
|
2046
|
-
|
2047
|
-
|
1911
|
+
// protected async ingestKeyFromMeta(meta: DbMeta): Promise<void> {
|
1912
|
+
// const { key } = meta;
|
1913
|
+
// if (key) {
|
1914
|
+
// await this.setKey(key);
|
1915
|
+
// }
|
1916
|
+
// }
|
1917
|
+
async loadCarHeaderFromMeta({ cars: cids }) {
|
1918
|
+
const reader = await this.loadCar(cids[0]);
|
1919
|
+
return await parseCarFile(reader, this.logger);
|
2048
1920
|
}
|
2049
|
-
//
|
2050
|
-
|
2051
|
-
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
|
2057
|
-
|
1921
|
+
// async _getKey(): Promise<string | undefined> {
|
1922
|
+
// if (this.key) return this.key;
|
1923
|
+
// // generate a random key
|
1924
|
+
// if (!this.ebOpts.public) {
|
1925
|
+
// await this.setKey(toHexString(this.ebOpts.crypto.randomBytes(32)));
|
1926
|
+
// }
|
1927
|
+
// return this.key || undefined;
|
1928
|
+
// }
|
1929
|
+
async commitFiles(t, done) {
|
1930
|
+
await this.ready();
|
1931
|
+
const fstore = await this.fileStore();
|
1932
|
+
const wstore = await this.WALStore();
|
1933
|
+
return this.commitQueue.enqueue(() => commitFiles(fstore, wstore, t, done));
|
2058
1934
|
}
|
2059
|
-
|
2060
|
-
return
|
1935
|
+
async loadFileCar(cid) {
|
1936
|
+
return await this.storesLoadCar(cid, await this.fileStore(), this.remoteFileStore);
|
2061
1937
|
}
|
2062
|
-
async
|
2063
|
-
|
2064
|
-
const
|
2065
|
-
|
2066
|
-
|
1938
|
+
async commit(t, done, opts = { noLoader: false, compact: false }) {
|
1939
|
+
await this.ready();
|
1940
|
+
const fstore = await this.fileStore();
|
1941
|
+
const params = {
|
1942
|
+
encoder: (await fstore.keyedCrypto()).codec(),
|
1943
|
+
carLog: this.carLog,
|
1944
|
+
carStore: fstore,
|
1945
|
+
WALStore: await this.WALStore(),
|
1946
|
+
metaStore: await this.metaStore(),
|
1947
|
+
threshold: this.ebOpts.threshold
|
1948
|
+
};
|
1949
|
+
return this.commitQueue.enqueue(async () => {
|
1950
|
+
await this.cacheTransaction(t);
|
1951
|
+
const ret = await commit(params, t, done, opts);
|
1952
|
+
await this.updateCarLog(ret.cgrp, ret.header, !!opts.compact);
|
1953
|
+
return ret.cgrp;
|
1954
|
+
});
|
1955
|
+
}
|
1956
|
+
async updateCarLog(cids, fp, compact) {
|
1957
|
+
if (compact) {
|
1958
|
+
const previousCompactCid = fp.compact[fp.compact.length - 1];
|
1959
|
+
fp.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
|
1960
|
+
this.carLog = [...uniqueCids([...this.carLog, ...fp.cars, cids], this.seenCompacted)];
|
1961
|
+
await this.removeCidsForCompact(previousCompactCid[0]).catch((e) => e);
|
1962
|
+
} else {
|
1963
|
+
this.carLog.unshift(cids);
|
2067
1964
|
}
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
1965
|
+
}
|
1966
|
+
async cacheTransaction(t) {
|
1967
|
+
for await (const block of t.entries()) {
|
1968
|
+
const sBlock = block.cid.toString();
|
1969
|
+
if (!this.getBlockCache.has(sBlock)) {
|
1970
|
+
this.getBlockCache.set(sBlock, block);
|
1971
|
+
}
|
2071
1972
|
}
|
2072
|
-
throw this.logger.Error().Msg("failed to commit car files").AsError();
|
2073
1973
|
}
|
2074
|
-
async
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
|
2080
|
-
|
1974
|
+
async cacheCarReader(carCidStr, reader) {
|
1975
|
+
if (this.processedCars.has(carCidStr)) return;
|
1976
|
+
this.processedCars.add(carCidStr);
|
1977
|
+
for await (const block of reader.blocks()) {
|
1978
|
+
const sBlock = block.cid.toString();
|
1979
|
+
if (!this.getBlockCache.has(sBlock)) {
|
1980
|
+
this.getBlockCache.set(sBlock, block);
|
2081
1981
|
}
|
2082
1982
|
}
|
2083
1983
|
}
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
super(ebOpts);
|
2088
|
-
this.compacting = false;
|
2089
|
-
this.logger = ensureLogger(this.sthis, "EncryptedBlockstore", {
|
2090
|
-
this: 1
|
1984
|
+
async removeCidsForCompact(cid) {
|
1985
|
+
const carHeader = await this.loadCarHeaderFromMeta({
|
1986
|
+
cars: [cid]
|
2091
1987
|
});
|
2092
|
-
|
1988
|
+
for (const cids of carHeader.compact) {
|
1989
|
+
for (const cid2 of cids) {
|
1990
|
+
await (await this.carStore()).remove(cid2);
|
1991
|
+
}
|
1992
|
+
}
|
2093
1993
|
}
|
2094
|
-
|
2095
|
-
|
1994
|
+
// async flushCars() {
|
1995
|
+
// await this.ready
|
1996
|
+
// // for each cid in car log, make a dbMeta
|
1997
|
+
// for (const cid of this.carLog) {
|
1998
|
+
// const dbMeta = { car: cid, key: this.key || null } as DbMeta
|
1999
|
+
// await this.remoteWAL!.enqueue(dbMeta, { public: false })
|
2000
|
+
// }
|
2001
|
+
// }
|
2002
|
+
async *entries(cache2 = true) {
|
2003
|
+
await this.ready();
|
2004
|
+
if (cache2) {
|
2005
|
+
for (const [, block] of this.getBlockCache) {
|
2006
|
+
yield block;
|
2007
|
+
}
|
2008
|
+
} else {
|
2009
|
+
for (const [, block] of this.getBlockCache) {
|
2010
|
+
yield block;
|
2011
|
+
}
|
2012
|
+
for (const cids of this.carLog) {
|
2013
|
+
for (const cid of cids) {
|
2014
|
+
const reader = await this.loadCar(cid);
|
2015
|
+
if (!reader) throw this.logger.Error().Ref("cid", cid).Msg("missing car reader").AsError();
|
2016
|
+
for await (const block of reader.blocks()) {
|
2017
|
+
const sCid = block.cid.toString();
|
2018
|
+
if (!this.getBlockCache.has(sCid)) {
|
2019
|
+
yield block;
|
2020
|
+
}
|
2021
|
+
}
|
2022
|
+
}
|
2023
|
+
}
|
2024
|
+
}
|
2096
2025
|
}
|
2097
|
-
|
2098
|
-
|
2026
|
+
async getBlock(cid) {
|
2027
|
+
await this.ready();
|
2028
|
+
const sCid = cid.toString();
|
2029
|
+
if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
|
2030
|
+
const getCarCid = async (carCid) => {
|
2031
|
+
if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
|
2032
|
+
const reader = await this.loadCar(carCid);
|
2033
|
+
if (!reader) {
|
2034
|
+
throw this.logger.Error().Ref("cid", carCid).Msg("missing car reader").AsError();
|
2035
|
+
}
|
2036
|
+
await this.cacheCarReader(carCid.toString(), reader).catch(() => {
|
2037
|
+
return;
|
2038
|
+
});
|
2039
|
+
if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
|
2040
|
+
throw this.logger.Error().Str("cid", sCid).Msg("block not in reader").AsError();
|
2041
|
+
};
|
2042
|
+
const getCompactCarCids = async (carCid) => {
|
2043
|
+
const reader = await this.loadCar(carCid);
|
2044
|
+
if (!reader) {
|
2045
|
+
throw this.logger.Error().Str("cid", carCid.toString()).Msg("missing car reader").AsError();
|
2046
|
+
}
|
2047
|
+
const header = await parseCarFile(reader, this.logger);
|
2048
|
+
const compacts = header.compact;
|
2049
|
+
let got2;
|
2050
|
+
const batchSize2 = 5;
|
2051
|
+
for (let i = 0; i < compacts.length; i += batchSize2) {
|
2052
|
+
const promises = [];
|
2053
|
+
for (let j = i; j < Math.min(i + batchSize2, compacts.length); j++) {
|
2054
|
+
for (const cid2 of compacts[j]) {
|
2055
|
+
promises.push(getCarCid(cid2));
|
2056
|
+
}
|
2057
|
+
}
|
2058
|
+
try {
|
2059
|
+
got2 = await Promise.any(promises);
|
2060
|
+
} catch {
|
2061
|
+
}
|
2062
|
+
if (got2) break;
|
2063
|
+
}
|
2064
|
+
if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
|
2065
|
+
throw this.logger.Error().Str("cid", sCid).Msg("block not in compact reader").AsError();
|
2066
|
+
};
|
2067
|
+
let got;
|
2068
|
+
const batchSize = 5;
|
2069
|
+
for (let i = 0; i < this.carLog.length; i += batchSize) {
|
2070
|
+
const batch = this.carLog.slice(i, i + batchSize);
|
2071
|
+
const promises = batch.flatMap((slice) => slice.map(getCarCid));
|
2072
|
+
try {
|
2073
|
+
got = await Promise.any(promises);
|
2074
|
+
} catch {
|
2075
|
+
}
|
2076
|
+
if (got) break;
|
2077
|
+
}
|
2078
|
+
if (!got) {
|
2079
|
+
try {
|
2080
|
+
got = await getCompactCarCids(this.carLog[this.carLog.length - 1][0]);
|
2081
|
+
} catch {
|
2082
|
+
}
|
2083
|
+
}
|
2084
|
+
return got;
|
2099
2085
|
}
|
2100
|
-
|
2101
|
-
|
2086
|
+
async loadCar(cid) {
|
2087
|
+
if (!this.carStore) {
|
2088
|
+
throw this.logger.Error().Msg("car store not initialized").AsError();
|
2089
|
+
}
|
2090
|
+
const loaded = await this.storesLoadCar(cid, await this.carStore(), this.remoteCarStore);
|
2091
|
+
return loaded;
|
2102
2092
|
}
|
2103
|
-
async
|
2104
|
-
const
|
2105
|
-
|
2106
|
-
|
2107
|
-
|
2093
|
+
async makeDecoderAndCarReader(cid, local, remote) {
|
2094
|
+
const cidsString = cid.toString();
|
2095
|
+
let loadedCar = void 0;
|
2096
|
+
let activeStore = local;
|
2097
|
+
try {
|
2098
|
+
this.logger.Debug().Str("cid", cidsString).Msg("loading car");
|
2099
|
+
loadedCar = await local.load(cid);
|
2100
|
+
this.logger.Debug().Bool("loadedCar", loadedCar).Msg("loaded");
|
2101
|
+
} catch (e) {
|
2102
|
+
if (remote) {
|
2103
|
+
const remoteCar = await remote.load(cid);
|
2104
|
+
if (remoteCar) {
|
2105
|
+
this.logger.Debug().Ref("cid", remoteCar.cid).Msg("saving remote car locally");
|
2106
|
+
await local.save(remoteCar);
|
2107
|
+
loadedCar = remoteCar;
|
2108
|
+
activeStore = remote;
|
2109
|
+
}
|
2110
|
+
} else {
|
2111
|
+
this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
|
2112
|
+
}
|
2108
2113
|
}
|
2109
|
-
|
2114
|
+
if (!loadedCar) {
|
2115
|
+
throw this.logger.Error().Url(local.url()).Str("cid", cidsString).Msg("missing car files").AsError();
|
2116
|
+
}
|
2117
|
+
const bytes = await decode({ bytes: loadedCar.bytes, hasher: import_sha23.sha256, codec: (await activeStore.keyedCrypto()).codec() });
|
2118
|
+
const rawReader = await import_car.CarReader.fromBytes(bytes.value);
|
2119
|
+
const readerP = Promise.resolve(rawReader);
|
2120
|
+
const cachedReaderP = readerP.then(async (reader) => {
|
2121
|
+
await this.cacheCarReader(cidsString, reader).catch((e) => {
|
2122
|
+
this.logger.Error().Err(e).Str("cid", cidsString).Msg("error caching car reader");
|
2123
|
+
return;
|
2124
|
+
});
|
2125
|
+
return reader;
|
2126
|
+
});
|
2127
|
+
this.carReaders.set(cidsString, cachedReaderP);
|
2128
|
+
return readerP;
|
2110
2129
|
}
|
2111
|
-
|
2112
|
-
|
2113
|
-
const
|
2114
|
-
this.
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
setTimeout(() => void this.compact(), 10);
|
2130
|
+
//What if instead it returns an Array of CarHeader
|
2131
|
+
async storesLoadCar(cid, local, remote) {
|
2132
|
+
const cidsString = cid.toString();
|
2133
|
+
let dacr = this.carReaders.get(cidsString);
|
2134
|
+
if (!dacr) {
|
2135
|
+
dacr = this.makeDecoderAndCarReader(cid, local, remote);
|
2136
|
+
this.carReaders.set(cidsString, dacr);
|
2119
2137
|
}
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2138
|
+
return dacr;
|
2139
|
+
}
|
2140
|
+
async getMoreReaders(cids) {
|
2141
|
+
const limit = (0, import_p_limit.default)(5);
|
2142
|
+
const missing = cids.filter((cid) => !this.carReaders.has(cid.toString()));
|
2143
|
+
await Promise.all(missing.map((cid) => limit(() => this.loadCar(cid))));
|
2144
|
+
}
|
2145
|
+
};
|
2146
|
+
|
2147
|
+
// src/runtime/keyed-crypto.ts
|
2148
|
+
var keyed_crypto_exports = {};
|
2149
|
+
__export(keyed_crypto_exports, {
|
2150
|
+
BlockIvKeyIdCodec: () => BlockIvKeyIdCodec,
|
2151
|
+
keyedCryptoFactory: () => keyedCryptoFactory
|
2152
|
+
});
|
2153
|
+
init_utils();
|
2154
|
+
var import_base583 = require("multiformats/bases/base58");
|
2155
|
+
var import_sha24 = require("multiformats/hashes/sha2");
|
2156
|
+
var CBOR = __toESM(require("cborg"), 1);
|
2157
|
+
var generateIV = {
|
2158
|
+
random: {
|
2159
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
2160
|
+
calc: async (ko, crypto, data) => {
|
2161
|
+
return crypto.randomBytes(ko.ivLength);
|
2162
|
+
},
|
2163
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
2164
|
+
verify: async (ko, crypto, iv, data) => {
|
2165
|
+
return true;
|
2166
|
+
}
|
2167
|
+
},
|
2168
|
+
hash: {
|
2169
|
+
calc: async (ko, crypto, data) => {
|
2170
|
+
const hash = await import_sha24.sha256.digest(data);
|
2171
|
+
const hashBytes = new Uint8Array(hash.bytes);
|
2172
|
+
const hashArray = new Uint8Array(ko.ivLength);
|
2173
|
+
for (let i = 0; i < hashBytes.length; i++) {
|
2174
|
+
hashArray[i % ko.ivLength] ^= hashBytes[i];
|
2175
|
+
}
|
2176
|
+
return hashArray;
|
2177
|
+
},
|
2178
|
+
verify: async function(ko, crypto, iv, data) {
|
2179
|
+
return ko.url.getParam("ivverify") !== "disable" && UInt8ArrayEqual(iv, await this.calc(ko, crypto, data));
|
2123
2180
|
}
|
2124
|
-
throw this.logger.Error().Msg("failed to commit car files").AsError();
|
2125
2181
|
}
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
2182
|
+
};
|
2183
|
+
function getGenerateIVFn(url, opts) {
|
2184
|
+
const ivhash = opts.ivCalc || url.getParam("ivhash") || "hash";
|
2185
|
+
return generateIV[ivhash] || generateIV["hash"];
|
2186
|
+
}
|
2187
|
+
var BlockIvKeyIdCodec = class {
|
2188
|
+
constructor(ko, iv, opts) {
|
2189
|
+
this.code = 3147065;
|
2190
|
+
this.name = "Fireproof@encrypted-block:aes-gcm";
|
2191
|
+
this.ko = ko;
|
2192
|
+
this.iv = iv;
|
2193
|
+
this.opts = opts || {};
|
2136
2194
|
}
|
2137
|
-
async
|
2138
|
-
await this.
|
2139
|
-
|
2140
|
-
|
2141
|
-
const
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
compact: true,
|
2148
|
-
noLoader: true
|
2195
|
+
async encode(data) {
|
2196
|
+
const calcIv = this.iv || await getGenerateIVFn(this.ko.url, this.opts).calc(this.ko, this.ko.crypto, data);
|
2197
|
+
const { iv } = this.ko.algo(calcIv);
|
2198
|
+
const fprt = await this.ko.fingerPrint();
|
2199
|
+
const keyId = import_base583.base58btc.decode(fprt);
|
2200
|
+
this.ko.logger.Debug().Str("fp", fprt).Msg("encode");
|
2201
|
+
return CBOR.encode({
|
2202
|
+
iv,
|
2203
|
+
keyId,
|
2204
|
+
data: await this.ko._encrypt({ iv, bytes: data })
|
2149
2205
|
});
|
2150
|
-
this.compacting = false;
|
2151
2206
|
}
|
2152
|
-
async
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
2157
|
-
|
2158
|
-
}
|
2159
|
-
for await (const blk of this.loader.entries(false)) {
|
2160
|
-
blocks.loggedBlocks.putSync(blk.cid, blk.bytes);
|
2207
|
+
async decode(abytes) {
|
2208
|
+
let bytes;
|
2209
|
+
if (abytes instanceof Uint8Array) {
|
2210
|
+
bytes = abytes;
|
2211
|
+
} else {
|
2212
|
+
bytes = new Uint8Array(abytes);
|
2161
2213
|
}
|
2162
|
-
|
2163
|
-
|
2164
|
-
|
2165
|
-
|
2214
|
+
const { iv, keyId, data } = CBOR.decode(bytes);
|
2215
|
+
const fprt = await this.ko.fingerPrint();
|
2216
|
+
this.ko.logger.Debug().Str("fp", import_base583.base58btc.encode(keyId)).Msg("decode");
|
2217
|
+
if (import_base583.base58btc.encode(keyId) !== fprt) {
|
2218
|
+
throw this.ko.logger.Error().Str("fp", fprt).Str("keyId", import_base583.base58btc.encode(keyId)).Msg("keyId mismatch").AsError();
|
2166
2219
|
}
|
2167
|
-
|
2168
|
-
|
2169
|
-
|
2170
|
-
for await (const blk of this.loader.entries()) {
|
2171
|
-
yield blk;
|
2220
|
+
const result = await this.ko._decrypt({ iv, bytes: data });
|
2221
|
+
if (!this.opts?.noIVVerify && !await getGenerateIVFn(this.ko.url, this.opts).verify(this.ko, this.ko.crypto, iv, result)) {
|
2222
|
+
throw this.ko.logger.Error().Msg("iv missmatch").AsError();
|
2172
2223
|
}
|
2224
|
+
return result;
|
2173
2225
|
}
|
2174
2226
|
};
|
2175
|
-
var
|
2176
|
-
constructor(
|
2177
|
-
this.
|
2178
|
-
this.
|
2227
|
+
var keyedCrypto = class {
|
2228
|
+
constructor(url, key, cyopt, sthis) {
|
2229
|
+
this.ivLength = 12;
|
2230
|
+
this.isEncrypting = true;
|
2231
|
+
this.logger = ensureLogger(sthis, "keyedCrypto");
|
2232
|
+
this.crypto = cyopt;
|
2233
|
+
this.key = key;
|
2234
|
+
this.url = url;
|
2179
2235
|
}
|
2180
|
-
|
2181
|
-
|
2182
|
-
if (block) this.loggedBlocks.putSync(cid, block.bytes);
|
2183
|
-
return falsyToUndef(block);
|
2236
|
+
fingerPrint() {
|
2237
|
+
return Promise.resolve(this.key.fingerPrint);
|
2184
2238
|
}
|
2185
|
-
|
2186
|
-
|
2187
|
-
// src/blockstore/commitor.ts
|
2188
|
-
var CBW = __toESM(require("@ipld/car/buffer-writer"), 1);
|
2189
|
-
var import_sha23 = require("multiformats/hashes/sha2");
|
2190
|
-
var dagCodec2 = __toESM(require("@ipld/dag-cbor"), 1);
|
2191
|
-
async function encodeCarFile(roots, t, codec3) {
|
2192
|
-
let size = 0;
|
2193
|
-
const headerSize = CBW.headerLength({ roots });
|
2194
|
-
size += headerSize;
|
2195
|
-
for (const { cid, bytes } of t.entries()) {
|
2196
|
-
size += CBW.blockLength({ cid, bytes });
|
2239
|
+
codec(iv, opts) {
|
2240
|
+
return new BlockIvKeyIdCodec(this, iv, opts);
|
2197
2241
|
}
|
2198
|
-
|
2199
|
-
|
2200
|
-
|
2201
|
-
|
2242
|
+
algo(iv) {
|
2243
|
+
return {
|
2244
|
+
name: "AES-GCM",
|
2245
|
+
iv: iv || this.crypto.randomBytes(this.ivLength),
|
2246
|
+
tagLength: 128
|
2247
|
+
};
|
2202
2248
|
}
|
2203
|
-
|
2204
|
-
|
2249
|
+
async _decrypt(data) {
|
2250
|
+
this.logger.Debug().Len(data.bytes, "bytes").Len(data.iv, "iv").Str("fp", this.key.fingerPrint).Msg("decrypting");
|
2251
|
+
return new Uint8Array(await this.crypto.decrypt(this.algo(data.iv), this.key.key, data.bytes));
|
2205
2252
|
}
|
2206
|
-
|
2207
|
-
|
2208
|
-
|
2209
|
-
|
2210
|
-
return encodeCarFile([cid], t, encoder);
|
2211
|
-
}
|
2212
|
-
async function commitFiles(fileStore, walStore, t, done) {
|
2213
|
-
const { files: roots } = makeFileCarHeader(done);
|
2214
|
-
const cids = [];
|
2215
|
-
const codec3 = (await fileStore.keyedCrypto()).codec();
|
2216
|
-
const cars = await prepareCarFilesFiles(codec3, roots, t);
|
2217
|
-
for (const car of cars) {
|
2218
|
-
const { cid, bytes } = car;
|
2219
|
-
await fileStore.save({ cid, bytes });
|
2220
|
-
await walStore.enqueueFile(
|
2221
|
-
cid
|
2222
|
-
/*, !!opts.public*/
|
2223
|
-
);
|
2224
|
-
cids.push(cid);
|
2253
|
+
async _encrypt(data) {
|
2254
|
+
this.logger.Debug().Len(data.bytes).Str("fp", this.key.fingerPrint).Msg("encrypting");
|
2255
|
+
const a = this.algo(data.iv);
|
2256
|
+
return new Uint8Array(await this.crypto.encrypt(a, this.key.key, data.bytes));
|
2225
2257
|
}
|
2226
|
-
|
2227
|
-
|
2228
|
-
|
2229
|
-
|
2230
|
-
|
2231
|
-
if (meta && typeof meta === "object" && "cid" in meta && meta !== null) {
|
2232
|
-
files.push(meta.cid);
|
2233
|
-
}
|
2258
|
+
};
|
2259
|
+
var nullCodec = class {
|
2260
|
+
constructor() {
|
2261
|
+
this.code = 0;
|
2262
|
+
this.name = "Fireproof@unencrypted-block";
|
2234
2263
|
}
|
2235
|
-
|
2236
|
-
|
2237
|
-
async function prepareCarFilesFiles(encoder, roots, t) {
|
2238
|
-
return [await encodeCarFile(roots, t, encoder)];
|
2239
|
-
}
|
2240
|
-
function makeCarHeader(meta, cars, compact = false) {
|
2241
|
-
const coreHeader = compact ? { cars: [], compact: cars } : { cars, compact: [] };
|
2242
|
-
return { ...coreHeader, meta };
|
2243
|
-
}
|
2244
|
-
async function encodeCarHeader(fp) {
|
2245
|
-
return await encode3({
|
2246
|
-
value: { fp },
|
2247
|
-
hasher: import_sha23.sha256,
|
2248
|
-
codec: dagCodec2
|
2249
|
-
});
|
2250
|
-
}
|
2251
|
-
async function commit(params, t, done, opts = { noLoader: false, compact: false }) {
|
2252
|
-
const fp = makeCarHeader(done, params.carLog, !!opts.compact);
|
2253
|
-
const rootBlock = await encodeCarHeader(fp);
|
2254
|
-
const cars = await prepareCarFiles(params.encoder, params.threshold, rootBlock, t);
|
2255
|
-
const cids = [];
|
2256
|
-
for (const car of cars) {
|
2257
|
-
const { cid, bytes } = car;
|
2258
|
-
await params.carStore.save({ cid, bytes });
|
2259
|
-
cids.push(cid);
|
2264
|
+
encode(data) {
|
2265
|
+
return data;
|
2260
2266
|
}
|
2261
|
-
|
2262
|
-
|
2263
|
-
await params.metaStore.save(newDbMeta);
|
2264
|
-
return { cgrp: cids, header: fp };
|
2265
|
-
}
|
2266
|
-
async function prepareCarFiles(encoder, threshold, rootBlock, t) {
|
2267
|
-
const carFiles = [];
|
2268
|
-
threshold = threshold || 128e3 * 8;
|
2269
|
-
let clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
|
2270
|
-
clonedt.putSync(rootBlock.cid, rootBlock.bytes);
|
2271
|
-
let newsize = CBW.blockLength(toCIDBlock(rootBlock));
|
2272
|
-
let cidRootBlock = rootBlock;
|
2273
|
-
for (const { cid, bytes } of t.entries()) {
|
2274
|
-
newsize += CBW.blockLength(toCIDBlock({ cid, bytes }));
|
2275
|
-
if (newsize >= threshold) {
|
2276
|
-
carFiles.push(await createCarFile(encoder, cidRootBlock.cid, clonedt));
|
2277
|
-
clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
|
2278
|
-
clonedt.putSync(cid, bytes);
|
2279
|
-
cidRootBlock = { cid, bytes };
|
2280
|
-
newsize = CBW.blockLength(toCIDBlock({ cid, bytes }));
|
2281
|
-
} else {
|
2282
|
-
clonedt.putSync(cid, bytes);
|
2283
|
-
}
|
2267
|
+
decode(data) {
|
2268
|
+
return data;
|
2284
2269
|
}
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2296
|
-
this.eventsWeHandled = /* @__PURE__ */ new Set();
|
2297
|
-
this.queue = [];
|
2298
|
-
this.isProcessing = false;
|
2299
|
-
this.logger = ensureLogger(sthis, "TaskManager");
|
2300
|
-
this.callback = callback;
|
2270
|
+
};
|
2271
|
+
var noCrypto = class {
|
2272
|
+
constructor(url, cyrt, sthis) {
|
2273
|
+
this.ivLength = 0;
|
2274
|
+
this.code = 0;
|
2275
|
+
this.name = "Fireproof@unencrypted-block";
|
2276
|
+
this.isEncrypting = false;
|
2277
|
+
this._fingerPrint = "noCrypto:" + Math.random();
|
2278
|
+
this.logger = ensureLogger(sthis, "noCrypto");
|
2279
|
+
this.crypto = cyrt;
|
2280
|
+
this.url = url;
|
2301
2281
|
}
|
2302
|
-
|
2303
|
-
|
2304
|
-
this.eventsWeHandled.add(parent.toString());
|
2305
|
-
}
|
2306
|
-
this.queue.push({ cid: cid.toString(), dbMeta, retries: 0 });
|
2307
|
-
this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
|
2308
|
-
void this.processQueue();
|
2282
|
+
fingerPrint() {
|
2283
|
+
return Promise.resolve(this._fingerPrint);
|
2309
2284
|
}
|
2310
|
-
|
2311
|
-
|
2312
|
-
|
2313
|
-
|
2314
|
-
|
2315
|
-
|
2316
|
-
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2320
|
-
|
2321
|
-
|
2322
|
-
|
2323
|
-
|
2324
|
-
|
2325
|
-
|
2326
|
-
|
2327
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
2328
|
-
throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
|
2329
|
-
} finally {
|
2330
|
-
this.isProcessing = false;
|
2331
|
-
if (this.queue.length > 0) {
|
2332
|
-
void this.processQueue();
|
2333
|
-
}
|
2334
|
-
}
|
2285
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
2286
|
+
codec(iv) {
|
2287
|
+
return new nullCodec();
|
2288
|
+
}
|
2289
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
2290
|
+
algo(iv) {
|
2291
|
+
return {
|
2292
|
+
name: "noCrypto",
|
2293
|
+
iv: new Uint8Array(),
|
2294
|
+
tagLength: 0
|
2295
|
+
};
|
2296
|
+
}
|
2297
|
+
_decrypt() {
|
2298
|
+
throw this.logger.Error().Msg("noCrypto.decrypt not implemented").AsError();
|
2299
|
+
}
|
2300
|
+
_encrypt() {
|
2301
|
+
throw this.logger.Error().Msg("noCrypto.decrypt not implemented").AsError();
|
2335
2302
|
}
|
2336
2303
|
};
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2343
|
-
|
2344
|
-
|
2345
|
-
|
2346
|
-
|
2347
|
-
|
2348
|
-
|
2304
|
+
async function keyedCryptoFactory(url, kb, sthis) {
|
2305
|
+
const storekey = url.getParam("storekey");
|
2306
|
+
if (storekey && storekey !== "insecure") {
|
2307
|
+
let rkey = await kb.getNamedKey(storekey, true);
|
2308
|
+
if (rkey.isErr()) {
|
2309
|
+
try {
|
2310
|
+
rkey = await kb.toKeyWithFingerPrint(storekey);
|
2311
|
+
} catch (e) {
|
2312
|
+
throw sthis.logger.Error().Err(e).Str("keybag", kb.rt.id()).Str("name", storekey).Msg("getNamedKey failed").AsError();
|
2313
|
+
}
|
2314
|
+
}
|
2315
|
+
return new keyedCrypto(url, rkey.Ok(), kb.rt.crypto, sthis);
|
2349
2316
|
}
|
2350
|
-
return
|
2317
|
+
return new noCrypto(url, kb.rt.crypto, sthis);
|
2351
2318
|
}
|
2352
|
-
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
this._carStore = new import_cement9.ResolveOnce();
|
2364
|
-
this._fileStore = new import_cement9.ResolveOnce();
|
2365
|
-
this._WALStore = new import_cement9.ResolveOnce();
|
2366
|
-
this._metaStore = new import_cement9.ResolveOnce();
|
2367
|
-
this.onceReady = new import_cement9.ResolveOnce();
|
2368
|
-
this.sthis = sthis;
|
2369
|
-
this.ebOpts = defaultedBlockstoreRuntime(
|
2370
|
-
sthis,
|
2371
|
-
{
|
2372
|
-
...ebOpts
|
2373
|
-
// name,
|
2374
|
-
},
|
2375
|
-
"Loader"
|
2376
|
-
);
|
2377
|
-
this.logger = this.ebOpts.logger;
|
2378
|
-
this.taskManager = new TaskManager(sthis, async (dbMeta) => {
|
2379
|
-
await this.handleDbMetasFromStore([dbMeta]);
|
2380
|
-
});
|
2319
|
+
|
2320
|
+
// src/blockstore/fragment-gateway.ts
|
2321
|
+
var import_cement8 = require("@adviser/cement");
|
2322
|
+
var import_base584 = require("multiformats/bases/base58");
|
2323
|
+
var import_cborg = require("cborg");
|
2324
|
+
init_utils();
|
2325
|
+
function getFragSize(url) {
|
2326
|
+
const fragSize = url.getParam("fragSize");
|
2327
|
+
let ret = 0;
|
2328
|
+
if (fragSize) {
|
2329
|
+
ret = parseInt(fragSize);
|
2381
2330
|
}
|
2382
|
-
|
2383
|
-
|
2384
|
-
async () => this.ebOpts.storeRuntime.makeDataStore({
|
2385
|
-
sthis: this.sthis,
|
2386
|
-
url: this.ebOpts.storeUrls.data,
|
2387
|
-
keybag: await this.keyBag()
|
2388
|
-
})
|
2389
|
-
);
|
2331
|
+
if (isNaN(ret) || ret <= 0) {
|
2332
|
+
ret = 0;
|
2390
2333
|
}
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
|
2396
|
-
|
2334
|
+
return ret;
|
2335
|
+
}
|
2336
|
+
async function getFrags(url, innerGW, headerSize, logger) {
|
2337
|
+
const fragSize = getFragSize(url);
|
2338
|
+
if (!fragSize) {
|
2339
|
+
const res = await innerGW.get(url);
|
2340
|
+
if (res.isErr()) {
|
2341
|
+
return [res];
|
2342
|
+
}
|
2343
|
+
const data = res.unwrap();
|
2344
|
+
return [
|
2345
|
+
import_cement8.Result.Ok({
|
2346
|
+
fid: new Uint8Array(0),
|
2347
|
+
ofs: 0,
|
2348
|
+
len: data.length,
|
2349
|
+
data
|
2397
2350
|
})
|
2398
|
-
|
2351
|
+
];
|
2399
2352
|
}
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
sthis: this.sthis,
|
2404
|
-
url: this.ebOpts.storeUrls.wal,
|
2405
|
-
keybag: await this.keyBag()
|
2406
|
-
})
|
2407
|
-
);
|
2353
|
+
const firstRaw = await innerGW.get(url.build().setParam("ofs", "0").URI());
|
2354
|
+
if (firstRaw.isErr()) {
|
2355
|
+
return [firstRaw];
|
2408
2356
|
}
|
2409
|
-
|
2410
|
-
|
2411
|
-
|
2412
|
-
|
2413
|
-
|
2414
|
-
|
2415
|
-
|
2357
|
+
const firstFragment = (0, import_cborg.decode)(firstRaw.unwrap());
|
2358
|
+
const blockSize = firstFragment.data.length;
|
2359
|
+
const ops = [Promise.resolve(import_cement8.Result.Ok(firstFragment))];
|
2360
|
+
const fidStr = import_base584.base58btc.encode(firstFragment.fid);
|
2361
|
+
const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
|
2362
|
+
for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
|
2363
|
+
ops.push(
|
2364
|
+
(async (furl, ofs2) => {
|
2365
|
+
const raw2 = await innerGW.get(furl);
|
2366
|
+
if (raw2.isErr()) {
|
2367
|
+
return raw2;
|
2368
|
+
}
|
2369
|
+
const fragment = (0, import_cborg.decode)(raw2.unwrap());
|
2370
|
+
if (import_base584.base58btc.encode(fragment.fid) !== fidStr) {
|
2371
|
+
return import_cement8.Result.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
|
2372
|
+
}
|
2373
|
+
if (fragment.ofs !== ofs2) {
|
2374
|
+
return import_cement8.Result.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
|
2375
|
+
}
|
2376
|
+
return import_cement8.Result.Ok(fragment);
|
2377
|
+
})(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
|
2416
2378
|
);
|
2417
2379
|
}
|
2418
|
-
|
2419
|
-
|
2420
|
-
|
2421
|
-
|
2422
|
-
|
2423
|
-
|
2424
|
-
|
2425
|
-
|
2426
|
-
|
2427
|
-
await this.handleDbMetasFromStore(metas);
|
2428
|
-
}
|
2429
|
-
});
|
2430
|
-
}
|
2431
|
-
async close() {
|
2432
|
-
await this.commitQueue.waitIdle();
|
2433
|
-
const toClose = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
|
2434
|
-
await Promise.all(toClose.map((store) => store.close()));
|
2435
|
-
}
|
2436
|
-
async destroy() {
|
2437
|
-
const toDestroy = await Promise.all([this.carStore(), this.metaStore(), this.fileStore(), this.WALStore()]);
|
2438
|
-
await Promise.all(toDestroy.map((store) => store.destroy()));
|
2380
|
+
return Promise.all(ops);
|
2381
|
+
}
|
2382
|
+
var FragmentGateway = class {
|
2383
|
+
constructor(sthis, innerGW) {
|
2384
|
+
this.fidLength = 4;
|
2385
|
+
this.headerSize = 32;
|
2386
|
+
this.sthis = ensureSuperLog(sthis, "FragmentGateway");
|
2387
|
+
this.logger = this.sthis.logger;
|
2388
|
+
this.innerGW = innerGW;
|
2439
2389
|
}
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
// }
|
2445
|
-
// const carHeader = await this.loadCarHeaderFromMeta({ car: carCid, key: this.key || null })
|
2446
|
-
// this.carLog = [carCid, ...carHeader.cars]
|
2447
|
-
// await this.getMoreReaders(carHeader.cars)
|
2448
|
-
// await this._applyCarHeader(carHeader, true)
|
2449
|
-
// }
|
2450
|
-
async handleDbMetasFromStore(metas) {
|
2451
|
-
this.logger.Debug().Any("metas", metas).Msg("handleDbMetasFromStore");
|
2452
|
-
for (const meta of metas) {
|
2453
|
-
await this.writeLimit(async () => {
|
2454
|
-
await this.mergeDbMetaIntoClock(meta);
|
2455
|
-
});
|
2390
|
+
slicer(url, body) {
|
2391
|
+
const fragSize = getFragSize(url);
|
2392
|
+
if (!fragSize) {
|
2393
|
+
return [this.innerGW.put(url, body)];
|
2456
2394
|
}
|
2457
|
-
|
2458
|
-
|
2459
|
-
|
2460
|
-
throw this.logger.Error().Msg("cannot merge while compacting").AsError();
|
2395
|
+
const blocksize = fragSize - this.headerSize;
|
2396
|
+
if (blocksize <= 0) {
|
2397
|
+
throw this.logger.Error().Uint64("fragSize", fragSize).Uint64("headerSize", this.headerSize).Msg("Fragment size is too small").AsError();
|
2461
2398
|
}
|
2462
|
-
|
2463
|
-
this.
|
2464
|
-
|
2465
|
-
|
2399
|
+
const ops = [];
|
2400
|
+
const fid = this.sthis.nextId(this.fidLength);
|
2401
|
+
const fragUrl = url.build().setParam("fid", fid.str).setParam("len", body.length.toString()).setParam("headerSize", this.headerSize.toString());
|
2402
|
+
for (let ofs = 0; ofs < body.length; ofs += blocksize) {
|
2403
|
+
const block = (0, import_cborg.encode)({
|
2404
|
+
fid: fid.bin,
|
2405
|
+
ofs,
|
2406
|
+
len: body.length,
|
2407
|
+
data: body.slice(ofs, ofs + blocksize)
|
2408
|
+
});
|
2409
|
+
if (block.length > fragSize) {
|
2410
|
+
throw this.logger.Error().Uint64("block", block.length).Uint64("fragSize", fragSize).Msg("Block size to big").AsError();
|
2411
|
+
}
|
2412
|
+
ops.push(this.innerGW.put(fragUrl.setParam("ofs", ofs.toString()).URI(), block));
|
2466
2413
|
}
|
2467
|
-
|
2468
|
-
carHeader.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
|
2469
|
-
await this.getMoreReaders(carHeader.cars.flat());
|
2470
|
-
this.carLog = [...uniqueCids([meta.cars, ...this.carLog, ...carHeader.cars], this.seenCompacted)];
|
2471
|
-
await this.ebOpts.applyMeta?.(carHeader.meta);
|
2472
|
-
}
|
2473
|
-
// protected async ingestKeyFromMeta(meta: DbMeta): Promise<void> {
|
2474
|
-
// const { key } = meta;
|
2475
|
-
// if (key) {
|
2476
|
-
// await this.setKey(key);
|
2477
|
-
// }
|
2478
|
-
// }
|
2479
|
-
async loadCarHeaderFromMeta({ cars: cids }) {
|
2480
|
-
const reader = await this.loadCar(cids[0]);
|
2481
|
-
return await parseCarFile(reader, this.logger);
|
2482
|
-
}
|
2483
|
-
// async _getKey(): Promise<string | undefined> {
|
2484
|
-
// if (this.key) return this.key;
|
2485
|
-
// // generate a random key
|
2486
|
-
// if (!this.ebOpts.public) {
|
2487
|
-
// await this.setKey(toHexString(this.ebOpts.crypto.randomBytes(32)));
|
2488
|
-
// }
|
2489
|
-
// return this.key || undefined;
|
2490
|
-
// }
|
2491
|
-
async commitFiles(t, done) {
|
2492
|
-
await this.ready();
|
2493
|
-
const fstore = await this.fileStore();
|
2494
|
-
const wstore = await this.WALStore();
|
2495
|
-
return this.commitQueue.enqueue(() => commitFiles(fstore, wstore, t, done));
|
2414
|
+
return ops;
|
2496
2415
|
}
|
2497
|
-
|
2498
|
-
return
|
2416
|
+
buildUrl(baseUrl, key) {
|
2417
|
+
return this.innerGW.buildUrl(baseUrl, key);
|
2499
2418
|
}
|
2500
|
-
async
|
2501
|
-
|
2502
|
-
const carStore = await this.carStore();
|
2503
|
-
const params = {
|
2504
|
-
encoder: (await carStore.keyedCrypto()).codec(),
|
2505
|
-
carLog: this.carLog,
|
2506
|
-
carStore,
|
2507
|
-
WALStore: await this.WALStore(),
|
2508
|
-
metaStore: await this.metaStore(),
|
2509
|
-
threshold: this.ebOpts.threshold
|
2510
|
-
};
|
2511
|
-
return this.commitQueue.enqueue(async () => {
|
2512
|
-
await this.cacheTransaction(t);
|
2513
|
-
const ret = await commit(params, t, done, opts);
|
2514
|
-
await this.updateCarLog(ret.cgrp, ret.header, !!opts.compact);
|
2515
|
-
return ret.cgrp;
|
2516
|
-
});
|
2419
|
+
async destroy(iurl) {
|
2420
|
+
return this.innerGW.destroy(iurl);
|
2517
2421
|
}
|
2518
|
-
async
|
2519
|
-
|
2520
|
-
|
2521
|
-
|
2522
|
-
|
2523
|
-
|
2524
|
-
|
2525
|
-
|
2526
|
-
}
|
2422
|
+
async start(url) {
|
2423
|
+
this.headerSize = (0, import_cborg.encode)({
|
2424
|
+
fid: this.sthis.nextId(this.fidLength).bin,
|
2425
|
+
ofs: 1024 * 1024,
|
2426
|
+
// 32bit
|
2427
|
+
len: 16 * 1024 * 1024,
|
2428
|
+
// 32bit
|
2429
|
+
data: new Uint8Array(1024)
|
2430
|
+
}).length - 1024;
|
2431
|
+
return this.innerGW.start(url);
|
2527
2432
|
}
|
2528
|
-
async
|
2529
|
-
|
2530
|
-
const sBlock = block.cid.toString();
|
2531
|
-
if (!this.getBlockCache.has(sBlock)) {
|
2532
|
-
this.getBlockCache.set(sBlock, block);
|
2533
|
-
}
|
2534
|
-
}
|
2433
|
+
async close(url) {
|
2434
|
+
return this.innerGW.close(url);
|
2535
2435
|
}
|
2536
|
-
async
|
2537
|
-
|
2538
|
-
|
2539
|
-
for await (const block of reader.blocks()) {
|
2540
|
-
const sBlock = block.cid.toString();
|
2541
|
-
if (!this.getBlockCache.has(sBlock)) {
|
2542
|
-
this.getBlockCache.set(sBlock, block);
|
2543
|
-
}
|
2544
|
-
}
|
2436
|
+
async put(url, body) {
|
2437
|
+
await Promise.all(this.slicer(url, body));
|
2438
|
+
return import_cement8.Result.Ok(void 0);
|
2545
2439
|
}
|
2546
|
-
async
|
2547
|
-
const
|
2548
|
-
|
2549
|
-
|
2550
|
-
|
2551
|
-
|
2552
|
-
await (await this.carStore()).remove(cid2);
|
2440
|
+
async get(url) {
|
2441
|
+
const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
|
2442
|
+
let buffer = void 0;
|
2443
|
+
for (const rfrag of rfrags) {
|
2444
|
+
if (rfrag.isErr()) {
|
2445
|
+
return import_cement8.Result.Err(rfrag.Err());
|
2553
2446
|
}
|
2447
|
+
const frag = rfrag.Ok();
|
2448
|
+
buffer = buffer || new Uint8Array(frag.len);
|
2449
|
+
buffer.set(frag.data, frag.ofs);
|
2554
2450
|
}
|
2451
|
+
return import_cement8.Result.Ok(buffer || new Uint8Array(0));
|
2555
2452
|
}
|
2556
|
-
|
2557
|
-
|
2558
|
-
|
2559
|
-
// for (const cid of this.carLog) {
|
2560
|
-
// const dbMeta = { car: cid, key: this.key || null } as DbMeta
|
2561
|
-
// await this.remoteWAL!.enqueue(dbMeta, { public: false })
|
2562
|
-
// }
|
2563
|
-
// }
|
2564
|
-
async *entries(cache2 = true) {
|
2565
|
-
await this.ready();
|
2566
|
-
if (cache2) {
|
2567
|
-
for (const [, block] of this.getBlockCache) {
|
2568
|
-
yield block;
|
2569
|
-
}
|
2453
|
+
async subscribe(url, callback) {
|
2454
|
+
if (this.innerGW.subscribe) {
|
2455
|
+
return this.innerGW.subscribe(url, callback);
|
2570
2456
|
} else {
|
2571
|
-
|
2572
|
-
yield block;
|
2573
|
-
}
|
2574
|
-
for (const cids of this.carLog) {
|
2575
|
-
for (const cid of cids) {
|
2576
|
-
const reader = await this.loadCar(cid);
|
2577
|
-
if (!reader) throw this.logger.Error().Ref("cid", cid).Msg("missing car reader").AsError();
|
2578
|
-
for await (const block of reader.blocks()) {
|
2579
|
-
const sCid = block.cid.toString();
|
2580
|
-
if (!this.getBlockCache.has(sCid)) {
|
2581
|
-
yield block;
|
2582
|
-
}
|
2583
|
-
}
|
2584
|
-
}
|
2585
|
-
}
|
2457
|
+
return import_cement8.Result.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
|
2586
2458
|
}
|
2587
2459
|
}
|
2588
|
-
async
|
2589
|
-
await this.
|
2590
|
-
const
|
2591
|
-
|
2592
|
-
|
2593
|
-
if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
|
2594
|
-
const reader = await this.loadCar(carCid);
|
2595
|
-
if (!reader) {
|
2596
|
-
throw this.logger.Error().Ref("cid", carCid).Msg("missing car reader").AsError();
|
2597
|
-
}
|
2598
|
-
await this.cacheCarReader(carCid.toString(), reader).catch(() => {
|
2599
|
-
return;
|
2600
|
-
});
|
2601
|
-
if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
|
2602
|
-
throw this.logger.Error().Str("cid", sCid).Msg("block not in reader").AsError();
|
2603
|
-
};
|
2604
|
-
const getCompactCarCids = async (carCid) => {
|
2605
|
-
const reader = await this.loadCar(carCid);
|
2606
|
-
if (!reader) {
|
2607
|
-
throw this.logger.Error().Str("cid", carCid.toString()).Msg("missing car reader").AsError();
|
2608
|
-
}
|
2609
|
-
const header = await parseCarFile(reader, this.logger);
|
2610
|
-
const compacts = header.compact;
|
2611
|
-
let got2;
|
2612
|
-
const batchSize2 = 5;
|
2613
|
-
for (let i = 0; i < compacts.length; i += batchSize2) {
|
2614
|
-
const promises = [];
|
2615
|
-
for (let j = i; j < Math.min(i + batchSize2, compacts.length); j++) {
|
2616
|
-
for (const cid2 of compacts[j]) {
|
2617
|
-
promises.push(getCarCid(cid2));
|
2618
|
-
}
|
2619
|
-
}
|
2620
|
-
try {
|
2621
|
-
got2 = await Promise.any(promises);
|
2622
|
-
} catch {
|
2623
|
-
}
|
2624
|
-
if (got2) break;
|
2625
|
-
}
|
2626
|
-
if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
|
2627
|
-
throw this.logger.Error().Str("cid", sCid).Msg("block not in compact reader").AsError();
|
2628
|
-
};
|
2629
|
-
let got;
|
2630
|
-
const batchSize = 5;
|
2631
|
-
for (let i = 0; i < this.carLog.length; i += batchSize) {
|
2632
|
-
const batch = this.carLog.slice(i, i + batchSize);
|
2633
|
-
const promises = batch.flatMap((slice) => slice.map(getCarCid));
|
2634
|
-
try {
|
2635
|
-
got = await Promise.any(promises);
|
2636
|
-
} catch {
|
2637
|
-
}
|
2638
|
-
if (got) break;
|
2639
|
-
}
|
2640
|
-
if (!got) {
|
2641
|
-
try {
|
2642
|
-
got = await getCompactCarCids(this.carLog[this.carLog.length - 1][0]);
|
2643
|
-
} catch {
|
2460
|
+
async delete(url) {
|
2461
|
+
const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
|
2462
|
+
for (const rfrag of rfrags) {
|
2463
|
+
if (rfrag.isErr()) {
|
2464
|
+
return import_cement8.Result.Err(rfrag.Err());
|
2644
2465
|
}
|
2466
|
+
const frag = rfrag.Ok();
|
2467
|
+
const fidStr = import_base584.base58btc.encode(frag.fid);
|
2468
|
+
const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
|
2469
|
+
await this.innerGW.delete(fragUrl);
|
2645
2470
|
}
|
2646
|
-
return
|
2471
|
+
return import_cement8.Result.Ok(void 0);
|
2647
2472
|
}
|
2648
|
-
|
2649
|
-
|
2650
|
-
|
2651
|
-
|
2652
|
-
|
2653
|
-
|
2473
|
+
};
|
2474
|
+
|
2475
|
+
// src/blockstore/meta-key-helper.ts
|
2476
|
+
var import_dag_json = require("@ipld/dag-json");
|
2477
|
+
var import_clock = require("@web3-storage/pail/clock");
|
2478
|
+
var import_multiformats2 = require("multiformats");
|
2479
|
+
var import_base64 = require("multiformats/bases/base64");
|
2480
|
+
var import_cement9 = require("@adviser/cement");
|
2481
|
+
async function decodeGatewayMetaBytesToDbMeta(sthis, byteHeads) {
|
2482
|
+
const crdtEntries = JSON.parse(sthis.txt.decode(byteHeads));
|
2483
|
+
if (!crdtEntries.length) {
|
2484
|
+
sthis.logger.Debug().Str("byteHeads", new TextDecoder().decode(byteHeads)).Msg("No CRDT entries found");
|
2485
|
+
return [];
|
2654
2486
|
}
|
2655
|
-
|
2656
|
-
|
2657
|
-
|
2658
|
-
|
2659
|
-
|
2660
|
-
|
2661
|
-
|
2662
|
-
|
2663
|
-
|
2664
|
-
|
2665
|
-
|
2666
|
-
|
2667
|
-
|
2668
|
-
|
2669
|
-
|
2670
|
-
|
2487
|
+
if (!crdtEntries.map) {
|
2488
|
+
sthis.logger.Debug().Str("crdtEntries", JSON.stringify(crdtEntries)).Msg("No data in CRDT entries");
|
2489
|
+
return [];
|
2490
|
+
}
|
2491
|
+
return Promise.all(
|
2492
|
+
crdtEntries.map(async (crdtEntry) => {
|
2493
|
+
const eventBlock = await (0, import_clock.decodeEventBlock)(import_base64.base64pad.decode(crdtEntry.data));
|
2494
|
+
const dbMeta = (0, import_dag_json.parse)(sthis.txt.decode(eventBlock.value.data.dbMeta));
|
2495
|
+
return {
|
2496
|
+
eventCid: eventBlock.cid,
|
2497
|
+
parents: crdtEntry.parents,
|
2498
|
+
dbMeta
|
2499
|
+
};
|
2500
|
+
})
|
2501
|
+
);
|
2502
|
+
}
|
2503
|
+
async function setCryptoKeyFromGatewayMetaPayload(uri, sthis, data) {
|
2504
|
+
try {
|
2505
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Setting crypto key from gateway meta payload");
|
2506
|
+
const keyInfo = await decodeGatewayMetaBytesToDbMeta(sthis, data);
|
2507
|
+
if (keyInfo.length) {
|
2508
|
+
const dbMeta = keyInfo[0].dbMeta;
|
2509
|
+
if (dbMeta.key) {
|
2510
|
+
const kb = await getKeyBag(sthis);
|
2511
|
+
const keyName = getStoreKeyName(uri);
|
2512
|
+
const res = await kb.setNamedKey(keyName, dbMeta.key);
|
2513
|
+
if (res.isErr()) {
|
2514
|
+
sthis.logger.Debug().Str("keyName", keyName).Str("dbMeta.key", dbMeta.key).Msg("Failed to set named key");
|
2515
|
+
throw res.Err();
|
2671
2516
|
}
|
2672
|
-
} else {
|
2673
|
-
this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
|
2674
2517
|
}
|
2518
|
+
sthis.logger.Debug().Str("dbMeta.key", dbMeta.key).Str("uri", uri.toString()).Msg("Set crypto key from gateway meta payload");
|
2519
|
+
return import_cement9.Result.Ok(dbMeta);
|
2675
2520
|
}
|
2676
|
-
|
2677
|
-
|
2678
|
-
|
2679
|
-
|
2680
|
-
|
2681
|
-
const readerP = Promise.resolve(rawReader);
|
2682
|
-
const cachedReaderP = readerP.then(async (reader) => {
|
2683
|
-
await this.cacheCarReader(cidsString, reader).catch((e) => {
|
2684
|
-
this.logger.Error().Err(e).Str("cid", cidsString).Msg("error caching car reader");
|
2685
|
-
return;
|
2686
|
-
});
|
2687
|
-
return reader;
|
2688
|
-
});
|
2689
|
-
this.carReaders.set(cidsString, cachedReaderP);
|
2690
|
-
return readerP;
|
2521
|
+
sthis.logger.Debug().Str("data", new TextDecoder().decode(data)).Msg("No crypto in gateway meta payload");
|
2522
|
+
return import_cement9.Result.Ok(void 0);
|
2523
|
+
} catch (error) {
|
2524
|
+
sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
|
2525
|
+
return import_cement9.Result.Err(error);
|
2691
2526
|
}
|
2692
|
-
|
2693
|
-
|
2694
|
-
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2527
|
+
}
|
2528
|
+
async function addCryptoKeyToGatewayMetaPayload(uri, sthis, body) {
|
2529
|
+
try {
|
2530
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Adding crypto key to gateway meta payload");
|
2531
|
+
const keyName = getStoreKeyName(uri);
|
2532
|
+
const kb = await getKeyBag(sthis);
|
2533
|
+
const res = await kb.getNamedExtractableKey(keyName, true);
|
2534
|
+
if (res.isErr()) {
|
2535
|
+
sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
|
2536
|
+
throw res.Err();
|
2699
2537
|
}
|
2700
|
-
|
2538
|
+
const keyData = await res.Ok().extract();
|
2539
|
+
const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
|
2540
|
+
const { dbMeta, parents } = dbMetas[0];
|
2541
|
+
const parentLinks = parents.map((p) => import_multiformats2.CID.parse(p));
|
2542
|
+
dbMeta.key = keyData.keyStr;
|
2543
|
+
const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
|
2544
|
+
const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
|
2545
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
|
2546
|
+
return import_cement9.Result.Ok(encoded);
|
2547
|
+
} catch (error) {
|
2548
|
+
sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
|
2549
|
+
return import_cement9.Result.Err(error);
|
2701
2550
|
}
|
2702
|
-
|
2703
|
-
|
2704
|
-
|
2705
|
-
|
2551
|
+
}
|
2552
|
+
function getStoreKeyName(url) {
|
2553
|
+
const storeKeyName = [url.getParam("localName") || url.getParam("name")];
|
2554
|
+
const idx = url.getParam("index");
|
2555
|
+
if (idx) {
|
2556
|
+
storeKeyName.push(idx);
|
2706
2557
|
}
|
2707
|
-
|
2558
|
+
storeKeyName.push("data");
|
2559
|
+
return `@${storeKeyName.join(":")}@`;
|
2560
|
+
}
|
2561
|
+
async function createDbMetaEventBlock(sthis, dbMeta, parents) {
|
2562
|
+
const event = await import_clock.EventBlock.create(
|
2563
|
+
{
|
2564
|
+
dbMeta: sthis.txt.encode((0, import_dag_json.format)(dbMeta))
|
2565
|
+
},
|
2566
|
+
parents
|
2567
|
+
);
|
2568
|
+
return event;
|
2569
|
+
}
|
2570
|
+
async function encodeEventsWithParents(sthis, events, parents) {
|
2571
|
+
const crdtEntries = events.map((event) => {
|
2572
|
+
const base64String = import_base64.base64pad.encode(event.bytes);
|
2573
|
+
return {
|
2574
|
+
cid: event.cid.toString(),
|
2575
|
+
data: base64String,
|
2576
|
+
parents: parents.map((p) => p.toString())
|
2577
|
+
};
|
2578
|
+
});
|
2579
|
+
return sthis.txt.encode(JSON.stringify(crdtEntries));
|
2580
|
+
}
|
2708
2581
|
|
2709
2582
|
// src/blockstore/store.ts
|
2583
|
+
var import_p_retry = __toESM(require("p-retry"), 1);
|
2584
|
+
var import_p_map = __toESM(require("p-map"), 1);
|
2710
2585
|
function guardVersion(url) {
|
2711
2586
|
if (!url.hasParam("version")) {
|
2712
2587
|
return import_cement10.Result.Err(`missing version: ${url.toString()}`);
|
@@ -2714,21 +2589,16 @@ function guardVersion(url) {
|
|
2714
2589
|
return import_cement10.Result.Ok(url);
|
2715
2590
|
}
|
2716
2591
|
var BaseStoreImpl = class {
|
2717
|
-
constructor(
|
2592
|
+
constructor(name, url, opts, sthis, logger) {
|
2718
2593
|
this._onStarted = [];
|
2719
2594
|
this._onClosed = [];
|
2595
|
+
this.name = name;
|
2720
2596
|
this._url = url;
|
2721
2597
|
this.keybag = opts.keybag;
|
2722
|
-
this.loader = opts.loader;
|
2723
2598
|
this.sthis = sthis;
|
2724
|
-
|
2725
|
-
if (!name) {
|
2726
|
-
throw logger.Error().Str("url", this._url.toString()).Msg("missing name").AsError();
|
2727
|
-
}
|
2728
|
-
this.name = name;
|
2729
|
-
this.logger = logger.With().Str("this", this.sthis.nextId().str).Ref("url", () => this._url.toString()).Logger();
|
2730
|
-
this.realGateway = opts.gateway;
|
2599
|
+
this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
|
2731
2600
|
this.gateway = new FragmentGateway(this.sthis, opts.gateway);
|
2601
|
+
this.loader = opts.loader;
|
2732
2602
|
}
|
2733
2603
|
url() {
|
2734
2604
|
return this._url;
|
@@ -2743,20 +2613,20 @@ var BaseStoreImpl = class {
|
|
2743
2613
|
return;
|
2744
2614
|
}
|
2745
2615
|
async keyedCrypto() {
|
2746
|
-
return keyedCryptoFactory(this._url, this.keybag, this.sthis);
|
2616
|
+
return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
|
2747
2617
|
}
|
2748
2618
|
async start() {
|
2749
2619
|
this.logger.Debug().Str("storeType", this.storeType).Msg("starting-gateway-pre");
|
2750
|
-
this._url = this._url.build().setParam("store"
|
2620
|
+
this._url = this._url.build().setParam("store", this.storeType).URI();
|
2751
2621
|
const res = await this.gateway.start(this._url);
|
2752
2622
|
if (res.isErr()) {
|
2753
2623
|
this.logger.Error().Result("gw-start", res).Msg("started-gateway");
|
2754
2624
|
return res;
|
2755
2625
|
}
|
2756
2626
|
this._url = res.Ok();
|
2757
|
-
const kb = await this.keybag;
|
2627
|
+
const kb = await this.keybag();
|
2758
2628
|
const skRes = await kb.ensureKeyFromUrl(this._url, () => {
|
2759
|
-
const idx = this._url.getParam("index"
|
2629
|
+
const idx = this._url.getParam("index");
|
2760
2630
|
const storeKeyName = [this.name];
|
2761
2631
|
if (idx) {
|
2762
2632
|
storeKeyName.push(idx);
|
@@ -2789,8 +2659,8 @@ var BaseStoreImpl = class {
|
|
2789
2659
|
};
|
2790
2660
|
var MetaStoreImpl = class extends BaseStoreImpl {
|
2791
2661
|
// remote: boolean;
|
2792
|
-
constructor(sthis, url, opts) {
|
2793
|
-
super(
|
2662
|
+
constructor(sthis, name, url, opts) {
|
2663
|
+
super(name, url, { ...opts }, sthis, ensureLogger(sthis, "MetaStoreImpl"));
|
2794
2664
|
this.storeType = "meta";
|
2795
2665
|
this.subscribers = /* @__PURE__ */ new Map();
|
2796
2666
|
this.parents = [];
|
@@ -2861,21 +2731,13 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
2861
2731
|
return import_cement10.Result.Ok(void 0);
|
2862
2732
|
}
|
2863
2733
|
async destroy() {
|
2864
|
-
this.logger.Debug().Msg("destroy");
|
2865
2734
|
return this.gateway.destroy(this.url());
|
2866
2735
|
}
|
2867
2736
|
};
|
2868
2737
|
var DataStoreImpl = class extends BaseStoreImpl {
|
2869
2738
|
// readonly tag: string = "car-base";
|
2870
|
-
constructor(sthis, url, opts) {
|
2871
|
-
super(
|
2872
|
-
sthis,
|
2873
|
-
url,
|
2874
|
-
{
|
2875
|
-
...opts
|
2876
|
-
},
|
2877
|
-
ensureLogger(sthis, "DataStoreImpl")
|
2878
|
-
);
|
2739
|
+
constructor(sthis, name, url, opts) {
|
2740
|
+
super(name, url, { ...opts }, sthis, ensureLogger(sthis, "DataStoreImpl"));
|
2879
2741
|
this.storeType = "data";
|
2880
2742
|
}
|
2881
2743
|
async load(cid) {
|
@@ -2916,32 +2778,23 @@ var DataStoreImpl = class extends BaseStoreImpl {
|
|
2916
2778
|
return import_cement10.Result.Ok(void 0);
|
2917
2779
|
}
|
2918
2780
|
destroy() {
|
2919
|
-
this.logger.Debug().Msg("destroy");
|
2920
2781
|
return this.gateway.destroy(this.url());
|
2921
2782
|
}
|
2922
2783
|
};
|
2923
2784
|
var WALStoreImpl = class extends BaseStoreImpl {
|
2924
|
-
constructor(
|
2925
|
-
super(
|
2926
|
-
sthis,
|
2927
|
-
url,
|
2928
|
-
{
|
2929
|
-
...opts
|
2930
|
-
},
|
2931
|
-
ensureLogger(sthis, "WALStoreImpl")
|
2932
|
-
);
|
2785
|
+
constructor(loader, url, opts) {
|
2786
|
+
super(loader.name, url, { ...opts }, loader.sthis, ensureLogger(loader.sthis, "WALStoreImpl"));
|
2933
2787
|
this.storeType = "wal";
|
2934
|
-
// readonly tag: string = "rwal-base";
|
2935
|
-
// readonly loader: Loadable;
|
2936
2788
|
this._ready = new import_cement10.ResolveOnce();
|
2937
2789
|
this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
|
2938
2790
|
this.processing = void 0;
|
2939
2791
|
this.processQueue = new CommitQueue();
|
2792
|
+
this.loader = loader;
|
2940
2793
|
}
|
2941
2794
|
async ready() {
|
2942
2795
|
return this._ready.once(async () => {
|
2943
2796
|
const walState = await this.load().catch((e) => {
|
2944
|
-
this.logger.Error().
|
2797
|
+
this.logger.Error().Any("error", e).Msg("error loading wal");
|
2945
2798
|
return void 0;
|
2946
2799
|
});
|
2947
2800
|
if (!walState) {
|
@@ -2974,7 +2827,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
2974
2827
|
}
|
2975
2828
|
async process() {
|
2976
2829
|
await this.ready();
|
2977
|
-
if (!this.loader
|
2830
|
+
if (!this.loader.remoteCarStore) return;
|
2978
2831
|
await this.processQueue.enqueue(async () => {
|
2979
2832
|
try {
|
2980
2833
|
await this._doProcess();
|
@@ -2987,7 +2840,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
2987
2840
|
});
|
2988
2841
|
}
|
2989
2842
|
async _doProcess() {
|
2990
|
-
if (!this.loader) return;
|
2991
2843
|
if (!this.loader.remoteCarStore) return;
|
2992
2844
|
const operations = [...this.walState.operations];
|
2993
2845
|
const noLoaderOps = [...this.walState.noLoaderOps];
|
@@ -3005,7 +2857,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3005
2857
|
noLoaderOps,
|
3006
2858
|
async (dbMeta) => {
|
3007
2859
|
await retryableUpload(async () => {
|
3008
|
-
if (!this.loader) return;
|
3009
2860
|
for (const cid of dbMeta.cars) {
|
3010
2861
|
const car = await (await this.loader.carStore()).load(cid);
|
3011
2862
|
if (!car) {
|
@@ -3025,7 +2876,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3025
2876
|
operations,
|
3026
2877
|
async (dbMeta) => {
|
3027
2878
|
await retryableUpload(async () => {
|
3028
|
-
if (!this.loader) return;
|
3029
2879
|
for (const cid of dbMeta.cars) {
|
3030
2880
|
const car = await (await this.loader.carStore()).load(cid);
|
3031
2881
|
if (!car) {
|
@@ -3045,7 +2895,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3045
2895
|
fileOperations,
|
3046
2896
|
async ({ cid: fileCid, public: publicFile }) => {
|
3047
2897
|
await retryableUpload(async () => {
|
3048
|
-
if (!this.loader) return;
|
3049
2898
|
const fileBlock = await (await this.loader.fileStore()).load(fileCid);
|
3050
2899
|
if (!fileBlock) {
|
3051
2900
|
throw this.logger.Error().Ref("cid", fileCid).Msg("missing file block").AsError();
|
@@ -3059,7 +2908,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3059
2908
|
if (operations.length) {
|
3060
2909
|
const lastOp = operations[operations.length - 1];
|
3061
2910
|
await retryableUpload(async () => {
|
3062
|
-
if (!this.loader) return;
|
3063
2911
|
await this.loader.remoteMetaStore?.save(lastOp);
|
3064
2912
|
}, `remoteMetaStore save with dbMeta.cars=${lastOp.cars.toString()}`);
|
3065
2913
|
}
|
@@ -3085,7 +2933,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3085
2933
|
}
|
3086
2934
|
try {
|
3087
2935
|
return bytes && (0, import_dag_json2.parse)(this.sthis.txt.decode(bytes.Ok()));
|
3088
|
-
return bytes && (0, import_dag_json2.parse)(this.sthis.txt.decode(bytes.Ok()));
|
3089
2936
|
} catch (e) {
|
3090
2937
|
throw this.logger.Error().Err(e).Msg("error parse").AsError();
|
3091
2938
|
}
|
@@ -3112,98 +2959,73 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3112
2959
|
return import_cement10.Result.Ok(void 0);
|
3113
2960
|
}
|
3114
2961
|
destroy() {
|
3115
|
-
this.logger.Debug().Msg("destroy");
|
3116
2962
|
return this.gateway.destroy(this.url());
|
3117
2963
|
}
|
3118
2964
|
};
|
3119
2965
|
|
3120
2966
|
// src/blockstore/store-factory.ts
|
3121
|
-
init_types();
|
3122
|
-
|
3123
|
-
// src/blockstore/register-store-protocol.ts
|
3124
|
-
var import_cement14 = require("@adviser/cement");
|
3125
|
-
init_version();
|
3126
|
-
|
3127
|
-
// src/runtime/gateways/memory/gateway.ts
|
3128
|
-
var import_cement11 = require("@adviser/cement");
|
3129
|
-
init_types();
|
3130
|
-
|
3131
|
-
// src/runtime/gateways/memory/version.ts
|
3132
|
-
var MEMORY_VERSION = "v0.19-memory";
|
3133
|
-
|
3134
|
-
// src/runtime/gateways/memory/gateway.ts
|
3135
2967
|
init_utils();
|
3136
|
-
|
3137
|
-
|
3138
|
-
|
2968
|
+
function ensureIsIndex(url, isIndex) {
|
2969
|
+
if (isIndex) {
|
2970
|
+
return url.build().setParam("index", isIndex).URI();
|
3139
2971
|
}
|
3140
|
-
|
3141
|
-
|
3142
|
-
|
3143
|
-
|
3144
|
-
return
|
3145
|
-
}
|
3146
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
3147
|
-
close(baseUrl) {
|
3148
|
-
return Promise.resolve(import_cement11.Result.Ok(void 0));
|
3149
|
-
}
|
3150
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
3151
|
-
destroy(baseUrl) {
|
3152
|
-
this.memorys.clear();
|
3153
|
-
return Promise.resolve(import_cement11.Result.Ok(void 0));
|
3154
|
-
}
|
3155
|
-
put(url, body) {
|
3156
|
-
this.memorys.set(url.toString(), body);
|
3157
|
-
return Promise.resolve(import_cement11.Result.Ok(void 0));
|
3158
|
-
}
|
3159
|
-
// get could return a NotFoundError if the key is not found
|
3160
|
-
get(url) {
|
3161
|
-
const x = this.memorys.get(url.toString());
|
3162
|
-
if (x === void 0) {
|
3163
|
-
return Promise.resolve(import_cement11.Result.Err(new NotFoundError("not found")));
|
3164
|
-
}
|
3165
|
-
return Promise.resolve(import_cement11.Result.Ok(x));
|
3166
|
-
}
|
3167
|
-
delete(url) {
|
3168
|
-
this.memorys.delete(url.toString());
|
3169
|
-
return Promise.resolve(import_cement11.Result.Ok(void 0));
|
3170
|
-
}
|
3171
|
-
};
|
3172
|
-
var MemoryTestGateway = class {
|
3173
|
-
constructor(memorys) {
|
3174
|
-
this.memorys = memorys;
|
3175
|
-
}
|
3176
|
-
async get(url, key) {
|
3177
|
-
return this.memorys.get(url.build().setParam("key" /* KEY */, key).toString());
|
2972
|
+
return url.build().delParam("index").URI();
|
2973
|
+
}
|
2974
|
+
function ensureName(name, url) {
|
2975
|
+
if (!url.hasParam("name")) {
|
2976
|
+
return url.build().setParam("name", name).URI();
|
3178
2977
|
}
|
3179
|
-
|
3180
|
-
|
3181
|
-
// src/blockstore/register-store-protocol.ts
|
2978
|
+
return url;
|
2979
|
+
}
|
3182
2980
|
var storeFactory = /* @__PURE__ */ new Map();
|
3183
|
-
function
|
3184
|
-
|
3185
|
-
|
3186
|
-
|
3187
|
-
|
3188
|
-
|
3189
|
-
|
3190
|
-
|
2981
|
+
function buildURL(optURL, loader) {
|
2982
|
+
const storeOpts = loader.ebOpts.store;
|
2983
|
+
const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
|
2984
|
+
let obuUrl;
|
2985
|
+
if (obuItem && obuItem.overrideBaseURL) {
|
2986
|
+
obuUrl = import_cement13.URI.from(obuItem.overrideBaseURL);
|
2987
|
+
}
|
2988
|
+
const ret = ensureIsIndex(
|
2989
|
+
import_cement13.URI.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
|
2990
|
+
storeOpts.isIndex
|
2991
|
+
);
|
2992
|
+
return ret;
|
2993
|
+
}
|
2994
|
+
var onceGateway = new import_cement13.KeyedResolvOnce();
|
2995
|
+
async function getGatewayFromURL(url, sthis) {
|
2996
|
+
return onceGateway.get(url.toString()).once(async () => {
|
2997
|
+
const item = storeFactory.get(url.protocol);
|
2998
|
+
if (item) {
|
2999
|
+
const ret = {
|
3000
|
+
gateway: await item.gateway(sthis),
|
3001
|
+
test: await item.test(sthis)
|
3002
|
+
};
|
3003
|
+
const res = await ret.gateway.start(url);
|
3004
|
+
if (res.isErr()) {
|
3005
|
+
sthis.logger.Error().Result("start", res).Msg("start failed");
|
3006
|
+
return void 0;
|
3007
|
+
}
|
3008
|
+
return ret;
|
3191
3009
|
}
|
3192
|
-
|
3193
|
-
|
3194
|
-
|
3195
|
-
throw sthis.logger.Error().Msg("no default found").AsError();
|
3196
|
-
}
|
3197
|
-
return found.defaultURI(sthis);
|
3010
|
+
sthis.logger.Warn().Url(url).Msg("unsupported protocol");
|
3011
|
+
return void 0;
|
3012
|
+
});
|
3198
3013
|
}
|
3199
3014
|
function registerStoreProtocol(item) {
|
3200
3015
|
let protocol = item.protocol;
|
3201
3016
|
if (!protocol.endsWith(":")) {
|
3202
3017
|
protocol += ":";
|
3203
3018
|
}
|
3204
|
-
if (
|
3019
|
+
if (storeFactory.has(protocol)) {
|
3020
|
+
if (!item.overrideBaseURL && storeFactory.get(protocol) !== item) {
|
3021
|
+
throw new Error(`we need a logger here`);
|
3022
|
+
return () => {
|
3023
|
+
};
|
3024
|
+
}
|
3025
|
+
}
|
3026
|
+
if (item.overrideBaseURL) {
|
3205
3027
|
Array.from(storeFactory.values()).forEach((items) => {
|
3206
|
-
items.
|
3028
|
+
items.overrideBaseURL = void 0;
|
3207
3029
|
});
|
3208
3030
|
}
|
3209
3031
|
storeFactory.set(protocol, item);
|
@@ -3211,186 +3033,134 @@ function registerStoreProtocol(item) {
|
|
3211
3033
|
storeFactory.delete(protocol);
|
3212
3034
|
};
|
3213
3035
|
}
|
3214
|
-
|
3215
|
-
|
3216
|
-
|
3217
|
-
|
3218
|
-
return {
|
3219
|
-
|
3220
|
-
|
3221
|
-
|
3222
|
-
|
3223
|
-
|
3224
|
-
|
3225
|
-
|
3226
|
-
|
3227
|
-
|
3228
|
-
|
3229
|
-
|
3230
|
-
return new FileTestStore2(sthis);
|
3231
|
-
}
|
3232
|
-
};
|
3233
|
-
}
|
3234
|
-
if ((0, import_cement14.runtimeFn)().isBrowser) {
|
3235
|
-
registerStoreProtocol({
|
3236
|
-
protocol: "indexdb:",
|
3237
|
-
isDefault: true,
|
3238
|
-
defaultURI: () => {
|
3239
|
-
return import_cement14.BuildURI.from("indexdb://").pathname("fp").URI();
|
3240
|
-
},
|
3241
|
-
gateway: async (logger) => {
|
3242
|
-
const { IndexDBGateway: IndexDBGateway2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
|
3243
|
-
return new IndexDBGateway2(logger);
|
3244
|
-
},
|
3245
|
-
test: async (logger) => {
|
3246
|
-
const { IndexDBTestStore: IndexDBTestStore2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
|
3247
|
-
return new IndexDBTestStore2(logger);
|
3248
|
-
}
|
3249
|
-
});
|
3250
|
-
} else {
|
3251
|
-
registerStoreProtocol(fileGatewayFactoryItem());
|
3252
|
-
}
|
3253
|
-
var memory = /* @__PURE__ */ new Map();
|
3254
|
-
registerStoreProtocol({
|
3255
|
-
protocol: "memory:",
|
3256
|
-
isDefault: false,
|
3257
|
-
defaultURI: () => {
|
3258
|
-
return import_cement14.BuildURI.from("memory://").pathname("ram").URI();
|
3259
|
-
},
|
3260
|
-
gateway: async () => {
|
3261
|
-
return new MemoryGateway(memory);
|
3262
|
-
},
|
3263
|
-
test: async () => {
|
3264
|
-
return new MemoryTestGateway(memory);
|
3265
|
-
}
|
3266
|
-
});
|
3267
|
-
|
3268
|
-
// src/blockstore/store-factory.ts
|
3269
|
-
var onceGateway = new import_cement15.KeyedResolvOnce();
|
3270
|
-
var gatewayInstances = new import_cement15.KeyedResolvOnce();
|
3271
|
-
async function getStartedGateway(sthis, url) {
|
3272
|
-
return onceGateway.get(url.toString()).once(async () => {
|
3273
|
-
const item = getGatewayFactoryItem(url.protocol);
|
3274
|
-
if (item) {
|
3275
|
-
const ret = {
|
3276
|
-
url,
|
3277
|
-
...await gatewayInstances.get(url.protocol).once(async () => ({
|
3278
|
-
gateway: await item.gateway(sthis),
|
3279
|
-
test: await item.test(sthis)
|
3280
|
-
}))
|
3281
|
-
};
|
3282
|
-
const res = await ret.gateway.start(url);
|
3283
|
-
if (res.isErr()) {
|
3284
|
-
return import_cement15.Result.Err(sthis.logger.Error().Result("start", res).Msg("start failed").AsError());
|
3285
|
-
}
|
3286
|
-
ret.url = res.Ok();
|
3287
|
-
return import_cement15.Result.Ok(ret);
|
3288
|
-
}
|
3289
|
-
return import_cement15.Result.Err(sthis.logger.Warn().Url(url).Msg("unsupported protocol").AsError());
|
3290
|
-
});
|
3291
|
-
}
|
3292
|
-
async function dataStoreFactory(sfi) {
|
3293
|
-
const storeUrl = sfi.url.build().setParam("store" /* STORE */, "data").URI();
|
3294
|
-
const rgateway = await getStartedGateway(sfi.sthis, storeUrl);
|
3295
|
-
if (rgateway.isErr()) {
|
3296
|
-
throw sfi.sthis.logger.Error().Result("err", rgateway).Url(sfi.url).Msg("notfound").AsError();
|
3297
|
-
}
|
3298
|
-
const gateway = rgateway.Ok();
|
3299
|
-
const store = new DataStoreImpl(sfi.sthis, gateway.url, {
|
3300
|
-
gateway: gateway.gateway,
|
3301
|
-
keybag: sfi.keybag
|
3036
|
+
var onceDataStoreFactory = new import_cement13.KeyedResolvOnce();
|
3037
|
+
async function dataStoreFactory(loader) {
|
3038
|
+
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
|
3039
|
+
const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
|
3040
|
+
return onceDataStoreFactory.get(url.toString()).once(async () => {
|
3041
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
3042
|
+
if (!gateway) {
|
3043
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
3044
|
+
}
|
3045
|
+
const store = new DataStoreImpl(sthis, loader.name, url, {
|
3046
|
+
gateway: gateway.gateway,
|
3047
|
+
keybag: () => getKeyBag(loader.sthis, {
|
3048
|
+
...loader.ebOpts.keyBag
|
3049
|
+
})
|
3050
|
+
});
|
3051
|
+
return store;
|
3302
3052
|
});
|
3303
|
-
return store;
|
3304
3053
|
}
|
3305
|
-
|
3306
|
-
|
3307
|
-
const
|
3308
|
-
|
3309
|
-
|
3310
|
-
|
3311
|
-
|
3312
|
-
|
3313
|
-
|
3314
|
-
|
3054
|
+
var onceMetaStoreFactory = new import_cement13.KeyedResolvOnce();
|
3055
|
+
async function metaStoreFactory(loader) {
|
3056
|
+
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
|
3057
|
+
const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
|
3058
|
+
return onceMetaStoreFactory.get(url.toString()).once(async () => {
|
3059
|
+
sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
|
3060
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
3061
|
+
if (!gateway) {
|
3062
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
3063
|
+
}
|
3064
|
+
const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
|
3065
|
+
gateway: gateway.gateway,
|
3066
|
+
keybag: () => getKeyBag(loader.sthis, {
|
3067
|
+
...loader.ebOpts.keyBag
|
3068
|
+
})
|
3069
|
+
});
|
3070
|
+
return store;
|
3315
3071
|
});
|
3316
|
-
return store;
|
3317
3072
|
}
|
3318
|
-
|
3319
|
-
|
3320
|
-
const
|
3321
|
-
|
3322
|
-
|
3323
|
-
|
3324
|
-
|
3325
|
-
|
3326
|
-
|
3327
|
-
|
3073
|
+
var onceRemoteWalFactory = new import_cement13.KeyedResolvOnce();
|
3074
|
+
async function remoteWalFactory(loader) {
|
3075
|
+
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
|
3076
|
+
const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
|
3077
|
+
return onceRemoteWalFactory.get(url.toString()).once(async () => {
|
3078
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
3079
|
+
if (!gateway) {
|
3080
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
3081
|
+
}
|
3082
|
+
sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
|
3083
|
+
const store = new WALStoreImpl(loader, url, {
|
3084
|
+
gateway: gateway.gateway,
|
3085
|
+
keybag: () => getKeyBag(loader.sthis, {
|
3086
|
+
...loader.ebOpts.keyBag
|
3087
|
+
})
|
3088
|
+
});
|
3089
|
+
return store;
|
3328
3090
|
});
|
3329
|
-
return store;
|
3330
3091
|
}
|
3331
3092
|
async function testStoreFactory(url, sthis) {
|
3332
|
-
|
3333
|
-
|
3093
|
+
sthis = ensureSuperLog(sthis, "testStoreFactory");
|
3094
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
3095
|
+
if (!gateway) {
|
3334
3096
|
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
3335
3097
|
}
|
3336
|
-
return
|
3098
|
+
return gateway.test;
|
3337
3099
|
}
|
3338
|
-
async function ensureStart(store) {
|
3100
|
+
async function ensureStart(store, logger) {
|
3339
3101
|
const ret = await store.start();
|
3340
3102
|
if (ret.isErr()) {
|
3341
|
-
throw
|
3103
|
+
throw logger.Error().Result("start", ret).Msg("start failed").AsError();
|
3342
3104
|
}
|
3343
|
-
|
3105
|
+
logger.Debug().Url(ret.Ok(), "prepared").Msg("produced");
|
3344
3106
|
return store;
|
3345
3107
|
}
|
3346
|
-
function
|
3347
|
-
|
3348
|
-
return {
|
3349
|
-
encodeFile: ende.encodeFile || encodeFile,
|
3350
|
-
decodeFile: ende.decodeFile || decodeFile
|
3351
|
-
};
|
3352
|
-
}
|
3353
|
-
function toStoreRuntime(sthis, endeOpts = {}) {
|
3108
|
+
function toStoreRuntime(opts, sthis) {
|
3109
|
+
const logger = ensureLogger(sthis, "toStoreRuntime", {});
|
3354
3110
|
return {
|
3355
|
-
makeMetaStore: async (
|
3356
|
-
|
3357
|
-
|
3358
|
-
|
3359
|
-
|
3360
|
-
|
3361
|
-
|
3362
|
-
|
3363
|
-
|
3364
|
-
|
3365
|
-
|
3366
|
-
|
3367
|
-
|
3368
|
-
|
3369
|
-
// return ensureStart(await (endeOpts.func?.makeDataStore || dataStoreFactory)(loader), logger);
|
3370
|
-
// },
|
3371
|
-
makeWALStore: async (sfi) => ensureStart(await WALStoreFactory(sfi)),
|
3372
|
-
// async (loader: Loadable) => {
|
3373
|
-
// logger
|
3374
|
-
// .Debug()
|
3375
|
-
// .Str("fromOpts", "" + !!endeOpts.func?.makeWALStore)
|
3376
|
-
// .Msg("makeRemoteWAL");
|
3377
|
-
// return ensureStart(await (endeOpts.func?.makeWALStore || remoteWalFactory)(loader), logger);
|
3378
|
-
// },
|
3379
|
-
...ensureStoreEnDeFile(endeOpts)
|
3111
|
+
makeMetaStore: async (loader) => {
|
3112
|
+
logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeMetaStore).Msg("makeMetaStore");
|
3113
|
+
return ensureStart(await (loader.ebOpts.store.makeMetaStore || metaStoreFactory)(loader), logger);
|
3114
|
+
},
|
3115
|
+
makeDataStore: async (loader) => {
|
3116
|
+
logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeDataStore).Msg("makeDataStore");
|
3117
|
+
return ensureStart(await (loader.ebOpts.store.makeDataStore || dataStoreFactory)(loader), logger);
|
3118
|
+
},
|
3119
|
+
makeWALStore: async (loader) => {
|
3120
|
+
logger.Debug().Str("fromOpts", "" + !!loader.ebOpts.store.makeWALStore).Msg("makeRemoteWAL");
|
3121
|
+
return ensureStart(await (loader.ebOpts.store.makeWALStore || remoteWalFactory)(loader), logger);
|
3122
|
+
},
|
3123
|
+
encodeFile: opts.encodeFile || encodeFile,
|
3124
|
+
decodeFile: opts.decodeFile || decodeFile
|
3380
3125
|
};
|
3381
3126
|
}
|
3382
|
-
|
3383
|
-
|
3384
|
-
|
3127
|
+
registerStoreProtocol({
|
3128
|
+
protocol: "file:",
|
3129
|
+
gateway: async (sthis) => {
|
3130
|
+
const { FileGateway: FileGateway2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
|
3131
|
+
return new FileGateway2(sthis);
|
3132
|
+
},
|
3133
|
+
test: async (sthis) => {
|
3134
|
+
const { FileTestStore: FileTestStore2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
|
3135
|
+
return new FileTestStore2(sthis);
|
3136
|
+
}
|
3137
|
+
});
|
3138
|
+
registerStoreProtocol({
|
3139
|
+
protocol: "indexdb:",
|
3140
|
+
gateway: async (sthis) => {
|
3141
|
+
const { IndexDBGateway: IndexDBGateway2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
|
3142
|
+
return new IndexDBGateway2(sthis);
|
3143
|
+
},
|
3144
|
+
test: async (sthis) => {
|
3145
|
+
const { IndexDBTestStore: IndexDBTestStore2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
|
3146
|
+
return new IndexDBTestStore2(sthis);
|
3147
|
+
}
|
3148
|
+
});
|
3385
3149
|
|
3386
3150
|
// src/blockstore/store-remote.ts
|
3387
3151
|
async function RemoteDataStore(sthis, name, url, opts) {
|
3388
|
-
const ds = new DataStoreImpl(sthis, url, opts);
|
3152
|
+
const ds = new DataStoreImpl(sthis, name, url, opts);
|
3389
3153
|
await ds.start();
|
3390
3154
|
return ds;
|
3391
3155
|
}
|
3392
3156
|
async function RemoteMetaStore(sthis, name, url, opts) {
|
3393
|
-
const ms = new MetaStoreImpl(
|
3157
|
+
const ms = new MetaStoreImpl(
|
3158
|
+
sthis,
|
3159
|
+
name,
|
3160
|
+
url,
|
3161
|
+
opts
|
3162
|
+
/* , true*/
|
3163
|
+
);
|
3394
3164
|
await ms.start();
|
3395
3165
|
return ms;
|
3396
3166
|
}
|
@@ -3415,17 +3185,14 @@ var ConnectionBase = class {
|
|
3415
3185
|
if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
|
3416
3186
|
this.loader = loader;
|
3417
3187
|
await this.onConnect();
|
3418
|
-
const metaUrl = this.url.build().defParam("store"
|
3419
|
-
const
|
3420
|
-
if (
|
3421
|
-
throw this.logger.Error().Result("err", rgateway).Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
|
3422
|
-
const name = metaUrl.toString();
|
3188
|
+
const metaUrl = this.url.build().defParam("store", "meta").URI();
|
3189
|
+
const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
|
3190
|
+
if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
|
3423
3191
|
const dbName = metaUrl.getParam("name");
|
3424
|
-
if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X:
|
3425
|
-
const
|
3426
|
-
const remote = await RemoteMetaStore(loader.sthis, name, metaUrl, {
|
3192
|
+
if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: name is required").AsError();
|
3193
|
+
const remote = await RemoteMetaStore(loader.sthis, dbName, metaUrl, {
|
3427
3194
|
gateway: gateway.gateway,
|
3428
|
-
keybag:
|
3195
|
+
keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag),
|
3429
3196
|
loader
|
3430
3197
|
});
|
3431
3198
|
this.loader.remoteMetaStore = remote;
|
@@ -3438,15 +3205,14 @@ var ConnectionBase = class {
|
|
3438
3205
|
async connectStorage_X({ loader }) {
|
3439
3206
|
if (!loader) throw this.logger.Error().Msg("connectStorage_X: loader is required").AsError();
|
3440
3207
|
this.loader = loader;
|
3441
|
-
const dataUrl = this.url.build().defParam("store"
|
3442
|
-
const
|
3443
|
-
if (
|
3444
|
-
throw this.logger.Error().Result("err", rgateway).Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
|
3208
|
+
const dataUrl = this.url.build().defParam("store", "data").URI();
|
3209
|
+
const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
|
3210
|
+
if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
|
3445
3211
|
const name = dataUrl.getParam("name");
|
3446
3212
|
if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: name is required").AsError;
|
3447
3213
|
loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
|
3448
|
-
gateway:
|
3449
|
-
keybag:
|
3214
|
+
gateway: gateway.gateway,
|
3215
|
+
keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
|
3450
3216
|
});
|
3451
3217
|
loader.remoteFileStore = loader.remoteCarStore;
|
3452
3218
|
}
|
@@ -3486,13 +3252,6 @@ var ConnectionBase = class {
|
|
3486
3252
|
};
|
3487
3253
|
|
3488
3254
|
// src/crdt-helpers.ts
|
3489
|
-
var import_link = require("multiformats/link");
|
3490
|
-
var import_sha25 = require("multiformats/hashes/sha2");
|
3491
|
-
var codec = __toESM(require("@ipld/dag-cbor"), 1);
|
3492
|
-
var import_crdt = require("@web3-storage/pail/crdt");
|
3493
|
-
var import_clock2 = require("@web3-storage/pail/clock");
|
3494
|
-
var Batch = __toESM(require("@web3-storage/pail/crdt/batch"), 1);
|
3495
|
-
init_types();
|
3496
3255
|
function time(tag) {
|
3497
3256
|
}
|
3498
3257
|
function timeEnd(tag) {
|
@@ -3540,7 +3299,7 @@ async function writeDocContent(store, blocks, update, logger) {
|
|
3540
3299
|
await processFiles(store, blocks, update.value, logger);
|
3541
3300
|
value = { doc: update.value };
|
3542
3301
|
}
|
3543
|
-
const block = await
|
3302
|
+
const block = await encode({ value, hasher: import_sha25.sha256, codec });
|
3544
3303
|
blocks.putSync(block.cid, block.bytes);
|
3545
3304
|
return block.cid;
|
3546
3305
|
}
|
@@ -3631,7 +3390,7 @@ function readFileset(blocks, files, isPublic = false) {
|
|
3631
3390
|
async function getValueFromLink(blocks, link, logger) {
|
3632
3391
|
const block = await blocks.get(link);
|
3633
3392
|
if (!block) throw logger.Error().Str("link", link.toString()).Msg(`Missing linked block`).AsError();
|
3634
|
-
const { value } = await
|
3393
|
+
const { value } = await decode({ bytes: block.bytes, hasher: import_sha25.sha256, codec });
|
3635
3394
|
const cvalue = {
|
3636
3395
|
...value,
|
3637
3396
|
cid: link
|
@@ -3752,19 +3511,16 @@ async function doCompact(blockLog, head, logger) {
|
|
3752
3511
|
async function getBlock(blocks, cidString) {
|
3753
3512
|
const block = await blocks.get((0, import_link.parse)(cidString));
|
3754
3513
|
if (!block) throw new Error(`Missing block ${cidString}`);
|
3755
|
-
const { cid, value } = await
|
3514
|
+
const { cid, value } = await decode({ bytes: block.bytes, codec, hasher: import_sha25.sha256 });
|
3756
3515
|
return new Block({ cid, value, bytes: block.bytes });
|
3757
3516
|
}
|
3758
3517
|
|
3759
|
-
// src/indexer.ts
|
3760
|
-
init_types();
|
3761
|
-
|
3762
3518
|
// src/indexer-helpers.ts
|
3763
3519
|
var import_sha26 = require("multiformats/hashes/sha2");
|
3764
3520
|
var codec2 = __toESM(require("@ipld/dag-cbor"), 1);
|
3765
3521
|
var import_charwise = __toESM(require("charwise"), 1);
|
3766
3522
|
var DbIndex = __toESM(require("prolly-trees/db-index"), 1);
|
3767
|
-
var
|
3523
|
+
var import_utils16 = require("prolly-trees/utils");
|
3768
3524
|
var import_cache = require("prolly-trees/cache");
|
3769
3525
|
var IndexTree = class {
|
3770
3526
|
};
|
@@ -3772,17 +3528,17 @@ function refCompare(aRef, bRef) {
|
|
3772
3528
|
if (Number.isNaN(aRef)) return -1;
|
3773
3529
|
if (Number.isNaN(bRef)) throw new Error("ref may not be Infinity or NaN");
|
3774
3530
|
if (aRef === Infinity) return 1;
|
3775
|
-
return (0,
|
3531
|
+
return (0, import_utils16.simpleCompare)(aRef, bRef);
|
3776
3532
|
}
|
3777
3533
|
function compare(a, b) {
|
3778
3534
|
const [aKey, aRef] = a;
|
3779
3535
|
const [bKey, bRef] = b;
|
3780
|
-
const comp = (0,
|
3536
|
+
const comp = (0, import_utils16.simpleCompare)(aKey, bKey);
|
3781
3537
|
if (comp !== 0) return comp;
|
3782
3538
|
return refCompare(aRef, bRef);
|
3783
3539
|
}
|
3784
|
-
var byKeyOpts = { cache: import_cache.nocache, chunker: (0,
|
3785
|
-
var byIdOpts = { cache: import_cache.nocache, chunker: (0,
|
3540
|
+
var byKeyOpts = { cache: import_cache.nocache, chunker: (0, import_utils16.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare };
|
3541
|
+
var byIdOpts = { cache: import_cache.nocache, chunker: (0, import_utils16.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare: import_utils16.simpleCompare };
|
3786
3542
|
function indexEntriesForChanges(changes, mapFn) {
|
3787
3543
|
const indexEntries = [];
|
3788
3544
|
changes.forEach(({ id: key, value, del }) => {
|
@@ -3813,8 +3569,7 @@ function makeProllyGetBlock(blocks) {
|
|
3813
3569
|
return create({ cid, bytes, hasher: import_sha26.sha256, codec: codec2 });
|
3814
3570
|
};
|
3815
3571
|
}
|
3816
|
-
async function bulkIndex(
|
3817
|
-
logger.Debug().Msg("enter bulkIndex");
|
3572
|
+
async function bulkIndex(tblocks, inIndex, indexEntries, opts) {
|
3818
3573
|
if (!indexEntries.length) return inIndex;
|
3819
3574
|
if (!inIndex.root) {
|
3820
3575
|
if (!inIndex.cid) {
|
@@ -3831,22 +3586,18 @@ async function bulkIndex(logger, tblocks, inIndex, indexEntries, opts) {
|
|
3831
3586
|
returnNode = node;
|
3832
3587
|
}
|
3833
3588
|
if (!returnNode || !returnRootBlock) throw new Error("failed to create index");
|
3834
|
-
logger.Debug().Msg("exit !root bulkIndex");
|
3835
3589
|
return { root: returnNode, cid: returnRootBlock.cid };
|
3836
3590
|
} else {
|
3837
3591
|
inIndex.root = await DbIndex.load({ cid: inIndex.cid, get: makeProllyGetBlock(tblocks), ...opts });
|
3838
3592
|
}
|
3839
3593
|
}
|
3840
|
-
logger.Debug().Msg("pre bulk bulkIndex");
|
3841
3594
|
const { root: root3, blocks: newBlocks } = await inIndex.root.bulk(indexEntries);
|
3842
3595
|
if (root3) {
|
3843
|
-
logger.Debug().Msg("pre root put bulkIndex");
|
3844
3596
|
for await (const block of newBlocks) {
|
3845
3597
|
await tblocks.put(block.cid, block.bytes);
|
3846
3598
|
}
|
3847
3599
|
return { root: root3, cid: (await root3.block).cid };
|
3848
3600
|
} else {
|
3849
|
-
logger.Debug().Msg("pre !root bulkIndex");
|
3850
3601
|
return { root: void 0, cid: void 0 };
|
3851
3602
|
}
|
3852
3603
|
}
|
@@ -3887,17 +3638,17 @@ function encodeKey(key) {
|
|
3887
3638
|
|
3888
3639
|
// src/indexer.ts
|
3889
3640
|
init_utils();
|
3890
|
-
function index(
|
3891
|
-
if (mapFn && meta) throw
|
3892
|
-
if (mapFn && mapFn.constructor.name !== "Function") throw
|
3893
|
-
if (
|
3894
|
-
const idx =
|
3641
|
+
function index(sthis, { _crdt }, name, mapFn, meta) {
|
3642
|
+
if (mapFn && meta) throw _crdt.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
|
3643
|
+
if (mapFn && mapFn.constructor.name !== "Function") throw _crdt.logger.Error().Msg("mapFn must be a function").AsError();
|
3644
|
+
if (_crdt.indexers.has(name)) {
|
3645
|
+
const idx = _crdt.indexers.get(name);
|
3895
3646
|
idx.applyMapFn(name, mapFn, meta);
|
3896
3647
|
} else {
|
3897
|
-
const idx = new Index(
|
3898
|
-
|
3648
|
+
const idx = new Index(sthis, _crdt, name, mapFn, meta);
|
3649
|
+
_crdt.indexers.set(name, idx);
|
3899
3650
|
}
|
3900
|
-
return
|
3651
|
+
return _crdt.indexers.get(name);
|
3901
3652
|
}
|
3902
3653
|
var Index = class {
|
3903
3654
|
constructor(sthis, crdt, name, mapFn, meta) {
|
@@ -3916,9 +3667,18 @@ var Index = class {
|
|
3916
3667
|
return Promise.all([this.blockstore.ready(), this.crdt.ready()]).then(() => {
|
3917
3668
|
});
|
3918
3669
|
}
|
3670
|
+
close() {
|
3671
|
+
return Promise.all([this.blockstore.close(), this.crdt.close()]).then(() => {
|
3672
|
+
});
|
3673
|
+
}
|
3674
|
+
destroy() {
|
3675
|
+
return Promise.all([this.blockstore.destroy(), this.crdt.destroy()]).then(() => {
|
3676
|
+
});
|
3677
|
+
}
|
3919
3678
|
applyMapFn(name, mapFn, meta) {
|
3920
3679
|
if (mapFn && meta) throw this.logger.Error().Msg("cannot provide both mapFn and meta").AsError();
|
3921
3680
|
if (this.name && this.name !== name) throw this.logger.Error().Msg("cannot change name").AsError();
|
3681
|
+
this.name = name;
|
3922
3682
|
try {
|
3923
3683
|
if (meta) {
|
3924
3684
|
if (this.indexHead && this.indexHead.map((c) => c.toString()).join() !== meta.head.map((c) => c.toString()).join()) {
|
@@ -3966,13 +3726,9 @@ var Index = class {
|
|
3966
3726
|
}
|
3967
3727
|
}
|
3968
3728
|
async query(opts = {}) {
|
3969
|
-
this.logger.Debug().Msg("enter query");
|
3970
3729
|
await this.ready();
|
3971
|
-
this.logger.Debug().Msg("post ready query");
|
3972
3730
|
await this._updateIndex();
|
3973
|
-
this.logger.Debug().Msg("post _updateIndex query");
|
3974
3731
|
await this._hydrateIndex();
|
3975
|
-
this.logger.Debug().Msg("post _hydrateIndex query");
|
3976
3732
|
if (!this.byKey.root) {
|
3977
3733
|
return await applyQuery(this.crdt, { result: [] }, opts);
|
3978
3734
|
}
|
@@ -4028,16 +3784,13 @@ var Index = class {
|
|
4028
3784
|
}
|
4029
3785
|
async _updateIndex() {
|
4030
3786
|
await this.ready();
|
4031
|
-
this.logger.Debug().Msg("enter _updateIndex");
|
4032
3787
|
if (this.initError) throw this.initError;
|
4033
3788
|
if (!this.mapFn) throw this.logger.Error().Msg("No map function defined").AsError();
|
4034
3789
|
let result, head;
|
4035
3790
|
if (!this.indexHead || this.indexHead.length === 0) {
|
4036
3791
|
({ result, head } = await this.crdt.allDocs());
|
4037
|
-
this.logger.Debug().Msg("enter crdt.allDocs");
|
4038
3792
|
} else {
|
4039
3793
|
({ result, head } = await this.crdt.changes(this.indexHead));
|
4040
|
-
this.logger.Debug().Msg("enter crdt.changes");
|
4041
3794
|
}
|
4042
3795
|
if (result.length === 0) {
|
4043
3796
|
this.indexHead = head;
|
@@ -4070,22 +3823,9 @@ var Index = class {
|
|
4070
3823
|
if (result.length === 0) {
|
4071
3824
|
return indexerMeta;
|
4072
3825
|
}
|
4073
|
-
this.logger.Debug().Msg("pre this.blockstore.transaction");
|
4074
3826
|
const { meta } = await this.blockstore.transaction(async (tblocks) => {
|
4075
|
-
this.byId = await bulkIndex(
|
4076
|
-
|
4077
|
-
tblocks,
|
4078
|
-
this.byId,
|
4079
|
-
removeIdIndexEntries.concat(byIdIndexEntries),
|
4080
|
-
byIdOpts
|
4081
|
-
);
|
4082
|
-
this.byKey = await bulkIndex(
|
4083
|
-
this.logger,
|
4084
|
-
tblocks,
|
4085
|
-
this.byKey,
|
4086
|
-
staleKeyIndexEntries.concat(indexEntries),
|
4087
|
-
byKeyOpts
|
4088
|
-
);
|
3827
|
+
this.byId = await bulkIndex(tblocks, this.byId, removeIdIndexEntries.concat(byIdIndexEntries), byIdOpts);
|
3828
|
+
this.byKey = await bulkIndex(tblocks, this.byKey, staleKeyIndexEntries.concat(indexEntries), byKeyOpts);
|
4089
3829
|
this.indexHead = head;
|
4090
3830
|
if (this.byId.cid && this.byKey.cid) {
|
4091
3831
|
const idxMeta = {
|
@@ -4097,10 +3837,8 @@ var Index = class {
|
|
4097
3837
|
};
|
4098
3838
|
indexerMeta.indexes?.set(this.name, idxMeta);
|
4099
3839
|
}
|
4100
|
-
this.logger.Debug().Any("indexerMeta", new Array(indexerMeta.indexes?.entries())).Msg("exit this.blockstore.transaction fn");
|
4101
3840
|
return indexerMeta;
|
4102
3841
|
});
|
4103
|
-
this.logger.Debug().Msg("post this.blockstore.transaction");
|
4104
3842
|
return meta;
|
4105
3843
|
}
|
4106
3844
|
};
|
@@ -4108,8 +3846,7 @@ var Index = class {
|
|
4108
3846
|
// src/crdt-clock.ts
|
4109
3847
|
var import_clock3 = require("@web3-storage/pail/clock");
|
4110
3848
|
var import_crdt2 = require("@web3-storage/pail/crdt");
|
4111
|
-
var
|
4112
|
-
init_types();
|
3849
|
+
var import_cement14 = require("@adviser/cement");
|
4113
3850
|
|
4114
3851
|
// src/apply-head-queue.ts
|
4115
3852
|
function applyHeadQueue(worker, logger) {
|
@@ -4167,7 +3904,7 @@ var CRDTClock = class {
|
|
4167
3904
|
this.zoomers = /* @__PURE__ */ new Set();
|
4168
3905
|
this.watchers = /* @__PURE__ */ new Set();
|
4169
3906
|
this.emptyWatchers = /* @__PURE__ */ new Set();
|
4170
|
-
this._ready = new
|
3907
|
+
this._ready = new import_cement14.ResolveOnce();
|
4171
3908
|
this.blockstore = blockstore;
|
4172
3909
|
this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
|
4173
3910
|
this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
|
@@ -4279,13 +4016,15 @@ async function advanceBlocks(logger, newHead, tblocks, head) {
|
|
4279
4016
|
// src/crdt.ts
|
4280
4017
|
init_utils();
|
4281
4018
|
var CRDT = class {
|
4282
|
-
constructor(sthis, opts) {
|
4019
|
+
constructor(sthis, name, opts = {}) {
|
4283
4020
|
this.indexers = /* @__PURE__ */ new Map();
|
4284
|
-
this.onceReady = new
|
4021
|
+
this.onceReady = new import_cement15.ResolveOnce();
|
4285
4022
|
this.sthis = sthis;
|
4023
|
+
this.name = name;
|
4286
4024
|
this.logger = ensureLogger(sthis, "CRDT");
|
4287
4025
|
this.opts = opts;
|
4288
4026
|
this.blockstore = blockstoreFactory(sthis, {
|
4027
|
+
name,
|
4289
4028
|
applyMeta: async (meta) => {
|
4290
4029
|
const crdtMeta = meta;
|
4291
4030
|
if (!crdtMeta.head) throw this.logger.Error().Msg("missing head").AsError();
|
@@ -4295,27 +4034,23 @@ var CRDT = class {
|
|
4295
4034
|
await doCompact(blocks, this.clock.head, this.logger);
|
4296
4035
|
return { head: this.clock.head };
|
4297
4036
|
},
|
4298
|
-
|
4299
|
-
|
4300
|
-
|
4301
|
-
|
4302
|
-
|
4303
|
-
meta: this.opts.meta
|
4304
|
-
// threshold: this.opts.threshold,
|
4037
|
+
autoCompact: this.opts.autoCompact || 100,
|
4038
|
+
store: { ...this.opts.store, isIndex: void 0 },
|
4039
|
+
public: this.opts.public,
|
4040
|
+
meta: this.opts.meta,
|
4041
|
+
threshold: this.opts.threshold
|
4305
4042
|
});
|
4306
4043
|
this.indexBlockstore = blockstoreFactory(sthis, {
|
4307
|
-
|
4044
|
+
name,
|
4308
4045
|
applyMeta: async (meta) => {
|
4309
4046
|
const idxCarMeta = meta;
|
4310
4047
|
if (!idxCarMeta.indexes) throw this.logger.Error().Msg("missing indexes").AsError();
|
4311
|
-
for (const [
|
4312
|
-
index({
|
4048
|
+
for (const [name2, idx] of Object.entries(idxCarMeta.indexes)) {
|
4049
|
+
index(this.sthis, { _crdt: this }, name2, void 0, idx);
|
4313
4050
|
}
|
4314
4051
|
},
|
4315
|
-
|
4316
|
-
|
4317
|
-
keyBag: this.opts.keyBag
|
4318
|
-
// public: this.opts.public,
|
4052
|
+
store: { ...this.opts.store, isIndex: this.opts.store?.isIndex || "idx" },
|
4053
|
+
public: this.opts.public
|
4319
4054
|
});
|
4320
4055
|
this.clock = new CRDTClock(this.blockstore);
|
4321
4056
|
this.clock.onZoom(() => {
|
@@ -4397,166 +4132,52 @@ var CRDT = class {
|
|
4397
4132
|
};
|
4398
4133
|
|
4399
4134
|
// src/database.ts
|
4400
|
-
init_types();
|
4401
4135
|
init_utils();
|
4402
|
-
var
|
4403
|
-
|
4404
|
-
|
4405
|
-
return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
|
4406
|
-
}
|
4407
|
-
function keyConfigOpts(sthis, name, opts) {
|
4408
|
-
return JSON.stringify(
|
4409
|
-
toSortedArray({
|
4410
|
-
name,
|
4411
|
-
stores: toSortedArray(JSON.parse(JSON.stringify(toStoreURIRuntime(sthis, name, opts?.storeUrls))))
|
4412
|
-
})
|
4413
|
-
);
|
4414
|
-
}
|
4415
|
-
function isDatabase(db) {
|
4416
|
-
return db instanceof DatabaseImpl || db instanceof DatabaseShell;
|
4417
|
-
}
|
4418
|
-
function DatabaseFactory(name, opts) {
|
4419
|
-
const sthis = ensureSuperThis(opts);
|
4420
|
-
return new DatabaseShell(
|
4421
|
-
databases.get(keyConfigOpts(sthis, name, opts)).once((key) => {
|
4422
|
-
const db = new DatabaseImpl(sthis, {
|
4423
|
-
name,
|
4424
|
-
meta: opts?.meta,
|
4425
|
-
keyBag: defaultKeyBagOpts(sthis, opts?.keyBag),
|
4426
|
-
storeUrls: toStoreURIRuntime(sthis, name, opts?.storeUrls),
|
4427
|
-
storeEnDe: {
|
4428
|
-
encodeFile,
|
4429
|
-
decodeFile,
|
4430
|
-
...opts?.storeEnDe
|
4431
|
-
}
|
4432
|
-
});
|
4433
|
-
db.onClosed(() => {
|
4434
|
-
databases.unget(key);
|
4435
|
-
});
|
4436
|
-
return db;
|
4437
|
-
})
|
4438
|
-
);
|
4439
|
-
}
|
4440
|
-
var DatabaseShell = class {
|
4441
|
-
constructor(ref) {
|
4442
|
-
this.ref = ref;
|
4443
|
-
ref.addShell(this);
|
4444
|
-
}
|
4445
|
-
get id() {
|
4446
|
-
return this.ref.id;
|
4447
|
-
}
|
4448
|
-
get logger() {
|
4449
|
-
return this.ref.logger;
|
4450
|
-
}
|
4451
|
-
get sthis() {
|
4452
|
-
return this.ref.sthis;
|
4453
|
-
}
|
4454
|
-
get crdt() {
|
4455
|
-
return this.ref.crdt;
|
4456
|
-
}
|
4457
|
-
name() {
|
4458
|
-
return this.ref.name();
|
4459
|
-
}
|
4460
|
-
onClosed(fn) {
|
4461
|
-
return this.ref.onClosed(fn);
|
4462
|
-
}
|
4463
|
-
close() {
|
4464
|
-
return this.ref.shellClose(this);
|
4465
|
-
}
|
4466
|
-
destroy() {
|
4467
|
-
return this.ref.destroy();
|
4468
|
-
}
|
4469
|
-
ready() {
|
4470
|
-
return this.ref.ready();
|
4471
|
-
}
|
4472
|
-
get(id) {
|
4473
|
-
return this.ref.get(id);
|
4474
|
-
}
|
4475
|
-
put(doc) {
|
4476
|
-
return this.ref.put(doc);
|
4477
|
-
}
|
4478
|
-
del(id) {
|
4479
|
-
return this.ref.del(id);
|
4480
|
-
}
|
4481
|
-
changes(since, opts) {
|
4482
|
-
return this.ref.changes(since, opts);
|
4483
|
-
}
|
4484
|
-
allDocs(opts) {
|
4485
|
-
return this.ref.allDocs(opts);
|
4486
|
-
}
|
4487
|
-
allDocuments() {
|
4488
|
-
return this.ref.allDocuments();
|
4489
|
-
}
|
4490
|
-
subscribe(listener, updates) {
|
4491
|
-
return this.ref.subscribe(listener, updates);
|
4492
|
-
}
|
4493
|
-
query(field, opts) {
|
4494
|
-
return this.ref.query(field, opts);
|
4495
|
-
}
|
4496
|
-
compact() {
|
4497
|
-
return this.ref.compact();
|
4498
|
-
}
|
4499
|
-
};
|
4500
|
-
var DatabaseImpl = class {
|
4501
|
-
constructor(sthis, opts) {
|
4136
|
+
var Database = class {
|
4137
|
+
constructor(name, opts) {
|
4138
|
+
this.opts = {};
|
4502
4139
|
this._listening = false;
|
4503
4140
|
this._listeners = /* @__PURE__ */ new Set();
|
4504
4141
|
this._noupdate_listeners = /* @__PURE__ */ new Set();
|
4505
|
-
|
4506
|
-
this.
|
4507
|
-
this.
|
4508
|
-
this.
|
4509
|
-
this.opts = opts;
|
4510
|
-
this.sthis = sthis;
|
4511
|
-
this.id = sthis.timeOrderedNextId().str;
|
4142
|
+
this._ready = new import_cement16.ResolveOnce();
|
4143
|
+
this.name = name;
|
4144
|
+
this.opts = opts || this.opts;
|
4145
|
+
this.sthis = ensureSuperThis(this.opts);
|
4512
4146
|
this.logger = ensureLogger(this.sthis, "Database");
|
4513
|
-
this.
|
4147
|
+
this._crdt = new CRDT(this.sthis, name, this.opts);
|
4148
|
+
this.blockstore = this._crdt.blockstore;
|
4514
4149
|
this._writeQueue = writeQueue(async (updates) => {
|
4515
|
-
return await this.
|
4150
|
+
return await this._crdt.bulk(updates);
|
4516
4151
|
});
|
4517
|
-
this.
|
4152
|
+
this._crdt.clock.onTock(() => {
|
4518
4153
|
this._no_update_notify();
|
4519
4154
|
});
|
4520
4155
|
}
|
4521
|
-
|
4522
|
-
this.
|
4523
|
-
}
|
4524
|
-
onClosed(fn) {
|
4525
|
-
this._onClosedFns.add(fn);
|
4156
|
+
static {
|
4157
|
+
this.databases = /* @__PURE__ */ new Map();
|
4526
4158
|
}
|
4527
4159
|
async close() {
|
4528
|
-
|
4529
|
-
|
4530
|
-
|
4531
|
-
if (!this.shells.has(db)) {
|
4532
|
-
throw this.logger.Error().Str("db", this.name()).Msg(`Database Shell mismatch`).AsError();
|
4533
|
-
}
|
4534
|
-
this.shells.delete(db);
|
4535
|
-
if (this.shells.size === 0) {
|
4536
|
-
await this.ready();
|
4537
|
-
await this.crdt.close();
|
4538
|
-
this._onClosedFns.forEach((fn) => fn());
|
4539
|
-
}
|
4160
|
+
await this.ready();
|
4161
|
+
await this._crdt.close();
|
4162
|
+
await this.blockstore.close();
|
4540
4163
|
}
|
4541
4164
|
async destroy() {
|
4542
4165
|
await this.ready();
|
4543
|
-
await this.
|
4166
|
+
await this._crdt.destroy();
|
4167
|
+
await this.blockstore.destroy();
|
4544
4168
|
}
|
4545
4169
|
async ready() {
|
4546
|
-
|
4170
|
+
return this._ready.once(async () => {
|
4547
4171
|
await this.sthis.start();
|
4548
|
-
await this.
|
4172
|
+
await this._crdt.ready();
|
4173
|
+
await this.blockstore.ready();
|
4549
4174
|
});
|
4550
|
-
return ret;
|
4551
|
-
}
|
4552
|
-
name() {
|
4553
|
-
return this.opts.storeUrls.data.data.getParam("name" /* NAME */) || "default";
|
4554
4175
|
}
|
4555
4176
|
async get(id) {
|
4556
|
-
if (!id) throw this.logger.Error().Str("db", this.name
|
4177
|
+
if (!id) throw this.logger.Error().Str("db", this.name).Msg(`Doc id is required`).AsError();
|
4557
4178
|
await this.ready();
|
4558
4179
|
this.logger.Debug().Str("id", id).Msg("get");
|
4559
|
-
const got = await this.
|
4180
|
+
const got = await this._crdt.get(id).catch((e) => {
|
4560
4181
|
throw new NotFoundError(`Not found: ${id} - ${e.message}`);
|
4561
4182
|
});
|
4562
4183
|
if (!got) throw new NotFoundError(`Not found: ${id}`);
|
@@ -4575,34 +4196,34 @@ var DatabaseImpl = class {
|
|
4575
4196
|
_id: docId
|
4576
4197
|
}
|
4577
4198
|
});
|
4578
|
-
return { id: docId, clock: result?.head, name: this.name
|
4199
|
+
return { id: docId, clock: result?.head, name: this.name };
|
4579
4200
|
}
|
4580
4201
|
async del(id) {
|
4581
4202
|
await this.ready();
|
4582
4203
|
this.logger.Debug().Str("id", id).Msg("del");
|
4583
4204
|
const result = await this._writeQueue.push({ id, del: true });
|
4584
|
-
return { id, clock: result?.head, name: this.name
|
4205
|
+
return { id, clock: result?.head, name: this.name };
|
4585
4206
|
}
|
4586
4207
|
async changes(since = [], opts = {}) {
|
4587
4208
|
await this.ready();
|
4588
4209
|
this.logger.Debug().Any("since", since).Any("opts", opts).Msg("changes");
|
4589
|
-
const { result, head } = await this.
|
4210
|
+
const { result, head } = await this._crdt.changes(since, opts);
|
4590
4211
|
const rows = result.map(({ id: key, value, del, clock }) => ({
|
4591
4212
|
key,
|
4592
4213
|
value: del ? { _id: key, _deleted: true } : { _id: key, ...value },
|
4593
4214
|
clock
|
4594
4215
|
}));
|
4595
|
-
return { rows, clock: head, name: this.name
|
4216
|
+
return { rows, clock: head, name: this.name };
|
4596
4217
|
}
|
4597
4218
|
async allDocs(opts = {}) {
|
4598
4219
|
await this.ready();
|
4599
4220
|
this.logger.Debug().Msg("allDocs");
|
4600
|
-
const { result, head } = await this.
|
4221
|
+
const { result, head } = await this._crdt.allDocs();
|
4601
4222
|
const rows = result.map(({ id: key, value, del }) => ({
|
4602
4223
|
key,
|
4603
4224
|
value: del ? { _id: key, _deleted: true } : { _id: key, ...value }
|
4604
4225
|
}));
|
4605
|
-
return { rows, clock: head, name: this.name
|
4226
|
+
return { rows, clock: head, name: this.name };
|
4606
4227
|
}
|
4607
4228
|
async allDocuments() {
|
4608
4229
|
return this.allDocs();
|
@@ -4612,7 +4233,7 @@ var DatabaseImpl = class {
|
|
4612
4233
|
if (updates) {
|
4613
4234
|
if (!this._listening) {
|
4614
4235
|
this._listening = true;
|
4615
|
-
this.
|
4236
|
+
this._crdt.clock.onTick((updates2) => {
|
4616
4237
|
void this._notify(updates2);
|
4617
4238
|
});
|
4618
4239
|
}
|
@@ -4631,13 +4252,13 @@ var DatabaseImpl = class {
|
|
4631
4252
|
async query(field, opts = {}) {
|
4632
4253
|
await this.ready();
|
4633
4254
|
this.logger.Debug().Any("field", field).Any("opts", opts).Msg("query");
|
4634
|
-
const _crdt = this.
|
4635
|
-
const idx = typeof field === "string" ? index({
|
4255
|
+
const _crdt = this._crdt;
|
4256
|
+
const idx = typeof field === "string" ? index(this.sthis, { _crdt }, field) : index(this.sthis, { _crdt }, makeName(field.toString()), field);
|
4636
4257
|
return await idx.query(opts);
|
4637
4258
|
}
|
4638
4259
|
async compact() {
|
4639
4260
|
await this.ready();
|
4640
|
-
await this.
|
4261
|
+
await this._crdt.compact();
|
4641
4262
|
}
|
4642
4263
|
async _notify(updates) {
|
4643
4264
|
await this.ready();
|
@@ -4661,62 +4282,23 @@ var DatabaseImpl = class {
|
|
4661
4282
|
}
|
4662
4283
|
}
|
4663
4284
|
};
|
4664
|
-
function
|
4665
|
-
|
4666
|
-
|
4667
|
-
if (!ret.hasParam("name" /* NAME */)) {
|
4668
|
-
const name = sthis.pathOps.basename(ret.URI().pathname);
|
4669
|
-
if (!name) {
|
4670
|
-
throw sthis.logger.Error().Url(ret).Any("ctx", ctx).Msg("Database name is required").AsError();
|
4671
|
-
}
|
4672
|
-
ret.setParam("name" /* NAME */, name);
|
4673
|
-
}
|
4674
|
-
if (ctx.idx) {
|
4675
|
-
ret.defParam("index" /* INDEX */, "idx");
|
4676
|
-
ret.defParam("storekey" /* STORE_KEY */, `@${ret.getParam("name" /* NAME */)}-${store}-idx@`);
|
4677
|
-
} else {
|
4678
|
-
ret.defParam("storekey" /* STORE_KEY */, `@${ret.getParam("name" /* NAME */)}-${store}@`);
|
4679
|
-
}
|
4680
|
-
if (store === "data") {
|
4681
|
-
if (ctx.file) {
|
4682
|
-
} else {
|
4683
|
-
ret.defParam("suffix" /* SUFFIX */, ".car");
|
4684
|
-
}
|
4685
|
-
}
|
4686
|
-
return ret.URI();
|
4687
|
-
}
|
4688
|
-
function toStoreURIRuntime(sthis, name, sopts) {
|
4689
|
-
sopts = sopts || {};
|
4690
|
-
if (!sopts.base) {
|
4691
|
-
const fp_env = sthis.env.get("FP_STORAGE_URL");
|
4692
|
-
if (fp_env) {
|
4693
|
-
sopts = { ...sopts, base: import_cement18.BuildURI.from(fp_env).setParam("urlGen" /* URL_GEN */, "fromEnv") };
|
4694
|
-
} else {
|
4695
|
-
sopts = { ...sopts, base: getDefaultURI(sthis).build().setParam("urlGen" /* URL_GEN */, "default") };
|
4696
|
-
}
|
4697
|
-
}
|
4698
|
-
const bbase = import_cement18.BuildURI.from(sopts.base);
|
4699
|
-
if (name) {
|
4700
|
-
bbase.setParam("name" /* NAME */, name);
|
4701
|
-
}
|
4702
|
-
const base = bbase.URI();
|
4703
|
-
return {
|
4704
|
-
idx: {
|
4705
|
-
data: defaultURI(sthis, sopts.idx?.data, base, "data", { idx: true }),
|
4706
|
-
file: defaultURI(sthis, sopts.idx?.data, base, "data", { file: true, idx: true }),
|
4707
|
-
meta: defaultURI(sthis, sopts.idx?.meta, base, "meta", { idx: true }),
|
4708
|
-
wal: defaultURI(sthis, sopts.idx?.wal, base, "wal", { idx: true })
|
4709
|
-
},
|
4710
|
-
data: {
|
4711
|
-
data: defaultURI(sthis, sopts.data?.data, base, "data"),
|
4712
|
-
file: defaultURI(sthis, sopts.data?.data, base, "data", { file: true }),
|
4713
|
-
meta: defaultURI(sthis, sopts.data?.meta, base, "meta"),
|
4714
|
-
wal: defaultURI(sthis, sopts.data?.wal, base, "wal")
|
4715
|
-
}
|
4716
|
-
};
|
4285
|
+
function toSortedArray(set) {
|
4286
|
+
if (!set) return [];
|
4287
|
+
return Object.entries(set).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => ({ [k]: v }));
|
4717
4288
|
}
|
4718
4289
|
function fireproof(name, opts) {
|
4719
|
-
|
4290
|
+
const key = JSON.stringify(
|
4291
|
+
toSortedArray({
|
4292
|
+
name,
|
4293
|
+
stores: toSortedArray(opts?.store?.stores)
|
4294
|
+
})
|
4295
|
+
);
|
4296
|
+
let db = Database.databases.get(key);
|
4297
|
+
if (!db) {
|
4298
|
+
db = new Database(name, opts);
|
4299
|
+
Database.databases.set(key, db);
|
4300
|
+
}
|
4301
|
+
return db;
|
4720
4302
|
}
|
4721
4303
|
function makeName(fnString) {
|
4722
4304
|
const regex = /\(([^,()]+,\s*[^,()]+|\[[^\]]+\],\s*[^,()]+)\)/g;
|
@@ -4735,9 +4317,6 @@ function makeName(fnString) {
|
|
4735
4317
|
}
|
4736
4318
|
}
|
4737
4319
|
|
4738
|
-
// src/index.ts
|
4739
|
-
init_types();
|
4740
|
-
|
4741
4320
|
// src/runtime/index.ts
|
4742
4321
|
var runtime_exports = {};
|
4743
4322
|
__export(runtime_exports, {
|
@@ -4750,7 +4329,7 @@ __export(runtime_exports, {
|
|
4750
4329
|
kb: () => key_bag_exports,
|
4751
4330
|
kc: () => keyed_crypto_exports,
|
4752
4331
|
mf: () => wait_pr_multiformats_exports,
|
4753
|
-
runtimeFn: () =>
|
4332
|
+
runtimeFn: () => import_cement17.runtimeFn,
|
4754
4333
|
toArrayBuffer: () => toArrayBuffer
|
4755
4334
|
});
|
4756
4335
|
init_utils2();
|
@@ -4766,7 +4345,7 @@ __export(wait_pr_multiformats_exports, {
|
|
4766
4345
|
var codec_interface_exports = {};
|
4767
4346
|
|
4768
4347
|
// src/runtime/index.ts
|
4769
|
-
var
|
4348
|
+
var import_cement17 = require("@adviser/cement");
|
4770
4349
|
init_version();
|
4771
4350
|
init_version2();
|
4772
4351
|
|
@@ -4775,6 +4354,6 @@ init_utils();
|
|
4775
4354
|
|
4776
4355
|
// src/version.ts
|
4777
4356
|
var PACKAGE_VERSION = Object.keys({
|
4778
|
-
"0.19.
|
4357
|
+
"0.19.103": "xxxx"
|
4779
4358
|
})[0];
|
4780
4359
|
//# sourceMappingURL=index.cjs.map
|