@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
@@ -32,9 +32,9 @@ import { Future } from "@adviser/cement";
|
|
32
32
|
|
33
33
|
describe("noop Gateway", function () {
|
34
34
|
let db: Ledger;
|
35
|
-
let carStore: bs.
|
35
|
+
let carStore: bs.CarStore;
|
36
36
|
let metaStore: bs.MetaStore;
|
37
|
-
let fileStore: bs.
|
37
|
+
let fileStore: bs.FileStore;
|
38
38
|
let walStore: bs.WALStore;
|
39
39
|
let carGateway: bs.SerdeGateway;
|
40
40
|
let metaGateway: bs.SerdeGateway;
|
@@ -43,21 +43,22 @@ describe("noop Gateway", function () {
|
|
43
43
|
const sthis = ensureSuperThis();
|
44
44
|
let ctx: { loader: bs.Loadable };
|
45
45
|
|
46
|
-
afterEach(async
|
46
|
+
afterEach(async () => {
|
47
47
|
await db.close();
|
48
48
|
await db.destroy();
|
49
49
|
});
|
50
|
-
beforeEach(async
|
50
|
+
beforeEach(async () => {
|
51
51
|
db = LedgerFactory("test-gateway-" + sthis.nextId().str, {
|
52
52
|
logger: sthis.logger,
|
53
53
|
});
|
54
|
-
|
54
|
+
await db.ready();
|
55
|
+
ctx = { loader: db.crdt.blockstore.loader };
|
55
56
|
|
56
57
|
// Extract stores from the loader
|
57
|
-
carStore =
|
58
|
-
metaStore =
|
59
|
-
fileStore =
|
60
|
-
walStore =
|
58
|
+
carStore = ctx.loader.attachedStores.local().active.car;
|
59
|
+
metaStore = ctx.loader.attachedStores.local().active.meta;
|
60
|
+
fileStore = ctx.loader.attachedStores.local().active.file;
|
61
|
+
walStore = ctx.loader.attachedStores.local().active.wal;
|
61
62
|
|
62
63
|
// Extract and log gateways
|
63
64
|
carGateway = carStore.realGateway;
|
@@ -66,7 +67,7 @@ describe("noop Gateway", function () {
|
|
66
67
|
walGateway = walStore.realGateway;
|
67
68
|
});
|
68
69
|
|
69
|
-
it("should have valid stores and gateways", async
|
70
|
+
it("should have valid stores and gateways", async () => {
|
70
71
|
// Add assertions
|
71
72
|
expect(carStore).toBeTruthy();
|
72
73
|
expect(metaStore).toBeTruthy();
|
@@ -79,7 +80,7 @@ describe("noop Gateway", function () {
|
|
79
80
|
expect(walGateway).toBeTruthy();
|
80
81
|
});
|
81
82
|
|
82
|
-
it("should have correct store names", async
|
83
|
+
it("should have correct store names", async () => {
|
83
84
|
// Check that all stores have the correct name
|
84
85
|
expect(carStore.url().getParam(PARAM.NAME)).toContain("test-gateway");
|
85
86
|
expect(metaStore.url().getParam(PARAM.NAME)).toContain("test-gateway");
|
@@ -87,16 +88,16 @@ describe("noop Gateway", function () {
|
|
87
88
|
expect(walStore.url().getParam(PARAM.NAME)).toContain("test-gateway");
|
88
89
|
});
|
89
90
|
|
90
|
-
it("should have correct store types in URLs", async
|
91
|
+
it("should have correct store types in URLs", async () => {
|
91
92
|
// Check that all stores have the correct store type in their URL
|
92
|
-
expect(carStore.url().toString()).toContain("store=
|
93
|
+
expect(carStore.url().toString()).toContain("store=car");
|
93
94
|
expect(carStore.url().toString()).toContain("suffix=.car");
|
94
95
|
expect(metaStore.url().toString()).toContain("store=meta");
|
95
|
-
expect(fileStore.url().toString()).toContain("store=
|
96
|
+
expect(fileStore.url().toString()).toContain("store=file");
|
96
97
|
expect(walStore.url().toString()).toContain("store=wal");
|
97
98
|
});
|
98
99
|
|
99
|
-
it("should have version specified in URLs", async
|
100
|
+
it("should have version specified in URLs", async () => {
|
100
101
|
// Verify that all stores have a version specified
|
101
102
|
expect(carStore.url().toString()).toContain("version=");
|
102
103
|
expect(metaStore.url().toString()).toContain("version=");
|
@@ -104,7 +105,7 @@ describe("noop Gateway", function () {
|
|
104
105
|
expect(walStore.url().toString()).toContain("version=");
|
105
106
|
});
|
106
107
|
|
107
|
-
it("should have correct gateway types", async
|
108
|
+
it("should have correct gateway types", async () => {
|
108
109
|
// Check that all gateways are instances of the expected gateway class
|
109
110
|
expect(typeof carGateway).toBe("object");
|
110
111
|
expect(typeof metaGateway).toBe("object");
|
@@ -112,18 +113,18 @@ describe("noop Gateway", function () {
|
|
112
113
|
expect(typeof walGateway).toBe("object");
|
113
114
|
});
|
114
115
|
|
115
|
-
it("should build CAR Gateway URL", async
|
116
|
+
it("should build CAR Gateway URL", async () => {
|
116
117
|
const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
|
117
118
|
const carUrl = await carGateway.buildUrl(ctx, carStore.url(), testKey);
|
118
119
|
expect(carUrl.Ok().hasParam("key")).toBeTruthy();
|
119
120
|
});
|
120
121
|
|
121
|
-
it("should start CAR Gateway", async
|
122
|
+
it("should start CAR Gateway", async () => {
|
122
123
|
const url = await carGateway.start(ctx, carStore.url());
|
123
124
|
expect(url.Ok().asObj()).toEqual(carStore.url().asObj());
|
124
125
|
});
|
125
126
|
|
126
|
-
it("should put data in CAR Gateway", async
|
127
|
+
it("should put data in CAR Gateway", async () => {
|
127
128
|
const carUrl = await carGateway.buildUrl(ctx, carStore.url(), fileContent.cid);
|
128
129
|
await carGateway.start(ctx, carStore.url());
|
129
130
|
const carPutResult = await carGateway.put(ctx, carUrl.Ok(), {
|
@@ -133,7 +134,7 @@ describe("noop Gateway", function () {
|
|
133
134
|
expect(carPutResult.isOk()).toBeTruthy();
|
134
135
|
});
|
135
136
|
|
136
|
-
it("should get data from CAR Gateway", async
|
137
|
+
it("should get data from CAR Gateway", async () => {
|
137
138
|
const carUrl = await carGateway.buildUrl(ctx, carStore.url(), fileContent.cid);
|
138
139
|
await carGateway.start(ctx, carStore.url());
|
139
140
|
await carGateway.put(ctx, carUrl.Ok(), {
|
@@ -146,7 +147,7 @@ describe("noop Gateway", function () {
|
|
146
147
|
// customExpect(carGetResult.Ok(), (v) => expect(v).toEqual(testData), "carGetResult should match testData");
|
147
148
|
});
|
148
149
|
|
149
|
-
it("should delete data from CAR Gateway", async
|
150
|
+
it("should delete data from CAR Gateway", async () => {
|
150
151
|
const carUrl = await carGateway.buildUrl(ctx, carStore.url(), fileContent.cid);
|
151
152
|
await carGateway.start(ctx, carStore.url());
|
152
153
|
await carGateway.put(ctx, carUrl.Ok(), {
|
@@ -157,33 +158,33 @@ describe("noop Gateway", function () {
|
|
157
158
|
expect(carDeleteResult.isOk()).toBeTruthy();
|
158
159
|
});
|
159
160
|
|
160
|
-
it("should close CAR Gateway", async
|
161
|
+
it("should close CAR Gateway", async () => {
|
161
162
|
await carGateway.close(ctx, carStore.url());
|
162
163
|
});
|
163
|
-
it("should build Meta Gateway URL", async
|
164
|
+
it("should build Meta Gateway URL", async () => {
|
164
165
|
const metaUrl = await metaGateway.buildUrl(ctx, metaStore.url(), "main");
|
165
166
|
expect(metaUrl.Ok()).toBeTruthy();
|
166
167
|
});
|
167
168
|
|
168
|
-
it("should start Meta Gateway", async
|
169
|
+
it("should start Meta Gateway", async () => {
|
169
170
|
await metaGateway.start(ctx, metaStore.url());
|
170
171
|
});
|
171
172
|
|
172
|
-
it("should close Meta Gateway", async
|
173
|
+
it("should close Meta Gateway", async () => {
|
173
174
|
await metaGateway.start(ctx, metaStore.url());
|
174
175
|
await metaGateway.close(ctx, metaStore.url());
|
175
176
|
});
|
176
177
|
|
177
|
-
it("should build File Gateway URL", async
|
178
|
+
it("should build File Gateway URL", async () => {
|
178
179
|
const fileUrl = await fileGateway.buildUrl(ctx, fileStore.url(), fileContent.cid);
|
179
180
|
expect(fileUrl.Ok()).toBeTruthy();
|
180
181
|
});
|
181
182
|
|
182
|
-
it("should start File Gateway", async
|
183
|
+
it("should start File Gateway", async () => {
|
183
184
|
await fileGateway.start(ctx, fileStore.url());
|
184
185
|
});
|
185
186
|
|
186
|
-
it("should put data to File Gateway", async
|
187
|
+
it("should put data to File Gateway", async () => {
|
187
188
|
const fileUrl = await fileGateway.buildUrl(ctx, fileStore.url(), fileContent.cid);
|
188
189
|
await fileGateway.start(ctx, fileStore.url());
|
189
190
|
const filePutResult = await fileGateway.put(ctx, fileUrl.Ok(), {
|
@@ -193,7 +194,7 @@ describe("noop Gateway", function () {
|
|
193
194
|
expect(filePutResult.Ok()).toBeFalsy();
|
194
195
|
});
|
195
196
|
|
196
|
-
it("should get data from File Gateway", async
|
197
|
+
it("should get data from File Gateway", async () => {
|
197
198
|
const fileUrl = await fileGateway.buildUrl(ctx, fileStore.url(), fileContent.cid);
|
198
199
|
await fileGateway.start(ctx, fileStore.url());
|
199
200
|
await fileGateway.put(ctx, fileUrl.Ok(), {
|
@@ -205,7 +206,7 @@ describe("noop Gateway", function () {
|
|
205
206
|
expect(fileGetResult.Ok().payload).toEqual(fileContent.block);
|
206
207
|
});
|
207
208
|
|
208
|
-
it("should delete data from File Gateway", async
|
209
|
+
it("should delete data from File Gateway", async () => {
|
209
210
|
const fileUrl = await fileGateway.buildUrl(ctx, fileStore.url(), fileContent.cid);
|
210
211
|
await fileGateway.start(ctx, fileStore.url());
|
211
212
|
await fileGateway.put(ctx, fileUrl.Ok(), {
|
@@ -216,20 +217,20 @@ describe("noop Gateway", function () {
|
|
216
217
|
expect(fileDeleteResult.isOk()).toBeTruthy();
|
217
218
|
});
|
218
219
|
|
219
|
-
it("should close File Gateway", async
|
220
|
+
it("should close File Gateway", async () => {
|
220
221
|
await fileGateway.close(ctx, fileStore.url());
|
221
222
|
});
|
222
|
-
it("should build WAL Gateway URL", async
|
223
|
+
it("should build WAL Gateway URL", async () => {
|
223
224
|
const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
|
224
225
|
const walUrl = await walGateway.buildUrl(ctx, walStore.url(), testKey);
|
225
226
|
expect(walUrl.Ok()).toBeTruthy();
|
226
227
|
});
|
227
228
|
|
228
|
-
it("should start WAL Gateway", async
|
229
|
+
it("should start WAL Gateway", async () => {
|
229
230
|
await walGateway.start(ctx, walStore.url());
|
230
231
|
});
|
231
232
|
|
232
|
-
it("should put data to WAL Gateway", async
|
233
|
+
it("should put data to WAL Gateway", async () => {
|
233
234
|
const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
|
234
235
|
const walUrl = await walGateway.buildUrl(ctx, walStore.url(), testKey);
|
235
236
|
await walGateway.start(ctx, walStore.url());
|
@@ -246,7 +247,7 @@ describe("noop Gateway", function () {
|
|
246
247
|
expect(walPutResult.Ok()).toBeFalsy();
|
247
248
|
});
|
248
249
|
|
249
|
-
it("should get data from WAL Gateway", async
|
250
|
+
it("should get data from WAL Gateway", async () => {
|
250
251
|
const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
|
251
252
|
const walUrl = await walGateway.buildUrl(ctx, walStore.url(), testKey);
|
252
253
|
await walGateway.start(ctx, walStore.url());
|
@@ -285,7 +286,7 @@ describe("noop Gateway", function () {
|
|
285
286
|
expect(ref).toEqual(walGetResult.Ok().payload);
|
286
287
|
});
|
287
288
|
|
288
|
-
it("should delete data from WAL Gateway", async
|
289
|
+
it("should delete data from WAL Gateway", async () => {
|
289
290
|
const testKey = "bafkreidxwt2nhvbl4fnqfw3ctlt6zbrir4kqwmjo5im6rf4q5si27kgo2i";
|
290
291
|
const walUrl = await walGateway.buildUrl(ctx, walStore.url(), testKey);
|
291
292
|
await walGateway.start(ctx, walStore.url());
|
@@ -315,12 +316,12 @@ describe("noop Gateway", function () {
|
|
315
316
|
expect(walDeleteResult.isOk()).toBeTruthy();
|
316
317
|
});
|
317
318
|
|
318
|
-
it("should close WAL Gateway", async
|
319
|
+
it("should close WAL Gateway", async () => {
|
319
320
|
await walGateway.start(ctx, walStore.url());
|
320
321
|
await walGateway.close(ctx, walStore.url());
|
321
322
|
});
|
322
323
|
|
323
|
-
// it("should have correct CAR Gateway properties", async
|
324
|
+
// it("should have correct CAR Gateway properties", async () =>{
|
324
325
|
// // CAR Gateway assertions
|
325
326
|
// expect(carGateway.fidLength).toBe(4);
|
326
327
|
// expect(carGateway.headerSize).toBe(36);
|
@@ -331,7 +332,7 @@ describe("noop Gateway", function () {
|
|
331
332
|
// expect(carStore.).toHaveProperty("url");
|
332
333
|
// });
|
333
334
|
|
334
|
-
// it("should have correct Meta Gateway properties", async
|
335
|
+
// it("should have correct Meta Gateway properties", async () =>{
|
335
336
|
// // Meta Gateway assertions
|
336
337
|
// expect(metaGateway.fidLength).toBe(4);
|
337
338
|
// expect(metaGateway.headerSize).toBe(36);
|
@@ -342,7 +343,7 @@ describe("noop Gateway", function () {
|
|
342
343
|
// expect(last).not.toHaveProperty("url");
|
343
344
|
// });
|
344
345
|
|
345
|
-
// it("should have correct File Gateway properties", async
|
346
|
+
// it("should have correct File Gateway properties", async () =>{
|
346
347
|
// // File Gateway assertions
|
347
348
|
// expect(fileGateway.fidLength).toBe(4);
|
348
349
|
// expect(fileGateway.headerSize).toBe(36);
|
@@ -353,7 +354,7 @@ describe("noop Gateway", function () {
|
|
353
354
|
// expect(last).toHaveProperty("url");
|
354
355
|
// });
|
355
356
|
|
356
|
-
// it("should have correct WAL Gateway properties", async
|
357
|
+
// it("should have correct WAL Gateway properties", async () =>{
|
357
358
|
// // WAL Gateway assertions
|
358
359
|
// expect(walGateway.fidLength).toBe(4);
|
359
360
|
// expect(walGateway.headerSize).toBe(36);
|
@@ -374,20 +375,22 @@ describe("noop Gateway subscribe", function () {
|
|
374
375
|
const sthis = ensureSuperThis();
|
375
376
|
let ctx: bs.SerdeGatewayCtx;
|
376
377
|
|
377
|
-
afterEach(async
|
378
|
+
afterEach(async () => {
|
378
379
|
await db.close();
|
379
380
|
await db.destroy();
|
380
381
|
});
|
381
|
-
beforeEach(async
|
382
|
+
beforeEach(async () => {
|
382
383
|
db = fireproof("test-gateway-" + sthis.nextId().str);
|
383
384
|
|
385
|
+
await db.ready();
|
386
|
+
|
384
387
|
ctx = { loader: db.ledger.crdt.blockstore.loader };
|
385
388
|
// Extract stores from the loader
|
386
|
-
metaStore =
|
389
|
+
metaStore = db.ledger.crdt.blockstore.loader.attachedStores.local().active.meta;
|
387
390
|
|
388
391
|
metaGateway = metaStore.realGateway;
|
389
392
|
});
|
390
|
-
it("should subscribe to meta Gateway", async
|
393
|
+
it("should subscribe to meta Gateway", async () => {
|
391
394
|
const metaUrl = await metaGateway.buildUrl(ctx, metaStore.url(), "main");
|
392
395
|
await metaGateway.start(ctx, metaStore.url());
|
393
396
|
|
@@ -427,11 +430,11 @@ describe("Gateway", function () {
|
|
427
430
|
|
428
431
|
let ctx: bs.SerdeGatewayCtx;
|
429
432
|
|
430
|
-
afterEach(async
|
433
|
+
afterEach(async () => {
|
431
434
|
await db.close();
|
432
435
|
await db.destroy();
|
433
436
|
});
|
434
|
-
beforeEach(async
|
437
|
+
beforeEach(async () => {
|
435
438
|
db = fireproof("test-gateway-" + sthis.nextId().str);
|
436
439
|
ctx = { loader: db.ledger.crdt.blockstore.loader };
|
437
440
|
const ok = await db.put({ _id: "test", foo: "bar" });
|
@@ -440,7 +443,7 @@ describe("Gateway", function () {
|
|
440
443
|
|
441
444
|
// Extract stores from the loader
|
442
445
|
// carStore = (await db.blockstore.loader.carStore()) as unknown as ExtendedStore;
|
443
|
-
metaStore =
|
446
|
+
metaStore = db.ledger.crdt.blockstore.loader.attachedStores.local().active.meta;
|
444
447
|
// fileStore = (await db.blockstore.loader.fileStore()) as unknown as ExtendedStore;
|
445
448
|
// walStore = (await db.blockstore.loader.WALStore()) as unknown as ExtendedStore;
|
446
449
|
|
@@ -451,7 +454,7 @@ describe("Gateway", function () {
|
|
451
454
|
// walGateway = walStore.gateway;
|
452
455
|
});
|
453
456
|
|
454
|
-
it("should get data from Meta Gateway", async
|
457
|
+
it("should get data from Meta Gateway", async () => {
|
455
458
|
const metaUrl = await metaGateway.buildUrl(ctx, metaStore.url(), "main");
|
456
459
|
await metaGateway.start(ctx, metaStore.url());
|
457
460
|
const metaGetResult = await metaGateway.get(ctx, metaUrl.Ok());
|
@@ -463,7 +466,7 @@ describe("Gateway", function () {
|
|
463
466
|
expect(Object.keys(meta[0])).toEqual(["eventCid", "parents", "dbMeta"]);
|
464
467
|
});
|
465
468
|
|
466
|
-
it("should delete data from Meta Gateway", async
|
469
|
+
it("should delete data from Meta Gateway", async () => {
|
467
470
|
const metaUrl = await metaGateway.buildUrl(ctx, metaStore.url(), "main");
|
468
471
|
await metaGateway.start(ctx, metaStore.url());
|
469
472
|
// should we be testing .destroy() instead?
|
@@ -0,0 +1,356 @@
|
|
1
|
+
import { URI } from "@adviser/cement";
|
2
|
+
import { stripper } from "@adviser/cement/utils";
|
3
|
+
import { Attachable, Database, ensureSuperThis, fireproof, GatewayUrlsParam, PARAM, rt, Attached, bs } from "@fireproof/core";
|
4
|
+
import { CarReader } from "@ipld/car/reader";
|
5
|
+
import * as dagCbor from "@ipld/dag-cbor";
|
6
|
+
import { sleep } from "../helpers.js";
|
7
|
+
import { mockLoader } from "../helpers.js";
|
8
|
+
|
9
|
+
describe("meta check", () => {
|
10
|
+
const sthis = ensureSuperThis();
|
11
|
+
it("empty Database", async () => {
|
12
|
+
const name = `remote-db-${sthis.nextId().str}`;
|
13
|
+
const db = fireproof(name, {
|
14
|
+
storeUrls: {
|
15
|
+
base: `memory://${name}`,
|
16
|
+
},
|
17
|
+
});
|
18
|
+
await db.ready();
|
19
|
+
const gws = db.ledger.crdt.blockstore.loader.attachedStores.local();
|
20
|
+
await db.close();
|
21
|
+
expect(
|
22
|
+
Array.from(((gws.active.car.realGateway as rt.gw.DefSerdeGateway).gw as rt.gw.memory.MemoryGateway).memorys.entries()).filter(
|
23
|
+
([k]) => k.startsWith(`memory://${name}`),
|
24
|
+
),
|
25
|
+
).toEqual([]);
|
26
|
+
});
|
27
|
+
|
28
|
+
it("one record Database", async () => {
|
29
|
+
const name = `remote-db-${sthis.nextId().str}`;
|
30
|
+
const db = fireproof(name, {
|
31
|
+
storeUrls: {
|
32
|
+
base: `memory://${name}`,
|
33
|
+
},
|
34
|
+
});
|
35
|
+
await db.put({ _id: `id-${0}`, value: `value-${0}` });
|
36
|
+
await db.close();
|
37
|
+
|
38
|
+
const db1 = fireproof(name, {
|
39
|
+
storeUrls: {
|
40
|
+
base: `memory://${name}`,
|
41
|
+
},
|
42
|
+
});
|
43
|
+
await db1.close();
|
44
|
+
});
|
45
|
+
|
46
|
+
it("multiple record Database", async () => {
|
47
|
+
const name = `remote-db-${sthis.nextId().str}`;
|
48
|
+
const base = `memory://${name}?storekey=insecure`;
|
49
|
+
const db = fireproof(name, {
|
50
|
+
storeUrls: {
|
51
|
+
base,
|
52
|
+
},
|
53
|
+
});
|
54
|
+
await db.ready();
|
55
|
+
await db.put({ _id: `id-${0}`, value: `value-${0}` });
|
56
|
+
const gws = db.ledger.crdt.blockstore.loader.attachedStores.local();
|
57
|
+
expect(db.ledger.crdt.blockstore.loader.carLog.asArray().map((i) => i.map((i) => i.toString()))).toEqual([
|
58
|
+
["baembeieldbalgnyxqp7rmj4cbrot75gweavqy3aw22km43zsfufrihfn7e"],
|
59
|
+
["baembeig2is4vdgz4gyiadfh5uutxxeiuqtacnesnytrnilpwcu7q5m5tmu"],
|
60
|
+
]);
|
61
|
+
await db.close();
|
62
|
+
expect(
|
63
|
+
Array.from(((gws.active.car.realGateway as rt.gw.DefSerdeGateway).gw as rt.gw.memory.MemoryGateway).memorys.entries())
|
64
|
+
.filter(([k]) => k.startsWith(`memory://${name}`))
|
65
|
+
.map(([k]) =>
|
66
|
+
stripper(
|
67
|
+
["name", "storekey", "version"],
|
68
|
+
Array.from(URI.from(k).getParams).reduce((acc, [k, v]) => ({ ...acc, [k]: v }), {}),
|
69
|
+
),
|
70
|
+
),
|
71
|
+
).toEqual([
|
72
|
+
{
|
73
|
+
key: "baembeig2is4vdgz4gyiadfh5uutxxeiuqtacnesnytrnilpwcu7q5m5tmu",
|
74
|
+
store: "car",
|
75
|
+
suffix: ".car",
|
76
|
+
},
|
77
|
+
{
|
78
|
+
key: "main",
|
79
|
+
store: "wal",
|
80
|
+
},
|
81
|
+
{
|
82
|
+
key: "main",
|
83
|
+
store: "meta",
|
84
|
+
},
|
85
|
+
{
|
86
|
+
key: "baembeieldbalgnyxqp7rmj4cbrot75gweavqy3aw22km43zsfufrihfn7e",
|
87
|
+
store: "car",
|
88
|
+
suffix: ".car",
|
89
|
+
},
|
90
|
+
]);
|
91
|
+
|
92
|
+
const db1 = fireproof(name, {
|
93
|
+
storeUrls: {
|
94
|
+
base,
|
95
|
+
},
|
96
|
+
});
|
97
|
+
expect(db1.ledger).not.equal(db.ledger);
|
98
|
+
await db1.ready();
|
99
|
+
expect(db1.ledger.crdt.blockstore.loader.carLog.asArray().map((i) => i.map((i) => i.toString()))).toEqual([
|
100
|
+
["baembeieldbalgnyxqp7rmj4cbrot75gweavqy3aw22km43zsfufrihfn7e"],
|
101
|
+
["baembeig2is4vdgz4gyiadfh5uutxxeiuqtacnesnytrnilpwcu7q5m5tmu"],
|
102
|
+
]);
|
103
|
+
|
104
|
+
const gensis = await db1.get(PARAM.GENESIS_CID);
|
105
|
+
expect(gensis).toEqual({ _id: PARAM.GENESIS_CID });
|
106
|
+
|
107
|
+
const val = await db1.allDocs();
|
108
|
+
expect(val.rows).toEqual([
|
109
|
+
{
|
110
|
+
key: "id-0",
|
111
|
+
value: {
|
112
|
+
_id: "id-0",
|
113
|
+
value: "value-0",
|
114
|
+
},
|
115
|
+
},
|
116
|
+
]);
|
117
|
+
const car = Array.from(
|
118
|
+
((gws.active.car.realGateway as rt.gw.DefSerdeGateway).gw as rt.gw.memory.MemoryGateway).memorys.entries(),
|
119
|
+
)
|
120
|
+
.filter(([k]) => k.startsWith(`memory://${name}`))
|
121
|
+
.map(([k, v]) => [URI.from(k).getParam(PARAM.KEY), v])
|
122
|
+
.find(([k]) => k === "baembeig2is4vdgz4gyiadfh5uutxxeiuqtacnesnytrnilpwcu7q5m5tmu") as [string, Uint8Array];
|
123
|
+
const rawReader = await CarReader.fromBytes(car[1]);
|
124
|
+
const blocks = [];
|
125
|
+
for await (const block of rawReader.blocks()) {
|
126
|
+
blocks.push(block);
|
127
|
+
}
|
128
|
+
expect(dagCbor.decode(blocks[1].bytes)).toEqual({
|
129
|
+
doc: {
|
130
|
+
_id: "baembeiarootfireproofgenesisblockaaaafireproofgenesisblocka",
|
131
|
+
},
|
132
|
+
});
|
133
|
+
|
134
|
+
expect(blocks.map((i) => i.cid.toString())).toEqual([
|
135
|
+
"bafyreibxibqhi6wh5klrje7ne4htffeqyyqfd6y7x2no6wnhid4nixizau",
|
136
|
+
"bafyreidnvv4mwvweup5w52ddre2sl4syhvczm6ejqsmuekajowdl2cf2q4",
|
137
|
+
"bafyreihh6nbfbhgkf5lz7hhsscjgiquw426rxzr3fprbgonekzmyvirrhe",
|
138
|
+
"bafyreiejg3twlaxr7gfvvhtxrhvwaydytdv4guidmtvaz5dskm6gp73ryi",
|
139
|
+
"bafyreiblui55o25dopc5faol3umsnuohb5carto7tot4kicnkfc37he4h4",
|
140
|
+
]);
|
141
|
+
});
|
142
|
+
});
|
143
|
+
|
144
|
+
describe("activate store", () => {
|
145
|
+
// activate(store: DataAndMetaStore | CoerceURI): ActiveStore {
|
146
|
+
// if (isCoerceURI(store)) {
|
147
|
+
// throw this.loadable.sthis.logger.Error().Msg("store must be an object").AsError();
|
148
|
+
// }
|
149
|
+
// return new ActiveStoreImpl(store as DataAndMetaStore, this);
|
150
|
+
// }
|
151
|
+
|
152
|
+
const sthis = ensureSuperThis();
|
153
|
+
let attach: bs.AttachedStores;
|
154
|
+
let firstAttached: Attached;
|
155
|
+
let secondAttached: Attached;
|
156
|
+
beforeEach(async () => {
|
157
|
+
attach = new bs.AttachedRemotesImpl(mockLoader(sthis));
|
158
|
+
firstAttached = await attach.attach({
|
159
|
+
name: "first",
|
160
|
+
prepare: async () => ({
|
161
|
+
car: { url: "memory://first?store=car" },
|
162
|
+
meta: { url: "memory://first?store=meta" },
|
163
|
+
file: { url: "memory://first" },
|
164
|
+
wal: { url: "memory://first?store=wal" },
|
165
|
+
}),
|
166
|
+
});
|
167
|
+
|
168
|
+
secondAttached = await attach.attach({
|
169
|
+
name: "second",
|
170
|
+
prepare: async () => ({
|
171
|
+
car: { url: "memory://second?store=car" },
|
172
|
+
meta: { url: "memory://second?store=meta" },
|
173
|
+
file: { url: "memory://second?store=file" },
|
174
|
+
}),
|
175
|
+
});
|
176
|
+
});
|
177
|
+
|
178
|
+
it("activate by store", async () => {
|
179
|
+
expect(attach.activate(secondAttached.stores).active.car.url().toString()).toBe(
|
180
|
+
"memory://second?name=second&store=car&storekey=%40second-data%40&suffix=.car&version=v0.19-memory",
|
181
|
+
);
|
182
|
+
expect(attach.activate(firstAttached.stores).local().active.car.url().toString()).toBe(
|
183
|
+
"memory://first?name=first&store=car&storekey=%40first-data%40&suffix=.car&version=v0.19-memory",
|
184
|
+
);
|
185
|
+
expect(attach.activate(firstAttached.stores).active.meta.url().toString()).toBe(
|
186
|
+
"memory://first?name=first&store=meta&storekey=%40first-meta%40&version=v0.19-memory",
|
187
|
+
);
|
188
|
+
});
|
189
|
+
|
190
|
+
it("activate by store", async () => {
|
191
|
+
expect(attach.activate("memory://second").active.car.url().toString()).toBe(
|
192
|
+
"memory://second?name=second&store=car&storekey=%40second-data%40&suffix=.car&version=v0.19-memory",
|
193
|
+
);
|
194
|
+
expect(attach.activate("memory://second").remotes()[0].active.car.url().toString()).toEqual(
|
195
|
+
"memory://second?name=second&store=car&storekey=%40second-data%40&suffix=.car&version=v0.19-memory",
|
196
|
+
);
|
197
|
+
expect(attach.activate("memory://first?store=meta").active.car.url().toString()).toBe(
|
198
|
+
"memory://first?name=first&store=car&storekey=%40first-data%40&suffix=.car&version=v0.19-memory",
|
199
|
+
);
|
200
|
+
});
|
201
|
+
});
|
202
|
+
|
203
|
+
describe("join function", () => {
|
204
|
+
const sthis = ensureSuperThis();
|
205
|
+
// export const connect: ConnectFunction = (
|
206
|
+
// db: Database,
|
207
|
+
// remoteDbName = "",
|
208
|
+
// url = "netlify://localhost:8888?protocol=ws"
|
209
|
+
// ) => {
|
210
|
+
// const { sthis, name: dbName } = db;
|
211
|
+
// if (!dbName) {
|
212
|
+
// throw new Error("dbName is required");
|
213
|
+
// }
|
214
|
+
// const urlObj = BuildURI.from(url);
|
215
|
+
// const existingName = urlObj.getParam("name");
|
216
|
+
// urlObj.defParam("name", remoteDbName || existingName || dbName);
|
217
|
+
// urlObj.defParam("localName", dbName);
|
218
|
+
// urlObj.defParam("storekey", `@${dbName}:data@`);
|
219
|
+
// return connectionCache.get(urlObj.toString()).once(() => {
|
220
|
+
// makeKeyBagUrlExtractable(sthis);
|
221
|
+
// const connection = connectionFactory(sthis, urlObj);
|
222
|
+
// connection.connect(db.ledger.crdt.blockstore);
|
223
|
+
// return connection;
|
224
|
+
// });
|
225
|
+
// };
|
226
|
+
class AJoinable implements Attachable {
|
227
|
+
readonly name: string;
|
228
|
+
constructor(name: string) {
|
229
|
+
this.name = name;
|
230
|
+
}
|
231
|
+
prepare(): Promise<GatewayUrlsParam> {
|
232
|
+
return Promise.resolve({
|
233
|
+
car: { url: `memory://car/${this.name}` },
|
234
|
+
meta: { url: `memory://meta/${this.name}` },
|
235
|
+
file: { url: `memory://file/${this.name}` },
|
236
|
+
});
|
237
|
+
}
|
238
|
+
}
|
239
|
+
function aJoinable(name: string): Attachable {
|
240
|
+
return new AJoinable(name);
|
241
|
+
}
|
242
|
+
|
243
|
+
let db: Database;
|
244
|
+
let joinableDBs: string[] = [];
|
245
|
+
beforeAll(async () => {
|
246
|
+
const set = sthis.nextId().str;
|
247
|
+
joinableDBs = await Promise.all(
|
248
|
+
new Array(10).fill(1).map(async (_, i) => {
|
249
|
+
const name = `remote-db-${i}-${set}`;
|
250
|
+
const db = fireproof(name, {
|
251
|
+
storeUrls: {
|
252
|
+
// base: `memory://${name}`,
|
253
|
+
data: {
|
254
|
+
car: `memory://car/${name}`,
|
255
|
+
meta: `memory://meta/${name}`,
|
256
|
+
file: `memory://file/${name}`,
|
257
|
+
wal: `memory://wal/${name}`,
|
258
|
+
},
|
259
|
+
},
|
260
|
+
});
|
261
|
+
// await db.put({ _id: `genesis`, value: `genesis` });
|
262
|
+
// await db.ready();
|
263
|
+
for (let j = 0; j < 10; j++) {
|
264
|
+
await db.put({ _id: `${i}-${j}`, value: `${i}-${j}` });
|
265
|
+
}
|
266
|
+
expect(await db.get(PARAM.GENESIS_CID)).toEqual({ _id: PARAM.GENESIS_CID });
|
267
|
+
await db.close();
|
268
|
+
return name;
|
269
|
+
}),
|
270
|
+
);
|
271
|
+
// await new Promise((resolve) => setTimeout(resolve, 1000));
|
272
|
+
|
273
|
+
db = fireproof(`db-${set}`, {
|
274
|
+
storeUrls: {
|
275
|
+
base: `memory://db-${set}`,
|
276
|
+
},
|
277
|
+
});
|
278
|
+
// await db.put({ _id: `genesis`, value: `genesis` });
|
279
|
+
for (let j = 0; j < 10; j++) {
|
280
|
+
await db.put({ _id: `db-${j}`, value: `db-${set}` });
|
281
|
+
}
|
282
|
+
expect(await db.get(PARAM.GENESIS_CID)).toEqual({ _id: PARAM.GENESIS_CID });
|
283
|
+
});
|
284
|
+
afterAll(async () => {
|
285
|
+
await db.close();
|
286
|
+
});
|
287
|
+
|
288
|
+
it("it is joinable detachable", async () => {
|
289
|
+
const my = fireproof("my", {
|
290
|
+
storeUrls: {
|
291
|
+
base: "memory://my",
|
292
|
+
},
|
293
|
+
});
|
294
|
+
await my.put({ _id: "genesis", value: "genesis" });
|
295
|
+
await Promise.all(
|
296
|
+
joinableDBs.map(async (name) => {
|
297
|
+
const tmp = fireproof(name, {
|
298
|
+
storeUrls: {
|
299
|
+
data: {
|
300
|
+
car: `memory://car/${name}`,
|
301
|
+
meta: `memory://meta/${name}`,
|
302
|
+
file: `memory://file/${name}`,
|
303
|
+
wal: `memory://wal/${name}`,
|
304
|
+
},
|
305
|
+
},
|
306
|
+
});
|
307
|
+
const res = await tmp.allDocs();
|
308
|
+
expect(res.rows.length).toBe(10);
|
309
|
+
await tmp.close();
|
310
|
+
const attached = await my.attach(aJoinable(name));
|
311
|
+
expect(attached).toBeDefined();
|
312
|
+
}),
|
313
|
+
);
|
314
|
+
expect(my.ledger.crdt.blockstore.loader.attachedStores.remotes().length).toBe(joinableDBs.length);
|
315
|
+
await my.close();
|
316
|
+
expect(my.ledger.crdt.blockstore.loader.attachedStores.remotes().length).toBe(0);
|
317
|
+
});
|
318
|
+
|
319
|
+
it("it is inbound syncing", async () => {
|
320
|
+
await Promise.all(
|
321
|
+
joinableDBs.map(async (name) => {
|
322
|
+
const attached = await db.attach(aJoinable(name));
|
323
|
+
expect(attached).toBeDefined();
|
324
|
+
}),
|
325
|
+
);
|
326
|
+
await sleep(100);
|
327
|
+
expect(db.ledger.crdt.blockstore.loader.attachedStores.remotes().length).toBe(joinableDBs.length);
|
328
|
+
const res = await db.allDocs();
|
329
|
+
expect(res.rows.length).toBe(10 + 10 * joinableDBs.length);
|
330
|
+
});
|
331
|
+
|
332
|
+
it("it empty inbound syncing", async () => {
|
333
|
+
const name = `empty-db-${sthis.nextId().str}`;
|
334
|
+
const db = fireproof(name, {
|
335
|
+
storeUrls: {
|
336
|
+
// base: `memory://${name}`,
|
337
|
+
data: {
|
338
|
+
car: `memory://car/${name}`,
|
339
|
+
meta: `memory://meta/${name}`,
|
340
|
+
file: `memory://file/${name}`,
|
341
|
+
wal: `memory://wal/${name}`,
|
342
|
+
},
|
343
|
+
},
|
344
|
+
});
|
345
|
+
await Promise.all(
|
346
|
+
joinableDBs.map(async (name) => {
|
347
|
+
const attached = await db.attach(aJoinable(name));
|
348
|
+
expect(attached).toBeDefined();
|
349
|
+
}),
|
350
|
+
);
|
351
|
+
await sleep(100);
|
352
|
+
expect(db.ledger.crdt.blockstore.loader.attachedStores.remotes().length).toBe(joinableDBs.length);
|
353
|
+
const res = await db.allDocs();
|
354
|
+
expect(res.rows.length).toBe(10 * joinableDBs.length);
|
355
|
+
});
|
356
|
+
});
|