@fireproof/core 0.19.5-dev → 0.19.8-dev-alldocs

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.
Files changed (55) hide show
  1. package/{chunk-QHSXUST7.js → chunk-5UFCF36O.js} +3 -3
  2. package/{chunk-HCXR2M5B.js → chunk-DG6XSV44.js} +175 -7
  3. package/chunk-DG6XSV44.js.map +1 -0
  4. package/{chunk-H3A2HMMM.js → chunk-OWQAHX2V.js} +2 -2
  5. package/chunk-OWQAHX2V.js.map +1 -0
  6. package/{chunk-7OGPZSGT.js → chunk-PRQHQG4I.js} +2 -2
  7. package/index.cjs +248 -191
  8. package/index.cjs.map +1 -1
  9. package/index.d.cts +174 -68
  10. package/index.d.ts +174 -68
  11. package/index.global.js +24688 -0
  12. package/index.global.js.map +1 -0
  13. package/index.js +60 -127
  14. package/index.js.map +1 -1
  15. package/metafile-cjs.json +1 -1
  16. package/metafile-esm.json +1 -1
  17. package/metafile-iife.json +1 -0
  18. package/{node-sys-container-E7LADX2Z.js → node-sys-container-TTGEC66A.js} +2 -2
  19. package/package.json +1 -1
  20. package/{sqlite-data-store-YS4U7AQ4.js → sqlite-data-store-MA55LVQE.js} +4 -4
  21. package/{sqlite-meta-store-FJZSZG4R.js → sqlite-meta-store-UNQKVYRM.js} +4 -4
  22. package/{sqlite-wal-store-6JZ4URNS.js → sqlite-wal-store-KVUOC4PO.js} +4 -4
  23. package/{store-file-HMHPQTUV.js → store-file-WD746RSY.js} +3 -3
  24. package/{store-indexdb-MRVZG4OG.js → store-indexdb-NG45BU3Q.js} +4 -4
  25. package/{store-sql-5XMJ5OWJ.js → store-sql-QVFNIGND.js} +7 -69
  26. package/store-sql-QVFNIGND.js.map +1 -0
  27. package/tests/blockstore/loader.test.ts +265 -0
  28. package/tests/blockstore/store.test.ts +164 -0
  29. package/tests/blockstore/transaction.test.ts +121 -0
  30. package/tests/fireproof/config.test.ts +212 -0
  31. package/tests/fireproof/crdt.test.ts +434 -0
  32. package/tests/fireproof/database.test.ts +466 -0
  33. package/tests/fireproof/fireproof.test.ts +602 -0
  34. package/tests/fireproof/hello.test.ts +54 -0
  35. package/tests/fireproof/indexer.test.ts +389 -0
  36. package/tests/helpers.ts +81 -0
  37. package/tests/react/useFireproof.test.tsx +19 -0
  38. package/tests/www/gallery.html +132 -0
  39. package/tests/www/iife.html +42 -0
  40. package/tests/www/todo-aws.html +232 -0
  41. package/tests/www/todo-ipfs.html +213 -0
  42. package/tests/www/todo-local.html +214 -0
  43. package/tests/www/todo-netlify.html +227 -0
  44. package/tests/www/todo.html +236 -0
  45. package/chunk-H3A2HMMM.js.map +0 -1
  46. package/chunk-HCXR2M5B.js.map +0 -1
  47. package/store-sql-5XMJ5OWJ.js.map +0 -1
  48. /package/{chunk-QHSXUST7.js.map → chunk-5UFCF36O.js.map} +0 -0
  49. /package/{chunk-7OGPZSGT.js.map → chunk-PRQHQG4I.js.map} +0 -0
  50. /package/{node-sys-container-E7LADX2Z.js.map → node-sys-container-TTGEC66A.js.map} +0 -0
  51. /package/{sqlite-data-store-YS4U7AQ4.js.map → sqlite-data-store-MA55LVQE.js.map} +0 -0
  52. /package/{sqlite-meta-store-FJZSZG4R.js.map → sqlite-meta-store-UNQKVYRM.js.map} +0 -0
  53. /package/{sqlite-wal-store-6JZ4URNS.js.map → sqlite-wal-store-KVUOC4PO.js.map} +0 -0
  54. /package/{store-file-HMHPQTUV.js.map → store-file-WD746RSY.js.map} +0 -0
  55. /package/{store-indexdb-MRVZG4OG.js.map → store-indexdb-NG45BU3Q.js.map} +0 -0
@@ -0,0 +1,466 @@
1
+ import { buildBlobFiles, FileWithCid } from "../helpers.js";
2
+ import { rt, bs, Database, DbResponse, DocFileMeta, DocWithId, DocFiles } from "@fireproof/core";
3
+
4
+ describe("basic Database", () => {
5
+ let db: Database;
6
+ afterEach(async () => {
7
+ await db.close();
8
+ await db.destroy();
9
+ });
10
+ beforeEach(async () => {
11
+ await rt.SysContainer.start();
12
+ db = new Database();
13
+ });
14
+ it("should put", async () => {
15
+ /** @type {Doc} */
16
+ const doc = { _id: "hello", value: "world" };
17
+ const ok = await db.put(doc);
18
+ expect(ok.id).toBe("hello");
19
+ });
20
+ it("get missing should throw", async () => {
21
+ const e = await db.get("missing").catch((e) => e);
22
+ expect(e.message).toMatch(/Not found/);
23
+ });
24
+ it("del missing should result in deleted state", async () => {
25
+ await db.del("missing");
26
+
27
+ const e = await db.get("missing").catch((e) => e);
28
+ expect(e.message).toMatch(/Not found/);
29
+ });
30
+ it("has no changes", async () => {
31
+ const { rows } = await db.changes([]);
32
+ expect(rows.length).toBe(0);
33
+ });
34
+ });
35
+
36
+ describe("basic Database with record", function () {
37
+ interface Doc {
38
+ readonly value: string;
39
+ }
40
+ let db: Database;
41
+ afterEach(async () => {
42
+ await db.close();
43
+ await db.destroy();
44
+ });
45
+ beforeEach(async function () {
46
+ await rt.SysContainer.start();
47
+ db = new Database();
48
+ const ok = await db.put<Doc>({ _id: "hello", value: "world" });
49
+ expect(ok.id).toBe("hello");
50
+ });
51
+ it("should get", async function () {
52
+ const doc = await db.get<Doc>("hello");
53
+ expect(doc).toBeTruthy();
54
+ expect(doc._id).toBe("hello");
55
+ expect(doc.value).toBe("world");
56
+ });
57
+ it("should update", async function () {
58
+ const ok = await db.put({ _id: "hello", value: "universe" });
59
+ expect(ok.id).toBe("hello");
60
+ const doc = await db.get<Doc>("hello");
61
+ expect(doc).toBeTruthy();
62
+ expect(doc._id).toBe("hello");
63
+ expect(doc.value).toBe("universe");
64
+ });
65
+ it("should del last record", async function () {
66
+ const ok = await db.del("hello");
67
+ expect(ok.id).toBe("hello");
68
+
69
+ const e = await db.get("hello").catch((e) => e);
70
+ expect(e.message).toMatch(/Not found/);
71
+ });
72
+ it("has changes", async function () {
73
+ const { rows } = await db.changes([]);
74
+ expect(rows.length).toBe(1);
75
+ expect(rows[0].key).toBe("hello");
76
+ expect(rows[0].value._id).toBe("hello");
77
+ });
78
+ it("is not persisted", async function () {
79
+ const db2 = new Database();
80
+ const { rows } = await db2.changes([]);
81
+ expect(rows.length).toBe(0);
82
+ const doc = await db2.get("hello").catch((e) => e);
83
+ expect(doc.message).toBeTruthy();
84
+ await db2.close();
85
+ await db2.destroy();
86
+ });
87
+ });
88
+
89
+ describe("named Database with record", function () {
90
+ interface Doc {
91
+ readonly value: string;
92
+ }
93
+ let db: Database;
94
+ afterEach(async () => {
95
+ await db.close();
96
+ await db.destroy();
97
+ });
98
+ beforeEach(async function () {
99
+ await rt.SysContainer.start();
100
+ db = new Database("test-db-name");
101
+ /** @type {Doc} */
102
+ const doc = { _id: "hello", value: "world" };
103
+ const ok = await db.put(doc);
104
+ expect(ok.id).toBe("hello");
105
+ });
106
+ it("should get", async function () {
107
+ const doc = await db.get<Doc>("hello");
108
+ expect(doc).toBeTruthy();
109
+ expect(doc._id).toBe("hello");
110
+ expect(doc.value).toBe("world");
111
+ });
112
+ it("should update", async function () {
113
+ const ok = await db.put({ _id: "hello", value: "universe" });
114
+ expect(ok.id).toBe("hello");
115
+ const doc = await db.get<Doc>("hello");
116
+ expect(doc).toBeTruthy();
117
+ expect(doc._id).toBe("hello");
118
+ expect(doc.value).toBe("universe");
119
+ });
120
+ it("should del last record", async function () {
121
+ const ok = await db.del("hello");
122
+ expect(ok.id).toBe("hello");
123
+
124
+ const e = await db.get("hello").catch((e) => e);
125
+ expect(e.message).toMatch(/Not found/);
126
+ });
127
+ it("has changes", async function () {
128
+ const { rows } = await db.changes([]);
129
+ expect(rows.length).toBe(1);
130
+ expect(rows[0].key).toBe("hello");
131
+ expect(rows[0].value._id).toBe("hello");
132
+ });
133
+ it("should have a key", async function () {
134
+ const { rows } = await db.changes([]);
135
+ expect(rows.length).toBe(1);
136
+ const blocks = db._crdt.blockstore as bs.EncryptedBlockstore;
137
+ const loader = blocks.loader;
138
+ expect(loader).toBeTruthy();
139
+ await loader.ready();
140
+ expect(loader.key?.length).toBe(64);
141
+ expect(loader.keyId?.length).toBe(64);
142
+ expect(loader.key).not.toBe(loader.keyId);
143
+ });
144
+ it("should work right with a sequence of changes", async function () {
145
+ const numDocs = 10;
146
+ for (let i = 0; i < numDocs; i++) {
147
+ const doc = { _id: `id-${i}`, hello: "world" };
148
+ const ok = await db.put(doc);
149
+ expect(ok.id).toBe(`id-${i}`);
150
+ }
151
+ const { rows } = await db.changes([]);
152
+ expect(rows.length).toBe(numDocs + 1);
153
+
154
+ const ok6 = await db.put({ _id: `id-${6}`, hello: "block" });
155
+ expect(ok6.id).toBe(`id-${6}`);
156
+
157
+ for (let i = 0; i < numDocs; i++) {
158
+ const id = `id-${i}`;
159
+ const doc = await db.get<{ hello: string }>(id);
160
+ expect(doc).toBeTruthy();
161
+ expect(doc._id).toBe(id);
162
+ expect(doc.hello.length).toBe(5);
163
+ }
164
+
165
+ const { rows: rows2 } = await db.changes([]);
166
+ expect(rows2.length).toBe(numDocs + 1);
167
+
168
+ const ok7 = await db.del(`id-${7}`);
169
+ expect(ok7.id).toBe(`id-${7}`);
170
+
171
+ const { rows: rows3 } = await db.changes([]);
172
+ expect(rows3.length).toBe(numDocs + 1);
173
+ expect(rows3[numDocs].key).toBe(`id-${7}`);
174
+ expect(rows3[numDocs].value._deleted).toBe(true);
175
+
176
+ // test limit
177
+ const { rows: rows4 } = await db.changes([], { limit: 5 });
178
+ expect(rows4.length).toBe(5);
179
+ });
180
+
181
+ it("should work right after compaction", async function () {
182
+ const numDocs = 10;
183
+ for (let i = 0; i < numDocs; i++) {
184
+ const doc = { _id: `id-${i}`, hello: "world" };
185
+ const ok = await db.put(doc);
186
+ expect(ok.id).toBe(`id-${i}`);
187
+ }
188
+ const { rows } = await db.changes([]);
189
+ expect(rows.length).toBe(numDocs + 1);
190
+
191
+ await db.compact();
192
+
193
+ const { rows: rows3 } = await db.changes([], { dirty: true });
194
+ expect(rows3.length).toBe(numDocs + 1);
195
+
196
+ const { rows: rows4 } = await db.changes([], { dirty: false });
197
+ expect(rows4.length).toBe(numDocs + 1);
198
+ });
199
+ });
200
+
201
+ // describe('basic Database parallel writes / public', function () {
202
+ // /** @type {Database} */
203
+ // let db
204
+ // const writes = []
205
+ // beforeEach(async function () {
206
+ // await resetDirectory(dataDir, 'test-parallel-writes')
207
+ // db = new Database('test-parallel-writes', { public: true })
208
+ // /** @type {Doc} */
209
+ // for (let i = 0; i < 10; i++) {
210
+ // const doc = { _id: `id-${i}`, hello: 'world' }
211
+ // writes.push(db.put(doc))
212
+ // }
213
+ // await Promise.all(writes)
214
+ // })
215
+
216
+ describe("basic Database parallel writes / public", function () {
217
+ let db: Database;
218
+ const writes: Promise<DbResponse>[] = [];
219
+ afterEach(async () => {
220
+ await db.close();
221
+ await db.destroy();
222
+ });
223
+ beforeEach(async function () {
224
+ await rt.SysContainer.start();
225
+ db = new Database("test-parallel-writes", { public: true });
226
+ for (let i = 0; i < 10; i++) {
227
+ const doc = { _id: `id-${i}`, hello: "world" };
228
+ writes.push(db.put(doc));
229
+ }
230
+ await Promise.all(writes);
231
+ });
232
+ it("should have one head", function () {
233
+ const crdt = db._crdt;
234
+ expect(crdt.clock.head.length).toBe(1);
235
+ });
236
+ it("should write all", async function () {
237
+ for (let i = 0; i < 10; i++) {
238
+ const id = `id-${i}`;
239
+ const doc = await db.get<{ hello: string }>(id);
240
+ expect(doc).toBeTruthy();
241
+ expect(doc._id).toBe(id);
242
+ expect(doc.hello).toBe("world");
243
+ }
244
+ });
245
+ it("should del all", async function () {
246
+ for (let i = 0; i < 10; i++) {
247
+ const id = `id-${i}`;
248
+ const ok = await db.del(id);
249
+ expect(ok.id).toBe(id);
250
+
251
+ const e = await db.get(id).catch((e) => e);
252
+ expect(e.message).toMatch(/Not found/);
253
+ }
254
+ });
255
+ it("should delete all in parallel", async function () {
256
+ const deletes: Promise<DbResponse>[] = [];
257
+ for (let i = 0; i < 10; i++) {
258
+ const id = `id-${i}`;
259
+ deletes.push(db.del(id));
260
+ }
261
+ await Promise.all(deletes);
262
+ for (let i = 0; i < 10; i++) {
263
+ const id = `id-${i}`;
264
+ const e = await db.get(id).catch((e) => e);
265
+ expect(e.message).toMatch(/Not found/);
266
+ }
267
+ });
268
+ it("has changes", async function () {
269
+ const { rows, clock } = await db.changes([]);
270
+ expect(clock[0]).toBe(db._crdt.clock.head[0]);
271
+ expect(rows.length).toBe(10);
272
+ // rows.sort((a, b) => a.key.localeCompare(b.key));
273
+ for (let i = 0; i < 10; i++) {
274
+ expect(rows[i].key).toBe("id-" + i);
275
+ expect(rows[i].clock).toBeTruthy();
276
+ }
277
+ });
278
+ it("should not have a key", async function () {
279
+ const { rows } = await db.changes([]);
280
+ expect(rows.length).toBe(10);
281
+ expect(db.opts.public).toBeTruthy();
282
+ expect(db._crdt.opts.public).toBeTruthy();
283
+ const blocks = db._crdt.blockstore as bs.EncryptedBlockstore;
284
+ const loader = blocks.loader;
285
+ expect(loader).toBeTruthy();
286
+ await loader.ready();
287
+ expect(loader.key).toBeUndefined();
288
+ expect(loader.keyId).toBeUndefined();
289
+ });
290
+ });
291
+
292
+ describe("basic Database with subscription", function () {
293
+ let db: Database;
294
+ let didRun: number;
295
+ let unsubscribe: () => void;
296
+ let lastDoc: DocWithId<NonNullable<unknown>>;
297
+ let waitForSub: Promise<void>;
298
+ afterEach(async () => {
299
+ await db.close();
300
+ await db.destroy();
301
+ });
302
+ beforeEach(async function () {
303
+ await rt.SysContainer.start();
304
+ db = new Database();
305
+ didRun = 0;
306
+ waitForSub = new Promise((resolve) => {
307
+ unsubscribe = db.subscribe((docs) => {
308
+ lastDoc = docs[0];
309
+ // lastDoc = {_id: "ok"};
310
+ didRun++;
311
+ resolve();
312
+ }, true);
313
+ });
314
+ });
315
+ it("should run on put", async function () {
316
+ const all = await db.allDocs();
317
+ expect(all.rows.length).toBe(0);
318
+ const doc = { _id: "hello", message: "world" };
319
+ expect(didRun).toBe(0);
320
+ const ok = await db.put(doc);
321
+ await waitForSub;
322
+ expect(didRun).toBeTruthy();
323
+ expect(lastDoc).toBeTruthy();
324
+ expect(lastDoc._id).toBe("hello");
325
+ expect(ok.id).toBe("hello");
326
+ expect(didRun).toBe(1);
327
+ });
328
+ it("should unsubscribe", async function () {
329
+ unsubscribe();
330
+ const doc = { _id: "hello", message: "again" };
331
+ const ok = await db.put(doc);
332
+ expect(ok.id).toBe("hello");
333
+ expect(didRun).toBe(0);
334
+ });
335
+ });
336
+
337
+ describe("basic Database with no update subscription", function () {
338
+ let db: Database;
339
+ let didRun: number;
340
+ let unsubscribe: () => void;
341
+ afterEach(async () => {
342
+ await db.close();
343
+ await db.destroy();
344
+ });
345
+ beforeEach(async function () {
346
+ await rt.SysContainer.start();
347
+ db = new Database();
348
+ didRun = 0;
349
+
350
+ unsubscribe = db.subscribe(() => {
351
+ didRun++;
352
+ });
353
+ });
354
+ it("should run on put", async function () {
355
+ const all = await db.allDocs();
356
+ expect(all.rows.length).toBe(0);
357
+ /** @type {Doc} */
358
+ const doc = { _id: "hello", message: "world" };
359
+ expect(didRun).toBe(0);
360
+ const ok = await db.put(doc);
361
+ expect(ok.id).toBe("hello");
362
+ expect(didRun).toBe(1);
363
+ });
364
+ it("should unsubscribe", async function () {
365
+ unsubscribe();
366
+ const doc = { _id: "hello", message: "again" };
367
+ const ok = await db.put(doc);
368
+ expect(ok.id).toBe("hello");
369
+ expect(didRun).toBe(0);
370
+ });
371
+ });
372
+
373
+ describe("database with files input", () => {
374
+ let db: Database;
375
+ let imagefiles: FileWithCid[] = [];
376
+ let result: DbResponse;
377
+
378
+ afterEach(async () => {
379
+ await db.close();
380
+ await db.destroy();
381
+ });
382
+ beforeEach(async function () {
383
+ await rt.SysContainer.start();
384
+ imagefiles = await buildBlobFiles();
385
+ db = new Database("fireproof-with-images");
386
+ const doc = {
387
+ _id: "images-main",
388
+ type: "files",
389
+ _files: {
390
+ one: imagefiles[0].file,
391
+ two: imagefiles[1].file,
392
+ },
393
+ };
394
+ result = await db.put(doc);
395
+ });
396
+
397
+ it("Should upload images", async function () {
398
+ expect(result.id).toBe("images-main");
399
+ });
400
+
401
+ it("Should fetch the images", async function () {
402
+ const doc = await db.get(result.id);
403
+ const files = doc._files as DocFiles;
404
+ expect(files).toBeTruthy();
405
+ const keys = Object.keys(files);
406
+ let fileMeta = files[keys[0]] as DocFileMeta;
407
+ expect(fileMeta).toBeTruthy();
408
+ expect(imagefiles[0].file.type).toBeTruthy();
409
+ expect(fileMeta.type).toBeTruthy();
410
+ expect(fileMeta.type).toBe(imagefiles[0].file.type);
411
+ expect(fileMeta.size).toBe(imagefiles[0].file.size);
412
+ expect(fileMeta.cid.toString()).toBe(imagefiles[0].cid);
413
+ expect(typeof fileMeta.file).toBe("function");
414
+ let file = (await fileMeta.file?.()) as File;
415
+
416
+ expect(file.type).toBe(imagefiles[0].file.type);
417
+ expect(file.size).toBe(imagefiles[0].file.size);
418
+ // expect(file.name).toBe('image.jpg') // see https://github.com/fireproof-storage/fireproof/issues/70
419
+
420
+ fileMeta = files[keys[1]] as DocFileMeta;
421
+ expect(fileMeta.type).toBe(imagefiles[1].file.type);
422
+ expect(fileMeta.size).toBe(imagefiles[1].file.size);
423
+ expect(fileMeta.cid.toString()).toBe(imagefiles[1].cid);
424
+ expect(typeof fileMeta.file).toBe("function");
425
+ file = (await fileMeta.file?.()) as File;
426
+
427
+ expect(file.type).toBe(imagefiles[1].file.type);
428
+ expect(file.size).toBe(imagefiles[1].file.size);
429
+ // expect(file.name).toBe('fireproof.png') // see https://github.com/fireproof-storage/fireproof/issues/70
430
+ });
431
+
432
+ it("should update the file document data without changing the files", async function () {
433
+ interface Doc {
434
+ type: string;
435
+ }
436
+ const doc = await db.get<Doc>(result.id);
437
+ let files = doc._files || {};
438
+ let keys = Object.keys(files);
439
+ let fileMeta = files[keys[0]] as DocFileMeta;
440
+ expect(fileMeta.type).toBe(imagefiles[0].file.type);
441
+ expect(fileMeta.size).toBe(imagefiles[0].file.size);
442
+ expect(fileMeta.cid.toString()).toBe(imagefiles[0].cid);
443
+ expect(typeof fileMeta.file).toBe("function");
444
+ let file = (await fileMeta.file?.()) as File;
445
+
446
+ expect(file.type).toBe(imagefiles[0].file.type);
447
+ expect(file.size).toBe(imagefiles[0].file.size);
448
+
449
+ doc.type = "images";
450
+ const r2 = await db.put(doc);
451
+ expect(r2.id).toBe("images-main");
452
+ const readDoc = await db.get<Doc>(r2.id);
453
+ expect(readDoc.type).toBe("images");
454
+ files = readDoc._files || {};
455
+ keys = Object.keys(files);
456
+ fileMeta = files[keys[0]] as DocFileMeta;
457
+ expect(fileMeta.type).toBe(imagefiles[0].file.type);
458
+ expect(fileMeta.size).toBe(imagefiles[0].file.size);
459
+ expect(fileMeta.cid.toString()).toBe(imagefiles[0].cid);
460
+ expect(typeof fileMeta.file).toBe("function");
461
+ file = (await fileMeta.file?.()) as File;
462
+
463
+ expect(file.type).toBe(imagefiles[0].file.type);
464
+ expect(file.size).toBe(imagefiles[0].file.size);
465
+ });
466
+ });