@fireproof/core 0.16.6 → 0.17.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +15 -6
- package/dist/browser/fireproof.cjs +79 -62
- package/dist/browser/fireproof.cjs.map +1 -1
- package/dist/browser/fireproof.d.cts +4 -4
- package/dist/browser/fireproof.d.ts +4 -4
- package/dist/browser/fireproof.global.js +730 -281
- package/dist/browser/fireproof.global.js.map +1 -1
- package/dist/browser/fireproof.js +81 -64
- package/dist/browser/fireproof.js.map +1 -1
- package/dist/browser/metafile-cjs.json +1 -1
- package/dist/browser/metafile-esm.json +1 -1
- package/dist/browser/metafile-iife.json +1 -1
- package/dist/memory/fireproof.cjs +79 -62
- package/dist/memory/fireproof.cjs.map +1 -1
- package/dist/memory/fireproof.d.cts +4 -4
- package/dist/memory/fireproof.d.ts +4 -4
- package/dist/memory/fireproof.global.js +730 -281
- package/dist/memory/fireproof.global.js.map +1 -1
- package/dist/memory/fireproof.js +81 -64
- package/dist/memory/fireproof.js.map +1 -1
- package/dist/memory/metafile-cjs.json +1 -1
- package/dist/memory/metafile-esm.json +1 -1
- package/dist/memory/metafile-iife.json +1 -1
- package/dist/node/fireproof.cjs +79 -62
- package/dist/node/fireproof.cjs.map +1 -1
- package/dist/node/fireproof.d.cts +4 -4
- package/dist/node/fireproof.d.ts +4 -4
- package/dist/node/fireproof.global.js +730 -281
- package/dist/node/fireproof.global.js.map +1 -1
- package/dist/node/fireproof.js +81 -64
- package/dist/node/fireproof.js.map +1 -1
- package/dist/node/metafile-cjs.json +1 -1
- package/dist/node/metafile-esm.json +1 -1
- package/dist/node/metafile-iife.json +1 -1
- package/package.json +4 -7
package/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
|
2
2
|
|
3
|
-
# <img src="https://fireproof.storage/static/img/flame.svg" alt="Fireproof logo" width="25"> Fireproof
|
3
|
+
# <img src="https://fireproof.storage/static/img/flame.svg" alt="Fireproof logo" width="25"> [Fireproof](https://fireproof.storage) – live database for the web
|
4
4
|
|
5
5
|
<p align="right">
|
6
6
|
<a href="https://github.com/fireproof-storage/fireproof/actions/workflows/test.yml">
|
@@ -10,7 +10,11 @@
|
|
10
10
|
|
11
11
|
Simplify your application state with a live database. Automatically update your UI based on local or remote changes, and optionally integrate with any cloud for replication and sharing.
|
12
12
|
|
13
|
-
Fireproof is an embedded JavaScript document database designed to streamline app development. Data resides locally, with optional encrypted cloud storage and
|
13
|
+
Fireproof is an embedded JavaScript document database designed to streamline app development. Data resides locally, with optional encrypted cloud storage and real-time sync and collaboration. Features like live queries, database branches and snapshots, and file attachments make Fireproof ideal for browser-based apps big or small.
|
14
|
+
|
15
|
+
Fireproof works in the browser, server, edge function, and any other JavaScript environment, with [connectors for popular backend services like AWS, Netlify, and PartyKit.]()
|
16
|
+
|
17
|
+
### Install Anywhere
|
14
18
|
|
15
19
|
Get started with just the NPM module:
|
16
20
|
|
@@ -24,13 +28,19 @@ or target specific builds via:
|
|
24
28
|
npm install @fireproof/core
|
25
29
|
```
|
26
30
|
|
27
|
-
|
31
|
+
The default build is optimized for browsers, to load the node build add `/node`:
|
32
|
+
|
33
|
+
```js
|
34
|
+
import { fireproof } from '@fireproof/core/node'
|
35
|
+
```
|
36
|
+
|
37
|
+
Add the database to any web page via HTML script tag:
|
28
38
|
|
29
39
|
```html
|
30
40
|
<script src="https://cdn.jsdelivr.net/npm/@fireproof/core/dist/web/fireproof.iife.js"></script>
|
31
41
|
```
|
32
42
|
|
33
|
-
|
43
|
+
Go ahead and write features, then [connect to any cloud backend](https://www.npmjs.com/package/@fireproof/connect) later.
|
34
44
|
|
35
45
|
### JavaScript Example
|
36
46
|
|
@@ -50,7 +60,6 @@ const result = await db.query("age", { range: [40, 52] })
|
|
50
60
|
|
51
61
|
Jump to the docs site [for JavaScript API basics.](https://use-fireproof.com/docs/database-api/basics) You can [find a real-world JavaScript app here.](https://github.com/mlc-ai/web-stable-diffusion/pull/52) Fireproof has been tested in many JavaScript environments. Read more about [bundler support](https://use-fireproof.com/docs/bundling).
|
52
62
|
|
53
|
-
|
54
63
|
### React Example
|
55
64
|
|
56
65
|
Fireproof has React hooks so you can avoid boilerplate and write expressive code. Instead of dealing with React contexts and reducers, simple hooks make your JSON documents feel like `setState()` objects.
|
@@ -67,7 +76,7 @@ Read the [step-by-step React tutorial](https://use-fireproof.com/docs/react-tuto
|
|
67
76
|
|
68
77
|
## Why choose Fireproof
|
69
78
|
|
70
|
-
Fireproof has a unique take on distributed data integrity, rooted in immutable data and cryptographically verifiable protocols. This allows you to add live data to
|
79
|
+
Fireproof has a unique take on distributed data integrity, rooted in immutable data and cryptographically verifiable protocols. This allows you to add live data to any app without complex configuration or installation (it's just an npm module) and if you decide to connect to the cloud you can easily choose storage providers or connect to your own S3 bucket. End-to-end encryption allows you to manage keys separately from data, defining custom security policies, so you can get started writing app features today, and connect to any environment when you are ready. This infrastructure independence makes Fireproof great for brownfield and greenfield projects alike.
|
71
80
|
|
72
81
|
[Read more about the thinking behind Fireproof on our blog.](https://fireproof.storage/blog/) The community is active on [Discord](https://discord.gg/cCryrNHePH) and [X](https://twitter.com/FireproofStorge), among other places.
|
73
82
|
|
@@ -91,8 +91,9 @@ var import_block = require("multiformats/block");
|
|
91
91
|
var import_link = require("multiformats/link");
|
92
92
|
var import_sha2 = require("multiformats/hashes/sha2");
|
93
93
|
var codec = __toESM(require("@ipld/dag-cbor"), 1);
|
94
|
-
var import_crdt = require("@
|
95
|
-
var import_clock = require("@
|
94
|
+
var import_crdt = require("@web3-storage/pail/crdt");
|
95
|
+
var import_clock = require("@web3-storage/pail/clock");
|
96
|
+
var Batch = __toESM(require("@web3-storage/pail/crdt/batch"), 1);
|
96
97
|
var import_encrypted_blockstore = require("@fireproof/encrypted-blockstore");
|
97
98
|
|
98
99
|
// src/files.ts
|
@@ -164,30 +165,43 @@ var UnixFSFileBuilder = class {
|
|
164
165
|
};
|
165
166
|
|
166
167
|
// src/crdt-helpers.ts
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
`missing root in additions: ${result.additions.length} ${resRoot} keys: ${updates.map((u) => u.key).toString()}`
|
179
|
-
);
|
180
|
-
result.head = head;
|
181
|
-
}
|
168
|
+
function time(tag) {
|
169
|
+
}
|
170
|
+
function timeEnd(tag) {
|
171
|
+
}
|
172
|
+
async function applyBulkUpdateToCrdt(tblocks, head, updates) {
|
173
|
+
let result = null;
|
174
|
+
if (updates.length > 1) {
|
175
|
+
const batch = await Batch.create(tblocks, head);
|
176
|
+
for (const update of updates) {
|
177
|
+
const link = await writeDocContent(tblocks, update);
|
178
|
+
await batch.put(update.key, link);
|
182
179
|
}
|
183
|
-
|
184
|
-
|
185
|
-
|
180
|
+
result = await batch.commit();
|
181
|
+
} else {
|
182
|
+
for (const update of updates) {
|
183
|
+
const link = await writeDocContent(tblocks, update);
|
184
|
+
result = await (0, import_crdt.put)(tblocks, head, update.key, link);
|
185
|
+
const resRoot = result.root.toString();
|
186
|
+
const isReturned = result.additions.some((a) => a.cid.toString() === resRoot);
|
187
|
+
if (!isReturned) {
|
188
|
+
const hasRoot = await tblocks.get(result.root);
|
189
|
+
if (!hasRoot) {
|
190
|
+
throw new Error(
|
191
|
+
`missing root in additions: ${result.additions.length} ${resRoot} keys: ${updates.map((u) => u.key).toString()}`
|
192
|
+
);
|
193
|
+
}
|
186
194
|
}
|
187
|
-
head = result.head;
|
188
195
|
}
|
189
196
|
}
|
190
|
-
|
197
|
+
if (!result)
|
198
|
+
throw new Error("Missing result");
|
199
|
+
if (result.event) {
|
200
|
+
for (const { cid, bytes } of [...result.additions, ...result.removals, result.event]) {
|
201
|
+
tblocks.putSync(cid, bytes);
|
202
|
+
}
|
203
|
+
}
|
204
|
+
return { head: result.head };
|
191
205
|
}
|
192
206
|
async function writeDocContent(blocks, update) {
|
193
207
|
let value;
|
@@ -325,38 +339,34 @@ async function gatherUpdates(blocks, eventsFetcher, head, since, updates = [], k
|
|
325
339
|
const { value: event } = await eventsFetcher.get(link);
|
326
340
|
if (!event)
|
327
341
|
continue;
|
328
|
-
const {
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
} else {
|
343
|
-
keys.add(key);
|
344
|
-
const docValue = await getValueFromLink(blocks, value);
|
345
|
-
updates.push({ key, value: docValue.doc, del: docValue.del, clock: link });
|
346
|
-
limit--;
|
347
|
-
if (event.parents) {
|
348
|
-
updates = await gatherUpdates(
|
349
|
-
blocks,
|
350
|
-
eventsFetcher,
|
351
|
-
event.parents,
|
352
|
-
since,
|
353
|
-
updates,
|
354
|
-
keys,
|
355
|
-
didLinks,
|
356
|
-
limit
|
357
|
-
);
|
342
|
+
const { type } = event.data;
|
343
|
+
let ops = [];
|
344
|
+
if (type === "batch") {
|
345
|
+
ops = event.data.ops;
|
346
|
+
} else if (type === "put") {
|
347
|
+
ops = [event.data];
|
348
|
+
}
|
349
|
+
for (let i = ops.length - 1; i >= 0; i--) {
|
350
|
+
const { key, value } = ops[i];
|
351
|
+
if (!keys.has(key)) {
|
352
|
+
const docValue = await getValueFromLink(blocks, value);
|
353
|
+
updates.push({ key, value: docValue.doc, del: docValue.del, clock: link });
|
354
|
+
limit--;
|
355
|
+
keys.add(key);
|
358
356
|
}
|
359
357
|
}
|
358
|
+
if (event.parents) {
|
359
|
+
updates = await gatherUpdates(
|
360
|
+
blocks,
|
361
|
+
eventsFetcher,
|
362
|
+
event.parents,
|
363
|
+
since,
|
364
|
+
updates,
|
365
|
+
keys,
|
366
|
+
didLinks,
|
367
|
+
limit
|
368
|
+
);
|
369
|
+
}
|
360
370
|
}
|
361
371
|
return updates;
|
362
372
|
}
|
@@ -378,25 +388,32 @@ async function doCompact(blockLog, head) {
|
|
378
388
|
return;
|
379
389
|
}
|
380
390
|
isCompacting = true;
|
391
|
+
time("compact head");
|
381
392
|
for (const cid of head) {
|
382
393
|
const bl = await blockLog.get(cid);
|
383
394
|
if (!bl)
|
384
395
|
throw new Error("Missing head block: " + cid.toString());
|
385
396
|
}
|
386
|
-
|
387
|
-
|
388
|
-
for await (const
|
389
|
-
const bl = await blockLog.get(link);
|
390
|
-
if (!bl)
|
391
|
-
throw new Error("Missing entry block: " + link.toString());
|
397
|
+
timeEnd("compact head");
|
398
|
+
time("compact all entries");
|
399
|
+
for await (const _entry of getAllEntries(blockLog, head)) {
|
392
400
|
}
|
401
|
+
timeEnd("compact all entries");
|
402
|
+
time("compact clock vis");
|
393
403
|
for await (const _line of (0, import_clock.vis)(blockLog, head)) {
|
394
404
|
}
|
405
|
+
timeEnd("compact clock vis");
|
406
|
+
time("compact root");
|
395
407
|
const result = await (0, import_crdt.root)(blockLog, head);
|
408
|
+
timeEnd("compact root");
|
409
|
+
time("compact root blocks");
|
396
410
|
for (const { cid, bytes } of [...result.additions, ...result.removals]) {
|
397
411
|
blockLog.loggedBlocks.putSync(cid, bytes);
|
398
412
|
}
|
413
|
+
timeEnd("compact root blocks");
|
414
|
+
time("compact changes");
|
399
415
|
await clockChangesSince(blockLog, head, [], {});
|
416
|
+
timeEnd("compact changes");
|
400
417
|
isCompacting = false;
|
401
418
|
}
|
402
419
|
async function getBlock(blocks, cidString) {
|
@@ -760,8 +777,8 @@ function makeMapFnFromName(name) {
|
|
760
777
|
}
|
761
778
|
|
762
779
|
// src/crdt-clock.ts
|
763
|
-
var import_clock2 = require("@
|
764
|
-
var import_crdt2 = require("@
|
780
|
+
var import_clock2 = require("@web3-storage/pail/clock");
|
781
|
+
var import_crdt2 = require("@web3-storage/pail/crdt");
|
765
782
|
|
766
783
|
// src/apply-head-queue.ts
|
767
784
|
function applyHeadQueue(worker) {
|
@@ -958,12 +975,12 @@ var CRDT = class {
|
|
958
975
|
}
|
959
976
|
});
|
960
977
|
}
|
961
|
-
async bulk(updates
|
978
|
+
async bulk(updates) {
|
962
979
|
await this.ready;
|
963
980
|
const prevHead = [...this.clock.head];
|
964
981
|
const meta = await this.blockstore.transaction(
|
965
982
|
async (blocks) => {
|
966
|
-
const { head } = await applyBulkUpdateToCrdt(blocks, this.clock.head, updates
|
983
|
+
const { head } = await applyBulkUpdateToCrdt(blocks, this.clock.head, updates);
|
967
984
|
updates = updates.map(({ key, value, del, clock }) => {
|
968
985
|
readFiles(this.blockstore, { doc: value });
|
969
986
|
return { key, value, del, clock };
|