@fireproof/core 0.20.0-dev-preview-40 → 0.20.0-dev-preview-50
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 +6 -4
- package/deno/index.js +2 -2
- package/deno/index.js.map +1 -1
- package/deno.json +3 -2
- package/index.cjs +955 -599
- package/index.cjs.map +1 -1
- package/index.d.cts +334 -127
- package/index.d.ts +334 -127
- package/index.js +939 -582
- package/index.js.map +1 -1
- package/indexeddb/index.cjs.map +1 -1
- package/indexeddb/index.js.map +1 -1
- package/indexeddb/metafile-cjs.json +1 -1
- package/indexeddb/metafile-esm.json +1 -1
- package/metafile-cjs.json +1 -1
- package/metafile-esm.json +1 -1
- package/package.json +7 -5
- package/react/index.cjs +17 -9
- package/react/index.cjs.map +1 -1
- package/react/index.d.cts +5 -4
- package/react/index.d.ts +5 -4
- package/react/index.js +17 -9
- package/react/index.js.map +1 -1
- package/react/metafile-cjs.json +1 -1
- package/react/metafile-esm.json +1 -1
- package/tests/blockstore/interceptor-gateway.test.ts +15 -1
- package/tests/blockstore/keyed-crypto-indexeddb-file.test.ts +8 -18
- package/tests/blockstore/keyed-crypto.test.ts +31 -53
- package/tests/blockstore/loader.test.ts +21 -19
- package/tests/blockstore/store.test.ts +52 -56
- package/tests/blockstore/transaction.test.ts +13 -11
- package/tests/fireproof/all-gateway.test.ts +53 -50
- package/tests/fireproof/attachable.test.ts +356 -0
- package/tests/fireproof/crdt.test.ts +100 -60
- package/tests/fireproof/database.test.ts +95 -54
- package/tests/fireproof/fireproof.test.ts +58 -55
- package/tests/fireproof/hello.test.ts +4 -4
- package/tests/fireproof/indexer.test.ts +44 -44
- package/tests/fireproof/stable-cid.test.ts +69 -0
- package/tests/fireproof/utils.test.ts +21 -10
- package/tests/gateway/file/loader-config.test.ts +25 -25
- package/tests/gateway/fp-envelope-serialize.test.ts +8 -8
- package/tests/gateway/indexeddb/loader-config.test.ts +6 -6
- package/tests/helpers.ts +81 -2
- package/tests/react/useFireproof.test.tsx +59 -17
package/index.js
CHANGED
@@ -5,7 +5,7 @@ var __export = (target, all) => {
|
|
5
5
|
};
|
6
6
|
|
7
7
|
// src/ledger.ts
|
8
|
-
import { BuildURI as BuildURI2, KeyedResolvOnce as
|
8
|
+
import { BuildURI as BuildURI2, KeyedResolvOnce as KeyedResolvOnce6, ResolveOnce as ResolveOnce7, URI as URI13 } from "@adviser/cement";
|
9
9
|
|
10
10
|
// src/utils.ts
|
11
11
|
import {
|
@@ -14,6 +14,7 @@ import {
|
|
14
14
|
Result,
|
15
15
|
ResolveOnce,
|
16
16
|
isURL,
|
17
|
+
URI,
|
17
18
|
envFactory,
|
18
19
|
toCryptoRuntime,
|
19
20
|
JSONFormatter,
|
@@ -44,8 +45,13 @@ var PARAM = {
|
|
44
45
|
FRAG_LEN: "len",
|
45
46
|
FRAG_HEAD: "headerSize",
|
46
47
|
EXTRACTKEY: "extractKey",
|
47
|
-
SELF_REFLECT: "selfReflect"
|
48
|
+
SELF_REFLECT: "selfReflect",
|
48
49
|
// if no subscribe in Gateway see your own META updates
|
50
|
+
CAR_PARALLEL: "parallel",
|
51
|
+
CAR_CACHE_SIZE: "carCacheSize",
|
52
|
+
CAR_COMPACT_CACHE_SIZE: "carCompactCacheSize",
|
53
|
+
CAR_META_CACHE_SIZE: "carMetaCacheSize",
|
54
|
+
GENESIS_CID: "baembeiarootfireproofgenesisblockaaaafireproofgenesisblocka"
|
49
55
|
// FS = "fs",
|
50
56
|
};
|
51
57
|
function throwFalsy(value) {
|
@@ -60,6 +66,18 @@ function falsyToUndef(value) {
|
|
60
66
|
}
|
61
67
|
return value;
|
62
68
|
}
|
69
|
+
var DataAndMetaAndWalAndBaseStore = class {
|
70
|
+
constructor(dam) {
|
71
|
+
this.wal = dam.wal;
|
72
|
+
this.file = dam.file;
|
73
|
+
this.car = dam.car;
|
74
|
+
this.meta = dam.meta;
|
75
|
+
this.baseStores = [this.file, this.car, this.meta];
|
76
|
+
if (this.wal) {
|
77
|
+
this.baseStores.push(this.wal);
|
78
|
+
}
|
79
|
+
}
|
80
|
+
};
|
63
81
|
|
64
82
|
// src/utils.ts
|
65
83
|
import { base58btc } from "multiformats/bases/base58";
|
@@ -270,21 +288,25 @@ function ensureLogger(sthis, componentName, ctx) {
|
|
270
288
|
return out;
|
271
289
|
}
|
272
290
|
function getStore(url, sthis, joiner) {
|
273
|
-
const
|
274
|
-
|
275
|
-
|
291
|
+
const fromUrl = url.getParam(PARAM.STORE);
|
292
|
+
let pathPart;
|
293
|
+
switch (fromUrl) {
|
294
|
+
case "car":
|
295
|
+
case "file":
|
296
|
+
pathPart = "data";
|
297
|
+
break;
|
276
298
|
case "wal":
|
277
299
|
case "meta":
|
300
|
+
pathPart = fromUrl;
|
278
301
|
break;
|
279
302
|
default:
|
280
303
|
throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
|
281
|
-
throw sthis.logger.Error().Url(url).Msg(`store not found`).AsError();
|
282
304
|
}
|
283
|
-
let name =
|
305
|
+
let name = pathPart;
|
284
306
|
if (url.hasParam("index")) {
|
285
307
|
name = joiner(url.getParam(PARAM.INDEX) || "idx", name);
|
286
308
|
}
|
287
|
-
return {
|
309
|
+
return { pathPart, fromUrl, name };
|
288
310
|
}
|
289
311
|
function getKey(url, logger) {
|
290
312
|
const result = url.getParam(PARAM.KEY);
|
@@ -386,6 +408,35 @@ function makeName(fnString) {
|
|
386
408
|
return found[1];
|
387
409
|
}
|
388
410
|
}
|
411
|
+
function storeType2DataMetaWal(store) {
|
412
|
+
switch (store) {
|
413
|
+
case "car":
|
414
|
+
case "file":
|
415
|
+
return "data";
|
416
|
+
case "meta":
|
417
|
+
case "wal":
|
418
|
+
return store;
|
419
|
+
default:
|
420
|
+
throw new Error(`unknown store ${store}`);
|
421
|
+
}
|
422
|
+
}
|
423
|
+
function ensureURIDefaults(sthis, name, curi, uri, store, ctx) {
|
424
|
+
ctx = ctx || {};
|
425
|
+
const ret = (curi ? URI.from(curi) : uri).build().setParam(PARAM.STORE, store).defParam(PARAM.NAME, name);
|
426
|
+
if (!ret.hasParam(PARAM.NAME)) {
|
427
|
+
throw sthis.logger.Error().Url(ret).Any("ctx", ctx).Msg("Ledger name is required").AsError();
|
428
|
+
}
|
429
|
+
if (ctx.idx) {
|
430
|
+
ret.defParam(PARAM.INDEX, "idx");
|
431
|
+
ret.defParam(PARAM.STORE_KEY, `@${ret.getParam(PARAM.NAME)}-${storeType2DataMetaWal(store)}-idx@`);
|
432
|
+
} else {
|
433
|
+
ret.defParam(PARAM.STORE_KEY, `@${ret.getParam(PARAM.NAME)}-${storeType2DataMetaWal(store)}@`);
|
434
|
+
}
|
435
|
+
if (store === "car") {
|
436
|
+
ret.defParam(PARAM.SUFFIX, ".car");
|
437
|
+
}
|
438
|
+
return ret.URI();
|
439
|
+
}
|
389
440
|
|
390
441
|
// src/write-queue.ts
|
391
442
|
import { Future } from "@adviser/cement";
|
@@ -1075,8 +1126,10 @@ function getFileName(url, sthis) {
|
|
1075
1126
|
const key = url.getParam("key");
|
1076
1127
|
if (!key) throw sthis.logger.Error().Url(url).Msg(`key not found`).AsError();
|
1077
1128
|
const res = getStore2(url, sthis, (...a) => a.join("-"));
|
1078
|
-
switch (res.
|
1079
|
-
case "
|
1129
|
+
switch (res.fromUrl) {
|
1130
|
+
case "file":
|
1131
|
+
return sthis.pathOps.join(res.name, key);
|
1132
|
+
case "car":
|
1080
1133
|
return sthis.pathOps.join(res.name, key + ".car");
|
1081
1134
|
case "wal":
|
1082
1135
|
case "meta":
|
@@ -1224,8 +1277,13 @@ var MemoryGateway = class {
|
|
1224
1277
|
close(baseUrl) {
|
1225
1278
|
return Promise.resolve(Result4.Ok(void 0));
|
1226
1279
|
}
|
1227
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
1228
1280
|
destroy(baseUrl) {
|
1281
|
+
const keyUrl = baseUrl.toString();
|
1282
|
+
for (const key of this.memorys.keys()) {
|
1283
|
+
if (key.startsWith(keyUrl)) {
|
1284
|
+
this.memorys.delete(key);
|
1285
|
+
}
|
1286
|
+
}
|
1229
1287
|
this.memorys.clear();
|
1230
1288
|
return Promise.resolve(Result4.Ok(void 0));
|
1231
1289
|
}
|
@@ -1237,7 +1295,7 @@ var MemoryGateway = class {
|
|
1237
1295
|
get(url) {
|
1238
1296
|
const x = this.memorys.get(url.toString());
|
1239
1297
|
if (!x) {
|
1240
|
-
return Promise.resolve(Result4.Err(new NotFoundError(
|
1298
|
+
return Promise.resolve(Result4.Err(new NotFoundError(`not found: ${url.toString()}`)));
|
1241
1299
|
}
|
1242
1300
|
return Promise.resolve(Result4.Ok(x));
|
1243
1301
|
}
|
@@ -1343,9 +1401,6 @@ async function decode2DbMetaEvents(sthis, rserializedMeta) {
|
|
1343
1401
|
if (!Array.isArray(serializedMeta)) {
|
1344
1402
|
return sthis.logger.Debug().Any("metaEntries", serializedMeta).Msg("No data in MetaEntries").ResultError();
|
1345
1403
|
}
|
1346
|
-
if (!serializedMeta.length) {
|
1347
|
-
return sthis.logger.Debug().Msg("No MetaEntries found").ResultError();
|
1348
|
-
}
|
1349
1404
|
return Result6.Ok(
|
1350
1405
|
await Promise.all(
|
1351
1406
|
serializedMeta.map(async (metaEntry) => {
|
@@ -1410,10 +1465,9 @@ async function fpDeserialize(sthis, url, intoRaw, pdecoder) {
|
|
1410
1465
|
...pdecoder
|
1411
1466
|
};
|
1412
1467
|
switch (url.getParam(PARAM.STORE)) {
|
1413
|
-
case "
|
1414
|
-
|
1415
|
-
|
1416
|
-
}
|
1468
|
+
case "car":
|
1469
|
+
return makeFPEnvelope(FPEnvelopeTypes.CAR, await decoder.car(sthis, raw2));
|
1470
|
+
case "file":
|
1417
1471
|
return makeFPEnvelope(FPEnvelopeTypes.FILE, await decoder.file(sthis, raw2));
|
1418
1472
|
case "wal":
|
1419
1473
|
return makeFPEnvelope(FPEnvelopeTypes.WAL, await decode2WalState(sthis, await decoder.wal(sthis, raw2)));
|
@@ -1475,7 +1529,7 @@ var DefSerdeGateway = class {
|
|
1475
1529
|
const urlWithoutKey = url.build().delParam(PARAM.KEY).delParam(PARAM.SELF_REFLECT).toString();
|
1476
1530
|
this.subscribeFn.set(urlWithoutKey, rawCallback);
|
1477
1531
|
return Result7.Ok(() => {
|
1478
|
-
this.subscribeFn.delete(
|
1532
|
+
this.subscribeFn.delete(urlWithoutKey);
|
1479
1533
|
});
|
1480
1534
|
}
|
1481
1535
|
const unreg = await this.gw.subscribe(url, rawCallback, sthis);
|
@@ -1604,37 +1658,49 @@ var Block = mfBlock;
|
|
1604
1658
|
async function decode({
|
1605
1659
|
bytes,
|
1606
1660
|
codec: codec3,
|
1607
|
-
hasher:
|
1661
|
+
hasher: hasher6
|
1608
1662
|
}) {
|
1609
1663
|
if (bytes == null) throw new Error('Missing required argument "bytes"');
|
1610
|
-
if (codec3 == null ||
|
1664
|
+
if (codec3 == null || hasher6 == null) throw new Error("Missing required argument: codec or hasher");
|
1611
1665
|
const value = await Promise.resolve(codec3.decode(bytes));
|
1612
|
-
|
1666
|
+
let toHash = bytes;
|
1667
|
+
if (codec3.valueToHashBytes) {
|
1668
|
+
toHash = await Promise.resolve(codec3.valueToHashBytes(value));
|
1669
|
+
}
|
1670
|
+
const hash = await hasher6.digest(toHash);
|
1613
1671
|
const cid = CID2.create(1, codec3.code, hash);
|
1614
|
-
return new mfBlock({ value, bytes, cid });
|
1672
|
+
return new mfBlock({ value, bytes: toHash, cid });
|
1615
1673
|
}
|
1616
1674
|
async function encode({
|
1617
1675
|
value,
|
1618
1676
|
codec: codec3,
|
1619
|
-
hasher:
|
1677
|
+
hasher: hasher6
|
1620
1678
|
}) {
|
1621
1679
|
if (typeof value === "undefined") throw new Error('Missing required argument "value"');
|
1622
|
-
if (codec3 == null ||
|
1623
|
-
|
1624
|
-
|
1680
|
+
if (codec3 == null || hasher6 == null) throw new Error("Missing required argument: codec or hasher");
|
1681
|
+
let bytes;
|
1682
|
+
let hash;
|
1683
|
+
if (codec3.bytesToHash) {
|
1684
|
+
const hashable = await Promise.resolve(codec3.bytesToHash(value));
|
1685
|
+
hash = await hasher6.digest(hashable);
|
1686
|
+
bytes = await Promise.resolve(codec3.encode(value));
|
1687
|
+
} else {
|
1688
|
+
bytes = await Promise.resolve(codec3.encode(value));
|
1689
|
+
hash = await hasher6.digest(bytes);
|
1690
|
+
}
|
1625
1691
|
const cid = CID2.create(1, codec3.code, hash);
|
1626
|
-
return new
|
1692
|
+
return new Block({ value, bytes, cid });
|
1627
1693
|
}
|
1628
1694
|
async function create({
|
1629
1695
|
bytes,
|
1630
1696
|
cid,
|
1631
|
-
hasher:
|
1697
|
+
hasher: hasher6,
|
1632
1698
|
codec: codec3
|
1633
1699
|
}) {
|
1634
1700
|
if (bytes == null) throw new Error('Missing required argument "bytes"');
|
1635
|
-
if (
|
1701
|
+
if (hasher6 == null) throw new Error('Missing required argument "hasher"');
|
1636
1702
|
const value = await Promise.resolve(codec3.decode(bytes));
|
1637
|
-
const hash = await
|
1703
|
+
const hash = await hasher6.digest(bytes);
|
1638
1704
|
if (!binary.equals(cid.multihash.bytes, hash.bytes)) {
|
1639
1705
|
throw new Error("CID hash does not match bytes");
|
1640
1706
|
}
|
@@ -2032,6 +2098,9 @@ var DatabaseImpl = class {
|
|
2032
2098
|
this.id = ledger.id;
|
2033
2099
|
this.logger = ensureLogger(this.sthis, "Database");
|
2034
2100
|
}
|
2101
|
+
attach(a) {
|
2102
|
+
return this.ledger.attach(a);
|
2103
|
+
}
|
2035
2104
|
get name() {
|
2036
2105
|
return this.ledger.name;
|
2037
2106
|
}
|
@@ -2127,19 +2196,27 @@ import { ResolveOnce as ResolveOnce6 } from "@adviser/cement";
|
|
2127
2196
|
// src/blockstore/index.ts
|
2128
2197
|
var blockstore_exports = {};
|
2129
2198
|
__export(blockstore_exports, {
|
2199
|
+
AttachedRemotesImpl: () => AttachedRemotesImpl,
|
2200
|
+
BaseActiveStore: () => BaseActiveStore,
|
2130
2201
|
BaseBlockstoreImpl: () => BaseBlockstoreImpl,
|
2131
2202
|
Car2FPMsg: () => Car2FPMsg,
|
2203
|
+
CarActiveStore: () => CarActiveStore,
|
2204
|
+
CarLog: () => CarLog,
|
2132
2205
|
CarTransactionImpl: () => CarTransactionImpl,
|
2133
2206
|
CompactionFetcher: () => CompactionFetcher,
|
2134
|
-
ConnectionBase: () => ConnectionBase,
|
2135
2207
|
DbMetaEventEqual: () => DbMetaEventEqual,
|
2136
2208
|
DbMetaEventsEqual: () => DbMetaEventsEqual,
|
2137
2209
|
EncryptedBlockstore: () => EncryptedBlockstore,
|
2138
2210
|
FPEnvelopeTypes: () => FPEnvelopeTypes,
|
2139
2211
|
File2FPMsg: () => File2FPMsg,
|
2212
|
+
FileActiveStore: () => FileActiveStore,
|
2140
2213
|
InterceptorGateway: () => InterceptorGateway,
|
2141
2214
|
Loader: () => Loader,
|
2215
|
+
MetaActiveStore: () => MetaActiveStore,
|
2142
2216
|
PassThroughGateway: () => PassThroughGateway,
|
2217
|
+
TaskManager: () => TaskManager,
|
2218
|
+
WALActiveStore: () => WALActiveStore,
|
2219
|
+
createAttachedStores: () => createAttachedStores,
|
2143
2220
|
createDbMetaEvent: () => createDbMetaEvent,
|
2144
2221
|
defaultGatewayFactoryItem: () => defaultGatewayFactoryItem,
|
2145
2222
|
ensureStoreEnDeFile: () => ensureStoreEnDeFile,
|
@@ -2153,6 +2230,37 @@ __export(blockstore_exports, {
|
|
2153
2230
|
});
|
2154
2231
|
|
2155
2232
|
// src/blockstore/types.ts
|
2233
|
+
var CarLog = class {
|
2234
|
+
constructor() {
|
2235
|
+
this._logs = [];
|
2236
|
+
}
|
2237
|
+
get length() {
|
2238
|
+
return this._logs.length;
|
2239
|
+
}
|
2240
|
+
last() {
|
2241
|
+
const x = [...this._logs[this._logs.length - 1]];
|
2242
|
+
Object.freeze(x);
|
2243
|
+
return x;
|
2244
|
+
}
|
2245
|
+
xunshift(logs) {
|
2246
|
+
this._logs.unshift(logs);
|
2247
|
+
}
|
2248
|
+
update(logs) {
|
2249
|
+
this._logs.length = 0;
|
2250
|
+
this._logs.push(...logs);
|
2251
|
+
}
|
2252
|
+
asArray() {
|
2253
|
+
const a = [
|
2254
|
+
...this._logs.map((l) => {
|
2255
|
+
const x = [...l];
|
2256
|
+
Object.freeze(x);
|
2257
|
+
return x;
|
2258
|
+
})
|
2259
|
+
];
|
2260
|
+
Object.freeze(a);
|
2261
|
+
return a;
|
2262
|
+
}
|
2263
|
+
};
|
2156
2264
|
function toCIDBlock(block) {
|
2157
2265
|
return block;
|
2158
2266
|
}
|
@@ -2162,9 +2270,19 @@ function DbMetaEventEqual(a, b) {
|
|
2162
2270
|
function DbMetaEventsEqual(a, b) {
|
2163
2271
|
return a.length === b.length && a.every((e, i) => DbMetaEventEqual(e, b[i]));
|
2164
2272
|
}
|
2273
|
+
var BaseActiveStore = class {
|
2274
|
+
};
|
2275
|
+
var CarActiveStore = class extends BaseActiveStore {
|
2276
|
+
};
|
2277
|
+
var FileActiveStore = class extends BaseActiveStore {
|
2278
|
+
};
|
2279
|
+
var MetaActiveStore = class extends BaseActiveStore {
|
2280
|
+
};
|
2281
|
+
var WALActiveStore = class extends BaseActiveStore {
|
2282
|
+
};
|
2165
2283
|
|
2166
2284
|
// src/blockstore/store-factory.ts
|
2167
|
-
import { KeyedResolvOnce as
|
2285
|
+
import { KeyedResolvOnce as KeyedResolvOnce5, Result as Result10 } from "@adviser/cement";
|
2168
2286
|
|
2169
2287
|
// src/blockstore/store.ts
|
2170
2288
|
import { exception2Result as exception2Result3, ResolveOnce as ResolveOnce4, Result as Result9 } from "@adviser/cement";
|
@@ -2172,14 +2290,14 @@ import { exception2Result as exception2Result3, ResolveOnce as ResolveOnce4, Res
|
|
2172
2290
|
// src/blockstore/loader.ts
|
2173
2291
|
import pLimit from "p-limit";
|
2174
2292
|
import { CarReader } from "@ipld/car/reader";
|
2175
|
-
import { ResolveOnce as ResolveOnce3 } from "@adviser/cement";
|
2293
|
+
import { KeyedResolvOnce as KeyedResolvOnce4, LRUSet, ResolveOnce as ResolveOnce3 } from "@adviser/cement";
|
2176
2294
|
|
2177
2295
|
// src/blockstore/loader-helpers.ts
|
2178
2296
|
import { sha256 as hasher2 } from "multiformats/hashes/sha2";
|
2179
2297
|
import * as dagCodec from "@ipld/dag-cbor";
|
2180
2298
|
async function parseCarFile(reader, logger) {
|
2181
|
-
const roots = await reader.
|
2182
|
-
const header =
|
2299
|
+
const roots = await reader.roots;
|
2300
|
+
const header = reader.blocks.find((i) => i.cid.equals(roots[0]));
|
2183
2301
|
if (!header) throw logger.Error().Msg("missing header block").AsError();
|
2184
2302
|
const dec = await decode({ bytes: header.bytes, hasher: hasher2, codec: dagCodec });
|
2185
2303
|
const fpvalue = dec.value;
|
@@ -2194,6 +2312,7 @@ import { MemoryBlockstore } from "@fireproof/vendor/@web3-storage/pail/block";
|
|
2194
2312
|
import { toCryptoRuntime as toCryptoRuntime3 } from "@adviser/cement";
|
2195
2313
|
var CarTransactionImpl = class {
|
2196
2314
|
#memblock = new MemoryBlockstore();
|
2315
|
+
#hackUnshift;
|
2197
2316
|
constructor(parent, opts = { add: true, noLoader: false }) {
|
2198
2317
|
if (opts.add) {
|
2199
2318
|
parent.transactions.add(this);
|
@@ -2201,7 +2320,7 @@ var CarTransactionImpl = class {
|
|
2201
2320
|
this.parent = parent;
|
2202
2321
|
}
|
2203
2322
|
async get(cid) {
|
2204
|
-
return await this.superGet(cid)
|
2323
|
+
return await this.superGet(cid) ?? falsyToUndef(await this.parent.get(cid));
|
2205
2324
|
}
|
2206
2325
|
async superGet(cid) {
|
2207
2326
|
return this.#memblock.get(cid);
|
@@ -2212,7 +2331,16 @@ var CarTransactionImpl = class {
|
|
2212
2331
|
putSync(cid, bytes) {
|
2213
2332
|
this.#memblock.putSync(cid, bytes);
|
2214
2333
|
}
|
2334
|
+
unshift(cid, bytes) {
|
2335
|
+
if (this.#hackUnshift) {
|
2336
|
+
throw new Error("unshift already called");
|
2337
|
+
}
|
2338
|
+
this.#hackUnshift = { cid, bytes };
|
2339
|
+
}
|
2215
2340
|
async *entries() {
|
2341
|
+
if (this.#hackUnshift) {
|
2342
|
+
yield this.#hackUnshift;
|
2343
|
+
}
|
2216
2344
|
for await (const blk of this.#memblock.entries()) {
|
2217
2345
|
yield blk;
|
2218
2346
|
}
|
@@ -2238,6 +2366,11 @@ function defaultedBlockstoreRuntime(sthis, opts, component, ctx) {
|
|
2238
2366
|
keyBag: opts.keyBag || {},
|
2239
2367
|
crypto: toCryptoRuntime3(opts.crypto),
|
2240
2368
|
storeUrls: opts.storeUrls,
|
2369
|
+
taskManager: {
|
2370
|
+
removeAfter: 3,
|
2371
|
+
retryTimeout: 50,
|
2372
|
+
...opts.taskManager
|
2373
|
+
},
|
2241
2374
|
// storeEnDeFile: ensureStoreEnDeFile(opts.storeEnDeFile),
|
2242
2375
|
// store,
|
2243
2376
|
storeRuntime: toStoreRuntime(sthis, ensureStoreEnDeFile(opts.storeEnDeFile))
|
@@ -2330,10 +2463,8 @@ var EncryptedBlockstore = class extends BaseBlockstoreImpl {
|
|
2330
2463
|
async get(cid) {
|
2331
2464
|
const got = await super.get(cid);
|
2332
2465
|
if (got) return got;
|
2333
|
-
|
2334
|
-
|
2335
|
-
}
|
2336
|
-
return falsyToUndef(await this.loader.getBlock(cid));
|
2466
|
+
const ret = falsyToUndef(await this.loader.getBlock(cid, this.loader.attachedStores.local()));
|
2467
|
+
return ret;
|
2337
2468
|
}
|
2338
2469
|
async transaction(fn, opts = { noLoader: false }) {
|
2339
2470
|
this.logger.Debug().Msg("enter transaction");
|
@@ -2353,11 +2484,8 @@ var EncryptedBlockstore = class extends BaseBlockstoreImpl {
|
|
2353
2484
|
async getFile(car, cid) {
|
2354
2485
|
await this.ready();
|
2355
2486
|
if (!this.loader) throw this.logger.Error().Msg("loader required to get file, ledger must be named").AsError();
|
2356
|
-
const reader = await this.loader.loadFileCar(
|
2357
|
-
|
2358
|
-
/*, isPublic */
|
2359
|
-
);
|
2360
|
-
const block = await reader.get(cid);
|
2487
|
+
const reader = await this.loader.loadFileCar(car, this.loader.attachedStores.local());
|
2488
|
+
const block = await reader.blocks.find((i) => i.cid.equals(cid));
|
2361
2489
|
if (!block) throw this.logger.Error().Str("cid", cid.toString()).Msg(`Missing block`).AsError();
|
2362
2490
|
return block.bytes;
|
2363
2491
|
}
|
@@ -2464,8 +2592,8 @@ var CommitQueue = class {
|
|
2464
2592
|
|
2465
2593
|
// src/blockstore/commitor.ts
|
2466
2594
|
import * as CBW from "@ipld/car/buffer-writer";
|
2467
|
-
import { sha256 as hasher3 } from "multiformats/hashes/sha2";
|
2468
2595
|
import * as dagCodec2 from "@ipld/dag-cbor";
|
2596
|
+
import { sha256 } from "multiformats/hashes/sha2";
|
2469
2597
|
async function encodeCarFile(roots, t, codec3) {
|
2470
2598
|
let size = 0;
|
2471
2599
|
const headerSize = CBW.headerLength({ roots });
|
@@ -2482,7 +2610,7 @@ async function encodeCarFile(roots, t, codec3) {
|
|
2482
2610
|
writer.write({ cid, bytes });
|
2483
2611
|
}
|
2484
2612
|
writer.close();
|
2485
|
-
return await encode({ value: writer.bytes, hasher:
|
2613
|
+
return await encode({ value: writer.bytes, hasher: sha256, codec: codec3 });
|
2486
2614
|
}
|
2487
2615
|
async function createCarFile(encoder, cid, t) {
|
2488
2616
|
return encodeCarFile([cid], t, encoder);
|
@@ -2490,7 +2618,7 @@ async function createCarFile(encoder, cid, t) {
|
|
2490
2618
|
async function commitFiles(fileStore, walStore, t, done) {
|
2491
2619
|
const { files: roots } = makeFileCarHeader(done);
|
2492
2620
|
const cids = [];
|
2493
|
-
const codec3 =
|
2621
|
+
const codec3 = await fileStore.keyedCrypto().then((i) => i.codec());
|
2494
2622
|
const cars = await prepareCarFilesFiles(codec3, roots, t);
|
2495
2623
|
for (const car of cars) {
|
2496
2624
|
const { cid, bytes } = car;
|
@@ -2516,13 +2644,13 @@ async function prepareCarFilesFiles(encoder, roots, t) {
|
|
2516
2644
|
return [await encodeCarFile(roots, t, encoder)];
|
2517
2645
|
}
|
2518
2646
|
function makeCarHeader(meta, cars, compact = false) {
|
2519
|
-
const coreHeader = compact ? { cars: [], compact: cars } : { cars, compact: [] };
|
2647
|
+
const coreHeader = compact ? { cars: [], compact: cars.asArray() } : { cars: cars.asArray(), compact: [] };
|
2520
2648
|
return { ...coreHeader, meta };
|
2521
2649
|
}
|
2522
2650
|
async function encodeCarHeader(fp) {
|
2523
2651
|
return await encode({
|
2524
2652
|
value: { fp },
|
2525
|
-
hasher:
|
2653
|
+
hasher: sha256,
|
2526
2654
|
codec: dagCodec2
|
2527
2655
|
});
|
2528
2656
|
}
|
@@ -2543,7 +2671,7 @@ async function commit(params, t, done, opts = { noLoader: false, compact: false
|
|
2543
2671
|
}
|
2544
2672
|
async function prepareCarFiles(encoder, threshold, rootBlock, t) {
|
2545
2673
|
const carFiles = [];
|
2546
|
-
threshold = threshold ||
|
2674
|
+
threshold = threshold || 16 * 65536;
|
2547
2675
|
let clonedt = new CarTransactionImpl(t.parent, { add: false, noLoader: false });
|
2548
2676
|
clonedt.putSync(rootBlock.cid, rootBlock.bytes);
|
2549
2677
|
let newsize = CBW.blockLength(toCIDBlock(rootBlock));
|
@@ -2565,23 +2693,24 @@ async function prepareCarFiles(encoder, threshold, rootBlock, t) {
|
|
2565
2693
|
}
|
2566
2694
|
|
2567
2695
|
// src/blockstore/loader.ts
|
2568
|
-
import { sha256 as
|
2696
|
+
import { sha256 as hasher3 } from "multiformats/hashes/sha2";
|
2569
2697
|
|
2570
2698
|
// src/blockstore/task-manager.ts
|
2571
2699
|
var TaskManager = class {
|
2572
|
-
constructor(sthis, callback) {
|
2700
|
+
constructor(sthis, callback, params) {
|
2573
2701
|
// we need to remove the events after some time
|
2574
2702
|
this.eventsWeHandled = /* @__PURE__ */ new Set();
|
2575
2703
|
this.queue = [];
|
2576
2704
|
this.isProcessing = false;
|
2577
2705
|
this.logger = ensureLogger(sthis, "TaskManager");
|
2578
2706
|
this.callback = callback;
|
2707
|
+
this.params = params;
|
2579
2708
|
}
|
2580
|
-
async handleEvent(cid, parents, dbMeta) {
|
2709
|
+
async handleEvent(cid, parents, dbMeta, store) {
|
2581
2710
|
for (const parent of parents) {
|
2582
2711
|
this.eventsWeHandled.add(parent.toString());
|
2583
2712
|
}
|
2584
|
-
this.queue.push({ cid: cid.toString(), dbMeta, retries: 0 });
|
2713
|
+
this.queue.push({ cid: cid.toString(), dbMeta, retries: 0, store });
|
2585
2714
|
this.queue = this.queue.filter(({ cid: cid2 }) => !this.eventsWeHandled.has(cid2));
|
2586
2715
|
void this.processQueue();
|
2587
2716
|
}
|
@@ -2595,7 +2724,7 @@ var TaskManager = class {
|
|
2595
2724
|
return;
|
2596
2725
|
}
|
2597
2726
|
try {
|
2598
|
-
await this.callback(first.dbMeta);
|
2727
|
+
await this.callback(first.dbMeta, first.store);
|
2599
2728
|
this.eventsWeHandled.add(first.cid);
|
2600
2729
|
this.queue = this.queue.filter(({ cid }) => !this.eventsWeHandled.has(cid));
|
2601
2730
|
} catch (err) {
|
@@ -2604,7 +2733,7 @@ var TaskManager = class {
|
|
2604
2733
|
this.queue = this.queue.filter(({ cid }) => cid !== first.cid);
|
2605
2734
|
}
|
2606
2735
|
await new Promise((resolve) => setTimeout(resolve, 50));
|
2607
|
-
|
2736
|
+
this.logger.Warn().Err(err).Msg("retry to process event block");
|
2608
2737
|
} finally {
|
2609
2738
|
this.isProcessing = false;
|
2610
2739
|
if (this.queue.length > 0) {
|
@@ -2614,13 +2743,299 @@ var TaskManager = class {
|
|
2614
2743
|
}
|
2615
2744
|
};
|
2616
2745
|
|
2746
|
+
// src/blockstore/attachable-store.ts
|
2747
|
+
import { KeyedResolvOnce as KeyedResolvOnce3, isCoerceURI, URI as URI9 } from "@adviser/cement";
|
2748
|
+
var AttachedImpl = class {
|
2749
|
+
constructor(gws, stores, unreg) {
|
2750
|
+
this.gatewayUrls = gws;
|
2751
|
+
this.stores = new DataAndMetaAndWalAndBaseStore(stores);
|
2752
|
+
this.unreg = unreg;
|
2753
|
+
}
|
2754
|
+
async detach() {
|
2755
|
+
const toClose = [this.stores.car.close(), this.stores.file.close(), this.stores.meta.close()];
|
2756
|
+
if (this.stores.wal) {
|
2757
|
+
toClose.push(this.stores.wal.close());
|
2758
|
+
}
|
2759
|
+
await Promise.all(toClose);
|
2760
|
+
this.unreg();
|
2761
|
+
}
|
2762
|
+
status() {
|
2763
|
+
return "attached";
|
2764
|
+
}
|
2765
|
+
};
|
2766
|
+
var FileActiveStoreImpl = class extends FileActiveStore {
|
2767
|
+
constructor(ref, active, attached) {
|
2768
|
+
super();
|
2769
|
+
this.ref = ref;
|
2770
|
+
this.active = active;
|
2771
|
+
this.xattached = attached;
|
2772
|
+
}
|
2773
|
+
local() {
|
2774
|
+
return this.xattached.local();
|
2775
|
+
}
|
2776
|
+
remotes() {
|
2777
|
+
return this.xattached.remotes();
|
2778
|
+
}
|
2779
|
+
};
|
2780
|
+
var CarActiveStoreImpl = class extends CarActiveStore {
|
2781
|
+
constructor(ref, active, attached) {
|
2782
|
+
super();
|
2783
|
+
this.ref = ref;
|
2784
|
+
this.active = active;
|
2785
|
+
this.xattached = attached;
|
2786
|
+
}
|
2787
|
+
local() {
|
2788
|
+
return this.xattached.local();
|
2789
|
+
}
|
2790
|
+
remotes() {
|
2791
|
+
return [this.active, ...this.xattached.remotes().filter((i) => i !== this.active)];
|
2792
|
+
}
|
2793
|
+
};
|
2794
|
+
var CarAttachedStoresImpl = class {
|
2795
|
+
constructor(attached) {
|
2796
|
+
this.attached = attached;
|
2797
|
+
}
|
2798
|
+
local() {
|
2799
|
+
return this.attached.local().active.car;
|
2800
|
+
}
|
2801
|
+
remotes() {
|
2802
|
+
return this.attached.remotes().map(({ active }) => active.car);
|
2803
|
+
}
|
2804
|
+
};
|
2805
|
+
var FileAttachedStoresImpl = class {
|
2806
|
+
constructor(attached) {
|
2807
|
+
this.attached = attached;
|
2808
|
+
}
|
2809
|
+
local() {
|
2810
|
+
return this.attached.local().active.file;
|
2811
|
+
}
|
2812
|
+
remotes() {
|
2813
|
+
return this.attached.remotes().map(({ active }) => active.file);
|
2814
|
+
}
|
2815
|
+
};
|
2816
|
+
var MetaActiveStoreImpl = class extends MetaActiveStore {
|
2817
|
+
constructor(ref, active, attached) {
|
2818
|
+
super();
|
2819
|
+
this.ref = ref;
|
2820
|
+
this.active = active;
|
2821
|
+
this.xattached = attached;
|
2822
|
+
}
|
2823
|
+
local() {
|
2824
|
+
return this.xattached.local();
|
2825
|
+
}
|
2826
|
+
remotes() {
|
2827
|
+
return [this.active, ...this.xattached.remotes().filter((i) => i !== this.active)];
|
2828
|
+
}
|
2829
|
+
};
|
2830
|
+
var MetaAttachedStoresImpl = class {
|
2831
|
+
constructor(attached) {
|
2832
|
+
this.attached = attached;
|
2833
|
+
}
|
2834
|
+
local() {
|
2835
|
+
return this.attached.local().active.meta;
|
2836
|
+
}
|
2837
|
+
remotes() {
|
2838
|
+
return this.attached.remotes().map(({ active }) => active.meta);
|
2839
|
+
}
|
2840
|
+
};
|
2841
|
+
var WALActiveStoreImpl = class extends WALActiveStore {
|
2842
|
+
constructor(ref, active, attached) {
|
2843
|
+
super();
|
2844
|
+
this.ref = ref;
|
2845
|
+
this.active = active;
|
2846
|
+
this.xattached = attached;
|
2847
|
+
}
|
2848
|
+
local() {
|
2849
|
+
return this.xattached.local();
|
2850
|
+
}
|
2851
|
+
remotes() {
|
2852
|
+
return this.xattached.remotes();
|
2853
|
+
}
|
2854
|
+
};
|
2855
|
+
var WALAttachedStoresImpl = class {
|
2856
|
+
constructor(attached) {
|
2857
|
+
this.attached = attached;
|
2858
|
+
}
|
2859
|
+
local() {
|
2860
|
+
return this.attached.local().active.wal;
|
2861
|
+
}
|
2862
|
+
remotes() {
|
2863
|
+
return this.attached.remotes().filter(({ active }) => active.wal).map(({ active }) => active.wal);
|
2864
|
+
}
|
2865
|
+
};
|
2866
|
+
var ActiveStoreImpl = class {
|
2867
|
+
constructor(active, attached) {
|
2868
|
+
this.active = active;
|
2869
|
+
this.xattached = attached;
|
2870
|
+
}
|
2871
|
+
local() {
|
2872
|
+
return this.xattached.local();
|
2873
|
+
}
|
2874
|
+
remotes() {
|
2875
|
+
return this.xattached.remotes();
|
2876
|
+
}
|
2877
|
+
baseStores() {
|
2878
|
+
const bs = [this.active.car, this.active.file, this.active.meta];
|
2879
|
+
if (this.active.wal) {
|
2880
|
+
bs.push(this.active.wal);
|
2881
|
+
}
|
2882
|
+
return bs;
|
2883
|
+
}
|
2884
|
+
carStore() {
|
2885
|
+
return new CarActiveStoreImpl(this, this.active.car, new CarAttachedStoresImpl(this.xattached));
|
2886
|
+
}
|
2887
|
+
fileStore() {
|
2888
|
+
return new FileActiveStoreImpl(this, this.active.file, new FileAttachedStoresImpl(this.xattached));
|
2889
|
+
}
|
2890
|
+
metaStore() {
|
2891
|
+
return new MetaActiveStoreImpl(this, this.active.meta, new MetaAttachedStoresImpl(this.xattached));
|
2892
|
+
}
|
2893
|
+
walStore() {
|
2894
|
+
if (!this.active.wal) {
|
2895
|
+
throw this.xattached.loadable.sthis.logger.Error().Msg("wal store not set").AsError();
|
2896
|
+
}
|
2897
|
+
return new WALActiveStoreImpl(this, this.active.wal, new WALAttachedStoresImpl(this.xattached));
|
2898
|
+
}
|
2899
|
+
};
|
2900
|
+
function isLoadable(unknown) {
|
2901
|
+
return !!unknown.sthis && !!unknown.attachedStores;
|
2902
|
+
}
|
2903
|
+
async function createAttachedStores(urlOrGup, arOrLoadable, name = "local") {
|
2904
|
+
let ar;
|
2905
|
+
if (!isLoadable(arOrLoadable)) {
|
2906
|
+
ar = arOrLoadable;
|
2907
|
+
} else {
|
2908
|
+
ar = arOrLoadable.attachedStores;
|
2909
|
+
}
|
2910
|
+
let gup;
|
2911
|
+
if (!urlOrGup) {
|
2912
|
+
throw new Error("urlOrGup is required");
|
2913
|
+
}
|
2914
|
+
if (isCoerceURI(urlOrGup)) {
|
2915
|
+
const url = urlOrGup;
|
2916
|
+
gup = {
|
2917
|
+
car: { url },
|
2918
|
+
file: { url },
|
2919
|
+
meta: { url },
|
2920
|
+
wal: { url }
|
2921
|
+
};
|
2922
|
+
} else {
|
2923
|
+
gup = urlOrGup;
|
2924
|
+
}
|
2925
|
+
return await ar.attach({
|
2926
|
+
name,
|
2927
|
+
prepare: async () => gup
|
2928
|
+
});
|
2929
|
+
}
|
2930
|
+
var AttachedRemotesImpl = class {
|
2931
|
+
constructor(loadable) {
|
2932
|
+
this._remotes = new KeyedResolvOnce3();
|
2933
|
+
this.loadable = loadable;
|
2934
|
+
}
|
2935
|
+
forRemotes(action) {
|
2936
|
+
return Promise.all(this.remotes().map((i) => action(i))).then(() => void 0);
|
2937
|
+
}
|
2938
|
+
remotes() {
|
2939
|
+
return this._remotes.values().filter(({ value }) => value.isOk() && !value.Ok().stores.wal).map(({ value }) => value.Ok().stores).map((i) => this.activate(i));
|
2940
|
+
}
|
2941
|
+
local() {
|
2942
|
+
if (!this._local) {
|
2943
|
+
throw this.loadable.sthis.logger.Error().Msg("local store not set").AsError();
|
2944
|
+
}
|
2945
|
+
return new ActiveStoreImpl(this._local.stores, this);
|
2946
|
+
}
|
2947
|
+
activate(store) {
|
2948
|
+
if (isCoerceURI(store)) {
|
2949
|
+
const activateUrl = URI9.from(store);
|
2950
|
+
let maxScore = 0;
|
2951
|
+
let maxStore;
|
2952
|
+
for (const { value } of this._remotes.values()) {
|
2953
|
+
if (value.isErr()) {
|
2954
|
+
continue;
|
2955
|
+
}
|
2956
|
+
for (const url of value.Ok().stores.baseStores.map((i) => i.url())) {
|
2957
|
+
const mr = url.match(activateUrl);
|
2958
|
+
if (mr.score > maxScore) {
|
2959
|
+
maxScore = mr.score;
|
2960
|
+
maxStore = value.Ok().stores;
|
2961
|
+
}
|
2962
|
+
}
|
2963
|
+
}
|
2964
|
+
if (!maxStore) {
|
2965
|
+
throw this.loadable.sthis.logger.Error().Url(activateUrl).Msg("no store found").AsError();
|
2966
|
+
}
|
2967
|
+
store = maxStore;
|
2968
|
+
}
|
2969
|
+
return new ActiveStoreImpl(store, this);
|
2970
|
+
}
|
2971
|
+
async detach() {
|
2972
|
+
await Promise.all(
|
2973
|
+
this._remotes.values().map(async ({ value: rvalue }) => {
|
2974
|
+
if (rvalue.isOk()) {
|
2975
|
+
await rvalue.Ok().detach();
|
2976
|
+
}
|
2977
|
+
})
|
2978
|
+
);
|
2979
|
+
}
|
2980
|
+
async attach(attached) {
|
2981
|
+
const gwp = await attached.prepare();
|
2982
|
+
const gws = {
|
2983
|
+
car: {
|
2984
|
+
...gwp.car,
|
2985
|
+
url: ensureURIDefaults(this.loadable.sthis, attached.name, gwp.car.url, URI9.from(gwp.car.url), "car")
|
2986
|
+
},
|
2987
|
+
file: {
|
2988
|
+
...gwp.file,
|
2989
|
+
url: ensureURIDefaults(this.loadable.sthis, attached.name, void 0, URI9.from(gwp.file.url), "file", { file: true })
|
2990
|
+
},
|
2991
|
+
meta: {
|
2992
|
+
...gwp.meta,
|
2993
|
+
url: ensureURIDefaults(this.loadable.sthis, attached.name, void 0, URI9.from(gwp.meta.url), "meta")
|
2994
|
+
},
|
2995
|
+
wal: gwp.wal ? {
|
2996
|
+
...gwp.wal,
|
2997
|
+
url: ensureURIDefaults(this.loadable.sthis, attached.name, void 0, URI9.from(gwp.wal.url), "wal")
|
2998
|
+
} : void 0
|
2999
|
+
};
|
3000
|
+
const key = JSON.stringify(
|
3001
|
+
toSortedArray({
|
3002
|
+
carUrl: gws.car.url.toString(),
|
3003
|
+
filesUrl: gws.file.url.toString(),
|
3004
|
+
metaUrl: gws.meta.url.toString(),
|
3005
|
+
walUrl: gws.wal?.url.toString()
|
3006
|
+
})
|
3007
|
+
);
|
3008
|
+
return this._remotes.get(key).once(async () => {
|
3009
|
+
const rt = toStoreRuntime(this.loadable.sthis);
|
3010
|
+
const result = new AttachedImpl(
|
3011
|
+
gws,
|
3012
|
+
await rt.makeStores({
|
3013
|
+
byStore: gws,
|
3014
|
+
loader: this.loadable
|
3015
|
+
}),
|
3016
|
+
() => {
|
3017
|
+
this._remotes.unget(key);
|
3018
|
+
}
|
3019
|
+
);
|
3020
|
+
if (result.stores.wal) {
|
3021
|
+
if (this._local) {
|
3022
|
+
throw this.loadable.sthis.logger.Error().Msg("local store could only set once").AsError();
|
3023
|
+
}
|
3024
|
+
this._local = result;
|
3025
|
+
}
|
3026
|
+
return result;
|
3027
|
+
});
|
3028
|
+
}
|
3029
|
+
};
|
3030
|
+
|
2617
3031
|
// src/blockstore/loader.ts
|
2618
3032
|
function carLogIncludesGroup(list, cids) {
|
2619
|
-
|
2620
|
-
|
2621
|
-
|
3033
|
+
const cidSet = cids.map((cid) => cid.toString()).sort().join(",");
|
3034
|
+
return list.some(
|
3035
|
+
(arr) => cidSet === arr.map((cid) => cid.toString()).sort().join(",")
|
3036
|
+
);
|
2622
3037
|
}
|
2623
|
-
function uniqueCids(list, remove =
|
3038
|
+
function uniqueCids(list, remove = new LRUSet()) {
|
2624
3039
|
const byString = /* @__PURE__ */ new Map();
|
2625
3040
|
for (const cid of list) {
|
2626
3041
|
if (remove.has(cid.toString())) continue;
|
@@ -2632,17 +3047,8 @@ var Loader = class {
|
|
2632
3047
|
constructor(sthis, ebOpts) {
|
2633
3048
|
this.commitQueue = new CommitQueue();
|
2634
3049
|
this.isCompacting = false;
|
2635
|
-
this.
|
2636
|
-
this.
|
2637
|
-
this.processedCars = /* @__PURE__ */ new Set();
|
2638
|
-
this.carLog = [];
|
2639
|
-
this.getBlockCache = /* @__PURE__ */ new Map();
|
2640
|
-
this.seenMeta = /* @__PURE__ */ new Set();
|
2641
|
-
this.writeLimit = pLimit(1);
|
2642
|
-
this._carStore = new ResolveOnce3();
|
2643
|
-
this._fileStore = new ResolveOnce3();
|
2644
|
-
this._WALStore = new ResolveOnce3();
|
2645
|
-
this._metaStore = new ResolveOnce3();
|
3050
|
+
this.maxConcurrentWrite = pLimit(1);
|
3051
|
+
this.carLog = new CarLog();
|
2646
3052
|
this.onceReady = new ResolveOnce3();
|
2647
3053
|
this.sthis = sthis;
|
2648
3054
|
this.ebOpts = defaultedBlockstoreRuntime(
|
@@ -2653,76 +3059,75 @@ var Loader = class {
|
|
2653
3059
|
},
|
2654
3060
|
"Loader"
|
2655
3061
|
);
|
2656
|
-
this.logger =
|
2657
|
-
this.
|
2658
|
-
|
3062
|
+
this.logger = ensureLogger(sthis, "Loader");
|
3063
|
+
this.cidCache = new KeyedResolvOnce4({
|
3064
|
+
lru: {
|
3065
|
+
maxEntries: parseInt(this.ebOpts.storeUrls.car.getParam(PARAM.CAR_CACHE_SIZE, "1000"), 10)
|
3066
|
+
}
|
2659
3067
|
});
|
2660
|
-
|
2661
|
-
|
2662
|
-
|
2663
|
-
|
2664
|
-
|
2665
|
-
|
2666
|
-
|
2667
|
-
|
2668
|
-
|
2669
|
-
|
2670
|
-
|
2671
|
-
|
2672
|
-
|
2673
|
-
return this._fileStore.once(
|
2674
|
-
async () => this.ebOpts.storeRuntime.makeDataStore({
|
2675
|
-
// sthis: this.sthis,
|
2676
|
-
gatewayInterceptor: this.ebOpts.gatewayInterceptor,
|
2677
|
-
url: this.ebOpts.storeUrls.file,
|
2678
|
-
// keybag: await this.keyBag(),
|
2679
|
-
loader: this
|
2680
|
-
})
|
2681
|
-
);
|
2682
|
-
}
|
2683
|
-
async WALStore() {
|
2684
|
-
return this._WALStore.once(
|
2685
|
-
async () => this.ebOpts.storeRuntime.makeWALStore({
|
2686
|
-
// sthis: this.sthis,
|
2687
|
-
gatewayInterceptor: this.ebOpts.gatewayInterceptor,
|
2688
|
-
url: this.ebOpts.storeUrls.wal,
|
2689
|
-
// keybag: await this.keyBag(),
|
2690
|
-
loader: this
|
2691
|
-
})
|
3068
|
+
this.seenMeta = new LRUSet({
|
3069
|
+
maxEntries: parseInt(this.ebOpts.storeUrls.meta.getParam(PARAM.CAR_META_CACHE_SIZE, "1000"), 10)
|
3070
|
+
});
|
3071
|
+
this.seenCompacted = new LRUSet({
|
3072
|
+
maxEntries: parseInt(this.ebOpts.storeUrls.car.getParam(PARAM.CAR_COMPACT_CACHE_SIZE, "1000"), 10)
|
3073
|
+
});
|
3074
|
+
this.maxConcurrentCarReader = pLimit(parseInt(this.ebOpts.storeUrls.car.getParam(PARAM.CAR_PARALLEL, "5"), 10));
|
3075
|
+
this.taskManager = new TaskManager(
|
3076
|
+
sthis,
|
3077
|
+
async (dbMeta, activeStore) => {
|
3078
|
+
await this.handleDbMetasFromStore([dbMeta], activeStore);
|
3079
|
+
},
|
3080
|
+
this.ebOpts.taskManager
|
2692
3081
|
);
|
3082
|
+
this.attachedStores = new AttachedRemotesImpl(this);
|
2693
3083
|
}
|
2694
|
-
async
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2702
|
-
|
2703
|
-
|
3084
|
+
async attach(attached) {
|
3085
|
+
const at = await this.attachedStores.attach(attached);
|
3086
|
+
if (!at.stores.wal) {
|
3087
|
+
try {
|
3088
|
+
const dbMeta = await at.stores.meta.load();
|
3089
|
+
if (!Array.isArray(dbMeta)) {
|
3090
|
+
throw this.logger.Error().Msg("missing dbMeta").AsError();
|
3091
|
+
}
|
3092
|
+
await this.handleDbMetasFromStore(dbMeta, this.attachedStores.activate(at.stores));
|
3093
|
+
} catch (e) {
|
3094
|
+
this.logger.Error().Err(e).Msg("error attaching store");
|
3095
|
+
at.detach();
|
3096
|
+
}
|
3097
|
+
}
|
3098
|
+
return at;
|
2704
3099
|
}
|
2705
3100
|
keyBag() {
|
2706
3101
|
return getKeyBag(this.sthis, this.ebOpts.keyBag);
|
2707
3102
|
}
|
2708
3103
|
async ready() {
|
2709
3104
|
return this.onceReady.once(async () => {
|
2710
|
-
|
3105
|
+
await createAttachedStores(
|
3106
|
+
{
|
3107
|
+
car: { url: this.ebOpts.storeUrls.car, gatewayInterceptor: this.ebOpts.gatewayInterceptor },
|
3108
|
+
file: { url: this.ebOpts.storeUrls.file, gatewayInterceptor: this.ebOpts.gatewayInterceptor },
|
3109
|
+
meta: { url: this.ebOpts.storeUrls.meta, gatewayInterceptor: this.ebOpts.gatewayInterceptor },
|
3110
|
+
wal: { url: this.ebOpts.storeUrls.wal, gatewayInterceptor: this.ebOpts.gatewayInterceptor }
|
3111
|
+
},
|
3112
|
+
this.attachedStores
|
3113
|
+
);
|
3114
|
+
const local = this.attachedStores.local();
|
3115
|
+
const metas = await local.active.meta.load();
|
2711
3116
|
if (this.ebOpts.meta) {
|
2712
|
-
await this.handleDbMetasFromStore([this.ebOpts.meta]);
|
3117
|
+
await this.handleDbMetasFromStore([this.ebOpts.meta, ...metas || []], local);
|
2713
3118
|
} else if (metas) {
|
2714
|
-
await this.handleDbMetasFromStore(metas);
|
3119
|
+
await this.handleDbMetasFromStore(metas, local);
|
2715
3120
|
}
|
2716
3121
|
});
|
2717
3122
|
}
|
2718
3123
|
async close() {
|
2719
3124
|
await this.commitQueue.waitIdle();
|
2720
|
-
|
2721
|
-
await Promise.all(toClose.map((store) => store.close()));
|
3125
|
+
await this.attachedStores.detach();
|
2722
3126
|
}
|
2723
3127
|
async destroy() {
|
2724
|
-
|
2725
|
-
|
3128
|
+
await Promise.all(
|
3129
|
+
this.attachedStores.local().baseStores().map((store) => store.destroy())
|
3130
|
+
);
|
2726
3131
|
}
|
2727
3132
|
// async snapToCar(carCid: AnyLink | string) {
|
2728
3133
|
// await this.ready
|
@@ -2734,28 +3139,38 @@ var Loader = class {
|
|
2734
3139
|
// await this.getMoreReaders(carHeader.cars)
|
2735
3140
|
// await this._applyCarHeader(carHeader, true)
|
2736
3141
|
// }
|
2737
|
-
async handleDbMetasFromStore(metas) {
|
2738
|
-
this.logger.Debug().Any("metas", metas).Msg("handleDbMetasFromStore");
|
3142
|
+
async handleDbMetasFromStore(metas, activeStore) {
|
3143
|
+
this.logger.Debug().Any("metas", metas).Url(activeStore.active.car.url()).Msg("handleDbMetasFromStore");
|
2739
3144
|
for (const meta of metas) {
|
2740
|
-
await this.
|
2741
|
-
await this.mergeDbMetaIntoClock(meta);
|
3145
|
+
await this.maxConcurrentWrite(async () => {
|
3146
|
+
await this.mergeDbMetaIntoClock(meta, activeStore);
|
2742
3147
|
});
|
2743
3148
|
}
|
2744
3149
|
}
|
2745
|
-
async mergeDbMetaIntoClock(meta) {
|
3150
|
+
async mergeDbMetaIntoClock(meta, activeStore) {
|
2746
3151
|
if (this.isCompacting) {
|
2747
3152
|
throw this.logger.Error().Msg("cannot merge while compacting").AsError();
|
2748
3153
|
}
|
2749
|
-
|
2750
|
-
|
2751
|
-
|
2752
|
-
return;
|
3154
|
+
try {
|
3155
|
+
this.isCompacting = true;
|
3156
|
+
const metaKey = meta.cars.map((i) => i.toString()).sort().join(",");
|
3157
|
+
if (this.seenMeta.has(metaKey)) return;
|
3158
|
+
this.seenMeta.add(metaKey);
|
3159
|
+
if (carLogIncludesGroup(this.carLog.asArray(), meta.cars)) {
|
3160
|
+
return;
|
3161
|
+
}
|
3162
|
+
const carHeader = await this.loadCarHeaderFromMeta(meta, activeStore);
|
3163
|
+
carHeader.compact.map((c) => c.toString()).forEach((k) => this.seenCompacted.add(k), this.seenCompacted);
|
3164
|
+
try {
|
3165
|
+
await this.getMoreReaders(carHeader.cars.flat(), activeStore);
|
3166
|
+
} catch (e) {
|
3167
|
+
this.logger.Error().Err(e).Msg("error getting more readers");
|
3168
|
+
}
|
3169
|
+
this.carLog.update(uniqueCids([meta.cars, ...this.carLog.asArray(), ...carHeader.cars], this.seenCompacted));
|
3170
|
+
await this.ebOpts.applyMeta?.(carHeader.meta);
|
3171
|
+
} finally {
|
3172
|
+
this.isCompacting = false;
|
2753
3173
|
}
|
2754
|
-
const carHeader = await this.loadCarHeaderFromMeta(meta);
|
2755
|
-
carHeader.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
|
2756
|
-
await this.getMoreReaders(carHeader.cars.flat());
|
2757
|
-
this.carLog = [...uniqueCids([meta.cars, ...this.carLog, ...carHeader.cars], this.seenCompacted)];
|
2758
|
-
await this.ebOpts.applyMeta?.(carHeader.meta);
|
2759
3174
|
}
|
2760
3175
|
// protected async ingestKeyFromMeta(meta: DbMeta): Promise<void> {
|
2761
3176
|
// const { key } = meta;
|
@@ -2763,8 +3178,8 @@ var Loader = class {
|
|
2763
3178
|
// await this.setKey(key);
|
2764
3179
|
// }
|
2765
3180
|
// }
|
2766
|
-
async loadCarHeaderFromMeta(
|
2767
|
-
const reader = await this.loadCar(
|
3181
|
+
async loadCarHeaderFromMeta(dbm, astore) {
|
3182
|
+
const reader = await this.loadCar(dbm.cars[0], astore);
|
2768
3183
|
return await parseCarFile(reader, this.logger);
|
2769
3184
|
}
|
2770
3185
|
// async _getKey(): Promise<string | undefined> {
|
@@ -2777,22 +3192,22 @@ var Loader = class {
|
|
2777
3192
|
// }
|
2778
3193
|
async commitFiles(t, done) {
|
2779
3194
|
await this.ready();
|
2780
|
-
const fstore =
|
2781
|
-
const wstore =
|
3195
|
+
const fstore = this.attachedStores.local().active.file;
|
3196
|
+
const wstore = this.attachedStores.local().active.wal;
|
2782
3197
|
return this.commitQueue.enqueue(() => commitFiles(fstore, wstore, t, done));
|
2783
3198
|
}
|
2784
|
-
async loadFileCar(cid) {
|
2785
|
-
return await this.storesLoadCar(cid,
|
3199
|
+
async loadFileCar(cid, store) {
|
3200
|
+
return await this.storesLoadCar(cid, store.fileStore());
|
2786
3201
|
}
|
2787
3202
|
async commit(t, done, opts = { noLoader: false, compact: false }) {
|
2788
3203
|
await this.ready();
|
2789
|
-
const carStore =
|
3204
|
+
const carStore = this.attachedStores.local().active.car;
|
2790
3205
|
const params = {
|
2791
3206
|
encoder: (await carStore.keyedCrypto()).codec(),
|
2792
3207
|
carLog: this.carLog,
|
2793
3208
|
carStore,
|
2794
|
-
WALStore:
|
2795
|
-
metaStore:
|
3209
|
+
WALStore: this.attachedStores.local().active.wal,
|
3210
|
+
metaStore: this.attachedStores.local().active.meta,
|
2796
3211
|
threshold: this.ebOpts.threshold
|
2797
3212
|
};
|
2798
3213
|
return this.commitQueue.enqueue(async () => {
|
@@ -2802,41 +3217,54 @@ var Loader = class {
|
|
2802
3217
|
return ret.cgrp;
|
2803
3218
|
});
|
2804
3219
|
}
|
2805
|
-
async updateCarLog(cids,
|
3220
|
+
async updateCarLog(cids, cHeader, compact) {
|
2806
3221
|
if (compact) {
|
2807
|
-
const previousCompactCid =
|
2808
|
-
|
2809
|
-
this.carLog
|
2810
|
-
await this.removeCidsForCompact(previousCompactCid[0]).catch((e) => e);
|
3222
|
+
const previousCompactCid = cHeader.compact[cHeader.compact.length - 1];
|
3223
|
+
cHeader.compact.map((c) => c.toString()).forEach(this.seenCompacted.add, this.seenCompacted);
|
3224
|
+
this.carLog.update(uniqueCids([...this.carLog.asArray(), ...cHeader.cars, cids], this.seenCompacted));
|
3225
|
+
await this.removeCidsForCompact(previousCompactCid[0], this.attachedStores.local()).catch((e) => e);
|
2811
3226
|
} else {
|
2812
|
-
this.carLog.
|
3227
|
+
this.carLog.xunshift(cids);
|
2813
3228
|
}
|
2814
3229
|
}
|
2815
3230
|
async cacheTransaction(t) {
|
2816
3231
|
for await (const block of t.entries()) {
|
2817
3232
|
const sBlock = block.cid.toString();
|
2818
|
-
|
2819
|
-
|
2820
|
-
|
2821
|
-
|
2822
|
-
|
2823
|
-
|
2824
|
-
|
2825
|
-
|
2826
|
-
for await (const block of reader.blocks()) {
|
2827
|
-
const sBlock = block.cid.toString();
|
2828
|
-
if (!this.getBlockCache.has(sBlock)) {
|
2829
|
-
this.getBlockCache.set(sBlock, block);
|
2830
|
-
}
|
3233
|
+
this.cidCache.get(sBlock).once(
|
3234
|
+
() => ({
|
3235
|
+
type: "block",
|
3236
|
+
cid: block.cid,
|
3237
|
+
blocks: [block],
|
3238
|
+
roots: []
|
3239
|
+
})
|
3240
|
+
);
|
2831
3241
|
}
|
2832
3242
|
}
|
2833
|
-
|
2834
|
-
|
2835
|
-
|
2836
|
-
|
3243
|
+
// /**
|
3244
|
+
// *
|
3245
|
+
// * @returns the list of blocks which was read from the car file
|
3246
|
+
// */
|
3247
|
+
// private async readCar(reader: CarReader): Promise<AnyBlock[]> {
|
3248
|
+
// const blocks: AnyBlock[] = [];
|
3249
|
+
// for await (const block of reader.blocks()) {
|
3250
|
+
// const sBlock = block.cid.toString();
|
3251
|
+
// this.cidCache.get(sBlock).once(() => {
|
3252
|
+
// blocks.push(block);
|
3253
|
+
// return [block];
|
3254
|
+
// });
|
3255
|
+
// }
|
3256
|
+
// return blocks;
|
3257
|
+
// }
|
3258
|
+
async removeCidsForCompact(cid, store) {
|
3259
|
+
const carHeader = await this.loadCarHeaderFromMeta(
|
3260
|
+
{
|
3261
|
+
cars: [cid]
|
3262
|
+
},
|
3263
|
+
store
|
3264
|
+
);
|
2837
3265
|
for (const cids of carHeader.compact) {
|
2838
3266
|
for (const cid2 of cids) {
|
2839
|
-
await
|
3267
|
+
await this.attachedStores.local().active.car.remove(cid2);
|
2840
3268
|
}
|
2841
3269
|
}
|
2842
3270
|
}
|
@@ -2848,148 +3276,134 @@ var Loader = class {
|
|
2848
3276
|
// await this.remoteWAL!.enqueue(dbMeta, { public: false })
|
2849
3277
|
// }
|
2850
3278
|
// }
|
2851
|
-
async *entries(
|
3279
|
+
async *entries() {
|
2852
3280
|
await this.ready();
|
2853
|
-
|
2854
|
-
|
2855
|
-
|
2856
|
-
|
2857
|
-
|
2858
|
-
|
2859
|
-
|
2860
|
-
|
2861
|
-
|
2862
|
-
|
2863
|
-
|
2864
|
-
|
2865
|
-
for await (const block of reader.blocks()) {
|
2866
|
-
const sCid = block.cid.toString();
|
2867
|
-
if (!this.getBlockCache.has(sCid)) {
|
2868
|
-
yield block;
|
2869
|
-
}
|
2870
|
-
}
|
3281
|
+
const seen = /* @__PURE__ */ new Set();
|
3282
|
+
for (const carCids of this.carLog.asArray()) {
|
3283
|
+
for (const carCid of carCids) {
|
3284
|
+
const reader = await this.loadCar(carCid, this.attachedStores.local());
|
3285
|
+
if (!reader || reader.type !== "car") {
|
3286
|
+
throw this.logger.Error().Any("reader", reader.type).Str("cid", carCid.toString()).Msg("missing car reader").AsError();
|
3287
|
+
}
|
3288
|
+
for (const block of reader.blocks) {
|
3289
|
+
const cidStr = block.cid.toString();
|
3290
|
+
if (seen.has(cidStr)) continue;
|
3291
|
+
seen.add(cidStr);
|
3292
|
+
yield block;
|
2871
3293
|
}
|
2872
3294
|
}
|
2873
3295
|
}
|
2874
3296
|
}
|
2875
|
-
async getBlock(cid) {
|
3297
|
+
async getBlock(cid, store) {
|
2876
3298
|
await this.ready();
|
2877
|
-
const
|
2878
|
-
|
2879
|
-
|
2880
|
-
|
2881
|
-
|
2882
|
-
|
2883
|
-
|
2884
|
-
|
2885
|
-
|
2886
|
-
|
2887
|
-
|
2888
|
-
|
2889
|
-
|
2890
|
-
|
2891
|
-
|
2892
|
-
|
2893
|
-
|
2894
|
-
|
2895
|
-
|
2896
|
-
|
2897
|
-
|
2898
|
-
|
2899
|
-
|
2900
|
-
for (let i = 0; i < compacts.length; i += batchSize2) {
|
2901
|
-
const promises = [];
|
2902
|
-
for (let j = i; j < Math.min(i + batchSize2, compacts.length); j++) {
|
2903
|
-
for (const cid2 of compacts[j]) {
|
2904
|
-
promises.push(getCarCid(cid2));
|
3299
|
+
const cidStr = cid.toString();
|
3300
|
+
const ci = await this.cidCache.get(cidStr).once(async () => {
|
3301
|
+
const getCompactCarCids = async (carCid) => {
|
3302
|
+
const sCid = carCid.toString();
|
3303
|
+
const reader = await this.loadCar(carCid, store);
|
3304
|
+
const header = await parseCarFile(reader, this.logger);
|
3305
|
+
const compacts = header.compact;
|
3306
|
+
const got2 = await Promise.allSettled(compacts.map((compact) => compact.map((cid2) => this.loadCar(cid2, store)).flat()));
|
3307
|
+
got2.filter((result) => result.status === "rejected").forEach((result) => {
|
3308
|
+
this.logger.Error().Err(result.reason).Str("cid", sCid).Msg("error getting compacted block");
|
3309
|
+
});
|
3310
|
+
};
|
3311
|
+
let got;
|
3312
|
+
for (const carCids of this.carLog.asArray()) {
|
3313
|
+
for (const carCid of carCids) {
|
3314
|
+
const ci2 = await this.loadCar(carCid, store);
|
3315
|
+
if (!ci2) {
|
3316
|
+
this.logger.Error().Str("cid", carCid.toString()).Msg("missing CarCID");
|
3317
|
+
continue;
|
3318
|
+
}
|
3319
|
+
got = ci2.blocks.find((block) => block.cid.equals(cid));
|
3320
|
+
if (got) {
|
3321
|
+
break;
|
2905
3322
|
}
|
2906
3323
|
}
|
2907
|
-
try {
|
2908
|
-
got2 = await Promise.any(promises);
|
2909
|
-
} catch {
|
2910
|
-
}
|
2911
|
-
if (got2) break;
|
2912
|
-
}
|
2913
|
-
if (this.getBlockCache.has(sCid)) return this.getBlockCache.get(sCid);
|
2914
|
-
throw this.logger.Error().Str("cid", sCid).Msg("block not in compact reader").AsError();
|
2915
|
-
};
|
2916
|
-
let got;
|
2917
|
-
const batchSize = 5;
|
2918
|
-
for (let i = 0; i < this.carLog.length; i += batchSize) {
|
2919
|
-
const batch = this.carLog.slice(i, i + batchSize);
|
2920
|
-
const promises = batch.flatMap((slice) => slice.map(getCarCid));
|
2921
|
-
try {
|
2922
|
-
got = await Promise.any(promises);
|
2923
|
-
} catch {
|
2924
3324
|
}
|
2925
|
-
if (got)
|
2926
|
-
|
2927
|
-
if (!got) {
|
2928
|
-
try {
|
2929
|
-
got = await getCompactCarCids(this.carLog[this.carLog.length - 1][0]);
|
2930
|
-
} catch {
|
3325
|
+
if (!got) {
|
3326
|
+
await getCompactCarCids(this.carLog.last()[0]);
|
2931
3327
|
}
|
3328
|
+
return {
|
3329
|
+
type: "block",
|
3330
|
+
cid,
|
3331
|
+
blocks: got ? [got] : [],
|
3332
|
+
roots: []
|
3333
|
+
};
|
3334
|
+
});
|
3335
|
+
if (!(ci.type === "block" && ci.blocks.length === 1)) {
|
3336
|
+
throw this.logger.Error().Str("cid", cidStr).Any("block", ci).Msg("missing block").AsError();
|
2932
3337
|
}
|
2933
|
-
return
|
3338
|
+
return ci.blocks[0];
|
2934
3339
|
}
|
2935
|
-
async loadCar(cid) {
|
2936
|
-
|
2937
|
-
throw this.logger.Error().Msg("car store not initialized").AsError();
|
2938
|
-
}
|
2939
|
-
const loaded = await this.storesLoadCar(cid, await this.carStore(), this.remoteCarStore);
|
3340
|
+
async loadCar(cid, store) {
|
3341
|
+
const loaded = await this.storesLoadCar(cid, store.carStore());
|
2940
3342
|
return loaded;
|
2941
3343
|
}
|
2942
|
-
async makeDecoderAndCarReader(
|
2943
|
-
const
|
3344
|
+
async makeDecoderAndCarReader(carCid, store) {
|
3345
|
+
const carCidStr = carCid.toString();
|
2944
3346
|
let loadedCar = void 0;
|
2945
|
-
let activeStore = local;
|
3347
|
+
let activeStore = store.local();
|
2946
3348
|
try {
|
2947
|
-
this.logger.Debug().Any("cid",
|
2948
|
-
loadedCar = await local.load(
|
3349
|
+
this.logger.Debug().Any("cid", carCidStr).Msg("loading car");
|
3350
|
+
loadedCar = await store.local().load(carCid);
|
2949
3351
|
this.logger.Debug().Bool("loadedCar", loadedCar).Msg("loaded");
|
2950
3352
|
} catch (e) {
|
2951
|
-
if (
|
2952
|
-
|
2953
|
-
|
2954
|
-
|
2955
|
-
|
2956
|
-
|
2957
|
-
|
3353
|
+
if (!isNotFoundError(e)) {
|
3354
|
+
throw this.logger.Error().Str("cid", carCidStr).Err(e).Msg("loading car");
|
3355
|
+
}
|
3356
|
+
for (const remote of store.remotes()) {
|
3357
|
+
try {
|
3358
|
+
const remoteCar = await remote.load(carCid);
|
3359
|
+
if (remoteCar) {
|
3360
|
+
this.logger.Debug().Ref("cid", remoteCar.cid).Msg("saving remote car locally");
|
3361
|
+
await store.local().save(remoteCar);
|
3362
|
+
loadedCar = remoteCar;
|
3363
|
+
activeStore = remote;
|
3364
|
+
break;
|
3365
|
+
} else {
|
3366
|
+
this.logger.Error().Str("cid", carCidStr).Err(e).Msg("loading car");
|
3367
|
+
}
|
3368
|
+
} catch (e2) {
|
3369
|
+
this.logger.Warn().Str("cid", carCidStr).Url(remote.url()).Err(e2).Msg("loading car");
|
2958
3370
|
}
|
2959
|
-
} else {
|
2960
|
-
this.logger.Error().Str("cid", cidsString).Err(e).Msg("loading car");
|
2961
3371
|
}
|
2962
3372
|
}
|
2963
3373
|
if (!loadedCar) {
|
2964
|
-
throw this.logger.Error().Url(local.url()).Str("cid",
|
2965
|
-
}
|
2966
|
-
const bytes = await decode({ bytes: loadedCar.bytes, hasher:
|
2967
|
-
const rawReader = await CarReader.fromBytes(bytes.value);
|
2968
|
-
const
|
2969
|
-
const
|
2970
|
-
|
2971
|
-
|
2972
|
-
|
2973
|
-
|
2974
|
-
|
2975
|
-
|
2976
|
-
|
2977
|
-
|
3374
|
+
throw this.logger.Error().Url(store.local().url()).Str("cid", carCidStr).Msg("missing car files").AsError();
|
3375
|
+
}
|
3376
|
+
const bytes = await decode({ bytes: loadedCar.bytes, hasher: hasher3, codec: (await activeStore.keyedCrypto()).codec() });
|
3377
|
+
const rawReader = await CarReader.fromBytes(bytes.value.data);
|
3378
|
+
const blocks = [];
|
3379
|
+
for await (const block of rawReader.blocks()) {
|
3380
|
+
const sBlock = block.cid.toString();
|
3381
|
+
blocks.push(block);
|
3382
|
+
this.cidCache.get(sBlock).once(() => ({
|
3383
|
+
type: "block",
|
3384
|
+
cid: block.cid,
|
3385
|
+
blocks: [block],
|
3386
|
+
roots: []
|
3387
|
+
}));
|
3388
|
+
}
|
3389
|
+
return {
|
3390
|
+
type: "car",
|
3391
|
+
cid: carCid,
|
3392
|
+
blocks,
|
3393
|
+
roots: await rawReader.getRoots()
|
3394
|
+
};
|
2978
3395
|
}
|
2979
3396
|
//What if instead it returns an Array of CarHeader
|
2980
|
-
async storesLoadCar(
|
2981
|
-
const
|
2982
|
-
|
2983
|
-
|
2984
|
-
|
2985
|
-
this.carReaders.set(cidsString, dacr);
|
2986
|
-
}
|
2987
|
-
return dacr;
|
3397
|
+
async storesLoadCar(carCid, store) {
|
3398
|
+
const carCidStr = carCid.toString();
|
3399
|
+
return this.cidCache.get(carCidStr).once(async () => {
|
3400
|
+
return this.maxConcurrentCarReader(() => this.makeDecoderAndCarReader(carCid, store));
|
3401
|
+
});
|
2988
3402
|
}
|
2989
|
-
async getMoreReaders(cids) {
|
2990
|
-
const
|
2991
|
-
|
2992
|
-
|
3403
|
+
async getMoreReaders(cids, store) {
|
3404
|
+
for (const cid of cids) {
|
3405
|
+
await this.loadCar(cid, store);
|
3406
|
+
}
|
2993
3407
|
}
|
2994
3408
|
};
|
2995
3409
|
|
@@ -3000,7 +3414,7 @@ __export(keyed_crypto_exports, {
|
|
3000
3414
|
keyedCryptoFactory: () => keyedCryptoFactory
|
3001
3415
|
});
|
3002
3416
|
import { base58btc as base58btc3 } from "multiformats/bases/base58";
|
3003
|
-
import { sha256 as
|
3417
|
+
import { sha256 as hasher4 } from "multiformats/hashes/sha2";
|
3004
3418
|
import * as CBOR from "cborg";
|
3005
3419
|
var generateIV = {
|
3006
3420
|
random: {
|
@@ -3015,7 +3429,7 @@ var generateIV = {
|
|
3015
3429
|
},
|
3016
3430
|
hash: {
|
3017
3431
|
calc: async (ko, crypto, data) => {
|
3018
|
-
const hash = await
|
3432
|
+
const hash = await hasher4.digest(data);
|
3019
3433
|
const hashBytes = new Uint8Array(hash.bytes);
|
3020
3434
|
const hashArray = new Uint8Array(ko.ivLength);
|
3021
3435
|
for (let i = 0; i < hashBytes.length; i++) {
|
@@ -3034,12 +3448,21 @@ function getGenerateIVFn(url, opts) {
|
|
3034
3448
|
}
|
3035
3449
|
var BlockIvKeyIdCodec = class {
|
3036
3450
|
constructor(ko, iv, opts) {
|
3037
|
-
this.code =
|
3451
|
+
this.code = 24;
|
3038
3452
|
this.name = "Fireproof@encrypted-block:aes-gcm";
|
3039
3453
|
this.ko = ko;
|
3040
3454
|
this.iv = iv;
|
3041
3455
|
this.opts = opts || {};
|
3042
3456
|
}
|
3457
|
+
// hashAsBytes(data: IvKeyIdData): AsyncHashAsBytes<Uint8Array<ArrayBufferLike>> {
|
3458
|
+
// return data;
|
3459
|
+
// }
|
3460
|
+
valueToHashBytes(value) {
|
3461
|
+
return Promise.resolve(value.data);
|
3462
|
+
}
|
3463
|
+
bytesToHash(data) {
|
3464
|
+
return Promise.resolve(data);
|
3465
|
+
}
|
3043
3466
|
async encode(data) {
|
3044
3467
|
const calcIv = this.iv || await getGenerateIVFn(this.ko.url, this.opts).calc(this.ko, this.ko.crypto, data);
|
3045
3468
|
const { iv } = this.ko.algo(calcIv);
|
@@ -3071,11 +3494,16 @@ var BlockIvKeyIdCodec = class {
|
|
3071
3494
|
if (!this.opts?.noIVVerify && !await getGenerateIVFn(this.ko.url, this.opts).verify(this.ko, this.ko.crypto, iv, result)) {
|
3072
3495
|
throw this.ko.logger.Error().Msg("iv missmatch").AsError();
|
3073
3496
|
}
|
3074
|
-
return
|
3497
|
+
return {
|
3498
|
+
iv,
|
3499
|
+
keyId,
|
3500
|
+
data: result
|
3501
|
+
};
|
3075
3502
|
}
|
3076
3503
|
};
|
3077
3504
|
var cryptoAction = class {
|
3078
3505
|
constructor(url, key, cyopt, sthis) {
|
3506
|
+
this.code = 24;
|
3079
3507
|
this.ivLength = 12;
|
3080
3508
|
this.isEncrypting = true;
|
3081
3509
|
this.logger = ensureLogger(sthis, "cryptoAction");
|
@@ -3109,14 +3537,19 @@ var cryptoAction = class {
|
|
3109
3537
|
};
|
3110
3538
|
var nullCodec = class {
|
3111
3539
|
constructor() {
|
3112
|
-
this.code =
|
3540
|
+
this.code = 24;
|
3113
3541
|
this.name = "Fireproof@unencrypted-block";
|
3542
|
+
this.empty = new Uint8Array();
|
3114
3543
|
}
|
3115
|
-
encode(data) {
|
3544
|
+
async encode(data) {
|
3116
3545
|
return data;
|
3117
3546
|
}
|
3118
|
-
decode(data) {
|
3119
|
-
return
|
3547
|
+
async decode(data) {
|
3548
|
+
return {
|
3549
|
+
iv: this.empty,
|
3550
|
+
keyId: this.empty,
|
3551
|
+
data
|
3552
|
+
};
|
3120
3553
|
}
|
3121
3554
|
};
|
3122
3555
|
var noCrypto = class {
|
@@ -3360,7 +3793,7 @@ var BaseStoreImpl = class {
|
|
3360
3793
|
async keyedCrypto() {
|
3361
3794
|
return keyedCryptoFactory(this._url, await this.loader.keyBag(), this.sthis);
|
3362
3795
|
}
|
3363
|
-
async start() {
|
3796
|
+
async start(dam) {
|
3364
3797
|
this.logger.Debug().Str("storeType", this.storeType).Msg("starting-gateway-pre");
|
3365
3798
|
this._url = this._url.build().setParam(PARAM.STORE, this.storeType).URI();
|
3366
3799
|
const res = await this.gateway.start({ loader: this.loader }, this._url);
|
@@ -3371,13 +3804,8 @@ var BaseStoreImpl = class {
|
|
3371
3804
|
this._url = res.Ok();
|
3372
3805
|
const kb = await this.loader.keyBag();
|
3373
3806
|
const skRes = await kb.ensureKeyFromUrl(this._url, () => {
|
3374
|
-
const
|
3375
|
-
|
3376
|
-
if (idx) {
|
3377
|
-
storeKeyName.push(idx);
|
3378
|
-
}
|
3379
|
-
storeKeyName.push(this.storeType);
|
3380
|
-
return storeKeyName.join(":");
|
3807
|
+
const key = this._url.getParam(PARAM.KEY);
|
3808
|
+
return key;
|
3381
3809
|
});
|
3382
3810
|
if (skRes.isErr()) {
|
3383
3811
|
return skRes;
|
@@ -3397,7 +3825,7 @@ var BaseStoreImpl = class {
|
|
3397
3825
|
return ready;
|
3398
3826
|
}
|
3399
3827
|
}
|
3400
|
-
this._onStarted.forEach((fn) => fn());
|
3828
|
+
this._onStarted.forEach((fn) => fn(dam));
|
3401
3829
|
this.logger.Debug().Msg("started");
|
3402
3830
|
return version;
|
3403
3831
|
}
|
@@ -3426,12 +3854,19 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
3426
3854
|
/*this.remote && */
|
3427
3855
|
opts.gateway.subscribe
|
3428
3856
|
) {
|
3429
|
-
this.onStarted(async () => {
|
3857
|
+
this.onStarted(async (dam) => {
|
3430
3858
|
this.logger.Debug().Str("url", this.url().toString()).Msg("Subscribing to the gateway");
|
3431
3859
|
opts.gateway.subscribe({ loader: this.loader }, this.url(), async ({ payload: dbMetas }) => {
|
3432
3860
|
this.logger.Debug().Msg("Received message from gateway");
|
3433
3861
|
await Promise.all(
|
3434
|
-
dbMetas.map(
|
3862
|
+
dbMetas.map(
|
3863
|
+
(dbMetaEv) => this.loader.taskManager?.handleEvent(
|
3864
|
+
dbMetaEv.eventCid,
|
3865
|
+
dbMetaEv.parents,
|
3866
|
+
dbMetaEv.dbMeta,
|
3867
|
+
this.loader.attachedStores.activate(dam)
|
3868
|
+
)
|
3869
|
+
)
|
3435
3870
|
);
|
3436
3871
|
this.updateParentsFromDbMetas(dbMetas);
|
3437
3872
|
});
|
@@ -3453,8 +3888,7 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
3453
3888
|
// }
|
3454
3889
|
// return (rDbMeta.Ok() as FPEnvelopeMeta).payload;
|
3455
3890
|
// }
|
3456
|
-
async load() {
|
3457
|
-
const branch = "main";
|
3891
|
+
async load(branch = "main") {
|
3458
3892
|
const url = await this.gateway.buildUrl({ loader: this.loader }, this.url(), branch);
|
3459
3893
|
if (url.isErr()) {
|
3460
3894
|
throw this.logger.Error().Result("buildUrl", url).Str("branch", branch).Msg("got error from gateway.buildUrl").AsError();
|
@@ -3466,10 +3900,11 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
3466
3900
|
}
|
3467
3901
|
throw this.logger.Error().Url(url.Ok()).Err(rfpEnv).Msg("gateway get").AsError();
|
3468
3902
|
}
|
3469
|
-
const
|
3470
|
-
|
3471
|
-
this.
|
3472
|
-
|
3903
|
+
const fpMeta = rfpEnv.Ok().payload;
|
3904
|
+
const dbMetas = fpMeta.map((m) => m.dbMeta);
|
3905
|
+
await this.loader.handleDbMetasFromStore(dbMetas, this.loader.attachedStores.activate(url.Ok()));
|
3906
|
+
this.updateParentsFromDbMetas(fpMeta);
|
3907
|
+
return dbMetas;
|
3473
3908
|
}
|
3474
3909
|
async save(meta, branch) {
|
3475
3910
|
branch = branch || "main";
|
@@ -3499,9 +3934,8 @@ var MetaStoreImpl = class extends BaseStoreImpl {
|
|
3499
3934
|
}
|
3500
3935
|
};
|
3501
3936
|
var DataStoreImpl = class extends BaseStoreImpl {
|
3502
|
-
constructor(sthis, url, opts) {
|
3503
|
-
super(sthis, url, { ...opts },
|
3504
|
-
this.storeType = "data";
|
3937
|
+
constructor(sthis, url, opts, logger) {
|
3938
|
+
super(sthis, url, { ...opts }, logger);
|
3505
3939
|
}
|
3506
3940
|
async load(cid) {
|
3507
3941
|
this.logger.Debug().Any("cid", cid).Msg("loading");
|
@@ -3516,7 +3950,6 @@ var DataStoreImpl = class extends BaseStoreImpl {
|
|
3516
3950
|
const fpenv = res.Ok();
|
3517
3951
|
switch (fpenv.type) {
|
3518
3952
|
case "car":
|
3519
|
-
return { cid, bytes: fpenv.payload };
|
3520
3953
|
case "file":
|
3521
3954
|
return { cid, bytes: fpenv.payload };
|
3522
3955
|
default:
|
@@ -3532,12 +3965,11 @@ var DataStoreImpl = class extends BaseStoreImpl {
|
|
3532
3965
|
}
|
3533
3966
|
let fpMsg;
|
3534
3967
|
switch (url.Ok().getParam(PARAM.STORE)) {
|
3535
|
-
case "
|
3536
|
-
|
3537
|
-
|
3538
|
-
|
3539
|
-
|
3540
|
-
}
|
3968
|
+
case "car":
|
3969
|
+
fpMsg = Car2FPMsg(car.bytes);
|
3970
|
+
break;
|
3971
|
+
case "file":
|
3972
|
+
fpMsg = File2FPMsg(car.bytes);
|
3541
3973
|
break;
|
3542
3974
|
default:
|
3543
3975
|
throw this.logger.Error().Str("store", url.Ok().getParam(PARAM.STORE)).Msg("unexpected store").AsError();
|
@@ -3568,6 +4000,18 @@ var DataStoreImpl = class extends BaseStoreImpl {
|
|
3568
4000
|
return this.gateway.destroy({ loader: this.loader }, this.url());
|
3569
4001
|
}
|
3570
4002
|
};
|
4003
|
+
var CarStoreImpl = class extends DataStoreImpl {
|
4004
|
+
constructor(sthis, url, opts) {
|
4005
|
+
super(sthis, url, { ...opts }, ensureLogger(sthis, "CarStoreImpl"));
|
4006
|
+
this.storeType = "car";
|
4007
|
+
}
|
4008
|
+
};
|
4009
|
+
var FileStoreImpl = class extends DataStoreImpl {
|
4010
|
+
constructor(sthis, url, opts) {
|
4011
|
+
super(sthis, url, { ...opts }, ensureLogger(sthis, "FileStoreImpl"));
|
4012
|
+
this.storeType = "file";
|
4013
|
+
}
|
4014
|
+
};
|
3571
4015
|
var WALStoreImpl = class extends BaseStoreImpl {
|
3572
4016
|
constructor(sthis, url, opts) {
|
3573
4017
|
super(sthis, url, { ...opts }, ensureLogger(sthis, "WALStoreImpl"));
|
@@ -3615,7 +4059,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3615
4059
|
}
|
3616
4060
|
async process() {
|
3617
4061
|
await this.ready();
|
3618
|
-
if (!this.loader.remoteCarStore) return;
|
3619
4062
|
await this.processQueue.enqueue(async () => {
|
3620
4063
|
try {
|
3621
4064
|
await this._doProcess();
|
@@ -3629,7 +4072,6 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3629
4072
|
}
|
3630
4073
|
async _doProcess() {
|
3631
4074
|
if (!this.loader) return;
|
3632
|
-
if (!this.loader.remoteCarStore) return;
|
3633
4075
|
const operations = [...this.walState.operations];
|
3634
4076
|
const noLoaderOps = [...this.walState.noLoaderOps];
|
3635
4077
|
const fileOperations = [...this.walState.fileOperations];
|
@@ -3650,13 +4092,13 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3650
4092
|
return;
|
3651
4093
|
}
|
3652
4094
|
for (const cid of dbMeta.cars) {
|
3653
|
-
const car = await
|
4095
|
+
const car = await this.loader.attachedStores.local().active.car.load(cid);
|
3654
4096
|
if (!car) {
|
3655
|
-
if (carLogIncludesGroup(this.loader.carLog, dbMeta.cars)) {
|
4097
|
+
if (carLogIncludesGroup(this.loader.carLog.asArray(), dbMeta.cars)) {
|
3656
4098
|
throw this.logger.Error().Ref("cid", cid).Msg("missing local car").AsError();
|
3657
4099
|
}
|
3658
4100
|
} else {
|
3659
|
-
await
|
4101
|
+
await this.loader.attachedStores.forRemotes((x) => x.active.car.save(car));
|
3660
4102
|
}
|
3661
4103
|
}
|
3662
4104
|
inplaceFilter(this.walState.noLoaderOps, (op) => op !== dbMeta);
|
@@ -3672,13 +4114,13 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3672
4114
|
return;
|
3673
4115
|
}
|
3674
4116
|
for (const cid of dbMeta.cars) {
|
3675
|
-
const car = await
|
4117
|
+
const car = await this.loader.attachedStores.local().active.car.load(cid);
|
3676
4118
|
if (!car) {
|
3677
|
-
if (carLogIncludesGroup(this.loader.carLog, dbMeta.cars)) {
|
4119
|
+
if (carLogIncludesGroup(this.loader.carLog.asArray(), dbMeta.cars)) {
|
3678
4120
|
throw this.logger.Error().Ref("cid", cid).Msg(`missing local car`).AsError();
|
3679
4121
|
}
|
3680
4122
|
} else {
|
3681
|
-
await
|
4123
|
+
await this.loader.attachedStores.forRemotes((x) => x.active.car.save(car));
|
3682
4124
|
}
|
3683
4125
|
}
|
3684
4126
|
inplaceFilter(this.walState.operations, (op) => op !== dbMeta);
|
@@ -3693,11 +4135,11 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3693
4135
|
if (!this.loader) {
|
3694
4136
|
return;
|
3695
4137
|
}
|
3696
|
-
const fileBlock = await
|
4138
|
+
const fileBlock = await this.loader.attachedStores.local().active.file.load(fileCid);
|
3697
4139
|
if (!fileBlock) {
|
3698
4140
|
throw this.logger.Error().Ref("cid", fileCid).Msg("missing file block").AsError();
|
3699
4141
|
}
|
3700
|
-
await this.loader.
|
4142
|
+
await this.loader.attachedStores.forRemotes((x) => x.active.file.save(fileBlock, { public: publicFile }));
|
3701
4143
|
inplaceFilter(this.walState.fileOperations, (op) => op.cid !== fileCid);
|
3702
4144
|
}, `fileOperation with cid=${fileCid.toString()}`);
|
3703
4145
|
},
|
@@ -3709,7 +4151,7 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3709
4151
|
if (!this.loader) {
|
3710
4152
|
return;
|
3711
4153
|
}
|
3712
|
-
await this.loader.
|
4154
|
+
await this.loader.attachedStores.forRemotes((x) => x.active.meta.save(lastOp));
|
3713
4155
|
}, `remoteMetaStore save with dbMeta.cars=${lastOp.cars.toString()}`);
|
3714
4156
|
}
|
3715
4157
|
} catch (error) {
|
@@ -3762,16 +4204,17 @@ var WALStoreImpl = class extends BaseStoreImpl {
|
|
3762
4204
|
};
|
3763
4205
|
|
3764
4206
|
// src/blockstore/store-factory.ts
|
3765
|
-
var onceGateway = new
|
3766
|
-
var gatewayInstances = new
|
4207
|
+
var onceGateway = new KeyedResolvOnce5();
|
4208
|
+
var gatewayInstances = new KeyedResolvOnce5();
|
3767
4209
|
async function getStartedGateway(ctx, url) {
|
3768
4210
|
return onceGateway.get(url.toString()).once(async () => {
|
3769
4211
|
const item = getGatewayFactoryItem(url.protocol);
|
3770
4212
|
if (item) {
|
3771
4213
|
const ret = {
|
3772
4214
|
url,
|
3773
|
-
...await gatewayInstances.get(url.protocol).once(async () => ({
|
3774
|
-
|
4215
|
+
...await gatewayInstances.get(url.protocol).once(async () => ({
|
4216
|
+
gateway: await item.serdegateway(ctx.loader.sthis)
|
4217
|
+
}))
|
3775
4218
|
};
|
3776
4219
|
const res = await ret.gateway.start(ctx, url);
|
3777
4220
|
if (res.isErr()) {
|
@@ -3783,50 +4226,64 @@ async function getStartedGateway(ctx, url) {
|
|
3783
4226
|
return Result10.Err(ctx.loader.sthis.logger.Warn().Url(url).Msg("unsupported protocol").AsError());
|
3784
4227
|
});
|
3785
4228
|
}
|
3786
|
-
async function
|
3787
|
-
const storeUrl =
|
3788
|
-
const rgateway = await getStartedGateway(
|
4229
|
+
async function carStoreFactory(ctx, uai) {
|
4230
|
+
const storeUrl = uai.url.build().setParam(PARAM.STORE, "car").URI();
|
4231
|
+
const rgateway = await getStartedGateway(ctx, storeUrl);
|
3789
4232
|
if (rgateway.isErr()) {
|
3790
|
-
throw
|
4233
|
+
throw ctx.loader.sthis.logger.Error().Result("err", rgateway).Url(uai.url).Msg("notfound").AsError();
|
3791
4234
|
}
|
3792
4235
|
const gateway = rgateway.Ok();
|
3793
|
-
const store = new
|
4236
|
+
const store = new CarStoreImpl(ctx.loader.sthis, gateway.url, {
|
3794
4237
|
gateway: gateway.gateway,
|
3795
|
-
gatewayInterceptor:
|
3796
|
-
loader:
|
4238
|
+
gatewayInterceptor: uai.gatewayInterceptor,
|
4239
|
+
loader: ctx.loader
|
3797
4240
|
});
|
3798
4241
|
return store;
|
3799
4242
|
}
|
3800
|
-
async function
|
3801
|
-
const storeUrl =
|
3802
|
-
const rgateway = await getStartedGateway(
|
4243
|
+
async function fileStoreFactory(ctx, uai) {
|
4244
|
+
const storeUrl = uai.url.build().setParam(PARAM.STORE, "file").URI();
|
4245
|
+
const rgateway = await getStartedGateway(ctx, storeUrl);
|
3803
4246
|
if (rgateway.isErr()) {
|
3804
|
-
throw
|
4247
|
+
throw ctx.loader.sthis.logger.Error().Result("err", rgateway).Url(uai.url).Msg("notfound").AsError();
|
3805
4248
|
}
|
3806
4249
|
const gateway = rgateway.Ok();
|
3807
|
-
const store = new
|
4250
|
+
const store = new FileStoreImpl(ctx.loader.sthis, gateway.url, {
|
3808
4251
|
gateway: gateway.gateway,
|
3809
|
-
gatewayInterceptor:
|
3810
|
-
loader:
|
4252
|
+
gatewayInterceptor: uai.gatewayInterceptor,
|
4253
|
+
loader: ctx.loader
|
3811
4254
|
});
|
3812
4255
|
return store;
|
3813
4256
|
}
|
3814
|
-
async function
|
3815
|
-
const storeUrl =
|
3816
|
-
const rgateway = await getStartedGateway(
|
4257
|
+
async function metaStoreFactory(ctx, uai) {
|
4258
|
+
const storeUrl = uai.url.build().setParam(PARAM.STORE, "meta").URI();
|
4259
|
+
const rgateway = await getStartedGateway(ctx, storeUrl);
|
3817
4260
|
if (rgateway.isErr()) {
|
3818
|
-
throw
|
4261
|
+
throw ctx.loader.sthis.logger.Error().Result("err", rgateway).Url(uai.url).Msg("notfound").AsError();
|
3819
4262
|
}
|
3820
4263
|
const gateway = rgateway.Ok();
|
3821
|
-
const store = new
|
4264
|
+
const store = new MetaStoreImpl(ctx.loader.sthis, gateway.url, {
|
3822
4265
|
gateway: gateway.gateway,
|
3823
|
-
gatewayInterceptor:
|
3824
|
-
loader:
|
4266
|
+
gatewayInterceptor: uai.gatewayInterceptor,
|
4267
|
+
loader: ctx.loader
|
3825
4268
|
});
|
3826
4269
|
return store;
|
3827
4270
|
}
|
3828
|
-
async function
|
3829
|
-
const
|
4271
|
+
async function WALStoreFactory(ctx, uai) {
|
4272
|
+
const storeUrl = uai.url.build().setParam(PARAM.STORE, "wal").URI();
|
4273
|
+
const rgateway = await getStartedGateway(ctx, storeUrl);
|
4274
|
+
if (rgateway.isErr()) {
|
4275
|
+
throw ctx.loader.sthis.logger.Error().Result("err", rgateway).Url(uai.url).Msg("notfound").AsError();
|
4276
|
+
}
|
4277
|
+
const gateway = rgateway.Ok();
|
4278
|
+
const store = new WALStoreImpl(ctx.loader.sthis, gateway.url, {
|
4279
|
+
gateway: gateway.gateway,
|
4280
|
+
gatewayInterceptor: uai.gatewayInterceptor,
|
4281
|
+
loader: ctx.loader
|
4282
|
+
});
|
4283
|
+
return store;
|
4284
|
+
}
|
4285
|
+
async function ensureStart(store, damaw) {
|
4286
|
+
const ret = await store.start(damaw);
|
3830
4287
|
if (ret.isErr()) {
|
3831
4288
|
throw store.logger.Error().Result("start", ret).Msg("start failed").AsError();
|
3832
4289
|
}
|
@@ -3842,194 +4299,35 @@ function ensureStoreEnDeFile(ende) {
|
|
3842
4299
|
}
|
3843
4300
|
function toStoreRuntime(sthis, endeOpts = {}) {
|
3844
4301
|
return {
|
3845
|
-
|
3846
|
-
|
3847
|
-
|
3848
|
-
|
3849
|
-
|
3850
|
-
|
3851
|
-
|
3852
|
-
|
3853
|
-
|
3854
|
-
|
3855
|
-
|
3856
|
-
|
3857
|
-
|
3858
|
-
|
3859
|
-
|
3860
|
-
|
3861
|
-
|
3862
|
-
|
3863
|
-
|
3864
|
-
//
|
3865
|
-
//
|
3866
|
-
//
|
3867
|
-
// return ensureStart(await (endeOpts.func?.makeWALStore || remoteWalFactory)(loader), logger);
|
3868
|
-
// },
|
4302
|
+
makeStores: async (sfi) => {
|
4303
|
+
const ctx = {
|
4304
|
+
loader: sfi.loader
|
4305
|
+
};
|
4306
|
+
const storeSet = {};
|
4307
|
+
storeSet.meta = await metaStoreFactory(ctx, sfi.byStore.meta);
|
4308
|
+
storeSet.car = await carStoreFactory(ctx, sfi.byStore.car);
|
4309
|
+
storeSet.file = await fileStoreFactory(ctx, sfi.byStore.file);
|
4310
|
+
if (sfi.byStore.wal) {
|
4311
|
+
storeSet.wal = await WALStoreFactory(ctx, sfi.byStore.wal);
|
4312
|
+
}
|
4313
|
+
await ensureStart(storeSet.meta, storeSet);
|
4314
|
+
await ensureStart(storeSet.car, storeSet);
|
4315
|
+
await ensureStart(storeSet.file, storeSet);
|
4316
|
+
if (storeSet.wal) {
|
4317
|
+
await ensureStart(storeSet.wal, storeSet);
|
4318
|
+
}
|
4319
|
+
return storeSet;
|
4320
|
+
},
|
4321
|
+
// makeMetaStore: async (sfi: StoreFactoryItem) => ensureStart(await metaStoreFactory(sfi)),
|
4322
|
+
// makeDataStore: async (sfi: StoreFactoryItem) => ensureStart(await dataStoreFactory(sfi)),
|
4323
|
+
// makeWALStore: async (sfi: StoreFactoryItem) => ensureStart(await WALStoreFactory(sfi)),
|
3869
4324
|
...ensureStoreEnDeFile(endeOpts)
|
3870
4325
|
};
|
3871
4326
|
}
|
3872
4327
|
|
3873
|
-
// src/blockstore/connection-base.ts
|
3874
|
-
import { exception2Result as exception2Result4, Future as Future3 } from "@adviser/cement";
|
3875
|
-
|
3876
|
-
// src/blockstore/store-remote.ts
|
3877
|
-
async function RemoteDataStore(sthis, url, opts) {
|
3878
|
-
const ds = new DataStoreImpl(sthis, url, opts);
|
3879
|
-
await ds.start();
|
3880
|
-
return ds;
|
3881
|
-
}
|
3882
|
-
async function RemoteMetaStore(sthis, url, opts) {
|
3883
|
-
const ms = new MetaStoreImpl(sthis, url, opts);
|
3884
|
-
await ms.start();
|
3885
|
-
return ms;
|
3886
|
-
}
|
3887
|
-
|
3888
|
-
// src/context.ts
|
3889
|
-
var Context = class {
|
3890
|
-
constructor() {
|
3891
|
-
this.ctx = /* @__PURE__ */ new Map();
|
3892
|
-
}
|
3893
|
-
set(key, value) {
|
3894
|
-
this.ctx.set(key, value);
|
3895
|
-
}
|
3896
|
-
get(key) {
|
3897
|
-
return this.ctx.get(key);
|
3898
|
-
}
|
3899
|
-
delete(key) {
|
3900
|
-
this.ctx.delete(key);
|
3901
|
-
}
|
3902
|
-
};
|
3903
|
-
|
3904
|
-
// src/blockstore/connection-base.ts
|
3905
|
-
function coerceLoader(ref) {
|
3906
|
-
const refl = ref;
|
3907
|
-
if (refl.loader) {
|
3908
|
-
return refl.loader;
|
3909
|
-
}
|
3910
|
-
const refb = ref;
|
3911
|
-
if (refb.blockstore) {
|
3912
|
-
return coerceLoader(refb.blockstore);
|
3913
|
-
}
|
3914
|
-
return void 0;
|
3915
|
-
}
|
3916
|
-
var ConnectionBase = class {
|
3917
|
-
constructor(url, logger) {
|
3918
|
-
// loaded: Promise<void> = Promise.resolve();
|
3919
|
-
this.context = new Context();
|
3920
|
-
this._loaded = /* @__PURE__ */ new Set();
|
3921
|
-
this._metaIsLoading = false;
|
3922
|
-
this.logger = logger;
|
3923
|
-
this.url = url;
|
3924
|
-
}
|
3925
|
-
loaded() {
|
3926
|
-
const f = new Future3();
|
3927
|
-
if (!this._metaIsLoading) {
|
3928
|
-
f.resolve();
|
3929
|
-
} else {
|
3930
|
-
this._loaded.add(f);
|
3931
|
-
}
|
3932
|
-
return f;
|
3933
|
-
}
|
3934
|
-
async refresh() {
|
3935
|
-
await throwFalsy(throwFalsy(this.loader).remoteMetaStore).load();
|
3936
|
-
await (await throwFalsy(this.loader).WALStore()).process();
|
3937
|
-
}
|
3938
|
-
async connect(refl) {
|
3939
|
-
await this.connectMeta(refl);
|
3940
|
-
await this.connectStorage(refl);
|
3941
|
-
}
|
3942
|
-
async connectMeta(refl) {
|
3943
|
-
const loader = coerceLoader(refl);
|
3944
|
-
if (!loader) throw this.logger.Error().Msg("connectMeta: loader is required").AsError();
|
3945
|
-
this.loader = loader;
|
3946
|
-
await this.onConnect();
|
3947
|
-
const metaUrl = this.url.build().defParam(PARAM.STORE, "meta").URI();
|
3948
|
-
const rgateway = await getStartedGateway({ loader }, metaUrl);
|
3949
|
-
if (rgateway.isErr())
|
3950
|
-
throw this.logger.Error().Result("err", rgateway).Url(metaUrl).Msg("connectMeta: gateway is required").AsError();
|
3951
|
-
const dbName = metaUrl.getParam(PARAM.NAME);
|
3952
|
-
if (!dbName) {
|
3953
|
-
throw this.logger.Error().Url(metaUrl).Msg("connectMeta: dbName is required").AsError();
|
3954
|
-
}
|
3955
|
-
const gateway = rgateway.Ok();
|
3956
|
-
const remote = await RemoteMetaStore(loader.sthis, metaUrl, {
|
3957
|
-
gateway: gateway.gateway,
|
3958
|
-
loader
|
3959
|
-
});
|
3960
|
-
this.loader.remoteMetaStore = remote;
|
3961
|
-
this._metaIsLoading = true;
|
3962
|
-
this.loader.ready().then(async () => {
|
3963
|
-
return remote.load().then(async () => {
|
3964
|
-
const res = await exception2Result4(async () => {
|
3965
|
-
return await (await throwFalsy(this.loader).WALStore()).process();
|
3966
|
-
});
|
3967
|
-
this._metaIsLoading = false;
|
3968
|
-
for (const f of this._loaded) {
|
3969
|
-
if (res.isErr()) {
|
3970
|
-
f.reject(res.Err());
|
3971
|
-
} else {
|
3972
|
-
f.resolve();
|
3973
|
-
}
|
3974
|
-
}
|
3975
|
-
this._loaded.clear();
|
3976
|
-
});
|
3977
|
-
});
|
3978
|
-
}
|
3979
|
-
async connectStorage(refl) {
|
3980
|
-
const loader = coerceLoader(refl);
|
3981
|
-
if (!loader) throw this.logger.Error().Msg("connectStorage: loader is required").AsError();
|
3982
|
-
this.loader = loader;
|
3983
|
-
const dataUrl = this.url.build().defParam(PARAM.STORE, "data").URI();
|
3984
|
-
const rgateway = await getStartedGateway({ loader }, dataUrl);
|
3985
|
-
if (rgateway.isErr())
|
3986
|
-
throw this.logger.Error().Result("err", rgateway).Url(dataUrl).Msg("connectStorage: gateway is required").AsError();
|
3987
|
-
const name = dataUrl.getParam(PARAM.NAME);
|
3988
|
-
if (!name) throw this.logger.Error().Url(dataUrl).Msg("connectStorage: name is required").AsError;
|
3989
|
-
loader.remoteCarStore = await RemoteDataStore(loader.sthis, this.url, {
|
3990
|
-
gateway: rgateway.Ok().gateway,
|
3991
|
-
loader
|
3992
|
-
});
|
3993
|
-
loader.remoteFileStore = loader.remoteCarStore;
|
3994
|
-
}
|
3995
|
-
// move this stuff to connect
|
3996
|
-
// async getDashboardURL(compact = true) {
|
3997
|
-
// const baseUrl = 'https://dashboard.fireproof.storage/'
|
3998
|
-
// if (!this.loader?.remoteCarStore) return new URL('/howto', baseUrl)
|
3999
|
-
// // if (compact) {
|
4000
|
-
// // await this.compact()
|
4001
|
-
// // }
|
4002
|
-
// const currents = await this.loader?.metaStore?.load()
|
4003
|
-
// if (!currents) throw new Error("Can't sync empty ledger: save data first")
|
4004
|
-
// if (currents.length > 1)
|
4005
|
-
// throw new Error("Can't sync ledger with split heads: make an update first")
|
4006
|
-
// const current = currents[0]
|
4007
|
-
// const params = {
|
4008
|
-
// car: current.car.toString()
|
4009
|
-
// }
|
4010
|
-
// if (current.key) {
|
4011
|
-
// // @ts-ignore
|
4012
|
-
// params.key = current.key.toString()
|
4013
|
-
// }
|
4014
|
-
// // @ts-ignore
|
4015
|
-
// if (this.name) {
|
4016
|
-
// // @ts-ignore
|
4017
|
-
// params.name = this.name
|
4018
|
-
// }
|
4019
|
-
// const url = new URL('/import#' + new URLSearchParams(params).toString(), baseUrl)
|
4020
|
-
// console.log('Import to dashboard: ' + url.toString())
|
4021
|
-
// return url
|
4022
|
-
// }
|
4023
|
-
// openDashboard() {
|
4024
|
-
// void this.getDashboardURL().then(url => {
|
4025
|
-
// if (url) window.open(url.toString(), '_blank')
|
4026
|
-
// })
|
4027
|
-
// }
|
4028
|
-
};
|
4029
|
-
|
4030
4328
|
// src/crdt-helpers.ts
|
4031
4329
|
import { parse as parse2 } from "multiformats/link";
|
4032
|
-
import { sha256 as
|
4330
|
+
import { sha256 as hasher5 } from "multiformats/hashes/sha2";
|
4033
4331
|
import * as codec2 from "@ipld/dag-cbor";
|
4034
4332
|
import { put, get, entries, root } from "@fireproof/vendor/@web3-storage/pail/crdt";
|
4035
4333
|
import { EventFetcher, vis } from "@fireproof/vendor/@web3-storage/pail/clock";
|
@@ -4047,6 +4345,34 @@ function toString(key, logger) {
|
|
4047
4345
|
throw logger.Error().Msg("Invalid key type").AsError();
|
4048
4346
|
}
|
4049
4347
|
}
|
4348
|
+
function sanitizeDocumentFields(obj) {
|
4349
|
+
if (Array.isArray(obj)) {
|
4350
|
+
return obj.map((item) => {
|
4351
|
+
if (typeof item === "object" && item !== null) {
|
4352
|
+
return sanitizeDocumentFields(item);
|
4353
|
+
}
|
4354
|
+
return item;
|
4355
|
+
});
|
4356
|
+
} else if (typeof obj === "object" && obj !== null) {
|
4357
|
+
const typedObj = obj;
|
4358
|
+
const result = {};
|
4359
|
+
for (const key in typedObj) {
|
4360
|
+
if (Object.hasOwnProperty.call(typedObj, key)) {
|
4361
|
+
const value = typedObj[key];
|
4362
|
+
if (value === null || !Number.isNaN(value) && value !== void 0) {
|
4363
|
+
if (typeof value === "object" && !key.startsWith("_")) {
|
4364
|
+
const sanitized = sanitizeDocumentFields(value);
|
4365
|
+
result[key] = sanitized;
|
4366
|
+
} else {
|
4367
|
+
result[key] = value;
|
4368
|
+
}
|
4369
|
+
}
|
4370
|
+
}
|
4371
|
+
}
|
4372
|
+
return result;
|
4373
|
+
}
|
4374
|
+
return obj;
|
4375
|
+
}
|
4050
4376
|
async function applyBulkUpdateToCrdt(store, tblocks, head, updates, logger) {
|
4051
4377
|
let result = null;
|
4052
4378
|
if (updates.length > 1) {
|
@@ -4081,7 +4407,7 @@ async function writeDocContent(store, blocks, update, logger) {
|
|
4081
4407
|
await processFiles(store, blocks, update.value, logger);
|
4082
4408
|
value = { doc: update.value };
|
4083
4409
|
}
|
4084
|
-
const block = await encode({ value, hasher:
|
4410
|
+
const block = await encode({ value, hasher: hasher5, codec: codec2 });
|
4085
4411
|
blocks.putSync(block.cid, block.bytes);
|
4086
4412
|
return block.cid;
|
4087
4413
|
}
|
@@ -4136,7 +4462,8 @@ async function getValueFromCrdt(blocks, head, key, logger) {
|
|
4136
4462
|
if (!head.length) throw logger.Debug().Msg("Getting from an empty ledger").AsError();
|
4137
4463
|
const link = await get(blocks, head, key);
|
4138
4464
|
if (!link) throw logger.Error().Str("key", key).Msg(`Missing key`).AsError();
|
4139
|
-
|
4465
|
+
const ret = await getValueFromLink(blocks, link, logger);
|
4466
|
+
return ret;
|
4140
4467
|
}
|
4141
4468
|
function readFiles(blocks, { doc }) {
|
4142
4469
|
if (!doc) return;
|
@@ -4172,7 +4499,7 @@ function readFileset(blocks, files, isPublic = false) {
|
|
4172
4499
|
async function getValueFromLink(blocks, link, logger) {
|
4173
4500
|
const block = await blocks.get(link);
|
4174
4501
|
if (!block) throw logger.Error().Str("link", link.toString()).Msg(`Missing linked block`).AsError();
|
4175
|
-
const { value } = await decode({ bytes: block.bytes, hasher:
|
4502
|
+
const { value } = await decode({ bytes: block.bytes, hasher: hasher5, codec: codec2 });
|
4176
4503
|
const cvalue = {
|
4177
4504
|
...value,
|
4178
4505
|
cid: link
|
@@ -4234,6 +4561,9 @@ async function gatherUpdates(blocks, eventsFetcher, head, since, updates = [], k
|
|
4234
4561
|
const { key, value } = ops[i];
|
4235
4562
|
if (!keys.has(key)) {
|
4236
4563
|
const docValue = await getValueFromLink(blocks, value, logger);
|
4564
|
+
if (key === PARAM.GENESIS_CID) {
|
4565
|
+
continue;
|
4566
|
+
}
|
4237
4567
|
updates.push({ id: key, value: docValue.doc, del: docValue.del, clock: link });
|
4238
4568
|
limit--;
|
4239
4569
|
keys.add(key);
|
@@ -4247,8 +4577,10 @@ async function gatherUpdates(blocks, eventsFetcher, head, since, updates = [], k
|
|
4247
4577
|
}
|
4248
4578
|
async function* getAllEntries(blocks, head, logger) {
|
4249
4579
|
for await (const [key, link] of entries(blocks, head)) {
|
4250
|
-
|
4251
|
-
|
4580
|
+
if (key !== PARAM.GENESIS_CID) {
|
4581
|
+
const docValue = await getValueFromLink(blocks, link, logger);
|
4582
|
+
yield { id: key, value: docValue.doc, del: docValue.del };
|
4583
|
+
}
|
4252
4584
|
}
|
4253
4585
|
}
|
4254
4586
|
async function* clockVis(blocks, head) {
|
@@ -4293,7 +4625,7 @@ async function doCompact(blockLog, head, logger) {
|
|
4293
4625
|
async function getBlock(blocks, cidString) {
|
4294
4626
|
const block = await blocks.get(parse2(cidString));
|
4295
4627
|
if (!block) throw new Error(`Missing block ${cidString}`);
|
4296
|
-
const { cid, value } = await decode({ bytes: block.bytes, codec: codec2, hasher:
|
4628
|
+
const { cid, value } = await decode({ bytes: block.bytes, codec: codec2, hasher: hasher5 });
|
4297
4629
|
return new Block({ cid, value, bytes: block.bytes });
|
4298
4630
|
}
|
4299
4631
|
|
@@ -4393,6 +4725,10 @@ var CRDTClockImpl = class {
|
|
4393
4725
|
this.notifyWatchers(internalUpdates || []);
|
4394
4726
|
}
|
4395
4727
|
notifyWatchers(updates) {
|
4728
|
+
updates = updates.filter((update) => update.id !== PARAM.GENESIS_CID);
|
4729
|
+
if (!updates.length) {
|
4730
|
+
return;
|
4731
|
+
}
|
4396
4732
|
this.emptyWatchers.forEach((fn) => fn());
|
4397
4733
|
this.watchers.forEach((fn) => fn(updates || []));
|
4398
4734
|
}
|
@@ -4472,7 +4808,7 @@ async function advanceBlocks(logger, newHead, tblocks, head) {
|
|
4472
4808
|
try {
|
4473
4809
|
head = await advance(tblocks, head, cid);
|
4474
4810
|
} catch (e) {
|
4475
|
-
logger.
|
4811
|
+
logger.Error().Err(e).Msg("failed to advance head");
|
4476
4812
|
continue;
|
4477
4813
|
}
|
4478
4814
|
}
|
@@ -4531,6 +4867,17 @@ var CRDTImpl = class {
|
|
4531
4867
|
}
|
4532
4868
|
async bulk(updates) {
|
4533
4869
|
await this.ready();
|
4870
|
+
updates = updates.map((dupdate) => ({
|
4871
|
+
...dupdate,
|
4872
|
+
value: sanitizeDocumentFields(dupdate.value)
|
4873
|
+
}));
|
4874
|
+
if (this.clock.head.length === 0) {
|
4875
|
+
const value = { id: PARAM.GENESIS_CID, value: { _id: PARAM.GENESIS_CID } };
|
4876
|
+
await this._bulk([value]);
|
4877
|
+
}
|
4878
|
+
return await this._bulk(updates);
|
4879
|
+
}
|
4880
|
+
async _bulk(updates) {
|
4534
4881
|
const prevHead = [...this.clock.head];
|
4535
4882
|
const done = await this.blockstore.transaction(async (blocks) => {
|
4536
4883
|
const { head } = await applyBulkUpdateToCrdt(
|
@@ -4601,8 +4948,24 @@ var CRDTImpl = class {
|
|
4601
4948
|
}
|
4602
4949
|
};
|
4603
4950
|
|
4951
|
+
// src/context.ts
|
4952
|
+
var Context = class {
|
4953
|
+
constructor() {
|
4954
|
+
this.ctx = /* @__PURE__ */ new Map();
|
4955
|
+
}
|
4956
|
+
set(key, value) {
|
4957
|
+
this.ctx.set(key, value);
|
4958
|
+
}
|
4959
|
+
get(key) {
|
4960
|
+
return this.ctx.get(key);
|
4961
|
+
}
|
4962
|
+
delete(key) {
|
4963
|
+
this.ctx.delete(key);
|
4964
|
+
}
|
4965
|
+
};
|
4966
|
+
|
4604
4967
|
// src/ledger.ts
|
4605
|
-
var ledgers = new
|
4968
|
+
var ledgers = new KeyedResolvOnce6();
|
4606
4969
|
function keyConfigOpts(sthis, name, opts) {
|
4607
4970
|
return JSON.stringify(
|
4608
4971
|
toSortedArray({
|
@@ -4645,6 +5008,9 @@ var LedgerShell = class {
|
|
4645
5008
|
this.name = ref.name;
|
4646
5009
|
ref.addShell(this);
|
4647
5010
|
}
|
5011
|
+
attach(a) {
|
5012
|
+
return this.ref.attach(a);
|
5013
|
+
}
|
4648
5014
|
get opts() {
|
4649
5015
|
return this.ref.opts;
|
4650
5016
|
}
|
@@ -4743,11 +5109,16 @@ var LedgerImpl = class {
|
|
4743
5109
|
});
|
4744
5110
|
return ret;
|
4745
5111
|
}
|
5112
|
+
async attach(a) {
|
5113
|
+
await this.ready();
|
5114
|
+
return this.crdt.blockstore.loader.attach(a);
|
5115
|
+
}
|
4746
5116
|
// readonly _asDb = new ResolveOnce<Database>();
|
4747
5117
|
// asDB(): Database {
|
4748
5118
|
// return this._asDb.once(() => new DatabaseImpl(this));
|
4749
5119
|
// }
|
4750
5120
|
subscribe(listener, updates) {
|
5121
|
+
this.ready();
|
4751
5122
|
this.logger.Debug().Bool("updates", updates).Msg("subscribe");
|
4752
5123
|
if (updates) {
|
4753
5124
|
if (!this._listening) {
|
@@ -4789,26 +5160,6 @@ var LedgerImpl = class {
|
|
4789
5160
|
}
|
4790
5161
|
}
|
4791
5162
|
};
|
4792
|
-
function defaultURI2(sthis, name, curi, uri, store, ctx) {
|
4793
|
-
ctx = ctx || {};
|
4794
|
-
const ret = (curi ? URI13.from(curi) : uri).build().setParam(PARAM.STORE, store).defParam(PARAM.NAME, name);
|
4795
|
-
if (!ret.hasParam(PARAM.NAME)) {
|
4796
|
-
throw sthis.logger.Error().Url(ret).Any("ctx", ctx).Msg("Ledger name is required").AsError();
|
4797
|
-
}
|
4798
|
-
if (ctx.idx) {
|
4799
|
-
ret.defParam(PARAM.INDEX, "idx");
|
4800
|
-
ret.defParam(PARAM.STORE_KEY, `@${ret.getParam(PARAM.NAME)}-${store}-idx@`);
|
4801
|
-
} else {
|
4802
|
-
ret.defParam(PARAM.STORE_KEY, `@${ret.getParam(PARAM.NAME)}-${store}@`);
|
4803
|
-
}
|
4804
|
-
if (store === "data") {
|
4805
|
-
if (ctx.file) {
|
4806
|
-
} else {
|
4807
|
-
ret.defParam(PARAM.SUFFIX, ".car");
|
4808
|
-
}
|
4809
|
-
}
|
4810
|
-
return ret.URI();
|
4811
|
-
}
|
4812
5163
|
function toStoreURIRuntime(sthis, name, sopts) {
|
4813
5164
|
sopts = sopts || {};
|
4814
5165
|
if (!sopts.base) {
|
@@ -4822,16 +5173,19 @@ function toStoreURIRuntime(sthis, name, sopts) {
|
|
4822
5173
|
const base = URI13.from(sopts.base);
|
4823
5174
|
return {
|
4824
5175
|
idx: {
|
4825
|
-
|
4826
|
-
file:
|
4827
|
-
|
4828
|
-
|
5176
|
+
car: ensureURIDefaults(sthis, name, sopts.idx?.car ?? sopts.data?.car, base, "car", { idx: true }),
|
5177
|
+
file: ensureURIDefaults(sthis, name, sopts.idx?.file ?? sopts.idx?.car ?? sopts.data?.file ?? sopts.data?.car, base, "file", {
|
5178
|
+
file: true,
|
5179
|
+
idx: true
|
5180
|
+
}),
|
5181
|
+
meta: ensureURIDefaults(sthis, name, sopts.idx?.meta ?? sopts.data?.meta, base, "meta", { idx: true }),
|
5182
|
+
wal: ensureURIDefaults(sthis, name, sopts.idx?.wal ?? sopts.data?.wal, base, "wal", { idx: true })
|
4829
5183
|
},
|
4830
5184
|
data: {
|
4831
|
-
|
4832
|
-
file:
|
4833
|
-
meta:
|
4834
|
-
wal:
|
5185
|
+
car: ensureURIDefaults(sthis, name, sopts.data?.car, base, "car"),
|
5186
|
+
file: ensureURIDefaults(sthis, name, sopts.data?.file ?? sopts.data?.car, base, "file", { file: true }),
|
5187
|
+
meta: ensureURIDefaults(sthis, name, sopts.data?.meta, base, "meta"),
|
5188
|
+
wal: ensureURIDefaults(sthis, name, sopts.data?.wal, base, "wal")
|
4835
5189
|
}
|
4836
5190
|
};
|
4837
5191
|
}
|
@@ -4895,10 +5249,11 @@ __export(file_exports, {
|
|
4895
5249
|
|
4896
5250
|
// src/version.ts
|
4897
5251
|
var PACKAGE_VERSION = Object.keys({
|
4898
|
-
"0.20.0-dev-preview-
|
5252
|
+
"0.20.0-dev-preview-50": "xxxx"
|
4899
5253
|
})[0];
|
4900
5254
|
export {
|
4901
5255
|
CRDTImpl,
|
5256
|
+
DataAndMetaAndWalAndBaseStore,
|
4902
5257
|
DatabaseImpl,
|
4903
5258
|
Index,
|
4904
5259
|
LedgerFactory,
|
@@ -4915,6 +5270,7 @@ export {
|
|
4915
5270
|
ensureLogger,
|
4916
5271
|
ensureSuperLog,
|
4917
5272
|
ensureSuperThis,
|
5273
|
+
ensureURIDefaults,
|
4918
5274
|
exceptionWrapper,
|
4919
5275
|
falsyToUndef,
|
4920
5276
|
fireproof,
|
@@ -4932,6 +5288,7 @@ export {
|
|
4932
5288
|
onSuperThis,
|
4933
5289
|
runtime_exports as rt,
|
4934
5290
|
runtime_exports as runtime,
|
5291
|
+
storeType2DataMetaWal,
|
4935
5292
|
throwFalsy,
|
4936
5293
|
toSortedArray,
|
4937
5294
|
toStoreURIRuntime
|