@fireproof/core 0.19.9-dev-frag → 0.19.11-dev-dryrun2
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/README.md +27 -0
- package/{chunk-YS4GL6OK.js → chunk-OFGPKRCM.js} +30 -6
- package/chunk-OFGPKRCM.js.map +1 -0
- package/{chunk-JO5AVWG7.js → chunk-WS3YRPIA.js} +14 -6
- package/chunk-WS3YRPIA.js.map +1 -0
- package/deno.json +20 -0
- package/{gateway-YSNUK2L3.js → gateway-5FCWPX5W.js} +4 -5
- package/{gateway-YSNUK2L3.js.map → gateway-5FCWPX5W.js.map} +1 -1
- package/{gateway-IZRHJWPE.js → gateway-H7UD6TNB.js} +3 -4
- package/gateway-H7UD6TNB.js.map +1 -0
- package/index.cjs +468 -338
- package/index.cjs.map +1 -1
- package/index.d.cts +80 -52
- package/index.d.ts +80 -52
- package/index.global.js +21378 -15079
- package/index.global.js.map +1 -1
- package/index.js +389 -293
- package/index.js.map +1 -1
- package/{key-bag-file-NMEBFSPM.js → key-bag-file-WADZBHYG.js} +3 -3
- package/{key-bag-indexdb-X5V6GNBZ.js → key-bag-indexdb-PGVAI3FJ.js} +3 -3
- package/key-bag-indexdb-PGVAI3FJ.js.map +1 -0
- package/{mem-filesystem-B6C6QOIP.js → mem-filesystem-YPPJV7Q2.js} +3 -3
- package/metafile-cjs.json +1 -1
- package/metafile-esm.json +1 -1
- package/metafile-iife.json +1 -1
- package/{node-filesystem-5JLBSHKQ.js → node-filesystem-INX4ZTHE.js} +8 -4
- package/node-filesystem-INX4ZTHE.js.map +1 -0
- package/package.json +8 -5
- package/tests/blockstore/keyed-crypto.test.ts +34 -4
- package/tests/blockstore/store.test.ts +18 -13
- package/tests/fireproof/all-gateway.test.ts +394 -0
- package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.car +0 -0
- package/tests/fireproof/cars/bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i.ts +316 -0
- package/tests/fireproof/fireproof.test.ts +18 -18
- package/tests/fireproof/hello.test.ts +33 -19
- package/tests/fireproof/utils.test.ts +19 -0
- package/tests/helpers.ts +7 -4
- package/tests/www/todo-local.html +1 -1
- package/tests/www/todo.html +12 -15
- package/{utils-IZPK4QS7.js → utils-QO2HIWGI.js} +3 -3
- package/chunk-JO5AVWG7.js.map +0 -1
- package/chunk-YS4GL6OK.js.map +0 -1
- package/gateway-IZRHJWPE.js.map +0 -1
- package/key-bag-indexdb-X5V6GNBZ.js.map +0 -1
- package/node-filesystem-5JLBSHKQ.js.map +0 -1
- /package/{key-bag-file-NMEBFSPM.js.map → key-bag-file-WADZBHYG.js.map} +0 -0
- /package/{mem-filesystem-B6C6QOIP.js.map → mem-filesystem-YPPJV7Q2.js.map} +0 -0
- /package/{utils-IZPK4QS7.js.map → utils-QO2HIWGI.js.map} +0 -0
package/index.cjs
CHANGED
@@ -117,6 +117,21 @@ function ensureLogger(sthis, componentName, ctx) {
|
|
117
117
|
sthis.env.onSet(
|
118
118
|
(key, value) => {
|
119
119
|
switch (key) {
|
120
|
+
case "FP_FORMAT": {
|
121
|
+
switch (value) {
|
122
|
+
case "jsonice":
|
123
|
+
logger.SetFormatter(new import_cement.JSONFormatter(logger.TxtEnDe(), 2));
|
124
|
+
break;
|
125
|
+
case "yaml":
|
126
|
+
logger.SetFormatter(new import_cement.YAMLFormatter(logger.TxtEnDe(), 2));
|
127
|
+
break;
|
128
|
+
case "json":
|
129
|
+
default:
|
130
|
+
logger.SetFormatter(new import_cement.JSONFormatter(logger.TxtEnDe()));
|
131
|
+
break;
|
132
|
+
}
|
133
|
+
break;
|
134
|
+
}
|
120
135
|
case "FP_DEBUG":
|
121
136
|
logger.SetDebug(value || []);
|
122
137
|
break;
|
@@ -125,6 +140,7 @@ function ensureLogger(sthis, componentName, ctx) {
|
|
125
140
|
break;
|
126
141
|
}
|
127
142
|
},
|
143
|
+
"FP_FORMAT",
|
128
144
|
"FP_DEBUG",
|
129
145
|
"FP_STACK"
|
130
146
|
);
|
@@ -170,9 +186,6 @@ function getName(sthis, url) {
|
|
170
186
|
}
|
171
187
|
return result;
|
172
188
|
}
|
173
|
-
function exception2Result(fn) {
|
174
|
-
return fn().then((value) => import_cement.Result.Ok(value)).catch((e) => import_cement.Result.Err(e));
|
175
|
-
}
|
176
189
|
async function exceptionWrapper(fn) {
|
177
190
|
return fn().catch((e) => import_cement.Result.Err(e));
|
178
191
|
}
|
@@ -230,6 +243,16 @@ var init_utils = __esm({
|
|
230
243
|
bin
|
231
244
|
};
|
232
245
|
}
|
246
|
+
timeOrderedNextId(now) {
|
247
|
+
now = typeof now === "number" ? now : (/* @__PURE__ */ new Date()).getTime();
|
248
|
+
const t = (281474976710656 + now).toString(16).replace(/^1/, "");
|
249
|
+
const bin = this.crypto.randomBytes(10);
|
250
|
+
bin[1] = bin[1] & 240 | (bin[1] | 8 && 11);
|
251
|
+
const hex = Array.from(bin).map((i) => i.toString(16).padStart(2, "0")).join("");
|
252
|
+
return {
|
253
|
+
str: `${t.slice(0, 8)}-${t.slice(8)}-7${hex.slice(0, 3)}-${hex.slice(3, 7)}-${hex.slice(7, 19)}`
|
254
|
+
};
|
255
|
+
}
|
233
256
|
start() {
|
234
257
|
return Promise.resolve();
|
235
258
|
}
|
@@ -318,11 +341,12 @@ var node_filesystem_exports = {};
|
|
318
341
|
__export(node_filesystem_exports, {
|
319
342
|
NodeFileSystem: () => NodeFileSystem
|
320
343
|
});
|
321
|
-
var NodeFileSystem;
|
344
|
+
var import_cement4, NodeFileSystem;
|
322
345
|
var init_node_filesystem = __esm({
|
323
346
|
"src/runtime/gateways/file/node-filesystem.ts"() {
|
324
347
|
"use strict";
|
325
348
|
init_utils2();
|
349
|
+
import_cement4 = require("@adviser/cement");
|
326
350
|
NodeFileSystem = class {
|
327
351
|
async start() {
|
328
352
|
this.fs = await import("fs/promises");
|
@@ -351,6 +375,9 @@ var init_node_filesystem = __esm({
|
|
351
375
|
return this.fs?.unlink(path);
|
352
376
|
}
|
353
377
|
async writefile(path, data) {
|
378
|
+
if ((0, import_cement4.runtimeFn)().isDeno) {
|
379
|
+
return this.fs?.writeFile(path, data);
|
380
|
+
}
|
354
381
|
return this.fs?.writeFile(path, Buffer.from(data));
|
355
382
|
}
|
356
383
|
};
|
@@ -375,11 +402,19 @@ async function getFileSystem(url) {
|
|
375
402
|
fs2 = new MemFileSystem2();
|
376
403
|
}
|
377
404
|
break;
|
378
|
-
case
|
379
|
-
|
380
|
-
|
405
|
+
// case 'deno': {
|
406
|
+
// const { DenoFileSystem } = await import("./deno-filesystem.js");
|
407
|
+
// fs = new DenoFileSystem();
|
408
|
+
// break;
|
409
|
+
// }
|
410
|
+
case "node": {
|
381
411
|
const { NodeFileSystem: NodeFileSystem2 } = await Promise.resolve().then(() => (init_node_filesystem(), node_filesystem_exports));
|
382
412
|
fs2 = new NodeFileSystem2();
|
413
|
+
break;
|
414
|
+
}
|
415
|
+
case "sys":
|
416
|
+
default: {
|
417
|
+
return getFileSystem(url.build().setParam("fs", "node").URI());
|
383
418
|
}
|
384
419
|
}
|
385
420
|
return fs2.start();
|
@@ -489,16 +524,16 @@ var key_bag_indexdb_exports = {};
|
|
489
524
|
__export(key_bag_indexdb_exports, {
|
490
525
|
KeyBagProviderIndexDB: () => KeyBagProviderIndexDB
|
491
526
|
});
|
492
|
-
var import_idb,
|
527
|
+
var import_idb, import_cement5, KeyBagProviderIndexDB;
|
493
528
|
var init_key_bag_indexdb = __esm({
|
494
529
|
"src/runtime/key-bag-indexdb.ts"() {
|
495
530
|
"use strict";
|
496
531
|
import_idb = require("idb");
|
497
532
|
init_utils2();
|
498
|
-
|
533
|
+
import_cement5 = require("@adviser/cement");
|
499
534
|
KeyBagProviderIndexDB = class {
|
500
535
|
constructor(url, sthis) {
|
501
|
-
this._db = new
|
536
|
+
this._db = new import_cement5.ResolveOnce();
|
502
537
|
this.sthis = sthis;
|
503
538
|
this.logger = sthis.logger;
|
504
539
|
this.url = url;
|
@@ -552,15 +587,15 @@ __export(gateway_exports, {
|
|
552
587
|
FileGateway: () => FileGateway,
|
553
588
|
FileTestStore: () => FileTestStore
|
554
589
|
});
|
555
|
-
var
|
590
|
+
var import_cement11, versionFiles, FileGateway, FileTestStore;
|
556
591
|
var init_gateway = __esm({
|
557
592
|
"src/runtime/gateways/file/gateway.ts"() {
|
558
593
|
"use strict";
|
559
594
|
init_version();
|
560
|
-
|
595
|
+
import_cement11 = require("@adviser/cement");
|
561
596
|
init_utils();
|
562
597
|
init_utils2();
|
563
|
-
versionFiles = new
|
598
|
+
versionFiles = new import_cement11.KeyedResolvOnce();
|
564
599
|
FileGateway = class {
|
565
600
|
get fs() {
|
566
601
|
if (!this._fs) throw this.logger.Error().Msg("fs not initialized").AsError();
|
@@ -590,7 +625,7 @@ var init_gateway = __esm({
|
|
590
625
|
});
|
591
626
|
}
|
592
627
|
start(baseURL) {
|
593
|
-
return exception2Result(async () => {
|
628
|
+
return (0, import_cement11.exception2Result)(async () => {
|
594
629
|
this._fs = await getFileSystem(baseURL);
|
595
630
|
await this.fs.start();
|
596
631
|
const url = baseURL.build();
|
@@ -605,10 +640,10 @@ var init_gateway = __esm({
|
|
605
640
|
});
|
606
641
|
}
|
607
642
|
async buildUrl(baseUrl, key) {
|
608
|
-
return
|
643
|
+
return import_cement11.Result.Ok(baseUrl.build().setParam("key", key).URI());
|
609
644
|
}
|
610
645
|
async close() {
|
611
|
-
return
|
646
|
+
return import_cement11.Result.Ok(void 0);
|
612
647
|
}
|
613
648
|
// abstract buildUrl(baseUrl: URL, key: string): Promise<Result<URL>>;
|
614
649
|
getFilePath(url) {
|
@@ -617,7 +652,7 @@ var init_gateway = __esm({
|
|
617
652
|
return this.sthis.pathOps.join(getPath(url, this.sthis), getFileName(url, this.sthis));
|
618
653
|
}
|
619
654
|
async put(url, body) {
|
620
|
-
return exception2Result(async () => {
|
655
|
+
return (0, import_cement11.exception2Result)(async () => {
|
621
656
|
const file = await this.getFilePath(url);
|
622
657
|
this.logger.Debug().Str("url", url.toString()).Str("file", file).Msg("put");
|
623
658
|
await this.fs.writefile(file, body);
|
@@ -629,17 +664,17 @@ var init_gateway = __esm({
|
|
629
664
|
try {
|
630
665
|
const res = await this.fs.readfile(file);
|
631
666
|
this.logger.Debug().Url(url.asURL()).Str("file", file).Msg("get");
|
632
|
-
return
|
667
|
+
return import_cement11.Result.Ok(new Uint8Array(res));
|
633
668
|
} catch (e) {
|
634
669
|
if (isNotFoundError(e)) {
|
635
|
-
return
|
670
|
+
return import_cement11.Result.Err(new NotFoundError(`file not found: ${file}`));
|
636
671
|
}
|
637
|
-
return
|
672
|
+
return import_cement11.Result.Err(e);
|
638
673
|
}
|
639
674
|
});
|
640
675
|
}
|
641
676
|
async delete(url) {
|
642
|
-
return exception2Result(async () => {
|
677
|
+
return (0, import_cement11.exception2Result)(async () => {
|
643
678
|
await this.fs.unlink(this.getFilePath(url));
|
644
679
|
});
|
645
680
|
}
|
@@ -665,7 +700,7 @@ var init_gateway = __esm({
|
|
665
700
|
}
|
666
701
|
}
|
667
702
|
}
|
668
|
-
return
|
703
|
+
return import_cement11.Result.Ok(void 0);
|
669
704
|
}
|
670
705
|
};
|
671
706
|
FileTestStore = class {
|
@@ -754,15 +789,15 @@ function getIndexDBName(iurl, sthis) {
|
|
754
789
|
dbName
|
755
790
|
};
|
756
791
|
}
|
757
|
-
var import_idb2,
|
792
|
+
var import_idb2, import_cement12, onceIndexDB, IndexDBGateway, IndexDBTestStore;
|
758
793
|
var init_gateway2 = __esm({
|
759
794
|
"src/runtime/gateways/indexdb/gateway.ts"() {
|
760
795
|
"use strict";
|
761
796
|
import_idb2 = require("idb");
|
762
|
-
|
797
|
+
import_cement12 = require("@adviser/cement");
|
763
798
|
init_version2();
|
764
799
|
init_utils();
|
765
|
-
onceIndexDB = new
|
800
|
+
onceIndexDB = new import_cement12.KeyedResolvOnce();
|
766
801
|
IndexDBGateway = class {
|
767
802
|
constructor(sthis) {
|
768
803
|
this._db = {};
|
@@ -770,7 +805,7 @@ var init_gateway2 = __esm({
|
|
770
805
|
this.sthis = sthis;
|
771
806
|
}
|
772
807
|
async start(baseURL) {
|
773
|
-
return exception2Result(async () => {
|
808
|
+
return (0, import_cement12.exception2Result)(async () => {
|
774
809
|
this.logger.Debug().Url(baseURL).Msg("starting");
|
775
810
|
await this.sthis.start();
|
776
811
|
const ic = await connectIdb(baseURL, this.sthis);
|
@@ -780,10 +815,10 @@ var init_gateway2 = __esm({
|
|
780
815
|
});
|
781
816
|
}
|
782
817
|
async close() {
|
783
|
-
return
|
818
|
+
return import_cement12.Result.Ok(void 0);
|
784
819
|
}
|
785
820
|
async destroy(baseUrl) {
|
786
|
-
return exception2Result(async () => {
|
821
|
+
return (0, import_cement12.exception2Result)(async () => {
|
787
822
|
const type = getStore(baseUrl, this.sthis, joinDBName).name;
|
788
823
|
const idb = this._db;
|
789
824
|
const trans = idb.transaction(type, "readwrite");
|
@@ -799,7 +834,7 @@ var init_gateway2 = __esm({
|
|
799
834
|
});
|
800
835
|
}
|
801
836
|
buildUrl(baseUrl, key) {
|
802
|
-
return Promise.resolve(
|
837
|
+
return Promise.resolve(import_cement12.Result.Ok(baseUrl.build().setParam("key", key).URI()));
|
803
838
|
}
|
804
839
|
async get(url) {
|
805
840
|
return exceptionWrapper(async () => {
|
@@ -810,13 +845,13 @@ var init_gateway2 = __esm({
|
|
810
845
|
const bytes = await tx.objectStore(store).get(sanitzeKey(key));
|
811
846
|
await tx.done;
|
812
847
|
if (!bytes) {
|
813
|
-
return
|
848
|
+
return import_cement12.Result.Err(new NotFoundError(`missing ${key}`));
|
814
849
|
}
|
815
|
-
return
|
850
|
+
return import_cement12.Result.Ok(bytes);
|
816
851
|
});
|
817
852
|
}
|
818
853
|
async put(url, value) {
|
819
|
-
return exception2Result(async () => {
|
854
|
+
return (0, import_cement12.exception2Result)(async () => {
|
820
855
|
const key = getKey(url, this.logger);
|
821
856
|
const store = getStore(url, this.sthis, joinDBName).name;
|
822
857
|
this.logger.Debug().Url(url).Str("key", key).Str("store", store).Msg("putting");
|
@@ -826,14 +861,14 @@ var init_gateway2 = __esm({
|
|
826
861
|
});
|
827
862
|
}
|
828
863
|
async delete(url) {
|
829
|
-
return exception2Result(async () => {
|
864
|
+
return (0, import_cement12.exception2Result)(async () => {
|
830
865
|
const key = getKey(url, this.logger);
|
831
866
|
const store = getStore(url, this.sthis, joinDBName).name;
|
832
867
|
this.logger.Debug().Url(url).Str("key", key).Str("store", store).Msg("deleting");
|
833
868
|
const tx = this._db.transaction([store], "readwrite");
|
834
869
|
await tx.objectStore(store).delete(sanitzeKey(key));
|
835
870
|
await tx.done;
|
836
|
-
return
|
871
|
+
return import_cement12.Result.Ok(void 0);
|
837
872
|
});
|
838
873
|
}
|
839
874
|
};
|
@@ -873,7 +908,6 @@ __export(src_exports, {
|
|
873
908
|
ensureLogger: () => ensureLogger,
|
874
909
|
ensureSuperLog: () => ensureSuperLog,
|
875
910
|
ensureSuperThis: () => ensureSuperThis,
|
876
|
-
exception2Result: () => exception2Result,
|
877
911
|
exceptionWrapper: () => exceptionWrapper,
|
878
912
|
falsyToUndef: () => falsyToUndef,
|
879
913
|
fireproof: () => fireproof,
|
@@ -890,7 +924,7 @@ __export(src_exports, {
|
|
890
924
|
module.exports = __toCommonJS(src_exports);
|
891
925
|
|
892
926
|
// src/database.ts
|
893
|
-
var
|
927
|
+
var import_cement16 = require("@adviser/cement");
|
894
928
|
|
895
929
|
// src/write-queue.ts
|
896
930
|
function writeQueue(worker, payload = Infinity, unbounded = false) {
|
@@ -933,7 +967,7 @@ function writeQueue(worker, payload = Infinity, unbounded = false) {
|
|
933
967
|
}
|
934
968
|
|
935
969
|
// src/crdt.ts
|
936
|
-
var
|
970
|
+
var import_cement15 = require("@adviser/cement");
|
937
971
|
|
938
972
|
// src/runtime/wait-pr-multiformats/block.ts
|
939
973
|
var block_exports = {};
|
@@ -1024,10 +1058,12 @@ __export(blockstore_exports, {
|
|
1024
1058
|
EncryptedBlockstore: () => EncryptedBlockstore,
|
1025
1059
|
FragmentGateway: () => FragmentGateway,
|
1026
1060
|
Loader: () => Loader,
|
1061
|
+
addCryptoKeyToGatewayMetaPayload: () => addCryptoKeyToGatewayMetaPayload,
|
1027
1062
|
ensureStart: () => ensureStart,
|
1028
1063
|
getGatewayFromURL: () => getGatewayFromURL,
|
1029
1064
|
parseCarFile: () => parseCarFile,
|
1030
1065
|
registerStoreProtocol: () => registerStoreProtocol,
|
1066
|
+
setCryptoKeyFromGatewayMetaPayload: () => setCryptoKeyFromGatewayMetaPayload,
|
1031
1067
|
testStoreFactory: () => testStoreFactory,
|
1032
1068
|
toCIDBlock: () => toCIDBlock,
|
1033
1069
|
toStoreRuntime: () => toStoreRuntime
|
@@ -1039,7 +1075,7 @@ function toCIDBlock(block) {
|
|
1039
1075
|
}
|
1040
1076
|
|
1041
1077
|
// src/blockstore/store-factory.ts
|
1042
|
-
var
|
1078
|
+
var import_cement13 = require("@adviser/cement");
|
1043
1079
|
|
1044
1080
|
// src/runtime/files.ts
|
1045
1081
|
var files_exports = {};
|
@@ -1114,8 +1150,8 @@ var UnixFSFileBuilder = class {
|
|
1114
1150
|
|
1115
1151
|
// src/blockstore/store.ts
|
1116
1152
|
var import_p_limit2 = __toESM(require("p-limit"), 1);
|
1117
|
-
var
|
1118
|
-
var
|
1153
|
+
var import_dag_json2 = require("@ipld/dag-json");
|
1154
|
+
var import_cement10 = require("@adviser/cement");
|
1119
1155
|
|
1120
1156
|
// src/types.ts
|
1121
1157
|
function isFalsy(value) {
|
@@ -1140,7 +1176,7 @@ init_utils();
|
|
1140
1176
|
// src/blockstore/loader.ts
|
1141
1177
|
var import_p_limit = __toESM(require("p-limit"), 1);
|
1142
1178
|
var import_car = require("@ipld/car");
|
1143
|
-
var
|
1179
|
+
var import_cement7 = require("@adviser/cement");
|
1144
1180
|
|
1145
1181
|
// src/blockstore/loader-helpers.ts
|
1146
1182
|
var import_sha2 = require("multiformats/hashes/sha2");
|
@@ -1411,34 +1447,38 @@ __export(key_bag_exports, {
|
|
1411
1447
|
getKeyBag: () => getKeyBag,
|
1412
1448
|
registerKeyBagProviderFactory: () => registerKeyBagProviderFactory
|
1413
1449
|
});
|
1414
|
-
var
|
1450
|
+
var import_cement6 = require("@adviser/cement");
|
1415
1451
|
init_utils();
|
1416
1452
|
var import_base582 = require("multiformats/bases/base58");
|
1417
1453
|
var KeyBag = class {
|
1418
1454
|
constructor(rt) {
|
1419
1455
|
this.rt = rt;
|
1420
|
-
this.
|
1421
|
-
this.
|
1422
|
-
|
1423
|
-
});
|
1456
|
+
this._warnOnce = new import_cement6.ResolveOnce();
|
1457
|
+
this._seq = new import_cement6.ResolveSeq();
|
1458
|
+
this.logger = ensureLogger(rt.sthis, "KeyBag");
|
1424
1459
|
this.logger.Debug().Msg("KeyBag created");
|
1425
1460
|
}
|
1426
1461
|
async subtleKey(key) {
|
1462
|
+
const extractable = this.rt.url.getParam("extractKey") === "_deprecated_internal_api";
|
1463
|
+
if (extractable) {
|
1464
|
+
this._warnOnce.once(
|
1465
|
+
() => this.logger.Warn().Msg("extractKey is enabled via _deprecated_internal_api --- handle keys safely!!!")
|
1466
|
+
);
|
1467
|
+
}
|
1427
1468
|
return await this.rt.crypto.importKey(
|
1428
1469
|
"raw",
|
1429
1470
|
// raw or jwk
|
1430
1471
|
import_base582.base58btc.decode(key),
|
1431
1472
|
// hexStringToUint8Array(key), // raw data
|
1432
1473
|
"AES-GCM",
|
1433
|
-
|
1434
|
-
// extractable
|
1474
|
+
extractable,
|
1435
1475
|
["encrypt", "decrypt"]
|
1436
1476
|
);
|
1437
1477
|
}
|
1438
1478
|
async ensureKeyFromUrl(url, keyFactory) {
|
1439
1479
|
const storeKey = url.getParam("storekey");
|
1440
1480
|
if (storeKey === "insecure") {
|
1441
|
-
return
|
1481
|
+
return import_cement6.Result.Ok(url);
|
1442
1482
|
}
|
1443
1483
|
if (!storeKey) {
|
1444
1484
|
const keyName = `@${keyFactory()}@`;
|
@@ -1447,7 +1487,7 @@ var KeyBag = class {
|
|
1447
1487
|
return ret;
|
1448
1488
|
}
|
1449
1489
|
const urb = url.build().setParam("storekey", keyName);
|
1450
|
-
return
|
1490
|
+
return import_cement6.Result.Ok(urb.URI());
|
1451
1491
|
}
|
1452
1492
|
if (storeKey.startsWith("@") && storeKey.endsWith("@")) {
|
1453
1493
|
const ret = await this.getNamedKey(storeKey);
|
@@ -1455,13 +1495,13 @@ var KeyBag = class {
|
|
1455
1495
|
return ret;
|
1456
1496
|
}
|
1457
1497
|
}
|
1458
|
-
return
|
1498
|
+
return import_cement6.Result.Ok(url);
|
1459
1499
|
}
|
1460
1500
|
async toKeyWithFingerPrint(keyStr) {
|
1461
1501
|
const material = import_base582.base58btc.decode(keyStr);
|
1462
1502
|
const key = await this.subtleKey(keyStr);
|
1463
1503
|
const fpr = await this.rt.crypto.digestSHA256(material);
|
1464
|
-
return
|
1504
|
+
return import_cement6.Result.Ok({
|
1465
1505
|
key,
|
1466
1506
|
fingerPrint: import_base582.base58btc.encode(new Uint8Array(fpr))
|
1467
1507
|
});
|
@@ -1480,6 +1520,23 @@ var KeyBag = class {
|
|
1480
1520
|
await bag.set(name, item);
|
1481
1521
|
return await this.toKeyWithFingerPrint(item.key);
|
1482
1522
|
}
|
1523
|
+
async getNamedExtractableKey(name, failIfNotFound = false) {
|
1524
|
+
const ret = await this.getNamedKey(name, failIfNotFound);
|
1525
|
+
if (ret.isErr()) {
|
1526
|
+
return ret;
|
1527
|
+
}
|
1528
|
+
const named = ret.Ok();
|
1529
|
+
return import_cement6.Result.Ok({
|
1530
|
+
...named,
|
1531
|
+
extract: async () => {
|
1532
|
+
const ext = new Uint8Array(await this.rt.crypto.exportKey("raw", named.key));
|
1533
|
+
return {
|
1534
|
+
key: ext,
|
1535
|
+
keyStr: import_base582.base58btc.encode(ext)
|
1536
|
+
};
|
1537
|
+
}
|
1538
|
+
});
|
1539
|
+
}
|
1483
1540
|
async getNamedKey(name, failIfNotFound = false) {
|
1484
1541
|
const id = this.rt.sthis.nextId(4).str;
|
1485
1542
|
return this._seq.add(async () => {
|
@@ -1492,7 +1549,7 @@ var KeyBag = class {
|
|
1492
1549
|
}
|
1493
1550
|
if (failIfNotFound) {
|
1494
1551
|
this.logger.Debug().Str("id", id).Str("name", name).Msg("failIfNotFound getNamedKey");
|
1495
|
-
return
|
1552
|
+
return import_cement6.Result.Err(new Error(`Key not found: ${name}`));
|
1496
1553
|
}
|
1497
1554
|
const ret = await this._setNamedKey(name, import_base582.base58btc.encode(this.rt.crypto.randomBytes(this.rt.keyLength)));
|
1498
1555
|
this.logger.Debug().Str("id", id).Str("name", name).Result("fpr", ret).Msg("createKey getNamedKey-post");
|
@@ -1532,56 +1589,44 @@ function defaultKeyBagOpts(sthis, kbo) {
|
|
1532
1589
|
const logger = ensureLogger(sthis, "KeyBag");
|
1533
1590
|
let url;
|
1534
1591
|
if (kbo.url) {
|
1535
|
-
url =
|
1592
|
+
url = import_cement6.URI.from(kbo.url);
|
1536
1593
|
logger.Debug().Url(url).Msg("from opts");
|
1537
1594
|
} else {
|
1538
1595
|
let bagFnameOrUrl = sthis.env.get("FP_KEYBAG_URL");
|
1539
|
-
if ((0,
|
1540
|
-
url =
|
1596
|
+
if ((0, import_cement6.runtimeFn)().isBrowser) {
|
1597
|
+
url = import_cement6.URI.from(bagFnameOrUrl || "indexdb://fp-keybag");
|
1541
1598
|
} else {
|
1542
1599
|
if (!bagFnameOrUrl) {
|
1543
1600
|
const home = sthis.env.get("HOME");
|
1544
1601
|
bagFnameOrUrl = `${home}/.fireproof/keybag`;
|
1545
|
-
url =
|
1602
|
+
url = import_cement6.URI.from(`file://${bagFnameOrUrl}`);
|
1546
1603
|
} else {
|
1547
|
-
url =
|
1604
|
+
url = import_cement6.URI.from(bagFnameOrUrl);
|
1548
1605
|
}
|
1549
1606
|
}
|
1550
1607
|
logger.Debug().Url(url).Msg("from env");
|
1551
1608
|
}
|
1552
|
-
|
1553
|
-
|
1554
|
-
|
1555
|
-
keyProviderFactory = async () => {
|
1556
|
-
const { KeyBagProviderFile: KeyBagProviderFile2 } = await Promise.resolve().then(() => (init_key_bag_file(), key_bag_file_exports));
|
1557
|
-
return new KeyBagProviderFile2(url, sthis);
|
1558
|
-
};
|
1559
|
-
break;
|
1560
|
-
case "indexdb:":
|
1561
|
-
keyProviderFactory = async () => {
|
1562
|
-
const { KeyBagProviderIndexDB: KeyBagProviderIndexDB2 } = await Promise.resolve().then(() => (init_key_bag_indexdb(), key_bag_indexdb_exports));
|
1563
|
-
return new KeyBagProviderIndexDB2(url, sthis);
|
1564
|
-
};
|
1565
|
-
break;
|
1566
|
-
default:
|
1567
|
-
throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
|
1609
|
+
const kitem = keyBagProviderFactories.get(url.protocol);
|
1610
|
+
if (!kitem) {
|
1611
|
+
throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
|
1568
1612
|
}
|
1613
|
+
const getBag = async () => kitem.factory(url, sthis);
|
1569
1614
|
if (url.hasParam("masterkey")) {
|
1570
1615
|
throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
|
1571
1616
|
}
|
1572
1617
|
return {
|
1573
1618
|
url,
|
1574
|
-
crypto: kbo.crypto || (0,
|
1619
|
+
crypto: kbo.crypto || (0, import_cement6.toCryptoRuntime)({}),
|
1575
1620
|
sthis,
|
1576
1621
|
logger,
|
1577
1622
|
keyLength: kbo.keyLength || 16,
|
1578
|
-
getBag
|
1623
|
+
getBag,
|
1579
1624
|
id: () => {
|
1580
1625
|
return url.toString();
|
1581
1626
|
}
|
1582
1627
|
};
|
1583
1628
|
}
|
1584
|
-
var _keyBags = new
|
1629
|
+
var _keyBags = new import_cement6.KeyedResolvOnce();
|
1585
1630
|
async function getKeyBag(sthis, kbo = {}) {
|
1586
1631
|
await sthis.start();
|
1587
1632
|
const rt = defaultKeyBagOpts(sthis, kbo);
|
@@ -1669,7 +1714,7 @@ async function commit(params, t, done, opts = { noLoader: false, compact: false
|
|
1669
1714
|
}
|
1670
1715
|
async function prepareCarFiles(encoder, threshold, rootBlock, t) {
|
1671
1716
|
const carFiles = [];
|
1672
|
-
threshold = threshold ||
|
1717
|
+
threshold = threshold || 128e3 * 8;
|
1673
1718
|
let clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
|
1674
1719
|
clonedt.putSync(rootBlock.cid, rootBlock.bytes);
|
1675
1720
|
let newsize = CBW.blockLength(toCIDBlock(rootBlock));
|
@@ -1692,6 +1737,54 @@ async function prepareCarFiles(encoder, threshold, rootBlock, t) {
|
|
1692
1737
|
|
1693
1738
|
// src/blockstore/loader.ts
|
1694
1739
|
var import_sha23 = require("multiformats/hashes/sha2");
|
1740
|
+
|
1741
|
+
// src/blockstore/task-manager.ts
|
1742
|
+
init_utils();
|
1743
|
+
var TaskManager = class {
|
1744
|
+
constructor(sthis, callback) {
|
1745
|
+
this.eventsWeHandled = /* @__PURE__ */ new Set();
|
1746
|
+
this.queue = [];
|
1747
|
+
this.isProcessing = false;
|
1748
|
+
this.logger = ensureLogger(sthis, "TaskManager");
|
1749
|
+
this.callback = callback;
|
1750
|
+
}
|
1751
|
+
async handleEvent(cid, parents, dbMeta) {
|
1752
|
+
for (const parent of parents) {
|
1753
|
+
this.eventsWeHandled.add(parent.toString());
|
1754
|
+
}
|
1755
|
+
this.queue.push({ cid: cid.toString(), dbMeta, retries: 0 });
|
1756
|
+
this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
|
1757
|
+
void this.processQueue();
|
1758
|
+
}
|
1759
|
+
async processQueue() {
|
1760
|
+
if (this.isProcessing) return;
|
1761
|
+
this.isProcessing = true;
|
1762
|
+
const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
1763
|
+
const first = filteredQueue[0];
|
1764
|
+
if (!first) {
|
1765
|
+
return;
|
1766
|
+
}
|
1767
|
+
try {
|
1768
|
+
await this.callback(first.dbMeta);
|
1769
|
+
this.eventsWeHandled.add(first.cid);
|
1770
|
+
this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
1771
|
+
} catch (err) {
|
1772
|
+
if (first.retries++ > 3) {
|
1773
|
+
this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
|
1774
|
+
this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
|
1775
|
+
}
|
1776
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
1777
|
+
throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
|
1778
|
+
} finally {
|
1779
|
+
this.isProcessing = false;
|
1780
|
+
if (this.queue.length > 0) {
|
1781
|
+
void this.processQueue();
|
1782
|
+
}
|
1783
|
+
}
|
1784
|
+
}
|
1785
|
+
};
|
1786
|
+
|
1787
|
+
// src/blockstore/loader.ts
|
1695
1788
|
function carLogIncludesGroup(list, cids) {
|
1696
1789
|
return list.some((arr) => {
|
1697
1790
|
return arr.toString() === cids.toString();
|
@@ -1716,7 +1809,7 @@ var Loader = class {
|
|
1716
1809
|
this.getBlockCache = /* @__PURE__ */ new Map();
|
1717
1810
|
this.seenMeta = /* @__PURE__ */ new Set();
|
1718
1811
|
this.writeLimit = (0, import_p_limit.default)(1);
|
1719
|
-
this.onceReady = new
|
1812
|
+
this.onceReady = new import_cement7.ResolveOnce();
|
1720
1813
|
this.name = name;
|
1721
1814
|
this.sthis = sthis;
|
1722
1815
|
this.ebOpts = defaultedBlockstoreRuntime(
|
@@ -1728,6 +1821,9 @@ var Loader = class {
|
|
1728
1821
|
"Loader"
|
1729
1822
|
);
|
1730
1823
|
this.logger = this.ebOpts.logger;
|
1824
|
+
this.taskManager = new TaskManager(sthis, async (dbMeta) => {
|
1825
|
+
await this.handleDbMetasFromStore([dbMeta]);
|
1826
|
+
});
|
1731
1827
|
}
|
1732
1828
|
// readonly id = uuidv4();
|
1733
1829
|
async keyBag() {
|
@@ -1747,8 +1843,10 @@ var Loader = class {
|
|
1747
1843
|
}
|
1748
1844
|
async ready() {
|
1749
1845
|
return this.onceReady.once(async () => {
|
1750
|
-
const metas =
|
1751
|
-
if (
|
1846
|
+
const metas = await (await this.metaStore()).load();
|
1847
|
+
if (this.ebOpts.meta) {
|
1848
|
+
await this.handleDbMetasFromStore([this.ebOpts.meta]);
|
1849
|
+
} else if (metas) {
|
1752
1850
|
await this.handleDbMetasFromStore(metas);
|
1753
1851
|
}
|
1754
1852
|
});
|
@@ -1829,7 +1927,8 @@ var Loader = class {
|
|
1829
1927
|
carLog: this.carLog,
|
1830
1928
|
carStore: fstore,
|
1831
1929
|
WALStore: await this.WALStore(),
|
1832
|
-
metaStore: await this.metaStore()
|
1930
|
+
metaStore: await this.metaStore(),
|
1931
|
+
threshold: this.ebOpts.threshold
|
1833
1932
|
};
|
1834
1933
|
return this.commitQueue.enqueue(async () => {
|
1835
1934
|
await this.cacheTransaction(t);
|
@@ -2054,7 +2153,7 @@ var generateIV = {
|
|
2054
2153
|
calc: async (ko, crypto, data) => {
|
2055
2154
|
const hash = await import_sha24.sha256.digest(data);
|
2056
2155
|
const hashBytes = new Uint8Array(hash.bytes);
|
2057
|
-
const hashArray = new Uint8Array(ko.ivLength
|
2156
|
+
const hashArray = new Uint8Array(ko.ivLength);
|
2058
2157
|
for (let i = 0; i < hashBytes.length; i++) {
|
2059
2158
|
hashArray[i % ko.ivLength] ^= hashBytes[i];
|
2060
2159
|
}
|
@@ -2132,7 +2231,7 @@ var keyedCrypto = class {
|
|
2132
2231
|
};
|
2133
2232
|
}
|
2134
2233
|
async _decrypt(data) {
|
2135
|
-
this.logger.Debug().Len(data.bytes).Str("fp", this.key.fingerPrint).Msg("decrypting");
|
2234
|
+
this.logger.Debug().Len(data.bytes, "bytes").Len(data.iv, "iv").Str("fp", this.key.fingerPrint).Msg("decrypting");
|
2136
2235
|
return new Uint8Array(await this.crypto.decrypt(this.algo(data.iv), this.key.key, data.bytes));
|
2137
2236
|
}
|
2138
2237
|
async _encrypt(data) {
|
@@ -2203,8 +2302,10 @@ async function keyedCryptoFactory(url, kb, sthis) {
|
|
2203
2302
|
}
|
2204
2303
|
|
2205
2304
|
// src/blockstore/fragment-gateway.ts
|
2305
|
+
var import_cement8 = require("@adviser/cement");
|
2206
2306
|
var import_base584 = require("multiformats/bases/base58");
|
2207
2307
|
var import_cborg = require("cborg");
|
2308
|
+
init_utils();
|
2208
2309
|
function getFragSize(url) {
|
2209
2310
|
const fragSize = url.getParam("fragSize");
|
2210
2311
|
let ret = 0;
|
@@ -2225,7 +2326,7 @@ async function getFrags(url, innerGW, headerSize, logger) {
|
|
2225
2326
|
}
|
2226
2327
|
const data = res.unwrap();
|
2227
2328
|
return [
|
2228
|
-
|
2329
|
+
import_cement8.Result.Ok({
|
2229
2330
|
fid: new Uint8Array(0),
|
2230
2331
|
ofs: 0,
|
2231
2332
|
len: data.length,
|
@@ -2239,7 +2340,7 @@ async function getFrags(url, innerGW, headerSize, logger) {
|
|
2239
2340
|
}
|
2240
2341
|
const firstFragment = (0, import_cborg.decode)(firstRaw.unwrap());
|
2241
2342
|
const blockSize = firstFragment.data.length;
|
2242
|
-
const ops = [Promise.resolve(
|
2343
|
+
const ops = [Promise.resolve(import_cement8.Result.Ok(firstFragment))];
|
2243
2344
|
const fidStr = import_base584.base58btc.encode(firstFragment.fid);
|
2244
2345
|
const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
|
2245
2346
|
for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
|
@@ -2251,12 +2352,12 @@ async function getFrags(url, innerGW, headerSize, logger) {
|
|
2251
2352
|
}
|
2252
2353
|
const fragment = (0, import_cborg.decode)(raw2.unwrap());
|
2253
2354
|
if (import_base584.base58btc.encode(fragment.fid) !== fidStr) {
|
2254
|
-
return
|
2355
|
+
return import_cement8.Result.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
|
2255
2356
|
}
|
2256
2357
|
if (fragment.ofs !== ofs2) {
|
2257
|
-
return
|
2358
|
+
return import_cement8.Result.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
|
2258
2359
|
}
|
2259
|
-
return
|
2360
|
+
return import_cement8.Result.Ok(fragment);
|
2260
2361
|
})(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
|
2261
2362
|
);
|
2262
2363
|
}
|
@@ -2318,42 +2419,156 @@ var FragmentGateway = class {
|
|
2318
2419
|
}
|
2319
2420
|
async put(url, body) {
|
2320
2421
|
await Promise.all(this.slicer(url, body));
|
2321
|
-
return
|
2422
|
+
return import_cement8.Result.Ok(void 0);
|
2322
2423
|
}
|
2323
2424
|
async get(url) {
|
2324
2425
|
const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
|
2325
2426
|
let buffer = void 0;
|
2326
2427
|
for (const rfrag of rfrags) {
|
2327
2428
|
if (rfrag.isErr()) {
|
2328
|
-
return
|
2429
|
+
return import_cement8.Result.Err(rfrag.Err());
|
2329
2430
|
}
|
2330
2431
|
const frag = rfrag.Ok();
|
2331
2432
|
buffer = buffer || new Uint8Array(frag.len);
|
2332
2433
|
buffer.set(frag.data, frag.ofs);
|
2333
2434
|
}
|
2334
|
-
return
|
2435
|
+
return import_cement8.Result.Ok(buffer || new Uint8Array(0));
|
2436
|
+
}
|
2437
|
+
async subscribe(url, callback) {
|
2438
|
+
if (this.innerGW.subscribe) {
|
2439
|
+
return this.innerGW.subscribe(url, callback);
|
2440
|
+
} else {
|
2441
|
+
return import_cement8.Result.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
|
2442
|
+
}
|
2335
2443
|
}
|
2336
2444
|
async delete(url) {
|
2337
2445
|
const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
|
2338
2446
|
for (const rfrag of rfrags) {
|
2339
2447
|
if (rfrag.isErr()) {
|
2340
|
-
return
|
2448
|
+
return import_cement8.Result.Err(rfrag.Err());
|
2341
2449
|
}
|
2342
2450
|
const frag = rfrag.Ok();
|
2343
2451
|
const fidStr = import_base584.base58btc.encode(frag.fid);
|
2344
2452
|
const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
|
2345
2453
|
await this.innerGW.delete(fragUrl);
|
2346
2454
|
}
|
2347
|
-
return
|
2455
|
+
return import_cement8.Result.Ok(void 0);
|
2348
2456
|
}
|
2349
2457
|
};
|
2350
2458
|
|
2459
|
+
// src/blockstore/meta-key-helper.ts
|
2460
|
+
var import_dag_json = require("@ipld/dag-json");
|
2461
|
+
var import_clock = require("@web3-storage/pail/clock");
|
2462
|
+
var import_multiformats2 = require("multiformats");
|
2463
|
+
var import_base64 = require("multiformats/bases/base64");
|
2464
|
+
var import_cement9 = require("@adviser/cement");
|
2465
|
+
async function decodeGatewayMetaBytesToDbMeta(sthis, byteHeads) {
|
2466
|
+
const crdtEntries = JSON.parse(sthis.txt.decode(byteHeads));
|
2467
|
+
if (!crdtEntries.length) {
|
2468
|
+
sthis.logger.Debug().Str("byteHeads", new TextDecoder().decode(byteHeads)).Msg("No CRDT entries found");
|
2469
|
+
return [];
|
2470
|
+
}
|
2471
|
+
if (!crdtEntries.map) {
|
2472
|
+
sthis.logger.Debug().Str("crdtEntries", JSON.stringify(crdtEntries)).Msg("No data in CRDT entries");
|
2473
|
+
return [];
|
2474
|
+
}
|
2475
|
+
return Promise.all(
|
2476
|
+
crdtEntries.map(async (crdtEntry) => {
|
2477
|
+
const eventBlock = await (0, import_clock.decodeEventBlock)(import_base64.base64pad.decode(crdtEntry.data));
|
2478
|
+
const dbMeta = (0, import_dag_json.parse)(sthis.txt.decode(eventBlock.value.data.dbMeta));
|
2479
|
+
return {
|
2480
|
+
eventCid: eventBlock.cid,
|
2481
|
+
parents: crdtEntry.parents,
|
2482
|
+
dbMeta
|
2483
|
+
};
|
2484
|
+
})
|
2485
|
+
);
|
2486
|
+
}
|
2487
|
+
async function setCryptoKeyFromGatewayMetaPayload(uri, sthis, data) {
|
2488
|
+
try {
|
2489
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Setting crypto key from gateway meta payload");
|
2490
|
+
const keyInfo = await decodeGatewayMetaBytesToDbMeta(sthis, data);
|
2491
|
+
if (keyInfo.length) {
|
2492
|
+
const dbMeta = keyInfo[0].dbMeta;
|
2493
|
+
if (dbMeta.key) {
|
2494
|
+
const kb = await getKeyBag(sthis);
|
2495
|
+
const keyName = getStoreKeyName(uri);
|
2496
|
+
const res = await kb.setNamedKey(keyName, dbMeta.key);
|
2497
|
+
if (res.isErr()) {
|
2498
|
+
sthis.logger.Debug().Str("keyName", keyName).Str("dbMeta.key", dbMeta.key).Msg("Failed to set named key");
|
2499
|
+
throw res.Err();
|
2500
|
+
}
|
2501
|
+
}
|
2502
|
+
sthis.logger.Debug().Str("dbMeta.key", dbMeta.key).Str("uri", uri.toString()).Msg("Set crypto key from gateway meta payload");
|
2503
|
+
return import_cement9.Result.Ok(dbMeta);
|
2504
|
+
}
|
2505
|
+
sthis.logger.Debug().Str("data", new TextDecoder().decode(data)).Msg("No crypto in gateway meta payload");
|
2506
|
+
return import_cement9.Result.Ok(void 0);
|
2507
|
+
} catch (error) {
|
2508
|
+
sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
|
2509
|
+
return import_cement9.Result.Err(error);
|
2510
|
+
}
|
2511
|
+
}
|
2512
|
+
async function addCryptoKeyToGatewayMetaPayload(uri, sthis, body) {
|
2513
|
+
try {
|
2514
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Adding crypto key to gateway meta payload");
|
2515
|
+
const keyName = getStoreKeyName(uri);
|
2516
|
+
const kb = await getKeyBag(sthis);
|
2517
|
+
const res = await kb.getNamedExtractableKey(keyName, true);
|
2518
|
+
if (res.isErr()) {
|
2519
|
+
sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
|
2520
|
+
throw res.Err();
|
2521
|
+
}
|
2522
|
+
const keyData = await res.Ok().extract();
|
2523
|
+
const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
|
2524
|
+
const { dbMeta, parents } = dbMetas[0];
|
2525
|
+
const parentLinks = parents.map((p) => import_multiformats2.CID.parse(p));
|
2526
|
+
dbMeta.key = keyData.keyStr;
|
2527
|
+
const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
|
2528
|
+
const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
|
2529
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
|
2530
|
+
return import_cement9.Result.Ok(encoded);
|
2531
|
+
} catch (error) {
|
2532
|
+
sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
|
2533
|
+
return import_cement9.Result.Err(error);
|
2534
|
+
}
|
2535
|
+
}
|
2536
|
+
function getStoreKeyName(url) {
|
2537
|
+
const storeKeyName = [url.getParam("localName") || url.getParam("name")];
|
2538
|
+
const idx = url.getParam("index");
|
2539
|
+
if (idx) {
|
2540
|
+
storeKeyName.push(idx);
|
2541
|
+
}
|
2542
|
+
storeKeyName.push("data");
|
2543
|
+
return `@${storeKeyName.join(":")}@`;
|
2544
|
+
}
|
2545
|
+
async function createDbMetaEventBlock(sthis, dbMeta, parents) {
|
2546
|
+
const event = await import_clock.EventBlock.create(
|
2547
|
+
{
|
2548
|
+
dbMeta: sthis.txt.encode((0, import_dag_json.format)(dbMeta))
|
2549
|
+
},
|
2550
|
+
parents
|
2551
|
+
);
|
2552
|
+
return event;
|
2553
|
+
}
|
2554
|
+
async function encodeEventsWithParents(sthis, events, parents) {
|
2555
|
+
const crdtEntries = events.map((event) => {
|
2556
|
+
const base64String = import_base64.base64pad.encode(event.bytes);
|
2557
|
+
return {
|
2558
|
+
cid: event.cid.toString(),
|
2559
|
+
data: base64String,
|
2560
|
+
parents: parents.map((p) => p.toString())
|
2561
|
+
};
|
2562
|
+
});
|
2563
|
+
return sthis.txt.encode(JSON.stringify(crdtEntries));
|
2564
|
+
}
|
2565
|
+
|
2351
2566
|
// src/blockstore/store.ts
|
2352
2567
|
function guardVersion(url) {
|
2353
2568
|
if (!url.hasParam("version")) {
|
2354
|
-
return
|
2569
|
+
return import_cement10.Result.Err(`missing version: ${url.toString()}`);
|
2355
2570
|
}
|
2356
|
-
return
|
2571
|
+
return import_cement10.Result.Ok(url);
|
2357
2572
|
}
|
2358
2573
|
var BaseStoreImpl = class {
|
2359
2574
|
constructor(name, url, opts, sthis, logger) {
|
@@ -2365,6 +2580,7 @@ var BaseStoreImpl = class {
|
|
2365
2580
|
this.sthis = sthis;
|
2366
2581
|
this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
|
2367
2582
|
this.gateway = new FragmentGateway(this.sthis, opts.gateway);
|
2583
|
+
this.loader = opts.loader;
|
2368
2584
|
}
|
2369
2585
|
url() {
|
2370
2586
|
return this._url;
|
@@ -2375,6 +2591,9 @@ var BaseStoreImpl = class {
|
|
2375
2591
|
onClosed(fn) {
|
2376
2592
|
this._onClosed.push(fn);
|
2377
2593
|
}
|
2594
|
+
async ready() {
|
2595
|
+
return;
|
2596
|
+
}
|
2378
2597
|
async keyedCrypto() {
|
2379
2598
|
return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
|
2380
2599
|
}
|
@@ -2409,7 +2628,7 @@ var BaseStoreImpl = class {
|
|
2409
2628
|
}
|
2410
2629
|
if (this.ready) {
|
2411
2630
|
const fn = this.ready.bind(this);
|
2412
|
-
const ready = await exception2Result(fn);
|
2631
|
+
const ready = await (0, import_cement10.exception2Result)(fn);
|
2413
2632
|
if (ready.isErr()) {
|
2414
2633
|
await this.close();
|
2415
2634
|
return ready;
|
@@ -2421,67 +2640,44 @@ var BaseStoreImpl = class {
|
|
2421
2640
|
}
|
2422
2641
|
};
|
2423
2642
|
var MetaStoreImpl = class extends BaseStoreImpl {
|
2643
|
+
// remote: boolean;
|
2424
2644
|
constructor(sthis, name, url, opts) {
|
2425
|
-
super(
|
2426
|
-
name,
|
2427
|
-
url,
|
2428
|
-
{
|
2429
|
-
...opts
|
2430
|
-
},
|
2431
|
-
sthis,
|
2432
|
-
ensureLogger(sthis, "MetaStoreImpl")
|
2433
|
-
);
|
2645
|
+
super(name, url, { ...opts }, sthis, ensureLogger(sthis, "MetaStoreImpl"));
|
2434
2646
|
this.storeType = "meta";
|
2435
2647
|
this.subscribers = /* @__PURE__ */ new Map();
|
2436
|
-
|
2437
|
-
|
2438
|
-
|
2439
|
-
|
2440
|
-
|
2441
|
-
|
2442
|
-
|
2443
|
-
|
2444
|
-
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2449
|
-
|
2450
|
-
|
2451
|
-
|
2452
|
-
const got = (0, import_dag_json.parse)(headerData);
|
2453
|
-
return got;
|
2454
|
-
}
|
2455
|
-
async handleSubscribers(dbMetas, branch) {
|
2456
|
-
try {
|
2457
|
-
const subscribers = this.subscribers.get(branch) || [];
|
2458
|
-
await Promise.all(subscribers.map((subscriber) => subscriber(dbMetas)));
|
2459
|
-
} catch (e) {
|
2460
|
-
this.logger.Error().Err(e).Msg("handleSubscribers").AsError();
|
2648
|
+
this.parents = [];
|
2649
|
+
if (
|
2650
|
+
/*this.remote && */
|
2651
|
+
opts.gateway.subscribe
|
2652
|
+
) {
|
2653
|
+
this.onStarted(async () => {
|
2654
|
+
this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
|
2655
|
+
opts.gateway.subscribe?.(this.url(), async (message) => {
|
2656
|
+
this.logger.Debug().Msg("Received message from gateway");
|
2657
|
+
const dbMetas = await decodeGatewayMetaBytesToDbMeta(this.sthis, message);
|
2658
|
+
await Promise.all(
|
2659
|
+
dbMetas.map((dbMeta) => this.loader?.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
|
2660
|
+
);
|
2661
|
+
this.updateParentsFromDbMetas(dbMetas);
|
2662
|
+
});
|
2663
|
+
});
|
2461
2664
|
}
|
2462
2665
|
}
|
2463
|
-
|
2464
|
-
|
2465
|
-
|
2466
|
-
|
2467
|
-
|
2468
|
-
|
2469
|
-
}
|
2470
|
-
await this.handleSubscribers(dbMetas, branch);
|
2471
|
-
return dbMetas;
|
2666
|
+
updateParentsFromDbMetas(dbMetas) {
|
2667
|
+
const cids = dbMetas.map((m) => m.eventCid);
|
2668
|
+
const dbMetaParents = dbMetas.flatMap((m) => m.parents);
|
2669
|
+
const uniqueParentsMap = new Map([...this.parents, ...cids].map((p) => [p.toString(), p]));
|
2670
|
+
const dbMetaParentsSet = new Set(dbMetaParents.map((p) => p.toString()));
|
2671
|
+
this.parents = Array.from(uniqueParentsMap.values()).filter((p) => !dbMetaParentsSet.has(p.toString()));
|
2472
2672
|
}
|
2473
|
-
|
2474
|
-
return byteHeads
|
2475
|
-
const txt = this.sthis.txt.decode(bytes);
|
2476
|
-
return this.parseHeader(txt);
|
2477
|
-
});
|
2673
|
+
async handleByteHeads(byteHeads) {
|
2674
|
+
return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
|
2478
2675
|
}
|
2479
|
-
async load(
|
2480
|
-
branch =
|
2481
|
-
this.logger.Debug().Str("branch", branch).Msg("loading");
|
2676
|
+
async load() {
|
2677
|
+
const branch = "main";
|
2482
2678
|
const url = await this.gateway.buildUrl(this.url(), branch);
|
2483
2679
|
if (url.isErr()) {
|
2484
|
-
throw this.logger.Error().Result("
|
2680
|
+
throw this.logger.Error().Result("buildUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
|
2485
2681
|
}
|
2486
2682
|
const bytes = await this.gateway.get(url.Ok());
|
2487
2683
|
if (bytes.isErr()) {
|
@@ -2490,27 +2686,31 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
2490
2686
|
}
|
2491
2687
|
throw this.logger.Error().Url(url.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
|
2492
2688
|
}
|
2493
|
-
|
2689
|
+
const dbMetas = await this.handleByteHeads(bytes.Ok());
|
2690
|
+
await this.loader?.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
|
2691
|
+
this.updateParentsFromDbMetas(dbMetas);
|
2692
|
+
return dbMetas.map((m) => m.dbMeta);
|
2494
2693
|
}
|
2495
2694
|
async save(meta, branch) {
|
2496
2695
|
branch = branch || "main";
|
2497
2696
|
this.logger.Debug().Str("branch", branch).Any("meta", meta).Msg("saving meta");
|
2498
|
-
const
|
2697
|
+
const event = await createDbMetaEventBlock(this.sthis, meta, this.parents);
|
2698
|
+
const bytes = await encodeEventsWithParents(this.sthis, [event], this.parents);
|
2499
2699
|
const url = await this.gateway.buildUrl(this.url(), branch);
|
2500
2700
|
if (url.isErr()) {
|
2501
2701
|
throw this.logger.Error().Err(url.Err()).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
|
2502
2702
|
}
|
2503
|
-
|
2703
|
+
this.parents = [event.cid];
|
2704
|
+
const res = await this.gateway.put(url.Ok(), bytes);
|
2504
2705
|
if (res.isErr()) {
|
2505
2706
|
throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
|
2506
2707
|
}
|
2507
|
-
await this.handleSubscribers([meta], branch);
|
2508
2708
|
return res;
|
2509
2709
|
}
|
2510
2710
|
async close() {
|
2511
2711
|
await this.gateway.close(this.url());
|
2512
2712
|
this._onClosed.forEach((fn) => fn());
|
2513
|
-
return
|
2713
|
+
return import_cement10.Result.Ok(void 0);
|
2514
2714
|
}
|
2515
2715
|
async destroy() {
|
2516
2716
|
return this.gateway.destroy(this.url());
|
@@ -2519,15 +2719,7 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
2519
2719
|
var DataStoreImpl = class extends BaseStoreImpl {
|
2520
2720
|
// readonly tag: string = "car-base";
|
2521
2721
|
constructor(sthis, name, url, opts) {
|
2522
|
-
super(
|
2523
|
-
name,
|
2524
|
-
url,
|
2525
|
-
{
|
2526
|
-
...opts
|
2527
|
-
},
|
2528
|
-
sthis,
|
2529
|
-
ensureLogger(sthis, "DataStoreImpl")
|
2530
|
-
);
|
2722
|
+
super(name, url, { ...opts }, sthis, ensureLogger(sthis, "DataStoreImpl"));
|
2531
2723
|
this.storeType = "data";
|
2532
2724
|
}
|
2533
2725
|
async load(cid) {
|
@@ -2565,7 +2757,7 @@ var DataStoreImpl = class extends BaseStoreImpl {
|
|
2565
2757
|
async close() {
|
2566
2758
|
await this.gateway.close(this.url());
|
2567
2759
|
this._onClosed.forEach((fn) => fn());
|
2568
|
-
return
|
2760
|
+
return import_cement10.Result.Ok(void 0);
|
2569
2761
|
}
|
2570
2762
|
destroy() {
|
2571
2763
|
return this.gateway.destroy(this.url());
|
@@ -2573,46 +2765,43 @@ var DataStoreImpl = class extends BaseStoreImpl {
|
|
2573
2765
|
};
|
2574
2766
|
var WALStoreImpl = class extends BaseStoreImpl {
|
2575
2767
|
constructor(loader, url, opts) {
|
2576
|
-
super(
|
2577
|
-
loader.name,
|
2578
|
-
url,
|
2579
|
-
{
|
2580
|
-
...opts
|
2581
|
-
},
|
2582
|
-
loader.sthis,
|
2583
|
-
ensureLogger(loader.sthis, "WALStoreImpl")
|
2584
|
-
);
|
2768
|
+
super(loader.name, url, { ...opts }, loader.sthis, ensureLogger(loader.sthis, "WALStoreImpl"));
|
2585
2769
|
this.storeType = "wal";
|
2586
|
-
this._ready = new
|
2770
|
+
this._ready = new import_cement10.ResolveOnce();
|
2587
2771
|
this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
|
2588
2772
|
this.processing = void 0;
|
2589
2773
|
this.processQueue = new CommitQueue();
|
2590
|
-
this.ready = async () => {
|
2591
|
-
return this._ready.once(async () => {
|
2592
|
-
const walState = await this.load().catch((e) => {
|
2593
|
-
this.logger.Error().Any("error", e).Msg("error loading wal");
|
2594
|
-
return void 0;
|
2595
|
-
});
|
2596
|
-
if (!walState) {
|
2597
|
-
this.walState.operations = [];
|
2598
|
-
this.walState.fileOperations = [];
|
2599
|
-
} else {
|
2600
|
-
this.walState.operations = walState.operations || [];
|
2601
|
-
this.walState.fileOperations = walState.fileOperations || [];
|
2602
|
-
}
|
2603
|
-
});
|
2604
|
-
};
|
2605
2774
|
this.loader = loader;
|
2606
2775
|
}
|
2776
|
+
async ready() {
|
2777
|
+
return this._ready.once(async () => {
|
2778
|
+
const walState = await this.load().catch((e) => {
|
2779
|
+
this.logger.Error().Any("error", e).Msg("error loading wal");
|
2780
|
+
return void 0;
|
2781
|
+
});
|
2782
|
+
if (!walState) {
|
2783
|
+
this.walState.operations = [];
|
2784
|
+
this.walState.fileOperations = [];
|
2785
|
+
} else {
|
2786
|
+
this.walState.operations = walState.operations || [];
|
2787
|
+
this.walState.fileOperations = walState.fileOperations || [];
|
2788
|
+
}
|
2789
|
+
});
|
2790
|
+
}
|
2607
2791
|
async enqueue(dbMeta, opts) {
|
2608
2792
|
await this.ready();
|
2609
|
-
if (opts.
|
2793
|
+
if (opts.compact) {
|
2794
|
+
this.walState.operations = [];
|
2795
|
+
this.walState.noLoaderOps = [dbMeta];
|
2796
|
+
} else if (opts.noLoader) {
|
2610
2797
|
this.walState.noLoaderOps.push(dbMeta);
|
2611
2798
|
} else {
|
2612
2799
|
this.walState.operations.push(dbMeta);
|
2613
2800
|
}
|
2614
2801
|
await this.save(this.walState);
|
2615
|
-
|
2802
|
+
if (!opts.noLoader) {
|
2803
|
+
void this.process();
|
2804
|
+
}
|
2616
2805
|
}
|
2617
2806
|
async enqueueFile(fileCid, publicFile = false) {
|
2618
2807
|
await this.ready();
|
@@ -2639,7 +2828,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
2639
2828
|
const fileOperations = [...this.walState.fileOperations];
|
2640
2829
|
const uploads = [];
|
2641
2830
|
const noLoaderOps = [...this.walState.noLoaderOps];
|
2642
|
-
const limit = (0, import_p_limit2.default)(
|
2831
|
+
const limit = (0, import_p_limit2.default)(3);
|
2643
2832
|
if (operations.length + fileOperations.length + noLoaderOps.length === 0) return;
|
2644
2833
|
for (const dbMeta of noLoaderOps) {
|
2645
2834
|
const uploadP = limit(async () => {
|
@@ -2715,7 +2904,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
2715
2904
|
throw this.logger.Error().Err(bytes.Err()).Msg("error get").AsError();
|
2716
2905
|
}
|
2717
2906
|
try {
|
2718
|
-
return bytes && (0,
|
2907
|
+
return bytes && (0, import_dag_json2.parse)(this.sthis.txt.decode(bytes.Ok()));
|
2719
2908
|
} catch (e) {
|
2720
2909
|
throw this.logger.Error().Err(e).Msg("error parse").AsError();
|
2721
2910
|
}
|
@@ -2727,7 +2916,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
2727
2916
|
}
|
2728
2917
|
let encoded;
|
2729
2918
|
try {
|
2730
|
-
encoded = (0,
|
2919
|
+
encoded = (0, import_dag_json2.format)(state);
|
2731
2920
|
} catch (e) {
|
2732
2921
|
throw this.logger.Error().Err(e).Any("state", state).Msg("error format").AsError();
|
2733
2922
|
}
|
@@ -2739,7 +2928,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
2739
2928
|
async close() {
|
2740
2929
|
await this.gateway.close(this.url());
|
2741
2930
|
this._onClosed.forEach((fn) => fn());
|
2742
|
-
return
|
2931
|
+
return import_cement10.Result.Ok(void 0);
|
2743
2932
|
}
|
2744
2933
|
destroy() {
|
2745
2934
|
return this.gateway.destroy(this.url());
|
@@ -2766,15 +2955,15 @@ function buildURL(optURL, loader) {
|
|
2766
2955
|
const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
|
2767
2956
|
let obuUrl;
|
2768
2957
|
if (obuItem && obuItem.overrideBaseURL) {
|
2769
|
-
obuUrl =
|
2958
|
+
obuUrl = import_cement13.URI.from(obuItem.overrideBaseURL);
|
2770
2959
|
}
|
2771
2960
|
const ret = ensureIsIndex(
|
2772
|
-
|
2961
|
+
import_cement13.URI.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
|
2773
2962
|
storeOpts.isIndex
|
2774
2963
|
);
|
2775
2964
|
return ret;
|
2776
2965
|
}
|
2777
|
-
var onceGateway = new
|
2966
|
+
var onceGateway = new import_cement13.KeyedResolvOnce();
|
2778
2967
|
async function getGatewayFromURL(url, sthis) {
|
2779
2968
|
return onceGateway.get(url.toString()).once(async () => {
|
2780
2969
|
const item = storeFactory.get(url.protocol);
|
@@ -2816,52 +3005,61 @@ function registerStoreProtocol(item) {
|
|
2816
3005
|
storeFactory.delete(protocol);
|
2817
3006
|
};
|
2818
3007
|
}
|
3008
|
+
var onceDataStoreFactory = new import_cement13.KeyedResolvOnce();
|
2819
3009
|
async function dataStoreFactory(loader) {
|
2820
3010
|
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
|
2821
3011
|
const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
|
2822
|
-
|
2823
|
-
|
2824
|
-
|
2825
|
-
|
2826
|
-
|
2827
|
-
|
2828
|
-
|
2829
|
-
|
2830
|
-
|
3012
|
+
return onceDataStoreFactory.get(url.toString()).once(async () => {
|
3013
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
3014
|
+
if (!gateway) {
|
3015
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
3016
|
+
}
|
3017
|
+
const store = new DataStoreImpl(sthis, loader.name, url, {
|
3018
|
+
gateway: gateway.gateway,
|
3019
|
+
keybag: () => getKeyBag(loader.sthis, {
|
3020
|
+
...loader.ebOpts.keyBag
|
3021
|
+
})
|
3022
|
+
});
|
3023
|
+
return store;
|
2831
3024
|
});
|
2832
|
-
return store;
|
2833
3025
|
}
|
3026
|
+
var onceMetaStoreFactory = new import_cement13.KeyedResolvOnce();
|
2834
3027
|
async function metaStoreFactory(loader) {
|
2835
3028
|
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
|
2836
3029
|
const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
|
2837
|
-
|
2838
|
-
|
2839
|
-
|
2840
|
-
|
2841
|
-
|
2842
|
-
|
2843
|
-
|
2844
|
-
|
2845
|
-
|
2846
|
-
|
3030
|
+
return onceMetaStoreFactory.get(url.toString()).once(async () => {
|
3031
|
+
sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
|
3032
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
3033
|
+
if (!gateway) {
|
3034
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
3035
|
+
}
|
3036
|
+
const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
|
3037
|
+
gateway: gateway.gateway,
|
3038
|
+
keybag: () => getKeyBag(loader.sthis, {
|
3039
|
+
...loader.ebOpts.keyBag
|
3040
|
+
})
|
3041
|
+
});
|
3042
|
+
return store;
|
2847
3043
|
});
|
2848
|
-
return store;
|
2849
3044
|
}
|
3045
|
+
var onceRemoteWalFactory = new import_cement13.KeyedResolvOnce();
|
2850
3046
|
async function remoteWalFactory(loader) {
|
2851
3047
|
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
|
2852
3048
|
const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
3049
|
+
return onceRemoteWalFactory.get(url.toString()).once(async () => {
|
3050
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
3051
|
+
if (!gateway) {
|
3052
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
3053
|
+
}
|
3054
|
+
sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
|
3055
|
+
const store = new WALStoreImpl(loader, url, {
|
3056
|
+
gateway: gateway.gateway,
|
3057
|
+
keybag: () => getKeyBag(loader.sthis, {
|
3058
|
+
...loader.ebOpts.keyBag
|
3059
|
+
})
|
3060
|
+
});
|
3061
|
+
return store;
|
2863
3062
|
});
|
2864
|
-
return store;
|
2865
3063
|
}
|
2866
3064
|
async function testStoreFactory(url, sthis) {
|
2867
3065
|
sthis = ensureSuperLog(sthis, "testStoreFactory");
|
@@ -2900,79 +3098,27 @@ function toStoreRuntime(opts, sthis) {
|
|
2900
3098
|
}
|
2901
3099
|
registerStoreProtocol({
|
2902
3100
|
protocol: "file:",
|
2903
|
-
gateway: async (
|
3101
|
+
gateway: async (sthis) => {
|
2904
3102
|
const { FileGateway: FileGateway2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
|
2905
|
-
return new FileGateway2(
|
3103
|
+
return new FileGateway2(sthis);
|
2906
3104
|
},
|
2907
|
-
test: async (
|
3105
|
+
test: async (sthis) => {
|
2908
3106
|
const { FileTestStore: FileTestStore2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
|
2909
|
-
return new FileTestStore2(
|
3107
|
+
return new FileTestStore2(sthis);
|
2910
3108
|
}
|
2911
3109
|
});
|
2912
3110
|
registerStoreProtocol({
|
2913
3111
|
protocol: "indexdb:",
|
2914
|
-
gateway: async (
|
3112
|
+
gateway: async (sthis) => {
|
2915
3113
|
const { IndexDBGateway: IndexDBGateway2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
|
2916
|
-
return new IndexDBGateway2(
|
3114
|
+
return new IndexDBGateway2(sthis);
|
2917
3115
|
},
|
2918
|
-
test: async (
|
3116
|
+
test: async (sthis) => {
|
2919
3117
|
const { IndexDBTestStore: IndexDBTestStore2 } = await Promise.resolve().then(() => (init_gateway2(), gateway_exports2));
|
2920
|
-
return new IndexDBTestStore2(
|
3118
|
+
return new IndexDBTestStore2(sthis);
|
2921
3119
|
}
|
2922
3120
|
});
|
2923
3121
|
|
2924
|
-
// src/blockstore/connection-base.ts
|
2925
|
-
var import_clock = require("@web3-storage/pail/clock");
|
2926
|
-
var import_block6 = require("@web3-storage/pail/block");
|
2927
|
-
|
2928
|
-
// src/blockstore/task-manager.ts
|
2929
|
-
init_utils();
|
2930
|
-
var TaskManager = class {
|
2931
|
-
constructor(loader) {
|
2932
|
-
this.eventsWeHandled = /* @__PURE__ */ new Set();
|
2933
|
-
this.queue = [];
|
2934
|
-
this.isProcessing = false;
|
2935
|
-
this.loader = loader;
|
2936
|
-
this.logger = ensureLogger(loader.sthis, "TaskManager");
|
2937
|
-
}
|
2938
|
-
async handleEvent(eventBlock) {
|
2939
|
-
const cid = eventBlock.cid.toString();
|
2940
|
-
const parents = eventBlock.value.parents.map((cid2) => cid2.toString());
|
2941
|
-
for (const parent of parents) {
|
2942
|
-
this.eventsWeHandled.add(parent);
|
2943
|
-
}
|
2944
|
-
this.queue.push({ cid, eventBlock, retries: 0 });
|
2945
|
-
this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
|
2946
|
-
void this.processQueue();
|
2947
|
-
}
|
2948
|
-
async processQueue() {
|
2949
|
-
if (this.isProcessing) return;
|
2950
|
-
this.isProcessing = true;
|
2951
|
-
const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
2952
|
-
const first = filteredQueue[0];
|
2953
|
-
if (!first) {
|
2954
|
-
return;
|
2955
|
-
}
|
2956
|
-
try {
|
2957
|
-
this.loader?.remoteMetaStore?.handleByteHeads([first.eventBlock.value.data.dbMeta]);
|
2958
|
-
this.eventsWeHandled.add(first.cid);
|
2959
|
-
this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
2960
|
-
} catch (err) {
|
2961
|
-
if (first.retries++ > 3) {
|
2962
|
-
this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
|
2963
|
-
this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
|
2964
|
-
}
|
2965
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
2966
|
-
throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
|
2967
|
-
} finally {
|
2968
|
-
this.isProcessing = false;
|
2969
|
-
if (this.queue.length > 0) {
|
2970
|
-
void this.processQueue();
|
2971
|
-
}
|
2972
|
-
}
|
2973
|
-
}
|
2974
|
-
};
|
2975
|
-
|
2976
3122
|
// src/blockstore/store-remote.ts
|
2977
3123
|
async function RemoteDataStore(sthis, name, url, opts) {
|
2978
3124
|
const ds = new DataStoreImpl(sthis, name, url, opts);
|
@@ -2980,7 +3126,13 @@ async function RemoteDataStore(sthis, name, url, opts) {
|
|
2980
3126
|
return ds;
|
2981
3127
|
}
|
2982
3128
|
async function RemoteMetaStore(sthis, name, url, opts) {
|
2983
|
-
const ms = new MetaStoreImpl(
|
3129
|
+
const ms = new MetaStoreImpl(
|
3130
|
+
sthis,
|
3131
|
+
name,
|
3132
|
+
url,
|
3133
|
+
opts
|
3134
|
+
/* , true*/
|
3135
|
+
);
|
2984
3136
|
await ms.start();
|
2985
3137
|
return ms;
|
2986
3138
|
}
|
@@ -2988,16 +3140,12 @@ async function RemoteMetaStore(sthis, name, url, opts) {
|
|
2988
3140
|
// src/blockstore/connection-base.ts
|
2989
3141
|
var ConnectionBase = class {
|
2990
3142
|
constructor(url, logger) {
|
2991
|
-
// readonly ready: Promise<unknown>;
|
2992
|
-
// todo move to LRU blockstore https://github.com/web3-storage/w3clock/blob/main/src/worker/block.js
|
2993
|
-
this.eventBlocks = new import_block6.MemoryBlockstore();
|
2994
|
-
this.parents = [];
|
2995
3143
|
this.loaded = Promise.resolve();
|
2996
3144
|
this.logger = logger;
|
2997
3145
|
this.url = url;
|
2998
3146
|
}
|
2999
3147
|
async refresh() {
|
3000
|
-
await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load(
|
3148
|
+
await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
|
3001
3149
|
await (await throwFalsy(this.loader).WALStore()).process();
|
3002
3150
|
}
|
3003
3151
|
async connect_X({ loader }) {
|
@@ -3008,26 +3156,20 @@ var ConnectionBase = class {
|
|
3008
3156
|
async connectMeta_X({ loader }) {
|
3009
3157
|
if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
|
3010
3158
|
this.loader = loader;
|
3011
|
-
this.taskManager = new TaskManager(loader);
|
3012
3159
|
await this.onConnect();
|
3013
3160
|
const metaUrl = this.url.build().defParam("store", "meta").URI();
|
3014
3161
|
const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
|
3015
3162
|
if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
|
3016
|
-
const
|
3017
|
-
|
3163
|
+
const dbName = metaUrl.getParam("name");
|
3164
|
+
if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: name is required").AsError();
|
3165
|
+
const remote = await RemoteMetaStore(loader.sthis, dbName, metaUrl, {
|
3018
3166
|
gateway: gateway.gateway,
|
3019
|
-
keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag)
|
3020
|
-
|
3021
|
-
remote.onLoad("main", async (metas) => {
|
3022
|
-
if (metas) {
|
3023
|
-
this.logger.Debug().Any("metas", metas).Bool("loader", this.loader).Msg("connectMeta_X: handleDbMetasFromStore pre");
|
3024
|
-
await throwFalsy(this.loader).handleDbMetasFromStore(metas);
|
3025
|
-
this.logger.Debug().Any("metas", metas).Msg("connectMeta_X: handleDbMetasFromStore post");
|
3026
|
-
}
|
3167
|
+
keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag),
|
3168
|
+
loader
|
3027
3169
|
});
|
3028
3170
|
this.loader.remoteMetaStore = remote;
|
3029
3171
|
this.loaded = this.loader.ready().then(async () => {
|
3030
|
-
remote.load(
|
3172
|
+
remote.load().then(async () => {
|
3031
3173
|
(await throwFalsy(this.loader).WALStore()).process();
|
3032
3174
|
});
|
3033
3175
|
});
|
@@ -3038,28 +3180,14 @@ var ConnectionBase = class {
|
|
3038
3180
|
const dataUrl = this.url.build().defParam("store", "data").URI();
|
3039
3181
|
const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
|
3040
3182
|
if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
|
3041
|
-
const name = dataUrl.
|
3183
|
+
const name = dataUrl.getParam("name");
|
3184
|
+
if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: name is required").AsError;
|
3042
3185
|
loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
|
3043
3186
|
gateway: gateway.gateway,
|
3044
3187
|
keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
|
3045
3188
|
});
|
3046
3189
|
loader.remoteFileStore = loader.remoteCarStore;
|
3047
3190
|
}
|
3048
|
-
async createEventBlock(bytes) {
|
3049
|
-
const data = {
|
3050
|
-
dbMeta: bytes
|
3051
|
-
};
|
3052
|
-
const event = await import_clock.EventBlock.create(
|
3053
|
-
data,
|
3054
|
-
this.parents
|
3055
|
-
);
|
3056
|
-
await this.eventBlocks.put(event.cid, event.bytes);
|
3057
|
-
return event;
|
3058
|
-
}
|
3059
|
-
async decodeEventBlock(bytes) {
|
3060
|
-
const event = await (0, import_clock.decodeEventBlock)(bytes);
|
3061
|
-
return event;
|
3062
|
-
}
|
3063
3191
|
// move this stuff to connect
|
3064
3192
|
// async getDashboardURL(compact = true) {
|
3065
3193
|
// const baseUrl = 'https://dashboard.fireproof.storage/'
|
@@ -3364,7 +3492,7 @@ var import_sha26 = require("multiformats/hashes/sha2");
|
|
3364
3492
|
var codec2 = __toESM(require("@ipld/dag-cbor"), 1);
|
3365
3493
|
var import_charwise = __toESM(require("charwise"), 1);
|
3366
3494
|
var DbIndex = __toESM(require("prolly-trees/db-index"), 1);
|
3367
|
-
var
|
3495
|
+
var import_utils16 = require("prolly-trees/utils");
|
3368
3496
|
var import_cache = require("prolly-trees/cache");
|
3369
3497
|
var IndexTree = class {
|
3370
3498
|
};
|
@@ -3372,17 +3500,17 @@ function refCompare(aRef, bRef) {
|
|
3372
3500
|
if (Number.isNaN(aRef)) return -1;
|
3373
3501
|
if (Number.isNaN(bRef)) throw new Error("ref may not be Infinity or NaN");
|
3374
3502
|
if (aRef === Infinity) return 1;
|
3375
|
-
return (0,
|
3503
|
+
return (0, import_utils16.simpleCompare)(aRef, bRef);
|
3376
3504
|
}
|
3377
3505
|
function compare(a, b) {
|
3378
3506
|
const [aKey, aRef] = a;
|
3379
3507
|
const [bKey, bRef] = b;
|
3380
|
-
const comp = (0,
|
3508
|
+
const comp = (0, import_utils16.simpleCompare)(aKey, bKey);
|
3381
3509
|
if (comp !== 0) return comp;
|
3382
3510
|
return refCompare(aRef, bRef);
|
3383
3511
|
}
|
3384
|
-
var byKeyOpts = { cache: import_cache.nocache, chunker: (0,
|
3385
|
-
var byIdOpts = { cache: import_cache.nocache, chunker: (0,
|
3512
|
+
var byKeyOpts = { cache: import_cache.nocache, chunker: (0, import_utils16.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare };
|
3513
|
+
var byIdOpts = { cache: import_cache.nocache, chunker: (0, import_utils16.bf)(30), codec: codec2, hasher: import_sha26.sha256, compare: import_utils16.simpleCompare };
|
3386
3514
|
function indexEntriesForChanges(changes, mapFn) {
|
3387
3515
|
const indexEntries = [];
|
3388
3516
|
changes.forEach(({ id: key, value, del }) => {
|
@@ -3690,7 +3818,7 @@ var Index = class {
|
|
3690
3818
|
// src/crdt-clock.ts
|
3691
3819
|
var import_clock3 = require("@web3-storage/pail/clock");
|
3692
3820
|
var import_crdt2 = require("@web3-storage/pail/crdt");
|
3693
|
-
var
|
3821
|
+
var import_cement14 = require("@adviser/cement");
|
3694
3822
|
|
3695
3823
|
// src/apply-head-queue.ts
|
3696
3824
|
function applyHeadQueue(worker, logger) {
|
@@ -3705,7 +3833,7 @@ function applyHeadQueue(worker, logger) {
|
|
3705
3833
|
queue.sort((a, b) => b.updates ? 1 : -1);
|
3706
3834
|
const task = queue.shift();
|
3707
3835
|
if (!task) continue;
|
3708
|
-
await worker(task.newHead, task.prevHead, task.updates !==
|
3836
|
+
await worker(task.newHead, task.prevHead, task.updates !== void 0).catch((e) => {
|
3709
3837
|
throw logger.Error().Err(e).Msg("int_applyHead worker error").AsError();
|
3710
3838
|
});
|
3711
3839
|
if (task.updates) {
|
@@ -3748,7 +3876,7 @@ var CRDTClock = class {
|
|
3748
3876
|
this.zoomers = /* @__PURE__ */ new Set();
|
3749
3877
|
this.watchers = /* @__PURE__ */ new Set();
|
3750
3878
|
this.emptyWatchers = /* @__PURE__ */ new Set();
|
3751
|
-
this._ready = new
|
3879
|
+
this._ready = new import_cement14.ResolveOnce();
|
3752
3880
|
this.blockstore = blockstore;
|
3753
3881
|
this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
|
3754
3882
|
this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
|
@@ -3796,6 +3924,7 @@ var CRDTClock = class {
|
|
3796
3924
|
this.zoomers.add(fn);
|
3797
3925
|
}
|
3798
3926
|
async int_applyHead(newHead, prevHead, localUpdates) {
|
3927
|
+
const noLoader = !localUpdates;
|
3799
3928
|
const ogHead = sortClockHead(this.head);
|
3800
3929
|
newHead = sortClockHead(newHead);
|
3801
3930
|
if (compareClockHeads(ogHead, newHead)) {
|
@@ -3806,7 +3935,6 @@ var CRDTClock = class {
|
|
3806
3935
|
this.setHead(newHead);
|
3807
3936
|
return;
|
3808
3937
|
}
|
3809
|
-
const noLoader = !localUpdates;
|
3810
3938
|
if (!this.blockstore) {
|
3811
3939
|
throw this.logger.Error().Msg("missing blockstore").AsError();
|
3812
3940
|
}
|
@@ -3860,7 +3988,7 @@ init_utils();
|
|
3860
3988
|
var CRDT = class {
|
3861
3989
|
constructor(sthis, name, opts = {}) {
|
3862
3990
|
this.indexers = /* @__PURE__ */ new Map();
|
3863
|
-
this.onceReady = new
|
3991
|
+
this.onceReady = new import_cement15.ResolveOnce();
|
3864
3992
|
this.sthis = sthis;
|
3865
3993
|
this.name = name;
|
3866
3994
|
this.logger = ensureLogger(sthis, "CRDT");
|
@@ -3926,7 +4054,7 @@ var CRDT = class {
|
|
3926
4054
|
try {
|
3927
4055
|
await Promise.all([this.blockstore.ready(), this.indexBlockstore.ready(), this.clock.ready()]);
|
3928
4056
|
} catch (e) {
|
3929
|
-
throw this.logger.Error().Err(e).Msg(
|
4057
|
+
throw this.logger.Error().Err(e).Msg(`CRDT is not ready`).AsError();
|
3930
4058
|
}
|
3931
4059
|
});
|
3932
4060
|
}
|
@@ -3981,7 +4109,7 @@ var Database = class {
|
|
3981
4109
|
this._listening = false;
|
3982
4110
|
this._listeners = /* @__PURE__ */ new Set();
|
3983
4111
|
this._noupdate_listeners = /* @__PURE__ */ new Set();
|
3984
|
-
this._ready = new
|
4112
|
+
this._ready = new import_cement16.ResolveOnce();
|
3985
4113
|
this.name = name;
|
3986
4114
|
this.opts = opts || this.opts;
|
3987
4115
|
this.sthis = ensureSuperThis(this.opts);
|
@@ -4030,7 +4158,7 @@ var Database = class {
|
|
4030
4158
|
await this.ready();
|
4031
4159
|
this.logger.Debug().Str("id", doc._id).Msg("put");
|
4032
4160
|
const { _id, ...value } = doc;
|
4033
|
-
const docId = _id || this.sthis.
|
4161
|
+
const docId = _id || this.sthis.timeOrderedNextId().str;
|
4034
4162
|
const result = await this._writeQueue.push({
|
4035
4163
|
id: docId,
|
4036
4164
|
value: {
|
@@ -4171,6 +4299,7 @@ __export(runtime_exports, {
|
|
4171
4299
|
kb: () => key_bag_exports,
|
4172
4300
|
kc: () => keyed_crypto_exports,
|
4173
4301
|
mf: () => wait_pr_multiformats_exports,
|
4302
|
+
runtimeFn: () => import_cement17.runtimeFn,
|
4174
4303
|
toArrayBuffer: () => toArrayBuffer
|
4175
4304
|
});
|
4176
4305
|
init_utils2();
|
@@ -4186,6 +4315,7 @@ __export(wait_pr_multiformats_exports, {
|
|
4186
4315
|
var codec_interface_exports = {};
|
4187
4316
|
|
4188
4317
|
// src/runtime/index.ts
|
4318
|
+
var import_cement17 = require("@adviser/cement");
|
4189
4319
|
init_version();
|
4190
4320
|
init_version2();
|
4191
4321
|
|
@@ -4194,6 +4324,6 @@ init_utils();
|
|
4194
4324
|
|
4195
4325
|
// src/version.ts
|
4196
4326
|
var PACKAGE_VERSION = Object.keys({
|
4197
|
-
"0.19.
|
4327
|
+
"0.19.11-dev-dryrun2": "xxxx"
|
4198
4328
|
})[0];
|
4199
4329
|
//# sourceMappingURL=index.cjs.map
|