@fireproof/core 0.3.12 → 0.3.14

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/src/clock.js CHANGED
@@ -1,7 +1,7 @@
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'
4
+ // @ts-ignore
5
5
  import { CIDCounter } from 'prolly-trees/utils'
6
6
 
7
7
  /**
@@ -19,14 +19,28 @@ import { CIDCounter } from 'prolly-trees/utils'
19
19
  * @typedef {import('multiformats').Link<EventView<T>>} EventLink
20
20
  */
21
21
 
22
+ /**
23
+ * @typedef {{
24
+ * type: 'put'|'del'
25
+ * key: string
26
+ * value: import('./link').AnyLink
27
+ * root: import('./link').AnyLink
28
+ * }} EventData
29
+ * @typedef {{
30
+ * root: import('./link').AnyLink
31
+ * head: import('./clock').EventLink<EventData>[]
32
+ * event: import('./clock').EventBlockView<EventData>
33
+ * }} Result
34
+ */
35
+
22
36
  /**
23
37
  * Advance the clock by adding an event.
24
38
  *
25
39
  * @template T
26
- * @param {import('./blockstore').BlockFetcher} blocks Block storage.
40
+ * @param {import('./blockstore').TransactionBlockstore} blocks Block storage.
27
41
  * @param {EventLink<T>[]} head The head of the clock.
28
42
  * @param {EventLink<T>} event The event to add.
29
- * @returns {Promise<EventLink<T>[]>} The new head of the clock.
43
+ * @returns {Promise<{head:EventLink<T>[], cids:any[]}>} The new head of the clock.
30
44
  */
31
45
  export async function advance (blocks, head, event) {
32
46
  /** @type {EventFetcher<T>} */
@@ -34,7 +48,7 @@ export async function advance (blocks, head, event) {
34
48
  const headmap = new Map(head.map((cid) => [cid.toString(), cid]))
35
49
 
36
50
  // Check if the headmap already includes the event, return head if it does
37
- if (headmap.has(event.toString())) return { head, cids: events.cids }
51
+ if (headmap.has(event.toString())) return { head, cids: await events.all() }
38
52
 
39
53
  // Does event contain the clock?
40
54
  let changed = false
@@ -48,18 +62,18 @@ export async function advance (blocks, head, event) {
48
62
 
49
63
  // If the headmap has been changed, return the new headmap values
50
64
  if (changed) {
51
- return { head: [...headmap.values()], cids: events.cids }
65
+ return { head: [...headmap.values()], cids: await events.all() }
52
66
  }
53
67
 
54
68
  // Does clock contain the event?
55
69
  for (const p of head) {
56
70
  if (await contains(events, p, event)) {
57
- return { head, cids: events.cids }
71
+ return { head, cids: await events.all() }
58
72
  }
59
73
  }
60
74
 
61
75
  // Return the head concatenated with the new event if it passes both checks
62
- return { head: head.concat(event), cids: events.cids }
76
+ return { head: head.concat(event), cids: await events.all() }
63
77
  }
64
78
 
65
79
  /**
@@ -90,7 +104,7 @@ export class EventBlock extends Block {
90
104
 
91
105
  /** @template T */
92
106
  export class EventFetcher {
93
- /** @param {import('./blockstore').BlockFetcher} blocks */
107
+ /** @param {import('./blockstore').TransactionBlockstore} blocks */
94
108
  constructor (blocks) {
95
109
  /** @private */
96
110
  this._blocks = blocks
@@ -115,8 +129,8 @@ export class EventFetcher {
115
129
  }
116
130
 
117
131
  async all () {
118
- await Promise.all([...this._cids])
119
- return this._cids
132
+ // await Promise.all([...this._cids])
133
+ return this._cids.all()
120
134
  }
121
135
  }
122
136
 
@@ -169,12 +183,13 @@ async function contains (events, a, b) {
169
183
 
170
184
  /**
171
185
  * @template T
172
- * @param {import('./blockstore').BlockFetcher} blocks Block storage.
186
+ * @param {import('./blockstore').TransactionBlockstore} blocks Block storage.
173
187
  * @param {EventLink<T>[]} head
174
188
  * @param {object} [options]
175
189
  * @param {(b: EventBlockView<T>) => string} [options.renderNodeLabel]
176
190
  */
177
191
  export async function * vis (blocks, head, options = {}) {
192
+ // @ts-ignore
178
193
  const renderNodeLabel = options.renderNodeLabel ?? ((b) => b.value.data.value)
179
194
  const events = new EventFetcher(blocks)
180
195
  yield 'digraph clock {'
@@ -217,7 +232,7 @@ export async function findEventsToSync (blocks, head) {
217
232
  const toSync = await asyncFilter(sorted, async (uks) => !(await contains(events, ancestor, uks.cid)))
218
233
  // console.timeEnd(callTag + '.contains')
219
234
 
220
- return { cids: events.cids, events: toSync }
235
+ return { cids: events.all(), events: toSync }
221
236
  }
222
237
 
223
238
  const asyncFilter = async (arr, predicate) =>
@@ -336,10 +351,10 @@ async function findSortedEvents (events, head, tail) {
336
351
  }
337
352
 
338
353
  /**
339
- * @param {import('./clock').EventFetcher} events
340
- * @param {import('./clock').EventLink<EventData>} start
341
- * @param {import('./clock').EventLink<EventData>} end
342
- * @returns {Promise<Array<{ event: import('./clock').EventBlockView<EventData>, depth: number }>>}
354
+ * @param {EventFetcher} events
355
+ * @param {EventLink<EventData>} start
356
+ * @param {EventLink<EventData>} end
357
+ * @returns {Promise<Array<{ event: EventBlockView<EventData>, depth: number }>>}
343
358
  */
344
359
  async function findEvents (events, start, end, depth = 0) {
345
360
  // console.log('findEvents', start)
package/src/db-index.js CHANGED
@@ -1,4 +1,3 @@
1
- // @ts-nocheck
2
1
  // @ts-ignore
3
2
  import { create, load } from 'prolly-trees/db-index'
4
3
  // import { create, load } from '../../../../prolly-trees/src/db-index.js'
@@ -9,7 +8,8 @@ import { nocache as cache } from 'prolly-trees/cache'
9
8
  // @ts-ignore
10
9
  import { bf, simpleCompare } from 'prolly-trees/utils'
11
10
  import { makeGetBlock } from './prolly.js'
12
- import { cidsToProof } from './fireproof.js'
11
+ // eslint-disable-next-line no-unused-vars
12
+ import { Fireproof, cidsToProof } from './fireproof.js'
13
13
 
14
14
  import * as codec from '@ipld/dag-cbor'
15
15
  // import { create as createBlock } from 'multiformats/block'
@@ -94,11 +94,6 @@ const indexEntriesForChanges = (changes, mapFn) => {
94
94
  */
95
95
  export class DbIndex {
96
96
  constructor (database, mapFn, clock, opts = {}) {
97
- // console.log('DbIndex constructor', database.constructor.name, typeof mapFn, clock)
98
- /**
99
- * The database instance to DbIndex.
100
- * @type {Fireproof}
101
- */
102
97
  this.database = database
103
98
  if (!database.indexBlocks) {
104
99
  database.indexBlocks = new TransactionBlockstore(database.name + '.indexes', database.blocks.valet.getKeyMaterial())
package/src/fireproof.js CHANGED
@@ -3,11 +3,12 @@ import { randomBytes } from 'crypto'
3
3
  import { visMerkleClock, visMerkleTree, vis, put, get, getAll, eventsSince } from './prolly.js'
4
4
  import { TransactionBlockstore, doTransaction } from './blockstore.js'
5
5
  import charwise from 'charwise'
6
- // import { CID } from 'multiformats/dist/types/src/cid.js'
7
-
8
- // const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
9
6
 
10
- // class Proof {}
7
+ // TypeScript Types
8
+ // eslint-disable-next-line no-unused-vars
9
+ // import { CID } from 'multiformats/dist/types/src/cid.js'
10
+ // eslint-disable-next-line no-unused-vars
11
+ class Proof {}
11
12
 
12
13
  /**
13
14
  * @class Fireproof
@@ -65,6 +66,12 @@ export class Fireproof {
65
66
  }
66
67
  }
67
68
 
69
+ /**
70
+ * Returns the Merkle clock heads for the Fireproof instance.
71
+ * @returns {string[]} - The Merkle clock heads for the Fireproof instance.
72
+ * @memberof Fireproof
73
+ * @instance
74
+ */
68
75
  clockToJSON () {
69
76
  return this.clock.map(cid => cid.toString())
70
77
  }
@@ -79,8 +86,6 @@ export class Fireproof {
79
86
  /**
80
87
  * Triggers a notification to all listeners
81
88
  * of the Fireproof instance so they can repaint UI, etc.
82
- * @param {CID[] } clock
83
- * Clock to use for the snapshot.
84
89
  * @returns {Promise<void>}
85
90
  * @memberof Fireproof
86
91
  * @instance
@@ -98,7 +103,7 @@ export class Fireproof {
98
103
  * Returns the changes made to the Fireproof instance since the specified event.
99
104
  * @function changesSince
100
105
  * @param {CID[]} [event] - The clock head to retrieve changes since. If null or undefined, retrieves all changes.
101
- * @returns {Object<{rows : Object[], clock: CID[]}>} An object containing the rows and the head of the instance's clock.
106
+ * @returns {Promise<{rows : Object[], clock: CID[], proof: {}}>} An object containing the rows and the head of the instance's clock.
102
107
  * @memberof Fireproof
103
108
  * @instance
104
109
  */
@@ -117,7 +122,7 @@ export class Fireproof {
117
122
  }
118
123
  }
119
124
  rows = Array.from(docsMap.values())
120
- clockCIDs = resp.cids
125
+ clockCIDs = resp.clockCIDs
121
126
  // console.log('change rows', this.instanceId, rows)
122
127
  } else {
123
128
  const allResp = await getAll(this.blocks, this.clock)
package/src/listener.js CHANGED
@@ -1,11 +1,10 @@
1
- // @ts-nocheck
2
1
  /**
3
2
  * A Fireproof database Listener allows you to react to events in the database.
4
3
  *
5
4
  * @class Listener
6
5
  * @classdesc An listener attaches to a Fireproof database and runs a routing function on each change, sending the results to subscribers.
7
6
  *
8
- * @param {Fireproof} database - The Fireproof database instance to index.
7
+ * @param {import('./fireproof.js').Fireproof} database - The Fireproof database instance to index.
9
8
  * @param {Function} routingFn - The routing function to apply to each entry in the database.
10
9
  */
11
10
  // import { ChangeEvent } from './db-index'
@@ -14,20 +13,20 @@ export class Listener {
14
13
  subcribers = new Map()
15
14
  doStopListening = null
16
15
 
16
+ /**
17
+ * @param {import('./fireproof.js').Fireproof} database
18
+ * @param {(_: any, emit: any) => void} routingFn
19
+ */
17
20
  constructor (database, routingFn) {
18
- /** routingFn
19
- * The database instance to index.
20
- * @type {Fireproof}
21
- */
22
21
  this.database = database
23
- this.doStopListening = database.registerListener(changes => this.onChanges(changes))
22
+ this.doStopListening = database.registerListener((/** @type {any} */ changes) => this.onChanges(changes))
24
23
  /**
25
24
  * The map function to apply to each entry in the database.
26
25
  * @type {Function}
27
26
  */
28
27
  this.routingFn =
29
28
  routingFn ||
30
- function (_, emit) {
29
+ function (/** @type {any} */ _, /** @type {(arg0: string) => void} */ emit) {
31
30
  emit('*')
32
31
  }
33
32
  this.dbHead = null
@@ -40,6 +39,7 @@ export class Listener {
40
39
  * @returns {Function} A function to unsubscribe from the topic.
41
40
  * @memberof Listener
42
41
  * @instance
42
+ * @param {any} since
43
43
  */
44
44
  on (topic, subscriber, since) {
45
45
  const listOfTopicSubscribers = getTopicList(this.subcribers, topic)
@@ -47,7 +47,7 @@ export class Listener {
47
47
  if (typeof since !== 'undefined') {
48
48
  this.database.changesSince(since).then(({ rows: changes }) => {
49
49
  const keys = topicsForChanges(changes, this.routingFn).get(topic)
50
- if (keys) keys.forEach(key => subscriber(key))
50
+ if (keys) keys.forEach((/** @type {any} */ key) => subscriber(key))
51
51
  })
52
52
  }
53
53
  return () => {
@@ -56,22 +56,35 @@ export class Listener {
56
56
  }
57
57
  }
58
58
 
59
+ /**
60
+ * @typedef {import('./db-index').ChangeEvent} ChangeEvent
61
+ */
62
+
63
+ /**
64
+ * @param {ChangeEvent[]} changes
65
+ */
59
66
  onChanges (changes) {
60
67
  if (Array.isArray(changes)) {
61
68
  const seenTopics = topicsForChanges(changes, this.routingFn)
62
69
  for (const [topic, keys] of seenTopics) {
63
70
  const listOfTopicSubscribers = getTopicList(this.subcribers, topic)
64
- listOfTopicSubscribers.forEach(subscriber => keys.forEach(key => subscriber(key)))
71
+ listOfTopicSubscribers.forEach((/** @type {(arg0: any) => any} */ subscriber) =>
72
+ keys.forEach((/** @type {any} */ key) => subscriber(key))
73
+ )
65
74
  }
66
75
  } else {
67
76
  // non-arrays go to all subscribers
68
77
  for (const [, listOfTopicSubscribers] of this.subcribers) {
69
- listOfTopicSubscribers.forEach(subscriber => subscriber(changes))
78
+ listOfTopicSubscribers.forEach((/** @type {(arg0: any) => any} */ subscriber) => subscriber(changes))
70
79
  }
71
80
  }
72
81
  }
73
82
  }
74
83
 
84
+ /**
85
+ * @param {Map<any, any>} subscribersMap
86
+ * @param {string} name
87
+ */
75
88
  function getTopicList (subscribersMap, name) {
76
89
  let topicList = subscribersMap.get(name)
77
90
  if (!topicList) {
@@ -86,14 +99,14 @@ function getTopicList (subscribersMap, name) {
86
99
  *
87
100
  * @param {ChangeEvent[]} changes
88
101
  * @param {Function} routingFn
89
- * @returns {Array<string>} The topics emmitted by the event function.
102
+ * @returns {Map<string,string[]>} The topics emmitted by the event function.
90
103
  * @private
91
104
  */
92
105
  const topicsForChanges = (changes, routingFn) => {
93
106
  const seenTopics = new Map()
94
107
  changes.forEach(({ key, value, del }) => {
95
108
  if (del || !value) value = { _deleted: true }
96
- routingFn(({ _id: key, ...value }), t => {
109
+ routingFn({ _id: key, ...value }, (/** @type {any} */ t) => {
97
110
  const topicList = getTopicList(seenTopics, t)
98
111
  topicList.push(key)
99
112
  })
package/src/prolly.js CHANGED
@@ -1,4 +1,3 @@
1
- // @ts-nocheck
2
1
  import {
3
2
  advance,
4
3
  EventFetcher,
@@ -7,9 +6,12 @@ import {
7
6
  findEventsToSync,
8
7
  vis as visClock
9
8
  } from './clock.js'
10
- import { create, load } from 'prolly-trees/map'
11
9
  // import { create, load } from '../../../../prolly-trees/src/map.js'
10
+ // @ts-ignore
11
+ import { create, load } from 'prolly-trees/map'
12
+ // @ts-ignore
12
13
  import { nocache as cache } from 'prolly-trees/cache'
14
+ // @ts-ignore
13
15
  import { CIDCounter, bf, simpleCompare as compare } from 'prolly-trees/utils'
14
16
  import * as codec from '@ipld/dag-cbor'
15
17
  import { sha256 as hasher } from 'multiformats/hashes/sha2'
@@ -63,7 +65,7 @@ async function createAndSaveNewEvent ({
63
65
  : null),
64
66
  key
65
67
  }
66
-
68
+ // import('./clock').EventLink<import('./clock').EventData>
67
69
  if (del) {
68
70
  data.value = null
69
71
  data.type = 'del'
@@ -71,10 +73,11 @@ async function createAndSaveNewEvent ({
71
73
  data.value = value
72
74
  data.type = 'put'
73
75
  }
74
- /** @type {EventData} */
75
-
76
+ /** @type {import('./clock').EventData} */
77
+ // @ts-ignore
76
78
  const event = await EventBlock.create(data, head)
77
79
  bigPut(event)
80
+ // @ts-ignore
78
81
  ;({ head, cids } = await advance(inBlocks, head, event.cid))
79
82
 
80
83
  return {
@@ -130,7 +133,7 @@ const bulkFromEvents = (sorted, event) => {
130
133
  /**
131
134
  *
132
135
  * @param {EventFetcher} events
133
- * @param {Link} ancestor
136
+ * @param {import('./clock').EventLink<import('./clock').EventData>} ancestor
134
137
  * @param {*} getBlock
135
138
  * @returns
136
139
  */
@@ -185,12 +188,11 @@ const doProllyBulk = async (inBlocks, head, event) => {
185
188
  /**
186
189
  * Put a value (a CID) for the given key. If the key exists it's value is overwritten.
187
190
  *
188
- * @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
189
- * @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
190
- * @param {string} key The key of the value to put.
191
- * @param {CID} value The value to put.
191
+ * @param {import('./blockstore.js').Blockstore} inBlocks Bucket block storage.
192
+ * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
193
+ * @param {{key: string, value: import('./clock').EventLink<import('./clock').EventData>}} event The key of the value to put.
192
194
  * @param {object} [options]
193
- * @returns {Promise<Result>}
195
+ * @returns {Promise<any>}
194
196
  */
195
197
  export async function put (inBlocks, head, event, options) {
196
198
  const { bigPut } = makeGetAndPutBlock(inBlocks)
@@ -237,8 +239,8 @@ export async function put (inBlocks, head, event, options) {
237
239
  /**
238
240
  * Determine the effective prolly root given the current merkle clock head.
239
241
  *
240
- * @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
241
- * @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
242
+ * @param {import('./blockstore.js').TransactionBlockstore} inBlocks Bucket block storage.
243
+ * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
242
244
  */
243
245
  export async function root (inBlocks, head) {
244
246
  if (!head.length) {
@@ -257,15 +259,16 @@ export async function root (inBlocks, head) {
257
259
 
258
260
  /**
259
261
  * Get the list of events not known by the `since` event
260
- * @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
261
- * @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
262
- * @param {import('./clock').EventLink<EventData>} since Event to compare against.
263
- * @returns {Promise<{clockCIDs: CIDCounter, result: EventData[]}>}
262
+ * @param {import('./blockstore.js').TransactionBlockstore} blocks Bucket block storage.
263
+ * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
264
+ * @param {import('./clock').EventLink<import('./clock').EventData>} since Event to compare against.
265
+ * @returns {Promise<{clockCIDs: CIDCounter, result: import('./clock').EventData[]}>}
264
266
  */
265
267
  export async function eventsSince (blocks, head, since) {
266
268
  if (!head.length) {
267
269
  throw new Error('no head')
268
270
  }
271
+ // @ts-ignore
269
272
  const sinceHead = [...since, ...head] // ?
270
273
  const { cids, events: unknownSorted3 } = await findEventsToSync(blocks, sinceHead)
271
274
  return { clockCIDs: cids, result: unknownSorted3.map(({ value: { data } }) => data) }
@@ -273,10 +276,10 @@ export async function eventsSince (blocks, head, since) {
273
276
 
274
277
  /**
275
278
  *
276
- * @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
277
- * @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
279
+ * @param {import('./blockstore.js').TransactionBlockstore} blocks Bucket block storage.
280
+ * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
278
281
  *
279
- * @returns {Promise<{clockCIDs: CIDCounter, result: EventData[]}>}
282
+ * @returns {Promise<{cids: CIDCounter, clockCIDs: CIDCounter, result: import('./clock').EventData[]}>}
280
283
  *
281
284
  */
282
285
  export async function getAll (blocks, head) {
@@ -294,8 +297,8 @@ export async function getAll (blocks, head) {
294
297
  }
295
298
 
296
299
  /**
297
- * @param {import('./blockstore.js').BlockFetcher} blocks Bucket block storage.
298
- * @param {import('./clock').EventLink<EventData>[]} head Merkle clock head.
300
+ * @param {import('./blockstore.js').TransactionBlockstore} blocks Bucket block storage.
301
+ * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
299
302
  * @param {string} key The key of the value to retrieve.
300
303
  */
301
304
  export async function get (blocks, head, key) {
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'
@@ -8,16 +7,19 @@ import * as Block from 'multiformats/block'
8
7
  import * as dagcbor from '@ipld/dag-cbor'
9
8
  import { openDB } from 'idb'
10
9
  import cargoQueue from 'async/cargoQueue.js'
10
+ // @ts-ignore
11
11
  import { bf } from 'prolly-trees/utils'
12
+ // @ts-ignore
12
13
  import { nocache as cache } from 'prolly-trees/cache'
13
14
  import { encrypt, decrypt } from './crypto.js'
14
15
  import { Buffer } from 'buffer'
16
+ // @ts-ignore
15
17
  import * as codec from 'encrypted-block'
16
18
  import { rawSha1 as sha1sync } from './sha1.js'
17
19
  const chunker = bf(3)
18
20
 
19
- const NO_ENCRYPT =
20
- typeof process !== 'undefined' ? process.env.NO_ENCRYPT : import.meta && import.meta.env.VITE_NO_ENCRYPT
21
+ const NO_ENCRYPT = process.env?.NO_ENCRYPT
22
+ // typeof process !== 'undefined' ? process.env.NO_ENCRYPT : import.meta && import.meta.env.VITE_NO_ENCRYPT
21
23
 
22
24
  export class Valet {
23
25
  idb = null
@@ -89,7 +91,7 @@ export class Valet {
89
91
 
90
92
  /**
91
93
  * Group the blocks into a car and write it to the valet.
92
- * @param {InnerBlockstore} innerBlockstore
94
+ * @param {import('./blockstore.js').InnerBlockstore} innerBlockstore
93
95
  * @param {Set<string>} cids
94
96
  * @returns {Promise<void>}
95
97
  * @memberof Valet