@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.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,
|