@fireproof/core 0.19.9-dev-frag → 0.19.11-dev-dryrun2
Sign up to get free protection for your applications and to get access to all the features.
- 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.js
CHANGED
@@ -6,7 +6,7 @@ import {
|
|
6
6
|
getFileSystem,
|
7
7
|
getPath,
|
8
8
|
toArrayBuffer
|
9
|
-
} from "./chunk-
|
9
|
+
} from "./chunk-WS3YRPIA.js";
|
10
10
|
import {
|
11
11
|
INDEXDB_VERSION
|
12
12
|
} from "./chunk-PB4BKL4O.js";
|
@@ -19,16 +19,15 @@ import {
|
|
19
19
|
ensureLogger,
|
20
20
|
ensureSuperLog,
|
21
21
|
ensureSuperThis,
|
22
|
-
exception2Result,
|
23
22
|
exceptionWrapper,
|
24
23
|
getKey,
|
25
24
|
getName,
|
26
25
|
getStore,
|
27
26
|
isNotFoundError
|
28
|
-
} from "./chunk-
|
27
|
+
} from "./chunk-OFGPKRCM.js";
|
29
28
|
|
30
29
|
// src/database.ts
|
31
|
-
import { ResolveOnce as
|
30
|
+
import { ResolveOnce as ResolveOnce6 } from "@adviser/cement";
|
32
31
|
|
33
32
|
// src/write-queue.ts
|
34
33
|
function writeQueue(worker, payload = Infinity, unbounded = false) {
|
@@ -71,7 +70,7 @@ function writeQueue(worker, payload = Infinity, unbounded = false) {
|
|
71
70
|
}
|
72
71
|
|
73
72
|
// src/crdt.ts
|
74
|
-
import { ResolveOnce as
|
73
|
+
import { ResolveOnce as ResolveOnce5 } from "@adviser/cement";
|
75
74
|
|
76
75
|
// src/runtime/wait-pr-multiformats/block.ts
|
77
76
|
var block_exports = {};
|
@@ -145,7 +144,7 @@ async function createUnsafe({
|
|
145
144
|
}
|
146
145
|
|
147
146
|
// src/crdt-helpers.ts
|
148
|
-
import { parse as
|
147
|
+
import { parse as parse3 } from "multiformats/link";
|
149
148
|
import { sha256 as hasher5 } from "multiformats/hashes/sha2";
|
150
149
|
import * as codec from "@ipld/dag-cbor";
|
151
150
|
import { put, get, entries, root } from "@web3-storage/pail/crdt";
|
@@ -162,10 +161,12 @@ __export(blockstore_exports, {
|
|
162
161
|
EncryptedBlockstore: () => EncryptedBlockstore,
|
163
162
|
FragmentGateway: () => FragmentGateway,
|
164
163
|
Loader: () => Loader,
|
164
|
+
addCryptoKeyToGatewayMetaPayload: () => addCryptoKeyToGatewayMetaPayload,
|
165
165
|
ensureStart: () => ensureStart,
|
166
166
|
getGatewayFromURL: () => getGatewayFromURL,
|
167
167
|
parseCarFile: () => parseCarFile,
|
168
168
|
registerStoreProtocol: () => registerStoreProtocol,
|
169
|
+
setCryptoKeyFromGatewayMetaPayload: () => setCryptoKeyFromGatewayMetaPayload,
|
169
170
|
testStoreFactory: () => testStoreFactory,
|
170
171
|
toCIDBlock: () => toCIDBlock,
|
171
172
|
toStoreRuntime: () => toStoreRuntime
|
@@ -177,7 +178,7 @@ function toCIDBlock(block) {
|
|
177
178
|
}
|
178
179
|
|
179
180
|
// src/blockstore/store-factory.ts
|
180
|
-
import { KeyedResolvOnce as KeyedResolvOnce2, URI as
|
181
|
+
import { KeyedResolvOnce as KeyedResolvOnce2, URI as URI5 } from "@adviser/cement";
|
181
182
|
|
182
183
|
// src/runtime/files.ts
|
183
184
|
var files_exports = {};
|
@@ -252,8 +253,8 @@ var UnixFSFileBuilder = class {
|
|
252
253
|
|
253
254
|
// src/blockstore/store.ts
|
254
255
|
import pLimit2 from "p-limit";
|
255
|
-
import { format, parse } from "@ipld/dag-json";
|
256
|
-
import { ResolveOnce as
|
256
|
+
import { format as format2, parse as parse2 } from "@ipld/dag-json";
|
257
|
+
import { exception2Result, ResolveOnce as ResolveOnce3, Result as Result5 } from "@adviser/cement";
|
257
258
|
|
258
259
|
// src/types.ts
|
259
260
|
function isFalsy(value) {
|
@@ -275,7 +276,7 @@ function falsyToUndef(value) {
|
|
275
276
|
// src/blockstore/loader.ts
|
276
277
|
import pLimit from "p-limit";
|
277
278
|
import { CarReader } from "@ipld/car";
|
278
|
-
import { ResolveOnce } from "@adviser/cement";
|
279
|
+
import { ResolveOnce as ResolveOnce2 } from "@adviser/cement";
|
279
280
|
|
280
281
|
// src/blockstore/loader-helpers.ts
|
281
282
|
import { sha256 as hasher } from "multiformats/hashes/sha2";
|
@@ -547,6 +548,7 @@ __export(key_bag_exports, {
|
|
547
548
|
});
|
548
549
|
import {
|
549
550
|
KeyedResolvOnce,
|
551
|
+
ResolveOnce,
|
550
552
|
ResolveSeq,
|
551
553
|
Result as Result2,
|
552
554
|
runtimeFn,
|
@@ -557,21 +559,25 @@ import { base58btc } from "multiformats/bases/base58";
|
|
557
559
|
var KeyBag = class {
|
558
560
|
constructor(rt) {
|
559
561
|
this.rt = rt;
|
562
|
+
this._warnOnce = new ResolveOnce();
|
560
563
|
this._seq = new ResolveSeq();
|
561
|
-
this.logger = ensureLogger(rt.sthis, "KeyBag"
|
562
|
-
id: rt.id()
|
563
|
-
});
|
564
|
+
this.logger = ensureLogger(rt.sthis, "KeyBag");
|
564
565
|
this.logger.Debug().Msg("KeyBag created");
|
565
566
|
}
|
566
567
|
async subtleKey(key) {
|
568
|
+
const extractable = this.rt.url.getParam("extractKey") === "_deprecated_internal_api";
|
569
|
+
if (extractable) {
|
570
|
+
this._warnOnce.once(
|
571
|
+
() => this.logger.Warn().Msg("extractKey is enabled via _deprecated_internal_api --- handle keys safely!!!")
|
572
|
+
);
|
573
|
+
}
|
567
574
|
return await this.rt.crypto.importKey(
|
568
575
|
"raw",
|
569
576
|
// raw or jwk
|
570
577
|
base58btc.decode(key),
|
571
578
|
// hexStringToUint8Array(key), // raw data
|
572
579
|
"AES-GCM",
|
573
|
-
|
574
|
-
// extractable
|
580
|
+
extractable,
|
575
581
|
["encrypt", "decrypt"]
|
576
582
|
);
|
577
583
|
}
|
@@ -620,6 +626,23 @@ var KeyBag = class {
|
|
620
626
|
await bag.set(name, item);
|
621
627
|
return await this.toKeyWithFingerPrint(item.key);
|
622
628
|
}
|
629
|
+
async getNamedExtractableKey(name, failIfNotFound = false) {
|
630
|
+
const ret = await this.getNamedKey(name, failIfNotFound);
|
631
|
+
if (ret.isErr()) {
|
632
|
+
return ret;
|
633
|
+
}
|
634
|
+
const named = ret.Ok();
|
635
|
+
return Result2.Ok({
|
636
|
+
...named,
|
637
|
+
extract: async () => {
|
638
|
+
const ext = new Uint8Array(await this.rt.crypto.exportKey("raw", named.key));
|
639
|
+
return {
|
640
|
+
key: ext,
|
641
|
+
keyStr: base58btc.encode(ext)
|
642
|
+
};
|
643
|
+
}
|
644
|
+
});
|
645
|
+
}
|
623
646
|
async getNamedKey(name, failIfNotFound = false) {
|
624
647
|
const id = this.rt.sthis.nextId(4).str;
|
625
648
|
return this._seq.add(async () => {
|
@@ -645,14 +668,14 @@ var keyBagProviderFactories = new Map(
|
|
645
668
|
{
|
646
669
|
protocol: "file:",
|
647
670
|
factory: async (url, sthis) => {
|
648
|
-
const { KeyBagProviderFile } = await import("./key-bag-file-
|
671
|
+
const { KeyBagProviderFile } = await import("./key-bag-file-WADZBHYG.js");
|
649
672
|
return new KeyBagProviderFile(url, sthis);
|
650
673
|
}
|
651
674
|
},
|
652
675
|
{
|
653
676
|
protocol: "indexdb:",
|
654
677
|
factory: async (url, sthis) => {
|
655
|
-
const { KeyBagProviderIndexDB } = await import("./key-bag-indexdb-
|
678
|
+
const { KeyBagProviderIndexDB } = await import("./key-bag-indexdb-PGVAI3FJ.js");
|
656
679
|
return new KeyBagProviderIndexDB(url, sthis);
|
657
680
|
}
|
658
681
|
}
|
@@ -689,23 +712,11 @@ function defaultKeyBagOpts(sthis, kbo) {
|
|
689
712
|
}
|
690
713
|
logger.Debug().Url(url).Msg("from env");
|
691
714
|
}
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
keyProviderFactory = async () => {
|
696
|
-
const { KeyBagProviderFile } = await import("./key-bag-file-NMEBFSPM.js");
|
697
|
-
return new KeyBagProviderFile(url, sthis);
|
698
|
-
};
|
699
|
-
break;
|
700
|
-
case "indexdb:":
|
701
|
-
keyProviderFactory = async () => {
|
702
|
-
const { KeyBagProviderIndexDB } = await import("./key-bag-indexdb-X5V6GNBZ.js");
|
703
|
-
return new KeyBagProviderIndexDB(url, sthis);
|
704
|
-
};
|
705
|
-
break;
|
706
|
-
default:
|
707
|
-
throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
|
715
|
+
const kitem = keyBagProviderFactories.get(url.protocol);
|
716
|
+
if (!kitem) {
|
717
|
+
throw logger.Error().Url(url).Msg("unsupported protocol").AsError();
|
708
718
|
}
|
719
|
+
const getBag = async () => kitem.factory(url, sthis);
|
709
720
|
if (url.hasParam("masterkey")) {
|
710
721
|
throw logger.Error().Url(url).Msg("masterkey is not supported").AsError();
|
711
722
|
}
|
@@ -715,7 +726,7 @@ function defaultKeyBagOpts(sthis, kbo) {
|
|
715
726
|
sthis,
|
716
727
|
logger,
|
717
728
|
keyLength: kbo.keyLength || 16,
|
718
|
-
getBag
|
729
|
+
getBag,
|
719
730
|
id: () => {
|
720
731
|
return url.toString();
|
721
732
|
}
|
@@ -809,7 +820,7 @@ async function commit(params, t, done, opts = { noLoader: false, compact: false
|
|
809
820
|
}
|
810
821
|
async function prepareCarFiles(encoder, threshold, rootBlock, t) {
|
811
822
|
const carFiles = [];
|
812
|
-
threshold = threshold ||
|
823
|
+
threshold = threshold || 128e3 * 8;
|
813
824
|
let clonedt = new CarTransaction(t.parent, { add: false, noLoader: false });
|
814
825
|
clonedt.putSync(rootBlock.cid, rootBlock.bytes);
|
815
826
|
let newsize = CBW.blockLength(toCIDBlock(rootBlock));
|
@@ -832,6 +843,53 @@ async function prepareCarFiles(encoder, threshold, rootBlock, t) {
|
|
832
843
|
|
833
844
|
// src/blockstore/loader.ts
|
834
845
|
import { sha256 as hasher3 } from "multiformats/hashes/sha2";
|
846
|
+
|
847
|
+
// src/blockstore/task-manager.ts
|
848
|
+
var TaskManager = class {
|
849
|
+
constructor(sthis, callback) {
|
850
|
+
this.eventsWeHandled = /* @__PURE__ */ new Set();
|
851
|
+
this.queue = [];
|
852
|
+
this.isProcessing = false;
|
853
|
+
this.logger = ensureLogger(sthis, "TaskManager");
|
854
|
+
this.callback = callback;
|
855
|
+
}
|
856
|
+
async handleEvent(cid, parents, dbMeta) {
|
857
|
+
for (const parent of parents) {
|
858
|
+
this.eventsWeHandled.add(parent.toString());
|
859
|
+
}
|
860
|
+
this.queue.push({ cid: cid.toString(), dbMeta, retries: 0 });
|
861
|
+
this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
|
862
|
+
void this.processQueue();
|
863
|
+
}
|
864
|
+
async processQueue() {
|
865
|
+
if (this.isProcessing) return;
|
866
|
+
this.isProcessing = true;
|
867
|
+
const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
868
|
+
const first = filteredQueue[0];
|
869
|
+
if (!first) {
|
870
|
+
return;
|
871
|
+
}
|
872
|
+
try {
|
873
|
+
await this.callback(first.dbMeta);
|
874
|
+
this.eventsWeHandled.add(first.cid);
|
875
|
+
this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
876
|
+
} catch (err) {
|
877
|
+
if (first.retries++ > 3) {
|
878
|
+
this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
|
879
|
+
this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
|
880
|
+
}
|
881
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
882
|
+
throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
|
883
|
+
} finally {
|
884
|
+
this.isProcessing = false;
|
885
|
+
if (this.queue.length > 0) {
|
886
|
+
void this.processQueue();
|
887
|
+
}
|
888
|
+
}
|
889
|
+
}
|
890
|
+
};
|
891
|
+
|
892
|
+
// src/blockstore/loader.ts
|
835
893
|
function carLogIncludesGroup(list, cids) {
|
836
894
|
return list.some((arr) => {
|
837
895
|
return arr.toString() === cids.toString();
|
@@ -856,7 +914,7 @@ var Loader = class {
|
|
856
914
|
this.getBlockCache = /* @__PURE__ */ new Map();
|
857
915
|
this.seenMeta = /* @__PURE__ */ new Set();
|
858
916
|
this.writeLimit = pLimit(1);
|
859
|
-
this.onceReady = new
|
917
|
+
this.onceReady = new ResolveOnce2();
|
860
918
|
this.name = name;
|
861
919
|
this.sthis = sthis;
|
862
920
|
this.ebOpts = defaultedBlockstoreRuntime(
|
@@ -868,6 +926,9 @@ var Loader = class {
|
|
868
926
|
"Loader"
|
869
927
|
);
|
870
928
|
this.logger = this.ebOpts.logger;
|
929
|
+
this.taskManager = new TaskManager(sthis, async (dbMeta) => {
|
930
|
+
await this.handleDbMetasFromStore([dbMeta]);
|
931
|
+
});
|
871
932
|
}
|
872
933
|
// readonly id = uuidv4();
|
873
934
|
async keyBag() {
|
@@ -887,8 +948,10 @@ var Loader = class {
|
|
887
948
|
}
|
888
949
|
async ready() {
|
889
950
|
return this.onceReady.once(async () => {
|
890
|
-
const metas =
|
891
|
-
if (
|
951
|
+
const metas = await (await this.metaStore()).load();
|
952
|
+
if (this.ebOpts.meta) {
|
953
|
+
await this.handleDbMetasFromStore([this.ebOpts.meta]);
|
954
|
+
} else if (metas) {
|
892
955
|
await this.handleDbMetasFromStore(metas);
|
893
956
|
}
|
894
957
|
});
|
@@ -969,7 +1032,8 @@ var Loader = class {
|
|
969
1032
|
carLog: this.carLog,
|
970
1033
|
carStore: fstore,
|
971
1034
|
WALStore: await this.WALStore(),
|
972
|
-
metaStore: await this.metaStore()
|
1035
|
+
metaStore: await this.metaStore(),
|
1036
|
+
threshold: this.ebOpts.threshold
|
973
1037
|
};
|
974
1038
|
return this.commitQueue.enqueue(async () => {
|
975
1039
|
await this.cacheTransaction(t);
|
@@ -1193,7 +1257,7 @@ var generateIV = {
|
|
1193
1257
|
calc: async (ko, crypto, data) => {
|
1194
1258
|
const hash = await hasher4.digest(data);
|
1195
1259
|
const hashBytes = new Uint8Array(hash.bytes);
|
1196
|
-
const hashArray = new Uint8Array(ko.ivLength
|
1260
|
+
const hashArray = new Uint8Array(ko.ivLength);
|
1197
1261
|
for (let i = 0; i < hashBytes.length; i++) {
|
1198
1262
|
hashArray[i % ko.ivLength] ^= hashBytes[i];
|
1199
1263
|
}
|
@@ -1271,7 +1335,7 @@ var keyedCrypto = class {
|
|
1271
1335
|
};
|
1272
1336
|
}
|
1273
1337
|
async _decrypt(data) {
|
1274
|
-
this.logger.Debug().Len(data.bytes).Str("fp", this.key.fingerPrint).Msg("decrypting");
|
1338
|
+
this.logger.Debug().Len(data.bytes, "bytes").Len(data.iv, "iv").Str("fp", this.key.fingerPrint).Msg("decrypting");
|
1275
1339
|
return new Uint8Array(await this.crypto.decrypt(this.algo(data.iv), this.key.key, data.bytes));
|
1276
1340
|
}
|
1277
1341
|
async _encrypt(data) {
|
@@ -1342,6 +1406,7 @@ async function keyedCryptoFactory(url, kb, sthis) {
|
|
1342
1406
|
}
|
1343
1407
|
|
1344
1408
|
// src/blockstore/fragment-gateway.ts
|
1409
|
+
import { Result as Result3 } from "@adviser/cement";
|
1345
1410
|
import { base58btc as base58btc3 } from "multiformats/bases/base58";
|
1346
1411
|
import { encode as encode3, decode as decode3 } from "cborg";
|
1347
1412
|
function getFragSize(url) {
|
@@ -1364,7 +1429,7 @@ async function getFrags(url, innerGW, headerSize, logger) {
|
|
1364
1429
|
}
|
1365
1430
|
const data = res.unwrap();
|
1366
1431
|
return [
|
1367
|
-
|
1432
|
+
Result3.Ok({
|
1368
1433
|
fid: new Uint8Array(0),
|
1369
1434
|
ofs: 0,
|
1370
1435
|
len: data.length,
|
@@ -1378,7 +1443,7 @@ async function getFrags(url, innerGW, headerSize, logger) {
|
|
1378
1443
|
}
|
1379
1444
|
const firstFragment = decode3(firstRaw.unwrap());
|
1380
1445
|
const blockSize = firstFragment.data.length;
|
1381
|
-
const ops = [Promise.resolve(
|
1446
|
+
const ops = [Promise.resolve(Result3.Ok(firstFragment))];
|
1382
1447
|
const fidStr = base58btc3.encode(firstFragment.fid);
|
1383
1448
|
const fragUrl = url.build().setParam("fid", fidStr).setParam("len", firstFragment.len.toString()).setParam("headerSize", headerSize.toString());
|
1384
1449
|
for (let ofs = blockSize; ofs < firstFragment.len; ofs += blockSize) {
|
@@ -1390,12 +1455,12 @@ async function getFrags(url, innerGW, headerSize, logger) {
|
|
1390
1455
|
}
|
1391
1456
|
const fragment = decode3(raw2.unwrap());
|
1392
1457
|
if (base58btc3.encode(fragment.fid) !== fidStr) {
|
1393
|
-
return
|
1458
|
+
return Result3.Err(logger.Error().Msg("Fragment fid mismatch").AsError());
|
1394
1459
|
}
|
1395
1460
|
if (fragment.ofs !== ofs2) {
|
1396
|
-
return
|
1461
|
+
return Result3.Err(logger.Error().Uint64("ofs", ofs2).Msg("Fragment ofs mismatch").AsError());
|
1397
1462
|
}
|
1398
|
-
return
|
1463
|
+
return Result3.Ok(fragment);
|
1399
1464
|
})(fragUrl.setParam("ofs", ofs.toString()).URI(), ofs)
|
1400
1465
|
);
|
1401
1466
|
}
|
@@ -1457,42 +1522,156 @@ var FragmentGateway = class {
|
|
1457
1522
|
}
|
1458
1523
|
async put(url, body) {
|
1459
1524
|
await Promise.all(this.slicer(url, body));
|
1460
|
-
return
|
1525
|
+
return Result3.Ok(void 0);
|
1461
1526
|
}
|
1462
1527
|
async get(url) {
|
1463
1528
|
const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
|
1464
1529
|
let buffer = void 0;
|
1465
1530
|
for (const rfrag of rfrags) {
|
1466
1531
|
if (rfrag.isErr()) {
|
1467
|
-
return
|
1532
|
+
return Result3.Err(rfrag.Err());
|
1468
1533
|
}
|
1469
1534
|
const frag = rfrag.Ok();
|
1470
1535
|
buffer = buffer || new Uint8Array(frag.len);
|
1471
1536
|
buffer.set(frag.data, frag.ofs);
|
1472
1537
|
}
|
1473
|
-
return
|
1538
|
+
return Result3.Ok(buffer || new Uint8Array(0));
|
1539
|
+
}
|
1540
|
+
async subscribe(url, callback) {
|
1541
|
+
if (this.innerGW.subscribe) {
|
1542
|
+
return this.innerGW.subscribe(url, callback);
|
1543
|
+
} else {
|
1544
|
+
return Result3.Err(this.logger.Error().Url(url).Msg("subscribe not supported").AsError());
|
1545
|
+
}
|
1474
1546
|
}
|
1475
1547
|
async delete(url) {
|
1476
1548
|
const rfrags = await getFrags(url, this.innerGW, this.headerSize, this.logger);
|
1477
1549
|
for (const rfrag of rfrags) {
|
1478
1550
|
if (rfrag.isErr()) {
|
1479
|
-
return
|
1551
|
+
return Result3.Err(rfrag.Err());
|
1480
1552
|
}
|
1481
1553
|
const frag = rfrag.Ok();
|
1482
1554
|
const fidStr = base58btc3.encode(frag.fid);
|
1483
1555
|
const fragUrl = url.build().setParam("fid", fidStr).setParam("len", frag.len.toString()).setParam("headerSize", this.headerSize.toString()).URI();
|
1484
1556
|
await this.innerGW.delete(fragUrl);
|
1485
1557
|
}
|
1486
|
-
return
|
1558
|
+
return Result3.Ok(void 0);
|
1487
1559
|
}
|
1488
1560
|
};
|
1489
1561
|
|
1562
|
+
// src/blockstore/meta-key-helper.ts
|
1563
|
+
import { format, parse } from "@ipld/dag-json";
|
1564
|
+
import { EventBlock, decodeEventBlock } from "@web3-storage/pail/clock";
|
1565
|
+
import { CID as CID2 } from "multiformats";
|
1566
|
+
import { base64pad } from "multiformats/bases/base64";
|
1567
|
+
import { Result as Result4 } from "@adviser/cement";
|
1568
|
+
async function decodeGatewayMetaBytesToDbMeta(sthis, byteHeads) {
|
1569
|
+
const crdtEntries = JSON.parse(sthis.txt.decode(byteHeads));
|
1570
|
+
if (!crdtEntries.length) {
|
1571
|
+
sthis.logger.Debug().Str("byteHeads", new TextDecoder().decode(byteHeads)).Msg("No CRDT entries found");
|
1572
|
+
return [];
|
1573
|
+
}
|
1574
|
+
if (!crdtEntries.map) {
|
1575
|
+
sthis.logger.Debug().Str("crdtEntries", JSON.stringify(crdtEntries)).Msg("No data in CRDT entries");
|
1576
|
+
return [];
|
1577
|
+
}
|
1578
|
+
return Promise.all(
|
1579
|
+
crdtEntries.map(async (crdtEntry) => {
|
1580
|
+
const eventBlock = await decodeEventBlock(base64pad.decode(crdtEntry.data));
|
1581
|
+
const dbMeta = parse(sthis.txt.decode(eventBlock.value.data.dbMeta));
|
1582
|
+
return {
|
1583
|
+
eventCid: eventBlock.cid,
|
1584
|
+
parents: crdtEntry.parents,
|
1585
|
+
dbMeta
|
1586
|
+
};
|
1587
|
+
})
|
1588
|
+
);
|
1589
|
+
}
|
1590
|
+
async function setCryptoKeyFromGatewayMetaPayload(uri, sthis, data) {
|
1591
|
+
try {
|
1592
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Setting crypto key from gateway meta payload");
|
1593
|
+
const keyInfo = await decodeGatewayMetaBytesToDbMeta(sthis, data);
|
1594
|
+
if (keyInfo.length) {
|
1595
|
+
const dbMeta = keyInfo[0].dbMeta;
|
1596
|
+
if (dbMeta.key) {
|
1597
|
+
const kb = await getKeyBag(sthis);
|
1598
|
+
const keyName = getStoreKeyName(uri);
|
1599
|
+
const res = await kb.setNamedKey(keyName, dbMeta.key);
|
1600
|
+
if (res.isErr()) {
|
1601
|
+
sthis.logger.Debug().Str("keyName", keyName).Str("dbMeta.key", dbMeta.key).Msg("Failed to set named key");
|
1602
|
+
throw res.Err();
|
1603
|
+
}
|
1604
|
+
}
|
1605
|
+
sthis.logger.Debug().Str("dbMeta.key", dbMeta.key).Str("uri", uri.toString()).Msg("Set crypto key from gateway meta payload");
|
1606
|
+
return Result4.Ok(dbMeta);
|
1607
|
+
}
|
1608
|
+
sthis.logger.Debug().Str("data", new TextDecoder().decode(data)).Msg("No crypto in gateway meta payload");
|
1609
|
+
return Result4.Ok(void 0);
|
1610
|
+
} catch (error) {
|
1611
|
+
sthis.logger.Debug().Err(error).Msg("Failed to set crypto key from gateway meta payload");
|
1612
|
+
return Result4.Err(error);
|
1613
|
+
}
|
1614
|
+
}
|
1615
|
+
async function addCryptoKeyToGatewayMetaPayload(uri, sthis, body) {
|
1616
|
+
try {
|
1617
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Adding crypto key to gateway meta payload");
|
1618
|
+
const keyName = getStoreKeyName(uri);
|
1619
|
+
const kb = await getKeyBag(sthis);
|
1620
|
+
const res = await kb.getNamedExtractableKey(keyName, true);
|
1621
|
+
if (res.isErr()) {
|
1622
|
+
sthis.logger.Error().Str("keyName", keyName).Msg("Failed to get named extractable key");
|
1623
|
+
throw res.Err();
|
1624
|
+
}
|
1625
|
+
const keyData = await res.Ok().extract();
|
1626
|
+
const dbMetas = await decodeGatewayMetaBytesToDbMeta(sthis, body);
|
1627
|
+
const { dbMeta, parents } = dbMetas[0];
|
1628
|
+
const parentLinks = parents.map((p) => CID2.parse(p));
|
1629
|
+
dbMeta.key = keyData.keyStr;
|
1630
|
+
const events = await Promise.all([dbMeta].map((dbMeta2) => createDbMetaEventBlock(sthis, dbMeta2, parentLinks)));
|
1631
|
+
const encoded = await encodeEventsWithParents(sthis, events, parentLinks);
|
1632
|
+
sthis.logger.Debug().Str("uri", uri.toString()).Msg("Added crypto key to gateway meta payload");
|
1633
|
+
return Result4.Ok(encoded);
|
1634
|
+
} catch (error) {
|
1635
|
+
sthis.logger.Error().Err(error).Msg("Failed to add crypto key to gateway meta payload");
|
1636
|
+
return Result4.Err(error);
|
1637
|
+
}
|
1638
|
+
}
|
1639
|
+
function getStoreKeyName(url) {
|
1640
|
+
const storeKeyName = [url.getParam("localName") || url.getParam("name")];
|
1641
|
+
const idx = url.getParam("index");
|
1642
|
+
if (idx) {
|
1643
|
+
storeKeyName.push(idx);
|
1644
|
+
}
|
1645
|
+
storeKeyName.push("data");
|
1646
|
+
return `@${storeKeyName.join(":")}@`;
|
1647
|
+
}
|
1648
|
+
async function createDbMetaEventBlock(sthis, dbMeta, parents) {
|
1649
|
+
const event = await EventBlock.create(
|
1650
|
+
{
|
1651
|
+
dbMeta: sthis.txt.encode(format(dbMeta))
|
1652
|
+
},
|
1653
|
+
parents
|
1654
|
+
);
|
1655
|
+
return event;
|
1656
|
+
}
|
1657
|
+
async function encodeEventsWithParents(sthis, events, parents) {
|
1658
|
+
const crdtEntries = events.map((event) => {
|
1659
|
+
const base64String = base64pad.encode(event.bytes);
|
1660
|
+
return {
|
1661
|
+
cid: event.cid.toString(),
|
1662
|
+
data: base64String,
|
1663
|
+
parents: parents.map((p) => p.toString())
|
1664
|
+
};
|
1665
|
+
});
|
1666
|
+
return sthis.txt.encode(JSON.stringify(crdtEntries));
|
1667
|
+
}
|
1668
|
+
|
1490
1669
|
// src/blockstore/store.ts
|
1491
1670
|
function guardVersion(url) {
|
1492
1671
|
if (!url.hasParam("version")) {
|
1493
|
-
return
|
1672
|
+
return Result5.Err(`missing version: ${url.toString()}`);
|
1494
1673
|
}
|
1495
|
-
return
|
1674
|
+
return Result5.Ok(url);
|
1496
1675
|
}
|
1497
1676
|
var BaseStoreImpl = class {
|
1498
1677
|
constructor(name, url, opts, sthis, logger) {
|
@@ -1504,6 +1683,7 @@ var BaseStoreImpl = class {
|
|
1504
1683
|
this.sthis = sthis;
|
1505
1684
|
this.logger = logger.With().Ref("url", () => this._url.toString()).Str("name", name).Logger();
|
1506
1685
|
this.gateway = new FragmentGateway(this.sthis, opts.gateway);
|
1686
|
+
this.loader = opts.loader;
|
1507
1687
|
}
|
1508
1688
|
url() {
|
1509
1689
|
return this._url;
|
@@ -1514,6 +1694,9 @@ var BaseStoreImpl = class {
|
|
1514
1694
|
onClosed(fn) {
|
1515
1695
|
this._onClosed.push(fn);
|
1516
1696
|
}
|
1697
|
+
async ready() {
|
1698
|
+
return;
|
1699
|
+
}
|
1517
1700
|
async keyedCrypto() {
|
1518
1701
|
return keyedCryptoFactory(this._url, await this.keybag(), this.sthis);
|
1519
1702
|
}
|
@@ -1560,67 +1743,44 @@ var BaseStoreImpl = class {
|
|
1560
1743
|
}
|
1561
1744
|
};
|
1562
1745
|
var MetaStoreImpl = class extends BaseStoreImpl {
|
1746
|
+
// remote: boolean;
|
1563
1747
|
constructor(sthis, name, url, opts) {
|
1564
|
-
super(
|
1565
|
-
name,
|
1566
|
-
url,
|
1567
|
-
{
|
1568
|
-
...opts
|
1569
|
-
},
|
1570
|
-
sthis,
|
1571
|
-
ensureLogger(sthis, "MetaStoreImpl")
|
1572
|
-
);
|
1748
|
+
super(name, url, { ...opts }, sthis, ensureLogger(sthis, "MetaStoreImpl"));
|
1573
1749
|
this.storeType = "meta";
|
1574
1750
|
this.subscribers = /* @__PURE__ */ new Map();
|
1575
|
-
|
1576
|
-
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1580
|
-
|
1581
|
-
|
1582
|
-
|
1583
|
-
|
1584
|
-
|
1585
|
-
|
1586
|
-
|
1587
|
-
|
1588
|
-
|
1589
|
-
|
1590
|
-
|
1591
|
-
const got = parse(headerData);
|
1592
|
-
return got;
|
1593
|
-
}
|
1594
|
-
async handleSubscribers(dbMetas, branch) {
|
1595
|
-
try {
|
1596
|
-
const subscribers = this.subscribers.get(branch) || [];
|
1597
|
-
await Promise.all(subscribers.map((subscriber) => subscriber(dbMetas)));
|
1598
|
-
} catch (e) {
|
1599
|
-
this.logger.Error().Err(e).Msg("handleSubscribers").AsError();
|
1751
|
+
this.parents = [];
|
1752
|
+
if (
|
1753
|
+
/*this.remote && */
|
1754
|
+
opts.gateway.subscribe
|
1755
|
+
) {
|
1756
|
+
this.onStarted(async () => {
|
1757
|
+
this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
|
1758
|
+
opts.gateway.subscribe?.(this.url(), async (message) => {
|
1759
|
+
this.logger.Debug().Msg("Received message from gateway");
|
1760
|
+
const dbMetas = await decodeGatewayMetaBytesToDbMeta(this.sthis, message);
|
1761
|
+
await Promise.all(
|
1762
|
+
dbMetas.map((dbMeta) => this.loader?.taskManager?.handleEvent(dbMeta.eventCid, dbMeta.parents, dbMeta.dbMeta))
|
1763
|
+
);
|
1764
|
+
this.updateParentsFromDbMetas(dbMetas);
|
1765
|
+
});
|
1766
|
+
});
|
1600
1767
|
}
|
1601
1768
|
}
|
1602
|
-
|
1603
|
-
|
1604
|
-
|
1605
|
-
|
1606
|
-
|
1607
|
-
|
1608
|
-
}
|
1609
|
-
await this.handleSubscribers(dbMetas, branch);
|
1610
|
-
return dbMetas;
|
1769
|
+
updateParentsFromDbMetas(dbMetas) {
|
1770
|
+
const cids = dbMetas.map((m) => m.eventCid);
|
1771
|
+
const dbMetaParents = dbMetas.flatMap((m) => m.parents);
|
1772
|
+
const uniqueParentsMap = new Map([...this.parents, ...cids].map((p) => [p.toString(), p]));
|
1773
|
+
const dbMetaParentsSet = new Set(dbMetaParents.map((p) => p.toString()));
|
1774
|
+
this.parents = Array.from(uniqueParentsMap.values()).filter((p) => !dbMetaParentsSet.has(p.toString()));
|
1611
1775
|
}
|
1612
|
-
|
1613
|
-
return byteHeads
|
1614
|
-
const txt = this.sthis.txt.decode(bytes);
|
1615
|
-
return this.parseHeader(txt);
|
1616
|
-
});
|
1776
|
+
async handleByteHeads(byteHeads) {
|
1777
|
+
return await decodeGatewayMetaBytesToDbMeta(this.sthis, byteHeads);
|
1617
1778
|
}
|
1618
|
-
async load(
|
1619
|
-
branch =
|
1620
|
-
this.logger.Debug().Str("branch", branch).Msg("loading");
|
1779
|
+
async load() {
|
1780
|
+
const branch = "main";
|
1621
1781
|
const url = await this.gateway.buildUrl(this.url(), branch);
|
1622
1782
|
if (url.isErr()) {
|
1623
|
-
throw this.logger.Error().Result("
|
1783
|
+
throw this.logger.Error().Result("buildUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
|
1624
1784
|
}
|
1625
1785
|
const bytes = await this.gateway.get(url.Ok());
|
1626
1786
|
if (bytes.isErr()) {
|
@@ -1629,27 +1789,31 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
1629
1789
|
}
|
1630
1790
|
throw this.logger.Error().Url(url.Ok()).Result("bytes:", bytes).Msg("gateway get").AsError();
|
1631
1791
|
}
|
1632
|
-
|
1792
|
+
const dbMetas = await this.handleByteHeads(bytes.Ok());
|
1793
|
+
await this.loader?.handleDbMetasFromStore(dbMetas.map((m) => m.dbMeta));
|
1794
|
+
this.updateParentsFromDbMetas(dbMetas);
|
1795
|
+
return dbMetas.map((m) => m.dbMeta);
|
1633
1796
|
}
|
1634
1797
|
async save(meta, branch) {
|
1635
1798
|
branch = branch || "main";
|
1636
1799
|
this.logger.Debug().Str("branch", branch).Any("meta", meta).Msg("saving meta");
|
1637
|
-
const
|
1800
|
+
const event = await createDbMetaEventBlock(this.sthis, meta, this.parents);
|
1801
|
+
const bytes = await encodeEventsWithParents(this.sthis, [event], this.parents);
|
1638
1802
|
const url = await this.gateway.buildUrl(this.url(), branch);
|
1639
1803
|
if (url.isErr()) {
|
1640
1804
|
throw this.logger.Error().Err(url.Err()).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
|
1641
1805
|
}
|
1642
|
-
|
1806
|
+
this.parents = [event.cid];
|
1807
|
+
const res = await this.gateway.put(url.Ok(), bytes);
|
1643
1808
|
if (res.isErr()) {
|
1644
1809
|
throw this.logger.Error().Err(res.Err()).Msg("got error from gateway.put").AsError();
|
1645
1810
|
}
|
1646
|
-
await this.handleSubscribers([meta], branch);
|
1647
1811
|
return res;
|
1648
1812
|
}
|
1649
1813
|
async close() {
|
1650
1814
|
await this.gateway.close(this.url());
|
1651
1815
|
this._onClosed.forEach((fn) => fn());
|
1652
|
-
return
|
1816
|
+
return Result5.Ok(void 0);
|
1653
1817
|
}
|
1654
1818
|
async destroy() {
|
1655
1819
|
return this.gateway.destroy(this.url());
|
@@ -1658,15 +1822,7 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
1658
1822
|
var DataStoreImpl = class extends BaseStoreImpl {
|
1659
1823
|
// readonly tag: string = "car-base";
|
1660
1824
|
constructor(sthis, name, url, opts) {
|
1661
|
-
super(
|
1662
|
-
name,
|
1663
|
-
url,
|
1664
|
-
{
|
1665
|
-
...opts
|
1666
|
-
},
|
1667
|
-
sthis,
|
1668
|
-
ensureLogger(sthis, "DataStoreImpl")
|
1669
|
-
);
|
1825
|
+
super(name, url, { ...opts }, sthis, ensureLogger(sthis, "DataStoreImpl"));
|
1670
1826
|
this.storeType = "data";
|
1671
1827
|
}
|
1672
1828
|
async load(cid) {
|
@@ -1704,7 +1860,7 @@ var DataStoreImpl = class extends BaseStoreImpl {
|
|
1704
1860
|
async close() {
|
1705
1861
|
await this.gateway.close(this.url());
|
1706
1862
|
this._onClosed.forEach((fn) => fn());
|
1707
|
-
return
|
1863
|
+
return Result5.Ok(void 0);
|
1708
1864
|
}
|
1709
1865
|
destroy() {
|
1710
1866
|
return this.gateway.destroy(this.url());
|
@@ -1712,46 +1868,43 @@ var DataStoreImpl = class extends BaseStoreImpl {
|
|
1712
1868
|
};
|
1713
1869
|
var WALStoreImpl = class extends BaseStoreImpl {
|
1714
1870
|
constructor(loader, url, opts) {
|
1715
|
-
super(
|
1716
|
-
loader.name,
|
1717
|
-
url,
|
1718
|
-
{
|
1719
|
-
...opts
|
1720
|
-
},
|
1721
|
-
loader.sthis,
|
1722
|
-
ensureLogger(loader.sthis, "WALStoreImpl")
|
1723
|
-
);
|
1871
|
+
super(loader.name, url, { ...opts }, loader.sthis, ensureLogger(loader.sthis, "WALStoreImpl"));
|
1724
1872
|
this.storeType = "wal";
|
1725
|
-
this._ready = new
|
1873
|
+
this._ready = new ResolveOnce3();
|
1726
1874
|
this.walState = { operations: [], noLoaderOps: [], fileOperations: [] };
|
1727
1875
|
this.processing = void 0;
|
1728
1876
|
this.processQueue = new CommitQueue();
|
1729
|
-
this.ready = async () => {
|
1730
|
-
return this._ready.once(async () => {
|
1731
|
-
const walState = await this.load().catch((e) => {
|
1732
|
-
this.logger.Error().Any("error", e).Msg("error loading wal");
|
1733
|
-
return void 0;
|
1734
|
-
});
|
1735
|
-
if (!walState) {
|
1736
|
-
this.walState.operations = [];
|
1737
|
-
this.walState.fileOperations = [];
|
1738
|
-
} else {
|
1739
|
-
this.walState.operations = walState.operations || [];
|
1740
|
-
this.walState.fileOperations = walState.fileOperations || [];
|
1741
|
-
}
|
1742
|
-
});
|
1743
|
-
};
|
1744
1877
|
this.loader = loader;
|
1745
1878
|
}
|
1879
|
+
async ready() {
|
1880
|
+
return this._ready.once(async () => {
|
1881
|
+
const walState = await this.load().catch((e) => {
|
1882
|
+
this.logger.Error().Any("error", e).Msg("error loading wal");
|
1883
|
+
return void 0;
|
1884
|
+
});
|
1885
|
+
if (!walState) {
|
1886
|
+
this.walState.operations = [];
|
1887
|
+
this.walState.fileOperations = [];
|
1888
|
+
} else {
|
1889
|
+
this.walState.operations = walState.operations || [];
|
1890
|
+
this.walState.fileOperations = walState.fileOperations || [];
|
1891
|
+
}
|
1892
|
+
});
|
1893
|
+
}
|
1746
1894
|
async enqueue(dbMeta, opts) {
|
1747
1895
|
await this.ready();
|
1748
|
-
if (opts.
|
1896
|
+
if (opts.compact) {
|
1897
|
+
this.walState.operations = [];
|
1898
|
+
this.walState.noLoaderOps = [dbMeta];
|
1899
|
+
} else if (opts.noLoader) {
|
1749
1900
|
this.walState.noLoaderOps.push(dbMeta);
|
1750
1901
|
} else {
|
1751
1902
|
this.walState.operations.push(dbMeta);
|
1752
1903
|
}
|
1753
1904
|
await this.save(this.walState);
|
1754
|
-
|
1905
|
+
if (!opts.noLoader) {
|
1906
|
+
void this.process();
|
1907
|
+
}
|
1755
1908
|
}
|
1756
1909
|
async enqueueFile(fileCid, publicFile = false) {
|
1757
1910
|
await this.ready();
|
@@ -1778,7 +1931,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
1778
1931
|
const fileOperations = [...this.walState.fileOperations];
|
1779
1932
|
const uploads = [];
|
1780
1933
|
const noLoaderOps = [...this.walState.noLoaderOps];
|
1781
|
-
const limit = pLimit2(
|
1934
|
+
const limit = pLimit2(3);
|
1782
1935
|
if (operations.length + fileOperations.length + noLoaderOps.length === 0) return;
|
1783
1936
|
for (const dbMeta of noLoaderOps) {
|
1784
1937
|
const uploadP = limit(async () => {
|
@@ -1854,7 +2007,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
1854
2007
|
throw this.logger.Error().Err(bytes.Err()).Msg("error get").AsError();
|
1855
2008
|
}
|
1856
2009
|
try {
|
1857
|
-
return bytes &&
|
2010
|
+
return bytes && parse2(this.sthis.txt.decode(bytes.Ok()));
|
1858
2011
|
} catch (e) {
|
1859
2012
|
throw this.logger.Error().Err(e).Msg("error parse").AsError();
|
1860
2013
|
}
|
@@ -1866,7 +2019,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
1866
2019
|
}
|
1867
2020
|
let encoded;
|
1868
2021
|
try {
|
1869
|
-
encoded =
|
2022
|
+
encoded = format2(state);
|
1870
2023
|
} catch (e) {
|
1871
2024
|
throw this.logger.Error().Err(e).Any("state", state).Msg("error format").AsError();
|
1872
2025
|
}
|
@@ -1878,7 +2031,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
1878
2031
|
async close() {
|
1879
2032
|
await this.gateway.close(this.url());
|
1880
2033
|
this._onClosed.forEach((fn) => fn());
|
1881
|
-
return
|
2034
|
+
return Result5.Ok(void 0);
|
1882
2035
|
}
|
1883
2036
|
destroy() {
|
1884
2037
|
return this.gateway.destroy(this.url());
|
@@ -1904,10 +2057,10 @@ function buildURL(optURL, loader) {
|
|
1904
2057
|
const obuItem = Array.from(storeFactory.values()).find((items) => items.overrideBaseURL);
|
1905
2058
|
let obuUrl;
|
1906
2059
|
if (obuItem && obuItem.overrideBaseURL) {
|
1907
|
-
obuUrl =
|
2060
|
+
obuUrl = URI5.from(obuItem.overrideBaseURL);
|
1908
2061
|
}
|
1909
2062
|
const ret = ensureIsIndex(
|
1910
|
-
|
2063
|
+
URI5.from(optURL || obuUrl || dataDir(loader.sthis, loader.name, storeOpts.stores?.base)),
|
1911
2064
|
storeOpts.isIndex
|
1912
2065
|
);
|
1913
2066
|
return ret;
|
@@ -1954,52 +2107,61 @@ function registerStoreProtocol(item) {
|
|
1954
2107
|
storeFactory.delete(protocol);
|
1955
2108
|
};
|
1956
2109
|
}
|
2110
|
+
var onceDataStoreFactory = new KeyedResolvOnce2();
|
1957
2111
|
async function dataStoreFactory(loader) {
|
1958
2112
|
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.data, loader)).build().setParam("store", "data").URI();
|
1959
2113
|
const sthis = ensureSuperLog(loader.sthis, "dataStoreFactory", { url: url.toString() });
|
1960
|
-
|
1961
|
-
|
1962
|
-
|
1963
|
-
|
1964
|
-
|
1965
|
-
|
1966
|
-
|
1967
|
-
|
1968
|
-
|
2114
|
+
return onceDataStoreFactory.get(url.toString()).once(async () => {
|
2115
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
2116
|
+
if (!gateway) {
|
2117
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
2118
|
+
}
|
2119
|
+
const store = new DataStoreImpl(sthis, loader.name, url, {
|
2120
|
+
gateway: gateway.gateway,
|
2121
|
+
keybag: () => getKeyBag(loader.sthis, {
|
2122
|
+
...loader.ebOpts.keyBag
|
2123
|
+
})
|
2124
|
+
});
|
2125
|
+
return store;
|
1969
2126
|
});
|
1970
|
-
return store;
|
1971
2127
|
}
|
2128
|
+
var onceMetaStoreFactory = new KeyedResolvOnce2();
|
1972
2129
|
async function metaStoreFactory(loader) {
|
1973
2130
|
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.meta, loader)).build().setParam("store", "meta").URI();
|
1974
2131
|
const sthis = ensureSuperLog(loader.sthis, "metaStoreFactory", { url: () => url.toString() });
|
1975
|
-
|
1976
|
-
|
1977
|
-
|
1978
|
-
|
1979
|
-
|
1980
|
-
|
1981
|
-
|
1982
|
-
|
1983
|
-
|
1984
|
-
|
2132
|
+
return onceMetaStoreFactory.get(url.toString()).once(async () => {
|
2133
|
+
sthis.logger.Debug().Str("protocol", url.protocol).Msg("pre-protocol switch");
|
2134
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
2135
|
+
if (!gateway) {
|
2136
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
2137
|
+
}
|
2138
|
+
const store = new MetaStoreImpl(loader.sthis, loader.name, url, {
|
2139
|
+
gateway: gateway.gateway,
|
2140
|
+
keybag: () => getKeyBag(loader.sthis, {
|
2141
|
+
...loader.ebOpts.keyBag
|
2142
|
+
})
|
2143
|
+
});
|
2144
|
+
return store;
|
1985
2145
|
});
|
1986
|
-
return store;
|
1987
2146
|
}
|
2147
|
+
var onceRemoteWalFactory = new KeyedResolvOnce2();
|
1988
2148
|
async function remoteWalFactory(loader) {
|
1989
2149
|
const url = ensureName(loader.name, buildURL(loader.ebOpts.store.stores?.wal, loader)).build().setParam("store", "wal").URI();
|
1990
2150
|
const sthis = ensureSuperLog(loader.sthis, "remoteWalFactory", { url: url.toString() });
|
1991
|
-
|
1992
|
-
|
1993
|
-
|
1994
|
-
|
1995
|
-
|
1996
|
-
|
1997
|
-
|
1998
|
-
|
1999
|
-
|
2000
|
-
|
2151
|
+
return onceRemoteWalFactory.get(url.toString()).once(async () => {
|
2152
|
+
const gateway = await getGatewayFromURL(url, sthis);
|
2153
|
+
if (!gateway) {
|
2154
|
+
throw sthis.logger.Error().Url(url).Msg("gateway not found").AsError();
|
2155
|
+
}
|
2156
|
+
sthis.logger.Debug().Str("prepared", url.toString()).Msg("produced");
|
2157
|
+
const store = new WALStoreImpl(loader, url, {
|
2158
|
+
gateway: gateway.gateway,
|
2159
|
+
keybag: () => getKeyBag(loader.sthis, {
|
2160
|
+
...loader.ebOpts.keyBag
|
2161
|
+
})
|
2162
|
+
});
|
2163
|
+
return store;
|
2001
2164
|
});
|
2002
|
-
return store;
|
2003
2165
|
}
|
2004
2166
|
async function testStoreFactory(url, sthis) {
|
2005
2167
|
sthis = ensureSuperLog(sthis, "testStoreFactory");
|
@@ -2038,78 +2200,27 @@ function toStoreRuntime(opts, sthis) {
|
|
2038
2200
|
}
|
2039
2201
|
registerStoreProtocol({
|
2040
2202
|
protocol: "file:",
|
2041
|
-
gateway: async (
|
2042
|
-
const { FileGateway } = await import("./gateway-
|
2043
|
-
return new FileGateway(
|
2203
|
+
gateway: async (sthis) => {
|
2204
|
+
const { FileGateway } = await import("./gateway-5FCWPX5W.js");
|
2205
|
+
return new FileGateway(sthis);
|
2044
2206
|
},
|
2045
|
-
test: async (
|
2046
|
-
const { FileTestStore } = await import("./gateway-
|
2047
|
-
return new FileTestStore(
|
2207
|
+
test: async (sthis) => {
|
2208
|
+
const { FileTestStore } = await import("./gateway-5FCWPX5W.js");
|
2209
|
+
return new FileTestStore(sthis);
|
2048
2210
|
}
|
2049
2211
|
});
|
2050
2212
|
registerStoreProtocol({
|
2051
2213
|
protocol: "indexdb:",
|
2052
|
-
gateway: async (
|
2053
|
-
const { IndexDBGateway } = await import("./gateway-
|
2054
|
-
return new IndexDBGateway(
|
2214
|
+
gateway: async (sthis) => {
|
2215
|
+
const { IndexDBGateway } = await import("./gateway-H7UD6TNB.js");
|
2216
|
+
return new IndexDBGateway(sthis);
|
2055
2217
|
},
|
2056
|
-
test: async (
|
2057
|
-
const { IndexDBTestStore } = await import("./gateway-
|
2058
|
-
return new IndexDBTestStore(
|
2218
|
+
test: async (sthis) => {
|
2219
|
+
const { IndexDBTestStore } = await import("./gateway-H7UD6TNB.js");
|
2220
|
+
return new IndexDBTestStore(sthis);
|
2059
2221
|
}
|
2060
2222
|
});
|
2061
2223
|
|
2062
|
-
// src/blockstore/connection-base.ts
|
2063
|
-
import { EventBlock, decodeEventBlock } from "@web3-storage/pail/clock";
|
2064
|
-
import { MemoryBlockstore as MemoryBlockstore2 } from "@web3-storage/pail/block";
|
2065
|
-
|
2066
|
-
// src/blockstore/task-manager.ts
|
2067
|
-
var TaskManager = class {
|
2068
|
-
constructor(loader) {
|
2069
|
-
this.eventsWeHandled = /* @__PURE__ */ new Set();
|
2070
|
-
this.queue = [];
|
2071
|
-
this.isProcessing = false;
|
2072
|
-
this.loader = loader;
|
2073
|
-
this.logger = ensureLogger(loader.sthis, "TaskManager");
|
2074
|
-
}
|
2075
|
-
async handleEvent(eventBlock) {
|
2076
|
-
const cid = eventBlock.cid.toString();
|
2077
|
-
const parents = eventBlock.value.parents.map((cid2) => cid2.toString());
|
2078
|
-
for (const parent of parents) {
|
2079
|
-
this.eventsWeHandled.add(parent);
|
2080
|
-
}
|
2081
|
-
this.queue.push({ cid, eventBlock, retries: 0 });
|
2082
|
-
this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
|
2083
|
-
void this.processQueue();
|
2084
|
-
}
|
2085
|
-
async processQueue() {
|
2086
|
-
if (this.isProcessing) return;
|
2087
|
-
this.isProcessing = true;
|
2088
|
-
const filteredQueue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
2089
|
-
const first = filteredQueue[0];
|
2090
|
-
if (!first) {
|
2091
|
-
return;
|
2092
|
-
}
|
2093
|
-
try {
|
2094
|
-
this.loader?.remoteMetaStore?.handleByteHeads([first.eventBlock.value.data.dbMeta]);
|
2095
|
-
this.eventsWeHandled.add(first.cid);
|
2096
|
-
this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
2097
|
-
} catch (err) {
|
2098
|
-
if (first.retries++ > 3) {
|
2099
|
-
this.logger.Error().Str("cid", first.cid).Msg("failed to process event block after 3 retries");
|
2100
|
-
this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
|
2101
|
-
}
|
2102
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
2103
|
-
throw this.logger.Error().Err(err).Msg("failed to process event block").AsError();
|
2104
|
-
} finally {
|
2105
|
-
this.isProcessing = false;
|
2106
|
-
if (this.queue.length > 0) {
|
2107
|
-
void this.processQueue();
|
2108
|
-
}
|
2109
|
-
}
|
2110
|
-
}
|
2111
|
-
};
|
2112
|
-
|
2113
2224
|
// src/blockstore/store-remote.ts
|
2114
2225
|
async function RemoteDataStore(sthis, name, url, opts) {
|
2115
2226
|
const ds = new DataStoreImpl(sthis, name, url, opts);
|
@@ -2117,7 +2228,13 @@ async function RemoteDataStore(sthis, name, url, opts) {
|
|
2117
2228
|
return ds;
|
2118
2229
|
}
|
2119
2230
|
async function RemoteMetaStore(sthis, name, url, opts) {
|
2120
|
-
const ms = new MetaStoreImpl(
|
2231
|
+
const ms = new MetaStoreImpl(
|
2232
|
+
sthis,
|
2233
|
+
name,
|
2234
|
+
url,
|
2235
|
+
opts
|
2236
|
+
/* , true*/
|
2237
|
+
);
|
2121
2238
|
await ms.start();
|
2122
2239
|
return ms;
|
2123
2240
|
}
|
@@ -2125,16 +2242,12 @@ async function RemoteMetaStore(sthis, name, url, opts) {
|
|
2125
2242
|
// src/blockstore/connection-base.ts
|
2126
2243
|
var ConnectionBase = class {
|
2127
2244
|
constructor(url, logger) {
|
2128
|
-
// readonly ready: Promise<unknown>;
|
2129
|
-
// todo move to LRU blockstore https://github.com/web3-storage/w3clock/blob/main/src/worker/block.js
|
2130
|
-
this.eventBlocks = new MemoryBlockstore2();
|
2131
|
-
this.parents = [];
|
2132
2245
|
this.loaded = Promise.resolve();
|
2133
2246
|
this.logger = logger;
|
2134
2247
|
this.url = url;
|
2135
2248
|
}
|
2136
2249
|
async refresh() {
|
2137
|
-
await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load(
|
2250
|
+
await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
|
2138
2251
|
await (await throwFalsy(this.loader).WALStore()).process();
|
2139
2252
|
}
|
2140
2253
|
async connect_X({ loader }) {
|
@@ -2145,26 +2258,20 @@ var ConnectionBase = class {
|
|
2145
2258
|
async connectMeta_X({ loader }) {
|
2146
2259
|
if (!loader) throw this.logger.Error().Msg("connectMeta_X: loader is required").AsError();
|
2147
2260
|
this.loader = loader;
|
2148
|
-
this.taskManager = new TaskManager(loader);
|
2149
2261
|
await this.onConnect();
|
2150
2262
|
const metaUrl = this.url.build().defParam("store", "meta").URI();
|
2151
2263
|
const gateway = await getGatewayFromURL(metaUrl, this.loader.sthis);
|
2152
2264
|
if (!gateway) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: gateway is required").AsError();
|
2153
|
-
const
|
2154
|
-
|
2265
|
+
const dbName = metaUrl.getParam("name");
|
2266
|
+
if (!dbName) throw this.logger.Error().Url(metaUrl).Msg("connectMeta_X: name is required").AsError();
|
2267
|
+
const remote = await RemoteMetaStore(loader.sthis, dbName, metaUrl, {
|
2155
2268
|
gateway: gateway.gateway,
|
2156
|
-
keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag)
|
2157
|
-
|
2158
|
-
remote.onLoad("main", async (metas) => {
|
2159
|
-
if (metas) {
|
2160
|
-
this.logger.Debug().Any("metas", metas).Bool("loader", this.loader).Msg("connectMeta_X: handleDbMetasFromStore pre");
|
2161
|
-
await throwFalsy(this.loader).handleDbMetasFromStore(metas);
|
2162
|
-
this.logger.Debug().Any("metas", metas).Msg("connectMeta_X: handleDbMetasFromStore post");
|
2163
|
-
}
|
2269
|
+
keybag: () => getKeyBag(loader.sthis, loader.ebOpts.keyBag),
|
2270
|
+
loader
|
2164
2271
|
});
|
2165
2272
|
this.loader.remoteMetaStore = remote;
|
2166
2273
|
this.loaded = this.loader.ready().then(async () => {
|
2167
|
-
remote.load(
|
2274
|
+
remote.load().then(async () => {
|
2168
2275
|
(await throwFalsy(this.loader).WALStore()).process();
|
2169
2276
|
});
|
2170
2277
|
});
|
@@ -2175,28 +2282,14 @@ var ConnectionBase = class {
|
|
2175
2282
|
const dataUrl = this.url.build().defParam("store", "data").URI();
|
2176
2283
|
const gateway = await getGatewayFromURL(dataUrl, this.loader.sthis);
|
2177
2284
|
if (!gateway) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: gateway is required").AsError();
|
2178
|
-
const name = dataUrl.
|
2285
|
+
const name = dataUrl.getParam("name");
|
2286
|
+
if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage_X: name is required").AsError;
|
2179
2287
|
loader.remoteCarStore = await RemoteDataStore(loader.sthis, name, this.url, {
|
2180
2288
|
gateway: gateway.gateway,
|
2181
2289
|
keybag: () => getKeyBag(loader.sthis, this.loader?.ebOpts.keyBag)
|
2182
2290
|
});
|
2183
2291
|
loader.remoteFileStore = loader.remoteCarStore;
|
2184
2292
|
}
|
2185
|
-
async createEventBlock(bytes) {
|
2186
|
-
const data = {
|
2187
|
-
dbMeta: bytes
|
2188
|
-
};
|
2189
|
-
const event = await EventBlock.create(
|
2190
|
-
data,
|
2191
|
-
this.parents
|
2192
|
-
);
|
2193
|
-
await this.eventBlocks.put(event.cid, event.bytes);
|
2194
|
-
return event;
|
2195
|
-
}
|
2196
|
-
async decodeEventBlock(bytes) {
|
2197
|
-
const event = await decodeEventBlock(bytes);
|
2198
|
-
return event;
|
2199
|
-
}
|
2200
2293
|
// move this stuff to connect
|
2201
2294
|
// async getDashboardURL(compact = true) {
|
2202
2295
|
// const baseUrl = 'https://dashboard.fireproof.storage/'
|
@@ -2490,7 +2583,7 @@ async function doCompact(blockLog, head, logger) {
|
|
2490
2583
|
isCompacting = false;
|
2491
2584
|
}
|
2492
2585
|
async function getBlock(blocks, cidString) {
|
2493
|
-
const block = await blocks.get(
|
2586
|
+
const block = await blocks.get(parse3(cidString));
|
2494
2587
|
if (!block) throw new Error(`Missing block ${cidString}`);
|
2495
2588
|
const { cid, value } = await decode({ bytes: block.bytes, codec, hasher: hasher5 });
|
2496
2589
|
return new Block({ cid, value, bytes: block.bytes });
|
@@ -2826,7 +2919,7 @@ var Index = class {
|
|
2826
2919
|
// src/crdt-clock.ts
|
2827
2920
|
import { advance } from "@web3-storage/pail/clock";
|
2828
2921
|
import { root as root2 } from "@web3-storage/pail/crdt";
|
2829
|
-
import { ResolveOnce as
|
2922
|
+
import { ResolveOnce as ResolveOnce4 } from "@adviser/cement";
|
2830
2923
|
|
2831
2924
|
// src/apply-head-queue.ts
|
2832
2925
|
function applyHeadQueue(worker, logger) {
|
@@ -2841,7 +2934,7 @@ function applyHeadQueue(worker, logger) {
|
|
2841
2934
|
queue.sort((a, b) => b.updates ? 1 : -1);
|
2842
2935
|
const task = queue.shift();
|
2843
2936
|
if (!task) continue;
|
2844
|
-
await worker(task.newHead, task.prevHead, task.updates !==
|
2937
|
+
await worker(task.newHead, task.prevHead, task.updates !== void 0).catch((e) => {
|
2845
2938
|
throw logger.Error().Err(e).Msg("int_applyHead worker error").AsError();
|
2846
2939
|
});
|
2847
2940
|
if (task.updates) {
|
@@ -2883,7 +2976,7 @@ var CRDTClock = class {
|
|
2883
2976
|
this.zoomers = /* @__PURE__ */ new Set();
|
2884
2977
|
this.watchers = /* @__PURE__ */ new Set();
|
2885
2978
|
this.emptyWatchers = /* @__PURE__ */ new Set();
|
2886
|
-
this._ready = new
|
2979
|
+
this._ready = new ResolveOnce4();
|
2887
2980
|
this.blockstore = blockstore;
|
2888
2981
|
this.logger = ensureLogger(blockstore.sthis, "CRDTClock");
|
2889
2982
|
this.applyHeadQueue = applyHeadQueue(this.int_applyHead.bind(this), this.logger);
|
@@ -2931,6 +3024,7 @@ var CRDTClock = class {
|
|
2931
3024
|
this.zoomers.add(fn);
|
2932
3025
|
}
|
2933
3026
|
async int_applyHead(newHead, prevHead, localUpdates) {
|
3027
|
+
const noLoader = !localUpdates;
|
2934
3028
|
const ogHead = sortClockHead(this.head);
|
2935
3029
|
newHead = sortClockHead(newHead);
|
2936
3030
|
if (compareClockHeads(ogHead, newHead)) {
|
@@ -2941,7 +3035,6 @@ var CRDTClock = class {
|
|
2941
3035
|
this.setHead(newHead);
|
2942
3036
|
return;
|
2943
3037
|
}
|
2944
|
-
const noLoader = !localUpdates;
|
2945
3038
|
if (!this.blockstore) {
|
2946
3039
|
throw this.logger.Error().Msg("missing blockstore").AsError();
|
2947
3040
|
}
|
@@ -2994,7 +3087,7 @@ async function advanceBlocks(logger, newHead, tblocks, head) {
|
|
2994
3087
|
var CRDT = class {
|
2995
3088
|
constructor(sthis, name, opts = {}) {
|
2996
3089
|
this.indexers = /* @__PURE__ */ new Map();
|
2997
|
-
this.onceReady = new
|
3090
|
+
this.onceReady = new ResolveOnce5();
|
2998
3091
|
this.sthis = sthis;
|
2999
3092
|
this.name = name;
|
3000
3093
|
this.logger = ensureLogger(sthis, "CRDT");
|
@@ -3060,7 +3153,7 @@ var CRDT = class {
|
|
3060
3153
|
try {
|
3061
3154
|
await Promise.all([this.blockstore.ready(), this.indexBlockstore.ready(), this.clock.ready()]);
|
3062
3155
|
} catch (e) {
|
3063
|
-
throw this.logger.Error().Err(e).Msg(
|
3156
|
+
throw this.logger.Error().Err(e).Msg(`CRDT is not ready`).AsError();
|
3064
3157
|
}
|
3065
3158
|
});
|
3066
3159
|
}
|
@@ -3114,7 +3207,7 @@ var Database = class {
|
|
3114
3207
|
this._listening = false;
|
3115
3208
|
this._listeners = /* @__PURE__ */ new Set();
|
3116
3209
|
this._noupdate_listeners = /* @__PURE__ */ new Set();
|
3117
|
-
this._ready = new
|
3210
|
+
this._ready = new ResolveOnce6();
|
3118
3211
|
this.name = name;
|
3119
3212
|
this.opts = opts || this.opts;
|
3120
3213
|
this.sthis = ensureSuperThis(this.opts);
|
@@ -3163,7 +3256,7 @@ var Database = class {
|
|
3163
3256
|
await this.ready();
|
3164
3257
|
this.logger.Debug().Str("id", doc._id).Msg("put");
|
3165
3258
|
const { _id, ...value } = doc;
|
3166
|
-
const docId = _id || this.sthis.
|
3259
|
+
const docId = _id || this.sthis.timeOrderedNextId().str;
|
3167
3260
|
const result = await this._writeQueue.push({
|
3168
3261
|
id: docId,
|
3169
3262
|
value: {
|
@@ -3304,6 +3397,7 @@ __export(runtime_exports, {
|
|
3304
3397
|
kb: () => key_bag_exports,
|
3305
3398
|
kc: () => keyed_crypto_exports,
|
3306
3399
|
mf: () => wait_pr_multiformats_exports,
|
3400
|
+
runtimeFn: () => runtimeFn2,
|
3307
3401
|
toArrayBuffer: () => toArrayBuffer
|
3308
3402
|
});
|
3309
3403
|
|
@@ -3317,9 +3411,12 @@ __export(wait_pr_multiformats_exports, {
|
|
3317
3411
|
// src/runtime/wait-pr-multiformats/codec-interface.ts
|
3318
3412
|
var codec_interface_exports = {};
|
3319
3413
|
|
3414
|
+
// src/runtime/index.ts
|
3415
|
+
import { runtimeFn as runtimeFn2 } from "@adviser/cement";
|
3416
|
+
|
3320
3417
|
// src/version.ts
|
3321
3418
|
var PACKAGE_VERSION = Object.keys({
|
3322
|
-
"0.19.
|
3419
|
+
"0.19.11-dev-dryrun2": "xxxx"
|
3323
3420
|
})[0];
|
3324
3421
|
export {
|
3325
3422
|
CRDT,
|
@@ -3335,7 +3432,6 @@ export {
|
|
3335
3432
|
ensureLogger,
|
3336
3433
|
ensureSuperLog,
|
3337
3434
|
ensureSuperThis,
|
3338
|
-
exception2Result,
|
3339
3435
|
exceptionWrapper,
|
3340
3436
|
falsyToUndef,
|
3341
3437
|
fireproof,
|