@fireproof/core 0.8.0 → 0.10.1-dev
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +5 -184
- package/dist/fireproof.browser.js +18879 -0
- package/dist/fireproof.browser.js.map +7 -0
- package/dist/fireproof.cjs.js +9305 -0
- package/dist/fireproof.cjs.js.map +7 -0
- package/dist/fireproof.esm.js +9295 -0
- package/dist/fireproof.esm.js.map +7 -0
- package/package.json +57 -105
- package/dist/blockstore.js +0 -268
- package/dist/clock.js +0 -459
- package/dist/crypto.js +0 -63
- package/dist/database.js +0 -434
- package/dist/db-index.js +0 -403
- package/dist/encrypted-block.js +0 -48
- package/dist/fireproof.js +0 -84
- package/dist/import.js +0 -29
- package/dist/listener.js +0 -111
- package/dist/loader.js +0 -13
- package/dist/prolly.js +0 -405
- package/dist/remote.js +0 -102
- package/dist/sha1.js +0 -74
- package/dist/src/fireproof.d.ts +0 -472
- package/dist/src/fireproof.js +0 -81191
- package/dist/src/fireproof.js.map +0 -1
- package/dist/src/fireproof.mjs +0 -81186
- package/dist/src/fireproof.mjs.map +0 -1
- package/dist/storage/base.js +0 -426
- package/dist/storage/blocksToEncryptedCarBlock.js +0 -144
- package/dist/storage/browser.js +0 -62
- package/dist/storage/filesystem.js +0 -67
- package/dist/storage/rest.js +0 -57
- package/dist/storage/ucan.js +0 -0
- package/dist/storage/utils.js +0 -144
- package/dist/sync.js +0 -218
- package/dist/utils.js +0 -16
- package/dist/valet.js +0 -102
- package/src/blockstore.js +0 -283
- package/src/clock.js +0 -486
- package/src/crypto.js +0 -70
- package/src/database.js +0 -469
- package/src/db-index.js +0 -426
- package/src/encrypted-block.js +0 -57
- package/src/fireproof.js +0 -98
- package/src/import.js +0 -34
- package/src/link.d.ts +0 -3
- package/src/loader.js +0 -16
- package/src/prolly.js +0 -445
- package/src/remote.js +0 -113
- package/src/sha1.js +0 -83
- package/src/storage/base.js +0 -463
- package/src/storage/browser.js +0 -67
- package/src/storage/filesystem.js +0 -73
- package/src/storage/rest.js +0 -59
- package/src/storage/ucan.js +0 -0
- package/src/storage/utils.js +0 -152
- package/src/sync.js +0 -237
- package/src/valet.js +0 -105
package/src/database.js
DELETED
@@ -1,469 +0,0 @@
|
|
1
|
-
// @ts-nocheck
|
2
|
-
import { visMerkleClock, visMerkleTree, vis, put, get, getAll, eventsSince } from './prolly.js'
|
3
|
-
import { doTransaction, TransactionBlockstore } from './blockstore.js'
|
4
|
-
import charwise from 'charwise'
|
5
|
-
import { CID } from 'multiformats'
|
6
|
-
import { DbIndex as Index } from './db-index.js'
|
7
|
-
|
8
|
-
import { Remote } from './remote.js'
|
9
|
-
|
10
|
-
// TypeScript Types
|
11
|
-
// eslint-disable-next-line no-unused-vars
|
12
|
-
// import { CID } from 'multiformats/dist/types/src/cid.js'
|
13
|
-
|
14
|
-
// eslint-disable-next-line no-unused-vars
|
15
|
-
class Proof {}
|
16
|
-
export const parseCID = cid => (typeof cid === 'string' ? CID.parse(cid) : cid)
|
17
|
-
|
18
|
-
/**
|
19
|
-
* @class Fireproof
|
20
|
-
* @classdesc Fireproof stores data in IndexedDB and provides a Merkle clock.
|
21
|
-
* This is the main class for saving and loading JSON and other documents with the database. You can find additional examples and
|
22
|
-
* usage guides in the repository README.
|
23
|
-
*
|
24
|
-
* @param {CID[]} clock - The Merkle clock head to use for the Fireproof instance.
|
25
|
-
* @param {object} [config] - Optional configuration options for the Fireproof instance.
|
26
|
-
* @param {object} [authCtx] - Optional authorization context object to use for any authentication checks.
|
27
|
-
*
|
28
|
-
*/
|
29
|
-
export class Database {
|
30
|
-
listeners = new Set()
|
31
|
-
indexes = new Map()
|
32
|
-
rootCache = null
|
33
|
-
eventsCache = new Map()
|
34
|
-
remote = null
|
35
|
-
name = ''
|
36
|
-
constructor (name, config = {}) {
|
37
|
-
this.name = name
|
38
|
-
this.clock = []
|
39
|
-
this.instanceId = `fp.${this.name}.${Math.random().toString(36).substring(2, 7)}`
|
40
|
-
this.blocks = new TransactionBlockstore(name, config)
|
41
|
-
this.indexBlocks = new TransactionBlockstore(name ? name + '.indexes' : null, { primary: config.index })
|
42
|
-
this.remote = new Remote(this, name, config)
|
43
|
-
this.config = config
|
44
|
-
// todo we can wait for index blocks elsewhere
|
45
|
-
this.ready = Promise.all([this.blocks.ready, this.indexBlocks.ready]).then(([blocksReady, indexReady]) => {
|
46
|
-
const clock = new Set()
|
47
|
-
// console.log('blocksReady', blocksReady)
|
48
|
-
if (!blocksReady) {
|
49
|
-
return
|
50
|
-
}
|
51
|
-
for (const headers of blocksReady) {
|
52
|
-
for (const [, header] of Object.entries(headers)) {
|
53
|
-
if (!header) continue
|
54
|
-
for (const cid of header.clock) {
|
55
|
-
clock.add(cid)
|
56
|
-
}
|
57
|
-
if (header.index) {
|
58
|
-
this.indexBlocks.valet.primary.setLastCar(header.index.car)
|
59
|
-
this.indexBlocks.valet.primary.setKeyMaterial(header.index.key)
|
60
|
-
}
|
61
|
-
if (header.indexes) {
|
62
|
-
for (const {
|
63
|
-
name,
|
64
|
-
code,
|
65
|
-
clock: { byId, byKey, db }
|
66
|
-
} of header.indexes) {
|
67
|
-
// console.log('index', name, code, { byId, byKey }, db, header.indexes)
|
68
|
-
Index.fromJSON(this, {
|
69
|
-
clock: {
|
70
|
-
byId: byId ? parseCID(byId) : null,
|
71
|
-
byKey: byKey ? parseCID(byKey) : null,
|
72
|
-
db: db && db.length > 0 ? db.map(c => parseCID(c)) : null
|
73
|
-
},
|
74
|
-
code,
|
75
|
-
name
|
76
|
-
})
|
77
|
-
}
|
78
|
-
}
|
79
|
-
}
|
80
|
-
}
|
81
|
-
this.clock = [...clock]
|
82
|
-
})
|
83
|
-
}
|
84
|
-
|
85
|
-
/**
|
86
|
-
* Renders the Fireproof instance as a JSON object.
|
87
|
-
* @returns {Object} - The JSON representation of the Fireproof instance. Includes clock heads for the database and its indexes.
|
88
|
-
* @memberof Fireproof
|
89
|
-
* @instance
|
90
|
-
*/
|
91
|
-
toJSON () {
|
92
|
-
// todo this prepareHeader ignores secondary storage, need both
|
93
|
-
return this.blocks.valet ? this.blocks.valet.primary.prepareHeader(this.toHeader(), false) : this.toHeader() // omg
|
94
|
-
}
|
95
|
-
|
96
|
-
toHeader () {
|
97
|
-
return {
|
98
|
-
// clock: this.clockToJSON(),
|
99
|
-
name: this.name,
|
100
|
-
index: {
|
101
|
-
key: this.indexBlocks.valet?.primary.keyMaterial,
|
102
|
-
car: this.indexBlocks.valet?.primary.lastCar?.toString()
|
103
|
-
},
|
104
|
-
indexes: [...this.indexes.values()].map(index => index.toJSON())
|
105
|
-
}
|
106
|
-
}
|
107
|
-
|
108
|
-
/**
|
109
|
-
* Returns the Merkle clock heads for the Fireproof instance.
|
110
|
-
* @returns {string[]} - The Merkle clock heads for the Fireproof instance.
|
111
|
-
* @memberof Fireproof
|
112
|
-
* @instance
|
113
|
-
*/
|
114
|
-
clockToJSON (clock = null) {
|
115
|
-
return (clock || this.clock).map(cid => cid.toString())
|
116
|
-
}
|
117
|
-
|
118
|
-
async maybeSaveClock () {
|
119
|
-
if (this.name && this.blocks.valet) {
|
120
|
-
await this.blocks.valet.saveHeader(this.toHeader())
|
121
|
-
}
|
122
|
-
}
|
123
|
-
|
124
|
-
index (name) {
|
125
|
-
const indexes = [...this.indexes.values()].filter(index => index.name === name)
|
126
|
-
if (indexes.length > 1) {
|
127
|
-
throw new Error(`Multiple indexes found with name ${name}`)
|
128
|
-
}
|
129
|
-
return indexes[0] || null
|
130
|
-
}
|
131
|
-
|
132
|
-
/**
|
133
|
-
* Triggers a notification to all listeners
|
134
|
-
* of the Fireproof instance so they can repaint UI, etc.
|
135
|
-
* @returns {Promise<void>}
|
136
|
-
* @memberof Fireproof
|
137
|
-
* @instance
|
138
|
-
*/
|
139
|
-
async notifyReset () {
|
140
|
-
await this.ready
|
141
|
-
await this.notifyListeners({ _reset: true, _clock: this.clockToJSON() })
|
142
|
-
}
|
143
|
-
|
144
|
-
async compact () {
|
145
|
-
if (this.name && this.blocks.valet) {
|
146
|
-
await this.blocks.valet.compact(this.clock)
|
147
|
-
await this.blocks.valet.saveHeader(this.toHeader())
|
148
|
-
}
|
149
|
-
}
|
150
|
-
|
151
|
-
/**
|
152
|
-
* Returns the changes made to the Fireproof instance since the specified event.
|
153
|
-
* @function changesSince
|
154
|
-
* @param {CID[]} [event] - The clock head to retrieve changes since. If null or undefined, retrieves all changes.
|
155
|
-
* @returns {Promise<{rows : Object[], clock: CID[], proof: {}}>} An object containing the rows and the head of the instance's clock.
|
156
|
-
* @memberof Fireproof
|
157
|
-
* @instance
|
158
|
-
*/
|
159
|
-
async changesSince (aClock) {
|
160
|
-
await this.ready
|
161
|
-
// console.log('events for', this.instanceId, aClock?.constructor.name)
|
162
|
-
// console.log('changesSince', this.instanceId, this.clockToJSON(aClock), this.clockToJSON())
|
163
|
-
let rows, dataCIDs, clockCIDs
|
164
|
-
// if (!aClock) aClock = []
|
165
|
-
if (aClock && aClock.length > 0) {
|
166
|
-
aClock = aClock.map(cid => cid.toString())
|
167
|
-
const eventKey = JSON.stringify([...this.clockToJSON(aClock), ...this.clockToJSON()])
|
168
|
-
|
169
|
-
let resp
|
170
|
-
if (this.eventsCache.has(eventKey)) {
|
171
|
-
// console.log('events from cache')
|
172
|
-
resp = this.eventsCache.get(eventKey)
|
173
|
-
} else {
|
174
|
-
resp = await eventsSince(this.blocks, this.clock, aClock)
|
175
|
-
this.eventsCache.set(eventKey, resp)
|
176
|
-
}
|
177
|
-
const docsMap = new Map()
|
178
|
-
for (const { key, type, value } of resp.result.map(decodeEvent)) {
|
179
|
-
if (type === 'del') {
|
180
|
-
docsMap.set(key, { key, del: true })
|
181
|
-
} else {
|
182
|
-
docsMap.set(key, { key, value })
|
183
|
-
}
|
184
|
-
}
|
185
|
-
rows = Array.from(docsMap.values())
|
186
|
-
clockCIDs = resp.clockCIDs
|
187
|
-
// console.log('change rows', this.instanceId, rows)
|
188
|
-
} else {
|
189
|
-
const allResp = await getAll(this.blocks, this.clock, this.rootCache)
|
190
|
-
this.rootCache = { root: allResp.root, clockCIDs: allResp.clockCIDs }
|
191
|
-
|
192
|
-
rows = allResp.result.map(({ key, value }) => decodeEvent({ key, value }))
|
193
|
-
dataCIDs = allResp.cids
|
194
|
-
// console.log('dbdoc rows', this.instanceId, rows)
|
195
|
-
}
|
196
|
-
return {
|
197
|
-
rows,
|
198
|
-
clock: this.clockToJSON(),
|
199
|
-
proof: { data: await cidsToProof(dataCIDs), clock: await cidsToProof(clockCIDs) }
|
200
|
-
}
|
201
|
-
}
|
202
|
-
|
203
|
-
async allDocuments () {
|
204
|
-
await this.ready
|
205
|
-
const allResp = await getAll(this.blocks, this.clock, this.rootCache)
|
206
|
-
this.rootCache = { root: allResp.root, clockCIDs: allResp.clockCIDs }
|
207
|
-
|
208
|
-
const rows = allResp.result
|
209
|
-
.map(({ key, value }) => decodeEvent({ key, value }))
|
210
|
-
.map(({ key, value }) => ({ key, value: { _id: key, ...value } }))
|
211
|
-
return {
|
212
|
-
rows,
|
213
|
-
clock: this.clockToJSON(),
|
214
|
-
proof: await cidsToProof(allResp.cids)
|
215
|
-
}
|
216
|
-
}
|
217
|
-
|
218
|
-
async allCIDs () {
|
219
|
-
await this.ready
|
220
|
-
const allResp = await getAll(this.blocks, this.clock, this.rootCache, true)
|
221
|
-
this.rootCache = { root: allResp.root, clockCIDs: allResp.clockCIDs }
|
222
|
-
// console.log('allcids', allResp.cids, allResp.clockCIDs)
|
223
|
-
const cids = await cidsToProof(allResp.cids)
|
224
|
-
const clockCids = await cidsToProof(allResp.clockCIDs)
|
225
|
-
// console.log('allcids', cids, clockCids)
|
226
|
-
return [...cids, ...clockCids] // clock CID last -- need to handle multiple entry clocks
|
227
|
-
}
|
228
|
-
|
229
|
-
async allStoredCIDs () {
|
230
|
-
await this.ready
|
231
|
-
const allCIDs = []
|
232
|
-
for await (const { cid } of this.blocks.entries()) {
|
233
|
-
allCIDs.push(cid)
|
234
|
-
}
|
235
|
-
return allCIDs
|
236
|
-
}
|
237
|
-
|
238
|
-
/**
|
239
|
-
* Retrieves the document with the specified ID from the database
|
240
|
-
*
|
241
|
-
* @param {string} key - the ID of the document to retrieve
|
242
|
-
* @param {Object} [opts] - options
|
243
|
-
* @returns {Promise<{_id: string}>} - the document with the specified ID
|
244
|
-
* @memberof Fireproof
|
245
|
-
* @instance
|
246
|
-
*/
|
247
|
-
async get (key, opts = {}) {
|
248
|
-
await this.ready
|
249
|
-
const clock = opts.clock || this.clock
|
250
|
-
const resp = await get(this.blocks, clock, charwise.encode(key), this.rootCache)
|
251
|
-
this.rootCache = { root: resp.root, clockCIDs: resp.clockCIDs }
|
252
|
-
// ? this tombstone is temporary until we can get the prolly tree to delete
|
253
|
-
if (!resp || resp.result === null) {
|
254
|
-
throw new Error('Not found')
|
255
|
-
}
|
256
|
-
const doc = { ...resp.result }
|
257
|
-
if (opts.mvcc === true) {
|
258
|
-
doc._clock = this.clockToJSON()
|
259
|
-
}
|
260
|
-
doc._proof = {
|
261
|
-
data: await cidsToProof(resp.cids),
|
262
|
-
clock: this.clockToJSON()
|
263
|
-
}
|
264
|
-
doc._id = key
|
265
|
-
return doc
|
266
|
-
}
|
267
|
-
/**
|
268
|
-
* @typedef {any} Document
|
269
|
-
* @property {string} _id - The ID of the document (required)
|
270
|
-
* @property {string} [_proof] - The proof of the document (optional)
|
271
|
-
* @property {string} [_clock] - The clock of the document (optional)
|
272
|
-
* @property {Object.<string, any>} [unknown: string] - Any other unknown properties (optional)
|
273
|
-
*/
|
274
|
-
|
275
|
-
/**
|
276
|
-
* Adds a new document to the database, or updates an existing document. Returns the ID of the document and the new clock head.
|
277
|
-
*
|
278
|
-
* @param {Document} doc - the document to be added
|
279
|
-
* @returns {Promise<{ id: string, clock: CID[] }>} - The result of adding the document to the database
|
280
|
-
* @memberof Fireproof
|
281
|
-
* @instance
|
282
|
-
*/
|
283
|
-
async put ({ _id, _proof, _clock, ...doc }) {
|
284
|
-
await this.ready
|
285
|
-
const id = _id || 'f' + Math.random().toString(36).slice(2)
|
286
|
-
doc = JSON.parse(JSON.stringify(doc))
|
287
|
-
if (_clock) doc._clock = _clock
|
288
|
-
await this.runValidation({ _id: id, ...doc })
|
289
|
-
return await this.putToProllyTree({ key: id, value: doc }, _clock)
|
290
|
-
}
|
291
|
-
|
292
|
-
/**
|
293
|
-
* Deletes a document from the database
|
294
|
-
* @param {string | any} docOrId - the document ID
|
295
|
-
* @returns {Promise<{ id: string, clock: CID[] }>} - The result of deleting the document from the database
|
296
|
-
* @memberof Fireproof
|
297
|
-
* @instance
|
298
|
-
*/
|
299
|
-
async del (docOrId) {
|
300
|
-
await this.ready
|
301
|
-
let id
|
302
|
-
let clock = null
|
303
|
-
if (docOrId._id) {
|
304
|
-
id = docOrId._id
|
305
|
-
clock = docOrId._clock
|
306
|
-
} else {
|
307
|
-
id = docOrId
|
308
|
-
}
|
309
|
-
await this.runValidation({ _id: id, _deleted: true })
|
310
|
-
return await this.putToProllyTree({ key: id, del: true }, clock) // not working at prolly tree layer?
|
311
|
-
// this tombstone is temporary until we can get the prolly tree to delete
|
312
|
-
// return await this.putToProllyTree({ key: id, value: null }, clock)
|
313
|
-
}
|
314
|
-
|
315
|
-
/**
|
316
|
-
* Runs validation on the specified document using the Fireproof instance's configuration. Throws an error if the document is invalid.
|
317
|
-
*
|
318
|
-
* @param {Object} doc - The document to validate.
|
319
|
-
* @returns {Promise<void>}
|
320
|
-
* @throws {Error} - Throws an error if the document is invalid.
|
321
|
-
* @memberof Fireproof
|
322
|
-
* @instance
|
323
|
-
*/
|
324
|
-
async runValidation (doc) {
|
325
|
-
if (this.config && this.config.validateChange) {
|
326
|
-
const oldDoc = await this.get(doc._id)
|
327
|
-
.then(doc => doc)
|
328
|
-
.catch(() => ({}))
|
329
|
-
this.config.validateChange(doc, oldDoc, this.authCtx)
|
330
|
-
}
|
331
|
-
}
|
332
|
-
|
333
|
-
/**
|
334
|
-
* Updates the underlying storage with the specified event.
|
335
|
-
* @private
|
336
|
-
* @param {{del?: true, key : string, value?: any}} decodedEvent - the event to add
|
337
|
-
* @returns {Promise<{ proof:{}, id: string, clock: CID[] }>} - The result of adding the event to storage
|
338
|
-
*/
|
339
|
-
async putToProllyTree (decodedEvent, clock = null) {
|
340
|
-
// console.log('putToProllyTree', decodedEvent)
|
341
|
-
const event = encodeEvent(decodedEvent)
|
342
|
-
if (clock && JSON.stringify(this.clockToJSON(clock)) !== JSON.stringify(this.clockToJSON())) {
|
343
|
-
// console.log('this.clock', this.clockToJSON())
|
344
|
-
// console.log('that.clock', this.clockToJSON(clock))
|
345
|
-
// we need to check and see what version of the document exists at the clock specified
|
346
|
-
// if it is the same as the one we are trying to put, then we can proceed
|
347
|
-
const resp = await eventsSince(this.blocks, this.clock, event.value._clock)
|
348
|
-
const missedChange = resp.result.find(({ key }) => key === event.key)
|
349
|
-
if (missedChange) {
|
350
|
-
throw new Error('MVCC conflict, document is changed, please reload the document and try again.')
|
351
|
-
}
|
352
|
-
}
|
353
|
-
const prevClock = [...this.clock]
|
354
|
-
// console.log('putToProllyTree', this.clockToJSON(), decodedEvent)
|
355
|
-
const result = await doTransaction(
|
356
|
-
'putToProllyTree',
|
357
|
-
this.blocks,
|
358
|
-
async blocks => await put(blocks, this.clock, event)
|
359
|
-
)
|
360
|
-
if (!result) {
|
361
|
-
console.error('failed', event)
|
362
|
-
throw new Error('failed to put at storage layer')
|
363
|
-
}
|
364
|
-
this.applyClock(prevClock, result.head)
|
365
|
-
await this.notifyListeners([decodedEvent]) // this type is odd
|
366
|
-
return {
|
367
|
-
id: decodedEvent.key,
|
368
|
-
clock: this.clockToJSON(),
|
369
|
-
proof: { data: await cidsToProof(result.cids), clock: await cidsToProof(result.clockCIDs) }
|
370
|
-
}
|
371
|
-
// todo should include additions (or split clock)
|
372
|
-
}
|
373
|
-
|
374
|
-
applyClock (prevClock, newClock) {
|
375
|
-
// console.log('prevClock', prevClock.length, prevClock.map((cid) => cid.toString()))
|
376
|
-
// console.log('newClock', newClock.length, newClock.map((cid) => cid.toString()))
|
377
|
-
// console.log('this.clock', this.clock.length, this.clockToJSON())
|
378
|
-
const stPrev = prevClock.map(cid => cid.toString())
|
379
|
-
const keptPrevClock = this.clock.filter(cid => stPrev.indexOf(cid.toString()) === -1)
|
380
|
-
const merged = keptPrevClock.concat(newClock)
|
381
|
-
const uniquebyCid = new Map()
|
382
|
-
for (const cid of merged) {
|
383
|
-
uniquebyCid.set(cid.toString(), cid)
|
384
|
-
}
|
385
|
-
this.clock = Array.from(uniquebyCid.values()).sort((a, b) => a.toString().localeCompare(b.toString()))
|
386
|
-
this.rootCache = null
|
387
|
-
this.eventsCache.clear()
|
388
|
-
// console.log('afterClock', this.clock.length, this.clockToJSON())
|
389
|
-
}
|
390
|
-
|
391
|
-
// /**
|
392
|
-
// * Advances the clock to the specified event and updates the root CID
|
393
|
-
// * Will be used by replication
|
394
|
-
// */
|
395
|
-
// async advance (event) {
|
396
|
-
// this.clock = await advance(this.blocks, this.clock, event)
|
397
|
-
// this.rootCid = await root(this.blocks, this.clock)
|
398
|
-
// return this.clock
|
399
|
-
// }
|
400
|
-
|
401
|
-
async * vis () {
|
402
|
-
return yield * vis(this.blocks, this.clock)
|
403
|
-
}
|
404
|
-
|
405
|
-
async visTree () {
|
406
|
-
return await visMerkleTree(this.blocks, this.clock)
|
407
|
-
}
|
408
|
-
|
409
|
-
async visClock () {
|
410
|
-
return await visMerkleClock(this.blocks, this.clock)
|
411
|
-
}
|
412
|
-
|
413
|
-
/**
|
414
|
-
* Registers a Listener to be called when the Fireproof instance's clock is updated.
|
415
|
-
* Recieves live changes from the database after they are committed.
|
416
|
-
* @param {Function} listener - The listener to be called when the clock is updated.
|
417
|
-
* @returns {Function} - A function that can be called to unregister the listener.
|
418
|
-
* @memberof Fireproof
|
419
|
-
*/
|
420
|
-
subscribe (listener) {
|
421
|
-
this.listeners.add(listener)
|
422
|
-
return () => {
|
423
|
-
this.listeners.delete(listener)
|
424
|
-
}
|
425
|
-
}
|
426
|
-
|
427
|
-
/**
|
428
|
-
* @deprecated 0.7.0 - renamed subscribe(listener)
|
429
|
-
* @param {Function} listener - The listener to be called when the clock is updated.
|
430
|
-
* @returns {Function} - A function that can be called to unregister the listener.
|
431
|
-
* @memberof Fireproof
|
432
|
-
*/
|
433
|
-
registerListener (listener) {
|
434
|
-
return this.subscribe(listener)
|
435
|
-
}
|
436
|
-
|
437
|
-
async notifyListeners (changes) {
|
438
|
-
// await sleep(10)
|
439
|
-
await this.maybeSaveClock()
|
440
|
-
for (const listener of this.listeners) {
|
441
|
-
await listener(changes)
|
442
|
-
}
|
443
|
-
}
|
444
|
-
|
445
|
-
setRemoteBlockReader (remoteBlockReaderFn) {
|
446
|
-
this.blocks.remoteBlockFunction = remoteBlockReaderFn
|
447
|
-
}
|
448
|
-
}
|
449
|
-
|
450
|
-
export async function cidsToProof (cids) {
|
451
|
-
if (!cids) return []
|
452
|
-
if (!cids.all) {
|
453
|
-
return [...cids]
|
454
|
-
}
|
455
|
-
|
456
|
-
const all = await cids.all()
|
457
|
-
return [...all].map(cid => cid.toString())
|
458
|
-
}
|
459
|
-
|
460
|
-
function decodeEvent (event) {
|
461
|
-
const decodedKey = charwise.decode(event.key)
|
462
|
-
return { ...event, key: decodedKey }
|
463
|
-
}
|
464
|
-
|
465
|
-
function encodeEvent (event) {
|
466
|
-
if (!(event && event.key)) return
|
467
|
-
const encodedKey = charwise.encode(event.key)
|
468
|
-
return { ...event, key: encodedKey }
|
469
|
-
}
|