@fireproof/core 0.3.2 → 0.3.4
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 +1 -1
- package/package.json +39 -5
- package/src/blockstore.js +3 -2
- package/src/clock.js +4 -3
- package/src/crypto.js +1 -0
- package/src/db-index.js +10 -5
- package/src/fireproof.js +15 -10
- package/src/hydrator.js +3 -3
- package/src/index.js +6 -0
- package/src/listener.js +2 -1
- package/src/prolly.js +11 -24
- package/src/sha1.js +2 -1
- package/src/valet.js +7 -5
- package/hooks/use-fireproof.js +0 -135
- package/index.js +0 -6
- package/scripts/keygen.js +0 -3
- package/test/block.js +0 -65
- package/test/clock.test.js +0 -694
- package/test/db-index.test.js +0 -261
- package/test/fireproof.test.js +0 -493
- package/test/fulltext.test.js +0 -66
- package/test/helpers.js +0 -45
- package/test/hydrator.test.js +0 -81
- package/test/listener.test.js +0 -102
- package/test/prolly.test.js +0 -190
- package/test/proofs.test.js +0 -53
- package/test/reproduce-fixture-bug.test.js +0 -65
- package/test/valet.test.js +0 -59
package/README.md
CHANGED
@@ -18,7 +18,7 @@ Fireproof is alpha software, you should only use it if you are planning to contr
|
|
18
18
|
## Usage
|
19
19
|
|
20
20
|
```js
|
21
|
-
import Fireproof from 'fireproof';
|
21
|
+
import { Fireproof } from 'fireproof';
|
22
22
|
|
23
23
|
async function main() {
|
24
24
|
const database = Fireproof.storage('my-db');
|
package/package.json
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fireproof/core",
|
3
|
-
"version": "0.3.
|
3
|
+
"version": "0.3.4",
|
4
4
|
"description": "Realtime database for IPFS",
|
5
|
-
"main": "index.js",
|
5
|
+
"main": "src/index.js",
|
6
6
|
"type": "module",
|
7
|
+
"types": "./dist/src/index.d.ts",
|
7
8
|
"scripts": {
|
8
9
|
"keygen": "node scripts/keygen.js",
|
9
10
|
"test": "standard && npm run test:unencrypted && npm run test:mocha",
|
@@ -14,7 +15,8 @@
|
|
14
15
|
"prepublishOnly": "cp ../../README.md .",
|
15
16
|
"postpublish": "rm README.md",
|
16
17
|
"lint": "standard",
|
17
|
-
"lint:fix": "standard --fix"
|
18
|
+
"lint:fix": "standard --fix",
|
19
|
+
"build": "tsc --build"
|
18
20
|
},
|
19
21
|
"keywords": [
|
20
22
|
"database",
|
@@ -32,7 +34,6 @@
|
|
32
34
|
],
|
33
35
|
"license": "Apache-2.0 OR MIT",
|
34
36
|
"dependencies": {
|
35
|
-
"prolly-trees": "1.0.4",
|
36
37
|
"@ipld/car": "^5.1.0",
|
37
38
|
"@ipld/dag-cbor": "^9.0.0",
|
38
39
|
"archy": "^1.0.0",
|
@@ -40,18 +41,25 @@
|
|
40
41
|
"car-transaction": "^1.0.1",
|
41
42
|
"charwise": "^3.0.1",
|
42
43
|
"cli-color": "^2.0.3",
|
44
|
+
"crypto-browserify": "^3.12.0",
|
43
45
|
"encrypted-block": "^0.0.3",
|
44
46
|
"idb": "^7.1.1",
|
45
47
|
"multiformats": "^11.0.1",
|
48
|
+
"node-polyfill-webpack-plugin": "^2.0.1",
|
49
|
+
"prolly-trees": "1.0.4",
|
46
50
|
"sade": "^1.8.1"
|
47
51
|
},
|
48
52
|
"devDependencies": {
|
49
53
|
"c8": "^7.12.0",
|
50
54
|
"fake-indexeddb": "^4.0.1",
|
51
55
|
"flexsearch": "^0.7.31",
|
56
|
+
"husky": "^8.0.3",
|
52
57
|
"mocha": "^10.2.0",
|
53
58
|
"nanoid": "^4.0.0",
|
54
|
-
"standard": "^17.0.0"
|
59
|
+
"standard": "^17.0.0",
|
60
|
+
"typescript": "^5.0.2",
|
61
|
+
"webpack": "^5.78.0",
|
62
|
+
"webpack-cli": "^5.0.1"
|
55
63
|
},
|
56
64
|
"mocha": {
|
57
65
|
"require": [
|
@@ -73,6 +81,32 @@
|
|
73
81
|
"url": "https://github.com/fireproof-storage/fireproof/issues"
|
74
82
|
},
|
75
83
|
"homepage": "https://fireproof.storage",
|
84
|
+
"exports": {
|
85
|
+
".": {
|
86
|
+
"types": "./dist/src/index.d.ts",
|
87
|
+
"import": "./src/index.js"
|
88
|
+
},
|
89
|
+
"./fireproof": {
|
90
|
+
"types": "./dist/src/fireproof.d.ts",
|
91
|
+
"import": "./src/fireproof.js"
|
92
|
+
},
|
93
|
+
"./hydrator": {
|
94
|
+
"types": "./dist/src/hydrator.d.ts",
|
95
|
+
"import": "./src/hydrator.js"
|
96
|
+
},
|
97
|
+
"./listener": {
|
98
|
+
"types": "./dist/src/listener.d.ts",
|
99
|
+
"import": "./src/listener.js"
|
100
|
+
},
|
101
|
+
"./db-index": {
|
102
|
+
"types": "./dist/src/db-index.d.ts",
|
103
|
+
"import": "./src/db-index.js"
|
104
|
+
}
|
105
|
+
},
|
106
|
+
"files": [
|
107
|
+
"src",
|
108
|
+
"dist"
|
109
|
+
],
|
76
110
|
"workspaces": [
|
77
111
|
"examples/todomvc"
|
78
112
|
]
|
package/src/blockstore.js
CHANGED
@@ -1,6 +1,7 @@
|
|
1
|
+
// @ts-nocheck
|
1
2
|
import { parse } from 'multiformats/link'
|
2
3
|
import { CID } from 'multiformats'
|
3
|
-
import Valet from './valet.js'
|
4
|
+
import { Valet } from './valet.js'
|
4
5
|
|
5
6
|
// const sleep = ms => new Promise(r => setTimeout(r, ms))
|
6
7
|
|
@@ -27,7 +28,7 @@ const husher = (id, workFn) => {
|
|
27
28
|
* A blockstore that caches writes to a transaction and only persists them when committed.
|
28
29
|
* @implements {Blockstore}
|
29
30
|
*/
|
30
|
-
export
|
31
|
+
export class TransactionBlockstore {
|
31
32
|
/** @type {Map<string, Uint8Array>} */
|
32
33
|
committedBlocks = new Map()
|
33
34
|
|
package/src/clock.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
// @ts-nocheck
|
1
2
|
import { Block, encode, decode } from 'multiformats/block'
|
2
3
|
import { sha256 } from 'multiformats/hashes/sha2'
|
3
4
|
import * as cbor from '@ipld/dag-cbor'
|
@@ -22,7 +23,7 @@ import { CIDCounter } from 'prolly-trees/utils'
|
|
22
23
|
* Advance the clock by adding an event.
|
23
24
|
*
|
24
25
|
* @template T
|
25
|
-
* @param {import('
|
26
|
+
* @param {import('./blockstore').BlockFetcher} blocks Block storage.
|
26
27
|
* @param {EventLink<T>[]} head The head of the clock.
|
27
28
|
* @param {EventLink<T>} event The event to add.
|
28
29
|
* @returns {Promise<EventLink<T>[]>} The new head of the clock.
|
@@ -89,7 +90,7 @@ export class EventBlock extends Block {
|
|
89
90
|
|
90
91
|
/** @template T */
|
91
92
|
export class EventFetcher {
|
92
|
-
/** @param {import('
|
93
|
+
/** @param {import('./blockstore').BlockFetcher} blocks */
|
93
94
|
constructor (blocks) {
|
94
95
|
/** @private */
|
95
96
|
this._blocks = blocks
|
@@ -168,7 +169,7 @@ async function contains (events, a, b) {
|
|
168
169
|
|
169
170
|
/**
|
170
171
|
* @template T
|
171
|
-
* @param {import('
|
172
|
+
* @param {import('./blockstore').BlockFetcher} blocks Block storage.
|
172
173
|
* @param {EventLink<T>[]} head
|
173
174
|
* @param {object} [options]
|
174
175
|
* @param {(b: EventBlockView<T>) => string} [options.renderNodeLabel]
|
package/src/crypto.js
CHANGED
package/src/db-index.js
CHANGED
@@ -1,15 +1,20 @@
|
|
1
|
+
// @ts-nocheck
|
2
|
+
// @ts-ignore
|
1
3
|
import { create, load } from 'prolly-trees/db-index'
|
2
4
|
// import { create, load } from '../../../../prolly-trees/src/db-index.js'
|
3
5
|
|
4
6
|
import { sha256 as hasher } from 'multiformats/hashes/sha2'
|
7
|
+
// @ts-ignore
|
5
8
|
import { nocache as cache } from 'prolly-trees/cache'
|
9
|
+
// @ts-ignore
|
6
10
|
import { bf, simpleCompare } from 'prolly-trees/utils'
|
7
11
|
import { makeGetBlock } from './prolly.js'
|
8
12
|
import { cidsToProof } from './fireproof.js'
|
9
13
|
|
10
14
|
import * as codec from '@ipld/dag-cbor'
|
11
15
|
// import { create as createBlock } from 'multiformats/block'
|
12
|
-
import TransactionBlockstore,
|
16
|
+
import { TransactionBlockstore, doTransaction } from './blockstore.js'
|
17
|
+
// @ts-ignore
|
13
18
|
import charwise from 'charwise'
|
14
19
|
|
15
20
|
const ALWAYS_REBUILD = false // todo: make false
|
@@ -87,7 +92,7 @@ const indexEntriesForChanges = (changes, mapFn) => {
|
|
87
92
|
* @param {Function} mapFn - The map function to apply to each entry in the database.
|
88
93
|
*
|
89
94
|
*/
|
90
|
-
export
|
95
|
+
export class DbIndex {
|
91
96
|
constructor (database, mapFn, clock, opts = {}) {
|
92
97
|
// console.log('DbIndex constructor', database.constructor.name, typeof mapFn, clock)
|
93
98
|
/**
|
@@ -172,7 +177,7 @@ export default class DbIndex {
|
|
172
177
|
/**
|
173
178
|
* Query object can have {range}
|
174
179
|
* @param {DbQuery} query - the query range to use
|
175
|
-
* @returns {Promise<{rows: Array<{id: string, key: string, value: any}>}>}
|
180
|
+
* @returns {Promise<{proof: {}, rows: Array<{id: string, key: string, value: any}>}>}
|
176
181
|
* @memberof DbIndex
|
177
182
|
* @instance
|
178
183
|
*/
|
@@ -259,8 +264,8 @@ export default class DbIndex {
|
|
259
264
|
|
260
265
|
/**
|
261
266
|
* Update the DbIndex with the given entries
|
262
|
-
* @param {Blockstore} blocks
|
263
|
-
* @param {
|
267
|
+
* @param {import('./blockstore.js').Blockstore} blocks
|
268
|
+
* @param {{root, cid}} inIndex
|
264
269
|
* @param {DbIndexEntry[]} indexEntries
|
265
270
|
* @private
|
266
271
|
*/
|
package/src/fireproof.js
CHANGED
@@ -1,23 +1,27 @@
|
|
1
|
+
// @ts-nocheck
|
1
2
|
import { randomBytes } from 'crypto'
|
2
3
|
import { visMerkleClock, visMerkleTree, vis, put, get, getAll, eventsSince } from './prolly.js'
|
3
|
-
import TransactionBlockstore,
|
4
|
+
import { TransactionBlockstore, doTransaction } from './blockstore.js'
|
4
5
|
import charwise from 'charwise'
|
6
|
+
// import { CID } from 'multiformats/dist/types/src/cid.js'
|
5
7
|
|
6
8
|
// const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
7
9
|
|
10
|
+
// class Proof {}
|
11
|
+
|
8
12
|
/**
|
9
13
|
* @class Fireproof
|
10
14
|
* @classdesc Fireproof stores data in IndexedDB and provides a Merkle clock.
|
11
15
|
* This is the main class for saving and loading JSON and other documents with the database. You can find additional examples and
|
12
16
|
* usage guides in the repository README.
|
13
17
|
*
|
14
|
-
* @param {
|
18
|
+
* @param {import('./blockstore.js').TransactionBlockstore} blocks - The block storage instance to use documents and indexes
|
15
19
|
* @param {CID[]} clock - The Merkle clock head to use for the Fireproof instance.
|
16
20
|
* @param {object} [config] - Optional configuration options for the Fireproof instance.
|
17
21
|
* @param {object} [authCtx] - Optional authorization context object to use for any authentication checks.
|
18
22
|
*
|
19
23
|
*/
|
20
|
-
export
|
24
|
+
export class Fireproof {
|
21
25
|
listeners = new Set()
|
22
26
|
|
23
27
|
/**
|
@@ -161,7 +165,7 @@ export default class Fireproof {
|
|
161
165
|
*
|
162
166
|
* @param {string} key - the ID of the document to retrieve
|
163
167
|
* @param {Object} [opts] - options
|
164
|
-
* @returns {
|
168
|
+
* @returns {Promise<{_id: string}>} - the document with the specified ID
|
165
169
|
* @memberof Fireproof
|
166
170
|
* @instance
|
167
171
|
*/
|
@@ -190,8 +194,9 @@ export default class Fireproof {
|
|
190
194
|
*
|
191
195
|
* @param {Object} doc - the document to be added
|
192
196
|
* @param {string} doc._id - the document ID. If not provided, a random ID will be generated.
|
193
|
-
* @param {
|
194
|
-
* @
|
197
|
+
* @param {CID[]} doc._clock - the document ID. If not provided, a random ID will be generated.
|
198
|
+
* @param {Proof} doc._proof - CIDs referenced by the update
|
199
|
+
* @returns {Promise<{ id: string, clock: CID[] }>} - The result of adding the document to the database
|
195
200
|
* @memberof Fireproof
|
196
201
|
* @instance
|
197
202
|
*/
|
@@ -203,8 +208,8 @@ export default class Fireproof {
|
|
203
208
|
|
204
209
|
/**
|
205
210
|
* Deletes a document from the database
|
206
|
-
* @param {string}
|
207
|
-
* @returns {
|
211
|
+
* @param {string | any} docOrId - the document ID
|
212
|
+
* @returns {Promise<{ id: string, clock: CID[] }>} - The result of deleting the document from the database
|
208
213
|
* @memberof Fireproof
|
209
214
|
* @instance
|
210
215
|
*/
|
@@ -226,8 +231,8 @@ export default class Fireproof {
|
|
226
231
|
/**
|
227
232
|
* Updates the underlying storage with the specified event.
|
228
233
|
* @private
|
229
|
-
* @param {
|
230
|
-
* @returns {
|
234
|
+
* @param {{del?: true, key : string, value?: any}} decodedEvent - the event to add
|
235
|
+
* @returns {Promise<{ proof:{}, id: string, clock: CID[] }>} - The result of adding the event to storage
|
231
236
|
*/
|
232
237
|
async putToProllyTree (decodedEvent, clock = null) {
|
233
238
|
const event = encodeEvent(decodedEvent)
|
package/src/hydrator.js
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
import DbIndex from './db-index.js'
|
2
|
-
import Fireproof from './fireproof.js'
|
1
|
+
import { DbIndex } from './db-index.js'
|
2
|
+
import { Fireproof } from './fireproof.js'
|
3
3
|
import { CID } from 'multiformats'
|
4
4
|
|
5
5
|
const parseCID = cid => typeof cid === 'string' ? CID.parse(cid) : cid
|
6
6
|
|
7
|
-
export
|
7
|
+
export class Hydrator {
|
8
8
|
static fromJSON (json, database) {
|
9
9
|
database.hydrate({ clock: json.clock.map(c => parseCID(c)), name: json.name, key: json.key })
|
10
10
|
if (json.indexes) {
|
package/src/index.js
ADDED
package/src/listener.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
// @ts-nocheck
|
1
2
|
/**
|
2
3
|
* A Fireproof database Listener allows you to react to events in the database.
|
3
4
|
*
|
@@ -9,7 +10,7 @@
|
|
9
10
|
*/
|
10
11
|
// import { ChangeEvent } from './db-index'
|
11
12
|
|
12
|
-
export
|
13
|
+
export class Listener {
|
13
14
|
subcribers = new Map()
|
14
15
|
doStopListening = null
|
15
16
|
|
package/src/prolly.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
// @ts-nocheck
|
1
2
|
import {
|
2
3
|
advance,
|
3
4
|
EventFetcher,
|
@@ -37,23 +38,9 @@ export const makeGetBlock = (blocks) => {
|
|
37
38
|
}
|
38
39
|
|
39
40
|
/**
|
40
|
-
*
|
41
|
-
* @param {
|
42
|
-
* @
|
43
|
-
* @param {Function} getBlock - A function that gets a block.
|
44
|
-
* @param {Function} bigPut - A function that puts a block.
|
45
|
-
* @param {import('prolly-trees/map').Root} root - The root node.
|
46
|
-
* @param {Object<{ key: string, value: any, del: boolean }>} event - The update event.
|
47
|
-
* @param {CID[]} head - The head of the event chain.
|
48
|
-
* @param {Array<import('multiformats/block').Block>} additions - A array of additions.
|
49
|
-
* @param {Array<mport('multiformats/block').Block>>} removals - An array of removals.
|
50
|
-
* @returns {Promise<{
|
51
|
-
* root: import('prolly-trees/map').Root,
|
52
|
-
* additions: Map<string, import('multiformats/block').Block>,
|
53
|
-
* removals: Array<string>,
|
54
|
-
* head: CID[],
|
55
|
-
* event: CID[]
|
56
|
-
* }>}
|
41
|
+
*
|
42
|
+
* @param {*} param0
|
43
|
+
* @returns
|
57
44
|
*/
|
58
45
|
async function createAndSaveNewEvent ({
|
59
46
|
inBlocks,
|
@@ -198,7 +185,7 @@ const doProllyBulk = async (inBlocks, head, event) => {
|
|
198
185
|
/**
|
199
186
|
* Put a value (a CID) for the given key. If the key exists it's value is overwritten.
|
200
187
|
*
|
201
|
-
* @param {import('
|
188
|
+
* @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
|
202
189
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
203
190
|
* @param {string} key The key of the value to put.
|
204
191
|
* @param {CID} value The value to put.
|
@@ -250,7 +237,7 @@ export async function put (inBlocks, head, event, options) {
|
|
250
237
|
/**
|
251
238
|
* Determine the effective prolly root given the current merkle clock head.
|
252
239
|
*
|
253
|
-
* @param {import('
|
240
|
+
* @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
|
254
241
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
255
242
|
*/
|
256
243
|
export async function root (inBlocks, head) {
|
@@ -270,10 +257,10 @@ export async function root (inBlocks, head) {
|
|
270
257
|
|
271
258
|
/**
|
272
259
|
* Get the list of events not known by the `since` event
|
273
|
-
* @param {import('
|
260
|
+
* @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
|
274
261
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
275
262
|
* @param {import('./clock').EventLink<EventData>} since Event to compare against.
|
276
|
-
* @returns {Promise<
|
263
|
+
* @returns {Promise<{clockCIDs: CIDCounter, result: EventData[]}>}
|
277
264
|
*/
|
278
265
|
export async function eventsSince (blocks, head, since) {
|
279
266
|
if (!head.length) {
|
@@ -286,10 +273,10 @@ export async function eventsSince (blocks, head, since) {
|
|
286
273
|
|
287
274
|
/**
|
288
275
|
*
|
289
|
-
* @param {import('
|
276
|
+
* @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
|
290
277
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
291
278
|
*
|
292
|
-
* @returns {Promise<
|
279
|
+
* @returns {Promise<{clockCIDs: CIDCounter, result: EventData[]}>}
|
293
280
|
*
|
294
281
|
*/
|
295
282
|
export async function getAll (blocks, head) {
|
@@ -307,7 +294,7 @@ export async function getAll (blocks, head) {
|
|
307
294
|
}
|
308
295
|
|
309
296
|
/**
|
310
|
-
* @param {import('
|
297
|
+
* @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
|
311
298
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
312
299
|
* @param {string} key The key of the value to retrieve.
|
313
300
|
*/
|
package/src/sha1.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
// @ts-nocheck
|
1
2
|
// from https://github.com/duzun/sync-sha1/blob/master/rawSha1.js
|
2
3
|
// MIT License Copyright (c) 2020 Dumitru Uzun
|
3
4
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -29,7 +30,7 @@
|
|
29
30
|
*
|
30
31
|
* @return {Uint8Array} sha1 hash
|
31
32
|
*/
|
32
|
-
export
|
33
|
+
export function rawSha1 (b) {
|
33
34
|
let i = b.byteLength
|
34
35
|
let bs = 0
|
35
36
|
let A; let B; let C; let D; let G
|
package/src/valet.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
// @ts-nocheck
|
1
2
|
import { CarReader } from '@ipld/car'
|
2
3
|
import { CID } from 'multiformats/cid'
|
3
4
|
import { sha256 } from 'multiformats/hashes/sha2'
|
@@ -12,13 +13,13 @@ import { nocache as cache } from 'prolly-trees/cache'
|
|
12
13
|
import { encrypt, decrypt } from './crypto.js'
|
13
14
|
import { Buffer } from 'buffer'
|
14
15
|
import * as codec from 'encrypted-block'
|
15
|
-
import sha1sync from './sha1.js'
|
16
|
+
import { rawSha1 as sha1sync } from './sha1.js'
|
16
17
|
const chunker = bf(3)
|
17
18
|
|
18
19
|
const NO_ENCRYPT =
|
19
20
|
typeof process !== 'undefined' ? process.env.NO_ENCRYPT : import.meta && import.meta.env.VITE_NO_ENCRYPT
|
20
21
|
|
21
|
-
export
|
22
|
+
export class Valet {
|
22
23
|
idb = null
|
23
24
|
name = null
|
24
25
|
uploadQueue = null
|
@@ -234,7 +235,8 @@ const blocksToEncryptedCarBlock = async (innerBlockStoreClockRootCid, blocks, ke
|
|
234
235
|
key: encryptionKey,
|
235
236
|
hasher: sha256,
|
236
237
|
chunker,
|
237
|
-
|
238
|
+
cache,
|
239
|
+
// codec: dagcbor, // should be crypto?
|
238
240
|
root: innerBlockStoreClockRootCid
|
239
241
|
})) {
|
240
242
|
encryptedBlocks.push(block)
|
@@ -262,8 +264,8 @@ const blocksFromEncryptedCarBlock = async (cid, get, keyMaterial) => {
|
|
262
264
|
key: decryptionKey,
|
263
265
|
chunker,
|
264
266
|
hasher: sha256,
|
265
|
-
cache
|
266
|
-
codec: dagcbor
|
267
|
+
cache
|
268
|
+
// codec: dagcbor
|
267
269
|
})) {
|
268
270
|
decryptedBlocks.push(block)
|
269
271
|
cids.add(block.cid.toString())
|
package/hooks/use-fireproof.js
DELETED
@@ -1,135 +0,0 @@
|
|
1
|
-
/* global localStorage */
|
2
|
-
// @ts-ignore
|
3
|
-
import { useEffect, useState, createContext } from 'react'
|
4
|
-
import { Fireproof, Listener, Hydrator } from '../index'
|
5
|
-
|
6
|
-
// export interface FireproofCtxValue {
|
7
|
-
// addSubscriber: (label: String, fn: Function) => void
|
8
|
-
// database: Fireproof
|
9
|
-
// ready: boolean
|
10
|
-
// persist: () => void
|
11
|
-
// }
|
12
|
-
export const FireproofCtx = createContext({
|
13
|
-
addSubscriber: () => {},
|
14
|
-
database: null,
|
15
|
-
ready: false
|
16
|
-
})
|
17
|
-
|
18
|
-
const inboundSubscriberQueue = new Map()
|
19
|
-
|
20
|
-
let startedSetup = false
|
21
|
-
let database
|
22
|
-
let listener
|
23
|
-
const initializeDatabase = name => {
|
24
|
-
if (database) return
|
25
|
-
database = Fireproof.storage(name)
|
26
|
-
listener = new Listener(database)
|
27
|
-
}
|
28
|
-
|
29
|
-
/**
|
30
|
-
* @function useFireproof
|
31
|
-
* React hook to initialize a Fireproof database, automatically saving and loading the clock.
|
32
|
-
* You might need to `import { nodePolyfills } from 'vite-plugin-node-polyfills'` in your vite.config.ts
|
33
|
-
* @param [defineDatabaseFn] Synchronous function that defines the database, run this before any async calls
|
34
|
-
* @param [setupDatabaseFn] Asynchronous function that sets up the database, run this to load fixture data etc
|
35
|
-
* @returns {FireproofCtxValue} { addSubscriber, database, ready }
|
36
|
-
*/
|
37
|
-
export function useFireproof (
|
38
|
-
defineDatabaseFn = () => {},
|
39
|
-
setupDatabaseFn = async () => {},
|
40
|
-
name
|
41
|
-
) {
|
42
|
-
const [ready, setReady] = useState(false)
|
43
|
-
initializeDatabase(name || 'useFireproof')
|
44
|
-
const localStorageKey = 'fp.' + database.name
|
45
|
-
|
46
|
-
const addSubscriber = (label, fn) => {
|
47
|
-
inboundSubscriberQueue.set(label, fn)
|
48
|
-
}
|
49
|
-
|
50
|
-
const listenerCallback = async event => {
|
51
|
-
localSet(localStorageKey, JSON.stringify(database))
|
52
|
-
if (event._external) return
|
53
|
-
for (const [, fn] of inboundSubscriberQueue) fn()
|
54
|
-
}
|
55
|
-
|
56
|
-
useEffect(() => {
|
57
|
-
const doSetup = async () => {
|
58
|
-
if (ready) return
|
59
|
-
if (startedSetup) return
|
60
|
-
startedSetup = true
|
61
|
-
defineDatabaseFn(database) // define indexes before querying them
|
62
|
-
console.log('Initializing database', database.name)
|
63
|
-
const fp = localGet(localStorageKey) // todo use db.name
|
64
|
-
if (fp) {
|
65
|
-
try {
|
66
|
-
const serialized = JSON.parse(fp)
|
67
|
-
// console.log('serialized', JSON.stringify(serialized.indexes.map(c => c.clock)))
|
68
|
-
console.log(`Loading previous database clock. (localStorage.removeItem('${localStorageKey}') to reset)`)
|
69
|
-
await Hydrator.fromJSON(serialized, database)
|
70
|
-
const changes = await database.changesSince()
|
71
|
-
if (changes.rows.length < 2) {
|
72
|
-
// console.log('Resetting database')
|
73
|
-
throw new Error('Resetting database')
|
74
|
-
}
|
75
|
-
} catch (e) {
|
76
|
-
console.error(`Error loading previous database clock. ${fp} Resetting.`, e)
|
77
|
-
await Hydrator.zoom(database, [])
|
78
|
-
await setupDatabaseFn(database)
|
79
|
-
localSet(localStorageKey, JSON.stringify(database))
|
80
|
-
}
|
81
|
-
} else {
|
82
|
-
await setupDatabaseFn(database)
|
83
|
-
localSet(localStorageKey, JSON.stringify(database))
|
84
|
-
}
|
85
|
-
setReady(true)
|
86
|
-
listener.on('*', listenerCallback)// hushed('*', listenerCallback, 250))
|
87
|
-
}
|
88
|
-
doSetup()
|
89
|
-
}, [ready])
|
90
|
-
|
91
|
-
return {
|
92
|
-
addSubscriber,
|
93
|
-
database,
|
94
|
-
ready,
|
95
|
-
persist: () => {
|
96
|
-
localSet(localStorageKey, JSON.stringify(database))
|
97
|
-
}
|
98
|
-
}
|
99
|
-
}
|
100
|
-
|
101
|
-
// const husherMap = new Map()
|
102
|
-
// const husher = (id, workFn, ms) => {
|
103
|
-
// if (!husherMap.has(id)) {
|
104
|
-
// const start = Date.now()
|
105
|
-
// husherMap.set(
|
106
|
-
// id,
|
107
|
-
// workFn().finally(() => setTimeout(() => husherMap.delete(id), ms - (Date.now() - start)))
|
108
|
-
// )
|
109
|
-
// }
|
110
|
-
// return husherMap.get(id)
|
111
|
-
// }
|
112
|
-
// const hushed =
|
113
|
-
// (id, workFn, ms) =>
|
114
|
-
// (...args) =>
|
115
|
-
// husher(id, () => workFn(...args), ms)
|
116
|
-
|
117
|
-
let storageSupported = false
|
118
|
-
try {
|
119
|
-
storageSupported = window.localStorage && true
|
120
|
-
} catch (e) {}
|
121
|
-
export function localGet (key) {
|
122
|
-
if (storageSupported) {
|
123
|
-
return localStorage && localStorage.getItem(key)
|
124
|
-
}
|
125
|
-
}
|
126
|
-
function localSet (key, value) {
|
127
|
-
if (storageSupported) {
|
128
|
-
return localStorage && localStorage.setItem(key, value)
|
129
|
-
}
|
130
|
-
}
|
131
|
-
// function localRemove(key) {
|
132
|
-
// if (storageSupported) {
|
133
|
-
// return localStorage && localStorage.removeItem(key)
|
134
|
-
// }
|
135
|
-
// }
|
package/index.js
DELETED
package/scripts/keygen.js
DELETED
package/test/block.js
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
import { parse } from 'multiformats/link'
|
2
|
-
|
3
|
-
/**
|
4
|
-
* @typedef {{ cid: import('../src/link').AnyLink, bytes: Uint8Array }} AnyBlock
|
5
|
-
* @typedef {{ get: (link: import('../src/link').AnyLink) => Promise<AnyBlock | undefined> }} BlockFetcher
|
6
|
-
*/
|
7
|
-
|
8
|
-
/** @implements {BlockFetcher} */
|
9
|
-
export class MemoryBlockstore {
|
10
|
-
/** @type {Map<string, Uint8Array>} */
|
11
|
-
blocks = new Map()
|
12
|
-
|
13
|
-
/**
|
14
|
-
* @param {import('../src/link').AnyLink} cid
|
15
|
-
* @returns {Promise<AnyBlock | undefined>}
|
16
|
-
*/
|
17
|
-
async get (cid) {
|
18
|
-
const bytes = this.blocks.get(cid.toString())
|
19
|
-
if (!bytes) return
|
20
|
-
return { cid, bytes }
|
21
|
-
}
|
22
|
-
|
23
|
-
/**
|
24
|
-
* @param {import('../src/link').AnyLink} cid
|
25
|
-
* @param {Uint8Array} bytes
|
26
|
-
*/
|
27
|
-
async put (cid, bytes) {
|
28
|
-
// console.log('put', cid)
|
29
|
-
this.blocks.set(cid.toString(), bytes)
|
30
|
-
}
|
31
|
-
|
32
|
-
/**
|
33
|
-
* @param {import('../src/link').AnyLink} cid
|
34
|
-
* @param {Uint8Array} bytes
|
35
|
-
*/
|
36
|
-
putSync (cid, bytes) {
|
37
|
-
this.blocks.set(cid.toString(), bytes)
|
38
|
-
}
|
39
|
-
|
40
|
-
* entries () {
|
41
|
-
for (const [str, bytes] of this.blocks) {
|
42
|
-
yield { cid: parse(str), bytes }
|
43
|
-
}
|
44
|
-
}
|
45
|
-
}
|
46
|
-
|
47
|
-
export class MultiBlockFetcher {
|
48
|
-
/** @type {BlockFetcher[]} */
|
49
|
-
fetchers
|
50
|
-
|
51
|
-
/** @param {BlockFetcher[]} fetchers */
|
52
|
-
constructor (...fetchers) {
|
53
|
-
this.fetchers = fetchers
|
54
|
-
}
|
55
|
-
|
56
|
-
/** @param {import('../src/link').AnyLink} link */
|
57
|
-
async get (link) {
|
58
|
-
for (const f of this.fetchers) {
|
59
|
-
const v = await f.get(link)
|
60
|
-
if (v) {
|
61
|
-
return v
|
62
|
-
}
|
63
|
-
}
|
64
|
-
}
|
65
|
-
}
|