@fireproof/core 0.3.7 → 0.3.9
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/hooks/use-fireproof.js +135 -0
- package/index.js +6 -0
- package/package.json +6 -39
- package/scripts/keygen.js +3 -0
- package/src/blockstore.js +2 -3
- package/src/clock.js +3 -4
- package/src/crypto.js +0 -1
- package/src/db-index.js +5 -10
- package/src/fireproof.js +10 -15
- package/src/hydrator.js +3 -3
- package/src/listener.js +1 -2
- package/src/prolly.js +24 -11
- package/src/sha1.js +1 -2
- package/src/valet.js +5 -7
- package/test/block.js +65 -0
- package/test/clock.test.js +694 -0
- package/test/db-index.test.js +261 -0
- package/test/fireproof.test.js +493 -0
- package/test/fulltext.test.js +66 -0
- package/test/helpers.js +45 -0
- package/test/hydrator.test.js +81 -0
- package/test/listener.test.js +102 -0
- package/test/prolly.test.js +190 -0
- package/test/proofs.test.js +53 -0
- package/test/reproduce-fixture-bug.test.js +65 -0
- package/test/valet.test.js +59 -0
- package/webpack.config.js +8 -0
- package/dist/main.js +0 -2
- package/dist/main.js.LICENSE.txt +0 -17
- package/src/index.js +0 -6
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
|
21
|
+
import Fireproof from 'fireproof';
|
22
22
|
|
23
23
|
async function main() {
|
24
24
|
const database = Fireproof.storage('my-db');
|
@@ -0,0 +1,135 @@
|
|
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
ADDED
package/package.json
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fireproof/core",
|
3
|
-
"version": "0.3.
|
3
|
+
"version": "0.3.9",
|
4
4
|
"description": "Realtime database for IPFS",
|
5
|
-
"main": "
|
5
|
+
"main": "index.js",
|
6
6
|
"type": "module",
|
7
|
-
"types": "./dist/src/index.d.ts",
|
8
7
|
"scripts": {
|
9
8
|
"keygen": "node scripts/keygen.js",
|
10
9
|
"test": "standard && npm run test:unencrypted && npm run test:mocha",
|
@@ -15,8 +14,7 @@
|
|
15
14
|
"prepublishOnly": "cp ../../README.md .",
|
16
15
|
"postpublish": "rm README.md",
|
17
16
|
"lint": "standard",
|
18
|
-
"lint:fix": "standard --fix"
|
19
|
-
"build": "tsc --build"
|
17
|
+
"lint:fix": "standard --fix"
|
20
18
|
},
|
21
19
|
"keywords": [
|
22
20
|
"database",
|
@@ -34,6 +32,7 @@
|
|
34
32
|
],
|
35
33
|
"license": "Apache-2.0 OR MIT",
|
36
34
|
"dependencies": {
|
35
|
+
"prolly-trees": "1.0.4",
|
37
36
|
"@ipld/car": "^5.1.0",
|
38
37
|
"@ipld/dag-cbor": "^9.0.0",
|
39
38
|
"archy": "^1.0.0",
|
@@ -44,8 +43,6 @@
|
|
44
43
|
"encrypted-block": "^0.0.3",
|
45
44
|
"idb": "^7.1.1",
|
46
45
|
"multiformats": "^11.0.1",
|
47
|
-
"node-polyfill-webpack-plugin": "^2.0.1",
|
48
|
-
"prolly-trees": "1.0.4",
|
49
46
|
"sade": "^1.8.1"
|
50
47
|
},
|
51
48
|
"devDependencies": {
|
@@ -54,10 +51,7 @@
|
|
54
51
|
"flexsearch": "^0.7.31",
|
55
52
|
"mocha": "^10.2.0",
|
56
53
|
"nanoid": "^4.0.0",
|
57
|
-
"standard": "^17.0.0"
|
58
|
-
"typescript": "^5.0.2",
|
59
|
-
"webpack": "^5.78.0",
|
60
|
-
"webpack-cli": "^5.0.1"
|
54
|
+
"standard": "^17.0.0"
|
61
55
|
},
|
62
56
|
"mocha": {
|
63
57
|
"require": [
|
@@ -68,7 +62,7 @@
|
|
68
62
|
"ignore": [
|
69
63
|
"examples/**/*.tsx",
|
70
64
|
"examples/**/dist",
|
71
|
-
"out/**"
|
65
|
+
"out/**", "dist/**"
|
72
66
|
]
|
73
67
|
},
|
74
68
|
"repository": {
|
@@ -79,33 +73,6 @@
|
|
79
73
|
"url": "https://github.com/fireproof-storage/fireproof/issues"
|
80
74
|
},
|
81
75
|
"homepage": "https://fireproof.storage",
|
82
|
-
"exports": {
|
83
|
-
".": {
|
84
|
-
"types": "./dist/src/index.d.ts",
|
85
|
-
"import": "./src/index.js"
|
86
|
-
},
|
87
|
-
"./fireproof": {
|
88
|
-
"types": "./dist/src/fireproof.d.ts",
|
89
|
-
"import": "./src/fireproof.js"
|
90
|
-
},
|
91
|
-
"./hydrator": {
|
92
|
-
"types": "./dist/src/hydrator.d.ts",
|
93
|
-
"import": "./src/hydrator.js"
|
94
|
-
},
|
95
|
-
"./listener": {
|
96
|
-
"types": "./dist/src/listener.d.ts",
|
97
|
-
"import": "./src/listener.js"
|
98
|
-
},
|
99
|
-
"./db-index": {
|
100
|
-
"types": "./dist/src/db-index.d.ts",
|
101
|
-
"import": "./src/db-index.js"
|
102
|
-
}
|
103
|
-
},
|
104
|
-
"files": [
|
105
|
-
"src",
|
106
|
-
"dist",
|
107
|
-
"README.md"
|
108
|
-
],
|
109
76
|
"workspaces": [
|
110
77
|
"examples/todomvc"
|
111
78
|
]
|
package/src/blockstore.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
import { parse } from 'multiformats/link'
|
3
2
|
import { CID } from 'multiformats'
|
4
|
-
import
|
3
|
+
import Valet from './valet.js'
|
5
4
|
|
6
5
|
// const sleep = ms => new Promise(r => setTimeout(r, ms))
|
7
6
|
|
@@ -28,7 +27,7 @@ const husher = (id, workFn) => {
|
|
28
27
|
* A blockstore that caches writes to a transaction and only persists them when committed.
|
29
28
|
* @implements {Blockstore}
|
30
29
|
*/
|
31
|
-
export class TransactionBlockstore {
|
30
|
+
export default class TransactionBlockstore {
|
32
31
|
/** @type {Map<string, Uint8Array>} */
|
33
32
|
committedBlocks = new Map()
|
34
33
|
|
package/src/clock.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
import { Block, encode, decode } from 'multiformats/block'
|
3
2
|
import { sha256 } from 'multiformats/hashes/sha2'
|
4
3
|
import * as cbor from '@ipld/dag-cbor'
|
@@ -23,7 +22,7 @@ import { CIDCounter } from 'prolly-trees/utils'
|
|
23
22
|
* Advance the clock by adding an event.
|
24
23
|
*
|
25
24
|
* @template T
|
26
|
-
* @param {import('
|
25
|
+
* @param {import('../test/block').BlockFetcher} blocks Block storage.
|
27
26
|
* @param {EventLink<T>[]} head The head of the clock.
|
28
27
|
* @param {EventLink<T>} event The event to add.
|
29
28
|
* @returns {Promise<EventLink<T>[]>} The new head of the clock.
|
@@ -90,7 +89,7 @@ export class EventBlock extends Block {
|
|
90
89
|
|
91
90
|
/** @template T */
|
92
91
|
export class EventFetcher {
|
93
|
-
/** @param {import('
|
92
|
+
/** @param {import('../test/block').BlockFetcher} blocks */
|
94
93
|
constructor (blocks) {
|
95
94
|
/** @private */
|
96
95
|
this._blocks = blocks
|
@@ -169,7 +168,7 @@ async function contains (events, a, b) {
|
|
169
168
|
|
170
169
|
/**
|
171
170
|
* @template T
|
172
|
-
* @param {import('
|
171
|
+
* @param {import('../test/block').BlockFetcher} blocks Block storage.
|
173
172
|
* @param {EventLink<T>[]} head
|
174
173
|
* @param {object} [options]
|
175
174
|
* @param {(b: EventBlockView<T>) => string} [options.renderNodeLabel]
|
package/src/crypto.js
CHANGED
package/src/db-index.js
CHANGED
@@ -1,20 +1,15 @@
|
|
1
|
-
// @ts-nocheck
|
2
|
-
// @ts-ignore
|
3
1
|
import { create, load } from 'prolly-trees/db-index'
|
4
2
|
// import { create, load } from '../../../../prolly-trees/src/db-index.js'
|
5
3
|
|
6
4
|
import { sha256 as hasher } from 'multiformats/hashes/sha2'
|
7
|
-
// @ts-ignore
|
8
5
|
import { nocache as cache } from 'prolly-trees/cache'
|
9
|
-
// @ts-ignore
|
10
6
|
import { bf, simpleCompare } from 'prolly-trees/utils'
|
11
7
|
import { makeGetBlock } from './prolly.js'
|
12
8
|
import { cidsToProof } from './fireproof.js'
|
13
9
|
|
14
10
|
import * as codec from '@ipld/dag-cbor'
|
15
11
|
// import { create as createBlock } from 'multiformats/block'
|
16
|
-
import
|
17
|
-
// @ts-ignore
|
12
|
+
import TransactionBlockstore, { doTransaction } from './blockstore.js'
|
18
13
|
import charwise from 'charwise'
|
19
14
|
|
20
15
|
const ALWAYS_REBUILD = false // todo: make false
|
@@ -92,7 +87,7 @@ const indexEntriesForChanges = (changes, mapFn) => {
|
|
92
87
|
* @param {Function} mapFn - The map function to apply to each entry in the database.
|
93
88
|
*
|
94
89
|
*/
|
95
|
-
export class DbIndex {
|
90
|
+
export default class DbIndex {
|
96
91
|
constructor (database, mapFn, clock, opts = {}) {
|
97
92
|
// console.log('DbIndex constructor', database.constructor.name, typeof mapFn, clock)
|
98
93
|
/**
|
@@ -177,7 +172,7 @@ export class DbIndex {
|
|
177
172
|
/**
|
178
173
|
* Query object can have {range}
|
179
174
|
* @param {DbQuery} query - the query range to use
|
180
|
-
* @returns {Promise<{
|
175
|
+
* @returns {Promise<{rows: Array<{id: string, key: string, value: any}>}>}
|
181
176
|
* @memberof DbIndex
|
182
177
|
* @instance
|
183
178
|
*/
|
@@ -264,8 +259,8 @@ export class DbIndex {
|
|
264
259
|
|
265
260
|
/**
|
266
261
|
* Update the DbIndex with the given entries
|
267
|
-
* @param {
|
268
|
-
* @param {
|
262
|
+
* @param {Blockstore} blocks
|
263
|
+
* @param {Block} inRoot
|
269
264
|
* @param {DbIndexEntry[]} indexEntries
|
270
265
|
* @private
|
271
266
|
*/
|
package/src/fireproof.js
CHANGED
@@ -1,27 +1,23 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
import { randomBytes } from 'crypto'
|
3
2
|
import { visMerkleClock, visMerkleTree, vis, put, get, getAll, eventsSince } from './prolly.js'
|
4
|
-
import
|
3
|
+
import TransactionBlockstore, { doTransaction } from './blockstore.js'
|
5
4
|
import charwise from 'charwise'
|
6
|
-
// import { CID } from 'multiformats/dist/types/src/cid.js'
|
7
5
|
|
8
6
|
// const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
9
7
|
|
10
|
-
// class Proof {}
|
11
|
-
|
12
8
|
/**
|
13
9
|
* @class Fireproof
|
14
10
|
* @classdesc Fireproof stores data in IndexedDB and provides a Merkle clock.
|
15
11
|
* This is the main class for saving and loading JSON and other documents with the database. You can find additional examples and
|
16
12
|
* usage guides in the repository README.
|
17
13
|
*
|
18
|
-
* @param {
|
14
|
+
* @param {Blockstore} blocks - The block storage instance to use documents and indexes
|
19
15
|
* @param {CID[]} clock - The Merkle clock head to use for the Fireproof instance.
|
20
16
|
* @param {object} [config] - Optional configuration options for the Fireproof instance.
|
21
17
|
* @param {object} [authCtx] - Optional authorization context object to use for any authentication checks.
|
22
18
|
*
|
23
19
|
*/
|
24
|
-
export class Fireproof {
|
20
|
+
export default class Fireproof {
|
25
21
|
listeners = new Set()
|
26
22
|
|
27
23
|
/**
|
@@ -165,7 +161,7 @@ export class Fireproof {
|
|
165
161
|
*
|
166
162
|
* @param {string} key - the ID of the document to retrieve
|
167
163
|
* @param {Object} [opts] - options
|
168
|
-
* @returns {
|
164
|
+
* @returns {Object<{_id: string, ...doc: Object}>} - the document with the specified ID
|
169
165
|
* @memberof Fireproof
|
170
166
|
* @instance
|
171
167
|
*/
|
@@ -194,9 +190,8 @@ export class Fireproof {
|
|
194
190
|
*
|
195
191
|
* @param {Object} doc - the document to be added
|
196
192
|
* @param {string} doc._id - the document ID. If not provided, a random ID will be generated.
|
197
|
-
* @param {
|
198
|
-
* @
|
199
|
-
* @returns {Promise<{ id: string, clock: CID[] }>} - The result of adding the document to the database
|
193
|
+
* @param {Object} doc.* - the document data to be added
|
194
|
+
* @returns {Object<{ id: string, clock: CID[] }>} - The result of adding the document to the database
|
200
195
|
* @memberof Fireproof
|
201
196
|
* @instance
|
202
197
|
*/
|
@@ -208,8 +203,8 @@ export class Fireproof {
|
|
208
203
|
|
209
204
|
/**
|
210
205
|
* Deletes a document from the database
|
211
|
-
* @param {string
|
212
|
-
* @returns {
|
206
|
+
* @param {string} id - the document ID
|
207
|
+
* @returns {Object<{ id: string, clock: CID[] }>} - The result of deleting the document from the database
|
213
208
|
* @memberof Fireproof
|
214
209
|
* @instance
|
215
210
|
*/
|
@@ -231,8 +226,8 @@ export class Fireproof {
|
|
231
226
|
/**
|
232
227
|
* Updates the underlying storage with the specified event.
|
233
228
|
* @private
|
234
|
-
* @param {{
|
235
|
-
* @returns {
|
229
|
+
* @param {Object<{key : string, value: any}>} event - the event to add
|
230
|
+
* @returns {Object<{ id: string, clock: CID[] }>} - The result of adding the event to storage
|
236
231
|
*/
|
237
232
|
async putToProllyTree (decodedEvent, clock = null) {
|
238
233
|
const event = encodeEvent(decodedEvent)
|
package/src/hydrator.js
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
import
|
2
|
-
import
|
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 class Hydrator {
|
7
|
+
export default 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/listener.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
/**
|
3
2
|
* A Fireproof database Listener allows you to react to events in the database.
|
4
3
|
*
|
@@ -10,7 +9,7 @@
|
|
10
9
|
*/
|
11
10
|
// import { ChangeEvent } from './db-index'
|
12
11
|
|
13
|
-
export class Listener {
|
12
|
+
export default class Listener {
|
14
13
|
subcribers = new Map()
|
15
14
|
doStopListening = null
|
16
15
|
|
package/src/prolly.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
import {
|
3
2
|
advance,
|
4
3
|
EventFetcher,
|
@@ -38,9 +37,23 @@ export const makeGetBlock = (blocks) => {
|
|
38
37
|
}
|
39
38
|
|
40
39
|
/**
|
41
|
-
*
|
42
|
-
* @param {
|
43
|
-
* @
|
40
|
+
* Creates and saves a new event.
|
41
|
+
* @param {import('./blockstore.js').Blockstore} inBlocks - A persistent blockstore.
|
42
|
+
* @param {MemoryBlockstore} mblocks - A temporary blockstore.
|
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
|
+
* }>}
|
44
57
|
*/
|
45
58
|
async function createAndSaveNewEvent ({
|
46
59
|
inBlocks,
|
@@ -185,7 +198,7 @@ const doProllyBulk = async (inBlocks, head, event) => {
|
|
185
198
|
/**
|
186
199
|
* Put a value (a CID) for the given key. If the key exists it's value is overwritten.
|
187
200
|
*
|
188
|
-
* @param {import('
|
201
|
+
* @param {import('../test/block.js').BlockFetcher} blocks Bucket block storage.
|
189
202
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
190
203
|
* @param {string} key The key of the value to put.
|
191
204
|
* @param {CID} value The value to put.
|
@@ -237,7 +250,7 @@ export async function put (inBlocks, head, event, options) {
|
|
237
250
|
/**
|
238
251
|
* Determine the effective prolly root given the current merkle clock head.
|
239
252
|
*
|
240
|
-
* @param {import('
|
253
|
+
* @param {import('../test/block.js').BlockFetcher} blocks Bucket block storage.
|
241
254
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
242
255
|
*/
|
243
256
|
export async function root (inBlocks, head) {
|
@@ -257,10 +270,10 @@ export async function root (inBlocks, head) {
|
|
257
270
|
|
258
271
|
/**
|
259
272
|
* Get the list of events not known by the `since` event
|
260
|
-
* @param {import('
|
273
|
+
* @param {import('../test/block.js').BlockFetcher} blocks Bucket block storage.
|
261
274
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
262
275
|
* @param {import('./clock').EventLink<EventData>} since Event to compare against.
|
263
|
-
* @returns {Promise<
|
276
|
+
* @returns {Promise<import('./clock').EventLink<EventData>[]>}
|
264
277
|
*/
|
265
278
|
export async function eventsSince (blocks, head, since) {
|
266
279
|
if (!head.length) {
|
@@ -273,10 +286,10 @@ export async function eventsSince (blocks, head, since) {
|
|
273
286
|
|
274
287
|
/**
|
275
288
|
*
|
276
|
-
* @param {import('
|
289
|
+
* @param {import('../test/block.js').BlockFetcher} blocks Bucket block storage.
|
277
290
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
278
291
|
*
|
279
|
-
* @returns {Promise<
|
292
|
+
* @returns {Promise<import('./prolly').Entry[]>}
|
280
293
|
*
|
281
294
|
*/
|
282
295
|
export async function getAll (blocks, head) {
|
@@ -294,7 +307,7 @@ export async function getAll (blocks, head) {
|
|
294
307
|
}
|
295
308
|
|
296
309
|
/**
|
297
|
-
* @param {import('
|
310
|
+
* @param {import('../test/block.js').BlockFetcher} blocks Bucket block storage.
|
298
311
|
* @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
|
299
312
|
* @param {string} key The key of the value to retrieve.
|
300
313
|
*/
|
package/src/sha1.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
// from https://github.com/duzun/sync-sha1/blob/master/rawSha1.js
|
3
2
|
// MIT License Copyright (c) 2020 Dumitru Uzun
|
4
3
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
@@ -30,7 +29,7 @@
|
|
30
29
|
*
|
31
30
|
* @return {Uint8Array} sha1 hash
|
32
31
|
*/
|
33
|
-
export function rawSha1 (b) {
|
32
|
+
export default function rawSha1 (b) {
|
34
33
|
let i = b.byteLength
|
35
34
|
let bs = 0
|
36
35
|
let A; let B; let C; let D; let G
|
package/src/valet.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
import { CarReader } from '@ipld/car'
|
3
2
|
import { CID } from 'multiformats/cid'
|
4
3
|
import { sha256 } from 'multiformats/hashes/sha2'
|
@@ -13,13 +12,13 @@ import { nocache as cache } from 'prolly-trees/cache'
|
|
13
12
|
import { encrypt, decrypt } from './crypto.js'
|
14
13
|
import { Buffer } from 'buffer'
|
15
14
|
import * as codec from 'encrypted-block'
|
16
|
-
import
|
15
|
+
import sha1sync from './sha1.js'
|
17
16
|
const chunker = bf(3)
|
18
17
|
|
19
18
|
const NO_ENCRYPT =
|
20
19
|
typeof process !== 'undefined' ? process.env.NO_ENCRYPT : import.meta && import.meta.env.VITE_NO_ENCRYPT
|
21
20
|
|
22
|
-
export class Valet {
|
21
|
+
export default class Valet {
|
23
22
|
idb = null
|
24
23
|
name = null
|
25
24
|
uploadQueue = null
|
@@ -235,8 +234,7 @@ const blocksToEncryptedCarBlock = async (innerBlockStoreClockRootCid, blocks, ke
|
|
235
234
|
key: encryptionKey,
|
236
235
|
hasher: sha256,
|
237
236
|
chunker,
|
238
|
-
|
239
|
-
// codec: dagcbor, // should be crypto?
|
237
|
+
codec: dagcbor, // should be crypto?
|
240
238
|
root: innerBlockStoreClockRootCid
|
241
239
|
})) {
|
242
240
|
encryptedBlocks.push(block)
|
@@ -264,8 +262,8 @@ const blocksFromEncryptedCarBlock = async (cid, get, keyMaterial) => {
|
|
264
262
|
key: decryptionKey,
|
265
263
|
chunker,
|
266
264
|
hasher: sha256,
|
267
|
-
cache
|
268
|
-
|
265
|
+
cache,
|
266
|
+
codec: dagcbor
|
269
267
|
})) {
|
270
268
|
decryptedBlocks.push(block)
|
271
269
|
cids.add(block.cid.toString())
|
package/test/block.js
ADDED
@@ -0,0 +1,65 @@
|
|
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
|
+
}
|