@fireproof/core 0.0.2 → 0.0.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.
@@ -0,0 +1,149 @@
1
+ # useFireproof hook for React
2
+
3
+ React hook to initialize a Fireproof database, automatically saving and loading the clock.
4
+
5
+ The hook takes two optional setup function arguments, `defineDatabaseFn` and `setupDatabaseFn`. See below for examples.
6
+
7
+ The return value looks like `{ ready, database, addSubscriber }` where the `database` is your Fireproof instance that you can interact with using `put` and `get`, or via your indexes. The `ready` flag turns true after setup completes, you can use this to activate your UI. The `addSubscriber` function is used to update your app in realtime, see example.
8
+
9
+ ## Usage Example
10
+
11
+ In App.js:
12
+
13
+ ```js
14
+ import { FireproofCtx, useFireproof } from '@fireproof/core/hooks/use-fireproof'
15
+
16
+ function App() {
17
+ // establish the Fireproof context value
18
+ const fpCtxValue = useFireproof()
19
+
20
+ // render the rest of the application wrapped in the Fireproof provider
21
+ return (
22
+ <FireproofCtx.Provider value={fpCtxValue}>
23
+ <MyComponent />
24
+ </FireproofCtx.Provider>
25
+ )
26
+ }
27
+ ```
28
+
29
+ In your components:
30
+
31
+ ```js
32
+ import { FireproofCtx } from '@fireproof/core/hooks/use-fireproof'
33
+
34
+ function MyComponent() {
35
+ // get Fireproof context
36
+ const { ready, database, addSubscriber } = useContext(FireproofCtx)
37
+
38
+ // set a default empty document
39
+ const [doc, setDoc] = useState({})
40
+
41
+ // function to load the document from the database
42
+ const getDataFn = async () => {
43
+ setDoc(await database.get("my-doc-id"))
44
+ }
45
+
46
+ // run that function when the database changes
47
+ addSubscriber('MyComponent', getDataFn)
48
+
49
+ // run the loader on first mount
50
+ useEffect(() => getDataFn(), [])
51
+
52
+ // a function to change the value of the document
53
+ const updateFn = async () => {
54
+ await database.put({ _id : "my-doc-id", hello: "world", updated_at: new Date()})
55
+ }
56
+
57
+ // render the document with a click handler to update it
58
+ return <pre onclick={updateFn}>JSON.stringify(doc)</pre>
59
+ }
60
+ ```
61
+
62
+ This should result in a tiny application that updates the document when you click it. In a real appliction you'd probably query an index to present eg. all of the photos in a gallery.
63
+
64
+ ## Setup Functions
65
+
66
+ ### defineDatabaseFn
67
+
68
+ Synchronous function that defines the database, run this before any async calls. You can use it to do stuff like set up Indexes. Here's an example:
69
+
70
+ ```js
71
+ const defineIndexes = (database) => {
72
+ database.allLists = new Index(database, function (doc, map) {
73
+ if (doc.type === 'list') map(doc.type, doc)
74
+ })
75
+ database.todosByList = new Index(database, function (doc, map) {
76
+ if (doc.type === 'todo' && doc.listId) {
77
+ map([doc.listId, doc.createdAt], doc)
78
+ }
79
+ })
80
+ window.fireproof = database // 🤫 for dev
81
+ return database
82
+ }
83
+ ```
84
+
85
+ ### setupDatabaseFn
86
+
87
+ Asynchronous function that uses the database when it's ready, run this to load fixture data, insert a dataset from somewhere else, etc. Here's a simple example:
88
+
89
+
90
+ ```
91
+ async function setupDatabase(database)) {
92
+ const apiData = await (await fetch('https://dummyjson.com/products')).json()
93
+ for (const product of apiData.products) {
94
+ await database.put(product)
95
+ }
96
+ }
97
+ ```
98
+
99
+ Note there are no protections against you running the same thing over and over again, so you probably want to put some logic in there to do the right thing.
100
+
101
+ Here is an example of generating deterministic fixtures, using `mulberry32` for determinstic randomness so re-runs give the same CID, avoiding unnecessary bloat at development time, taken from the TodoMVC demo app.
102
+
103
+ ```js
104
+ function mulberry32(a) {
105
+ return function () {
106
+ let t = (a += 0x6d2b79f5)
107
+ t = Math.imul(t ^ (t >>> 15), t | 1)
108
+ t ^= t + Math.imul(t ^ (t >>> 7), t | 61)
109
+ return ((t ^ (t >>> 14)) >>> 0) / 4294967296
110
+ }
111
+ }
112
+ const rand = mulberry32(1) // determinstic fixtures
113
+
114
+ export default async function loadFixtures(database) {
115
+ const nextId = (prefix = '') => prefix + rand().toString(32).slice(2)
116
+ const listTitles = ['Building Apps', 'Having Fun', 'Getting Groceries']
117
+ const todoTitles = [
118
+ [
119
+ 'In the browser',
120
+ 'On the phone',
121
+ 'With or without Redux',
122
+ 'Login components',
123
+ 'GraphQL queries',
124
+ 'Automatic replication and versioning',
125
+ ],
126
+ ['Rollerskating meetup', 'Motorcycle ride', 'Write a sci-fi story with ChatGPT'],
127
+ ['Macadamia nut milk', 'Avocado toast', 'Coffee', 'Bacon', 'Sourdough bread', 'Fruit salad'],
128
+ ]
129
+ let ok
130
+ for (let j = 0; j < 3; j++) {
131
+ ok = await database.put({
132
+ title: listTitles[j],
133
+ type: 'list',
134
+ _id: nextId('' + j)
135
+ })
136
+ for (let i = 0; i < todoTitles[j].length; i++) {
137
+ await database.put({
138
+ _id: nextId(),
139
+ title: todoTitles[j][i],
140
+ listId: ok.id,
141
+ completed: rand() > 0.75,
142
+ type: 'todo',
143
+ })
144
+ }
145
+ }
146
+ }
147
+ ```
148
+
149
+
@@ -0,0 +1,112 @@
1
+ /* global localStorage */
2
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3
+ // @ts-ignore
4
+ import { useEffect, useState, createContext } from 'react'
5
+ import { Fireproof, Listener } from '@fireproof/core'
6
+
7
+ export interface FireproofCtxValue {
8
+ addSubscriber: (label: String, fn: Function) => void
9
+ database: Fireproof
10
+ ready: boolean
11
+ }
12
+ export const FireproofCtx = createContext<FireproofCtxValue>({
13
+ addSubscriber: () => {},
14
+ database: null,
15
+ ready: false,
16
+ })
17
+
18
+
19
+
20
+ const inboundSubscriberQueue = new Map()
21
+ const database = Fireproof.storage()
22
+ const listener = new Listener(database)
23
+
24
+ /**
25
+ * @function useFireproof
26
+ * React hook to initialize a Fireproof database, automatically saving and loading the clock.
27
+ * @param [defineDatabaseFn] Synchronous function that defines the database, run this before any async calls
28
+ * @param [setupDatabaseFn] Asynchronous function that sets up the database, run this to load fixture data etc
29
+ * @returns {FireproofCtxValue} { addSubscriber, database, ready }
30
+ */
31
+ export function useFireproof(defineDatabaseFn: Function, setupDatabaseFn: Function): FireproofCtxValue {
32
+ const [ready, setReady] = useState(false)
33
+ defineDatabaseFn = defineDatabaseFn || (() => {})
34
+ setupDatabaseFn = setupDatabaseFn || (() => {})
35
+
36
+ if (!ready) {
37
+ defineDatabaseFn(database)
38
+ }
39
+
40
+ const addSubscriber = (label: String, fn: Function) => {
41
+ inboundSubscriberQueue.set(label, fn)
42
+ }
43
+
44
+ const listenerCallback = async () => {
45
+ localSet('fireproof', JSON.stringify(database))
46
+ for (const [, fn] of inboundSubscriberQueue) fn()
47
+ }
48
+
49
+ useEffect(() => {
50
+ const doSetup = async () => {
51
+ if (ready) return
52
+ const fp = localGet('fireproof')
53
+ if (fp) {
54
+ const { clock } = JSON.parse(fp)
55
+ console.log("Loading previous database clock. (localStorage.removeItem('fireproof') to reset)")
56
+ await database.setClock(clock)
57
+ try {
58
+ await database.changesSince()
59
+ } catch (e) {
60
+ console.error('Error loading previous database clock.', e)
61
+ await database.setClock([])
62
+ await setupDatabaseFn(database)
63
+ localSet('fireproof', JSON.stringify(database))
64
+ }
65
+ } else {
66
+ await setupDatabaseFn(database)
67
+ localSet('fireproof', JSON.stringify(database))
68
+ }
69
+ setReady(true)
70
+ listener.on('*', hushed('*', listenerCallback, 250))
71
+ }
72
+ doSetup()
73
+ }, [ready])
74
+
75
+ return {
76
+ addSubscriber,
77
+ database,
78
+ ready,
79
+ }
80
+ }
81
+
82
+ const husherMap = new Map()
83
+ const husher = (id: string, workFn: { (): Promise<any> }, ms: number) => {
84
+ if (!husherMap.has(id)) {
85
+ husherMap.set(
86
+ id,
87
+ workFn().finally(() => setTimeout(() => husherMap.delete(id), ms))
88
+ )
89
+ }
90
+ return husherMap.get(id)
91
+ }
92
+ const hushed = (id: string, workFn: { (): Promise<any> }, ms: number) => () => husher(id, workFn, ms)
93
+
94
+ let storageSupported = false
95
+ try {
96
+ storageSupported = window.localStorage && true
97
+ } catch (e) {}
98
+ export function localGet(key: string) {
99
+ if (storageSupported) {
100
+ return localStorage && localStorage.getItem(key)
101
+ }
102
+ }
103
+ function localSet(key: string, value: string) {
104
+ if (storageSupported) {
105
+ return localStorage && localStorage.setItem(key, value)
106
+ }
107
+ }
108
+ // function localRemove(key) {
109
+ // if (storageSupported) {
110
+ // return localStorage && localStorage.removeItem(key)
111
+ // }
112
+ // }
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "@fireproof/core",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Realtime database for IPFS",
5
5
  "main": "index.js",
6
6
  "type": "module",
7
7
  "scripts": {
8
- "test": "standard && mocha test/*.test.js",
8
+ "test": "standard && npm run test:mocha",
9
+ "test:mocha": "mocha test/*.test.js",
10
+ "test:watch": "npm run test:mocha -- -w --parallel test/*.test.js",
9
11
  "coverage": "c8 -r html -r text npm test",
10
12
  "lint": "standard",
11
13
  "lint:fix": "standard --fix"
@@ -29,6 +31,7 @@
29
31
  "@ipld/car": "^5.1.0",
30
32
  "@ipld/dag-cbor": "^9.0.0",
31
33
  "archy": "^1.0.0",
34
+ "async": "^3.2.4",
32
35
  "car-transaction": "^1.0.1",
33
36
  "charwise": "^3.0.1",
34
37
  "cli-color": "^2.0.3",
@@ -52,7 +55,8 @@
52
55
  "standard": {
53
56
  "ignore": [
54
57
  "examples/**/*.tsx",
55
- "examples/**/dist"
58
+ "examples/**/dist",
59
+ "out/**"
56
60
  ]
57
61
  },
58
62
  "repository": {
@@ -66,5 +70,4 @@
66
70
  "workspaces": [
67
71
  "examples/todomvc"
68
72
  ]
69
-
70
73
  }
package/src/block.js CHANGED
@@ -37,16 +37,6 @@ export class MemoryBlockstore {
37
37
  this.#blocks.set(cid.toString(), bytes)
38
38
  }
39
39
 
40
- /** @param {import('./link').AnyLink} cid */
41
- async delete (cid) {
42
- this.#blocks.delete(cid.toString())
43
- }
44
-
45
- /** @param {import('./link').AnyLink} cid */
46
- deleteSync (cid) {
47
- this.#blocks.delete(cid.toString())
48
- }
49
-
50
40
  * entries () {
51
41
  for (const [str, bytes] of this.#blocks) {
52
42
  yield { cid: parse(str), bytes }
package/src/blockstore.js CHANGED
@@ -3,11 +3,23 @@ import * as raw from 'multiformats/codecs/raw'
3
3
  import { sha256 } from 'multiformats/hashes/sha2'
4
4
  import * as Block from 'multiformats/block'
5
5
  import * as CBW from '@ipld/car/buffer-writer'
6
+ import { CID } from 'multiformats'
6
7
 
7
8
  import Valet from './valet.js'
8
9
 
9
10
  // const sleep = ms => new Promise(r => setTimeout(r, ms))
10
11
 
12
+ const husherMap = new Map()
13
+ const husher = (id, workFn) => {
14
+ if (!husherMap.has(id)) {
15
+ husherMap.set(
16
+ id,
17
+ workFn().finally(() => setTimeout(() => husherMap.delete(id), 100))
18
+ )
19
+ }
20
+ return husherMap.get(id)
21
+ }
22
+
11
23
  /**
12
24
  * @typedef {Object} AnyBlock
13
25
  * @property {import('./link').AnyLink} cid - The CID of the block
@@ -24,7 +36,7 @@ export default class TransactionBlockstore {
24
36
  /** @type {Map<string, Uint8Array>} */
25
37
  #oldBlocks = new Map()
26
38
 
27
- #valet = new Valet() // cars by cid
39
+ valet = new Valet() // cars by cid
28
40
 
29
41
  #instanceId = 'blkz.' + Math.random().toString(36).substring(2, 4)
30
42
  #inflightTransactions = new Set()
@@ -38,10 +50,10 @@ export default class TransactionBlockstore {
38
50
  async get (cid) {
39
51
  const key = cid.toString()
40
52
  // it is safe to read from the in-flight transactions becauase they are immutable
41
- // const bytes = this.#oldBlocks.get(key) || await this.#valet.getBlock(key)
42
- const bytes = await this.#transactionsGet(key) || await this.commitedGet(key)
43
- // const bytes = this.#blocks.get(key) || await this.#valet.getBlock(key)
44
- // console.log('bytes', typeof bytes)
53
+ const bytes = await Promise.any([this.#transactionsGet(key), this.commitedGet(key)]).catch((e) => {
54
+ console.log('networkGet', cid.toString(), e)
55
+ return this.networkGet(key)
56
+ })
45
57
  if (!bytes) throw new Error('Missing block: ' + key)
46
58
  return { cid, bytes }
47
59
  }
@@ -53,11 +65,30 @@ export default class TransactionBlockstore {
53
65
  const got = await transaction.get(key)
54
66
  if (got && got.bytes) return got.bytes
55
67
  }
68
+ throw new Error('Missing block: ' + key)
56
69
  }
57
70
 
58
71
  async commitedGet (key) {
59
- return this.#oldBlocks.get(key) || await this.#valet.getBlock(key)
60
- // return await this.#valet.getBlock(key) // todo this is just for testing
72
+ const old = this.#oldBlocks.get(key)
73
+ if (old) return old
74
+ return await this.valet.getBlock(key)
75
+ }
76
+
77
+ async networkGet (key) {
78
+ if (this.valet.remoteBlockFunction) {
79
+ const value = await husher(key, async () => await this.valet.remoteBlockFunction(key))
80
+ if (value) {
81
+ // console.log('networkGot: ' + key, value.length)
82
+ // dont turn this on until the Nan thing is fixed
83
+ // it keep the network blocks in indexedb but lets get the basics solid first
84
+ doTransaction('networkGot: ' + key, this, async (innerBlockstore) => {
85
+ await innerBlockstore.put(CID.parse(key), value)
86
+ })
87
+ return value
88
+ }
89
+ } else {
90
+ throw new Error('No remoteBlockFunction')
91
+ }
61
92
  }
62
93
 
63
94
  /**
@@ -91,11 +122,11 @@ export default class TransactionBlockstore {
91
122
  }
92
123
 
93
124
  /**
94
- * Begin a transaction. Ensures the uncommited blocks are empty at the begining.
95
- * Returns the blocks to read and write during the transaction.
96
- * @returns {InnerBlockstore}
97
- * @memberof TransactionBlockstore
98
- */
125
+ * Begin a transaction. Ensures the uncommited blocks are empty at the begining.
126
+ * Returns the blocks to read and write during the transaction.
127
+ * @returns {InnerBlockstore}
128
+ * @memberof TransactionBlockstore
129
+ */
99
130
  begin (label = '') {
100
131
  const innerTransactionBlockstore = new InnerBlockstore(label, this)
101
132
  this.#inflightTransactions.add(innerTransactionBlockstore)
@@ -103,10 +134,10 @@ export default class TransactionBlockstore {
103
134
  }
104
135
 
105
136
  /**
106
- * Commit the transaction. Writes the blocks to the store.
107
- * @returns {Promise<void>}
108
- * @memberof TransactionBlockstore
109
- */
137
+ * Commit the transaction. Writes the blocks to the store.
138
+ * @returns {Promise<void>}
139
+ * @memberof TransactionBlockstore
140
+ */
110
141
  async commit (innerBlockstore) {
111
142
  await this.#doCommit(innerBlockstore)
112
143
  }
@@ -128,7 +159,7 @@ export default class TransactionBlockstore {
128
159
  }
129
160
  }
130
161
  if (cids.size > 0) {
131
- console.log(innerBlockstore.label, 'committing', cids.size, 'blocks')
162
+ // console.log(innerBlockstore.label, 'committing', cids.size, 'blocks')
132
163
  await this.#valetWriteTransaction(innerBlockstore, cids)
133
164
  }
134
165
  }
@@ -144,15 +175,15 @@ export default class TransactionBlockstore {
144
175
  #valetWriteTransaction = async (innerBlockstore, cids) => {
145
176
  if (innerBlockstore.lastCid) {
146
177
  const newCar = await blocksToCarBlock(innerBlockstore.lastCid, innerBlockstore)
147
- await this.#valet.parkCar(newCar.cid.toString(), newCar.bytes, cids)
178
+ await this.valet.parkCar(newCar.cid.toString(), newCar.bytes, cids)
148
179
  }
149
180
  }
150
181
 
151
182
  /**
152
- * Retire the transaction. Clears the uncommited blocks.
153
- * @returns {void}
154
- * @memberof TransactionBlockstore
155
- */
183
+ * Retire the transaction. Clears the uncommited blocks.
184
+ * @returns {void}
185
+ * @memberof TransactionBlockstore
186
+ */
156
187
  retire (innerBlockstore) {
157
188
  this.#inflightTransactions.delete(innerBlockstore)
158
189
  }
package/src/db-index.js CHANGED
@@ -16,16 +16,33 @@ const makeGetBlock = (blocks) => async (address) => {
16
16
  }
17
17
  const makeDoc = ({ key, value }) => ({ _id: key, ...value })
18
18
 
19
- console.x = function () {}
19
+ /**
20
+ * JDoc for the result row type.
21
+ * @typedef {Object} ChangeEvent
22
+ * @property {string} key - The key of the document.
23
+ * @property {Object} value - The new value of the document.
24
+ * @property {boolean} [del] - Is the row deleted?
25
+ * @memberof DbIndex
26
+ */
20
27
 
21
28
  /**
22
- * Transforms a set of changes to index entries using a map function.
29
+ * JDoc for the result row type.
30
+ * @typedef {Object} DbIndexEntry
31
+ * @property {string[]} key - The key for the DbIndex entry.
32
+ * @property {Object} value - The value of the document.
33
+ * @property {boolean} [del] - Is the row deleted?
34
+ * @memberof DbIndex
35
+ */
36
+
37
+ /**
38
+ * Transforms a set of changes to DbIndex entries using a map function.
23
39
  *
24
- * @param {Array<{ key: string, value: import('./link').AnyLink, del?: boolean }>} changes
40
+ * @param {ChangeEvent[]} changes
25
41
  * @param {Function} mapFun
26
- * @returns {Array<{ key: [string, string], value: any }>} The index entries generated by the map function.
42
+ * @returns {DbIndexEntry[]} The DbIndex entries generated by the map function.
43
+ * @private
44
+ * @memberof DbIndex
27
45
  */
28
-
29
46
  const indexEntriesForChanges = (changes, mapFun) => {
30
47
  const indexEntries = []
31
48
  changes.forEach(({ key, value, del }) => {
@@ -49,25 +66,20 @@ const indexEntriesForOldChanges = async (blocks, byIDindexRoot, ids, mapFun) =>
49
66
  }
50
67
 
51
68
  /**
52
- * Represents an index for a Fireproof database.
69
+ * Represents an DbIndex for a Fireproof database.
53
70
  *
54
- * @class
55
- * @classdesc An index can be used to order and filter the documents in a Fireproof database.
71
+ * @class DbIndex
72
+ * @classdesc An DbIndex can be used to order and filter the documents in a Fireproof database.
56
73
  *
57
- * @param {import('./fireproof').Fireproof} database - The Fireproof database instance to index.
74
+ * @param {Fireproof} database - The Fireproof database instance to DbIndex.
58
75
  * @param {Function} mapFun - The map function to apply to each entry in the database.
59
76
  *
60
77
  */
61
- export default class Index {
62
- /**
63
- * Creates a new index with the given map function and database.
64
- * @param {import('./fireproof').Fireproof} database - The Fireproof database instance to index.
65
- * @param {Function} mapFun - The map function to apply to each entry in the database.
66
- */
78
+ export default class DbIndex {
67
79
  constructor (database, mapFun) {
68
80
  /**
69
- * The database instance to index.
70
- * @type {import('./fireproof').Fireproof}
81
+ * The database instance to DbIndex.
82
+ * @type {Fireproof}
71
83
  */
72
84
  this.database = database
73
85
  /**
@@ -80,26 +92,38 @@ export default class Index {
80
92
  this.dbHead = null
81
93
  }
82
94
 
95
+ /**
96
+ * JSDoc for Query type.
97
+ * @typedef {Object} DbQuery
98
+ * @property {string[]} [range] - The range to query.
99
+ * @memberof DbIndex
100
+ */
101
+
83
102
  /**
84
103
  * Query object can have {range}
85
- *
104
+ * @param {DbQuery} query - the query range to use
105
+ * @param {CID} [root] - an optional root to query a snapshot
106
+ * @returns {Promise<{rows: Array<{id: string, key: string, value: any}>}>}
107
+ * @memberof DbIndex
108
+ * @instance
86
109
  */
87
110
  async query (query, root = null) {
88
- if (!root) { // pass a root to query a snapshot
111
+ if (!root) {
112
+ // pass a root to query a snapshot
89
113
  await doTransaction('#updateIndex', this.database.blocks, async (blocks) => {
90
114
  await this.#updateIndex(blocks)
91
115
  })
92
116
  }
93
117
  const response = await doIndexQuery(this.database.blocks, root || this.indexRoot, query)
94
118
  return {
95
- // TODO fix this naming upstream in prolly/db-index
119
+ // TODO fix this naming upstream in prolly/db-DbIndex
96
120
  // todo maybe this is a hint about why deletes arent working?
97
121
  rows: response.result.map(({ id, key, row }) => ({ id: key, key: charwise.decode(id), value: row }))
98
122
  }
99
123
  }
100
124
 
101
125
  /**
102
- * Update the index with the latest changes
126
+ * Update the DbIndex with the latest changes
103
127
  * @private
104
128
  * @returns {Promise<void>}
105
129
  */
@@ -111,16 +135,23 @@ export default class Index {
111
135
  }
112
136
  const result = await this.database.changesSince(this.dbHead) // {key, value, del}
113
137
  if (this.dbHead) {
114
- const oldIndexEntries = (await indexEntriesForOldChanges(blocks, this.byIDindexRoot, result.rows.map(({ key }) => key), this.mapFun))
138
+ const oldIndexEntries = (
139
+ await indexEntriesForOldChanges(
140
+ blocks,
141
+ this.byIDindexRoot,
142
+ result.rows.map(({ key }) => key),
143
+ this.mapFun
144
+ )
145
+ )
115
146
  // .map((key) => ({ key, value: null })) // tombstone just adds more rows...
116
147
  .map((key) => ({ key, del: true })) // should be this
117
- // .map((key) => ({ key: undefined, del: true })) // todo why does this work?
148
+ // .map((key) => ({ key: undefined, del: true })) // todo why does this work?
118
149
 
119
150
  this.indexRoot = await bulkIndex(blocks, this.indexRoot, oldIndexEntries, opts)
120
151
  // console.x('oldIndexEntries', oldIndexEntries)
121
152
  // [ { key: ['b', 1], del: true } ]
122
153
  // [ { key: [ 5, 'x' ], del: true } ]
123
- // for now we just let the by id index grow and then don't use the results...
154
+ // for now we just let the by id DbIndex grow and then don't use the results...
124
155
  // const removeByIdIndexEntries = oldIndexEntries.map(({ key }) => ({ key: key[1], del: true }))
125
156
  // this.byIDindexRoot = await bulkIndex(blocks, this.byIDindexRoot, removeByIdIndexEntries, opts)
126
157
  }
@@ -130,67 +161,61 @@ export default class Index {
130
161
  this.byIDindexRoot = await bulkIndex(blocks, this.byIDindexRoot, byIdIndexEntries, opts)
131
162
  // console.log('indexEntries', indexEntries)
132
163
  this.indexRoot = await bulkIndex(blocks, this.indexRoot, indexEntries, opts)
133
- // console.log('did index', this.indexRoot)
164
+ // console.log('did DbIndex', this.indexRoot)
134
165
  this.dbHead = result.clock
135
166
  }
136
167
 
137
- // todo use the index from other peers?
168
+ // todo use the DbIndex from other peers?
138
169
  // we might need to add CRDT logic to it for that
139
170
  // it would only be a performance improvement, but might add a lot of complexity
140
171
  // advanceIndex ()) {}
141
172
  }
142
173
 
143
174
  /**
144
- * Update the index with the given entries
175
+ * Update the DbIndex with the given entries
145
176
  * @param {Blockstore} blocks
146
- * @param {import('multiformats/block').Block} inRoot
147
- * @param {import('prolly-trees/db-index').IndexEntry[]} indexEntries
177
+ * @param {Block} inRoot
178
+ * @param {DbIndexEntry[]} indexEntries
179
+ * @private
148
180
  */
149
181
  async function bulkIndex (blocks, inRoot, indexEntries) {
150
182
  if (!indexEntries.length) return inRoot
151
183
  const putBlock = blocks.put.bind(blocks)
152
184
  const getBlock = makeGetBlock(blocks)
153
185
  if (!inRoot) {
154
- // make a new index
186
+ // make a new DbIndex
155
187
 
156
188
  for await (const node of await create({ get: getBlock, list: indexEntries, ...opts })) {
157
189
  const block = await node.block
158
190
  await putBlock(block.cid, block.bytes)
159
191
  inRoot = block
160
192
  }
161
- // console.x('created index', inRoot.cid)
193
+ // console.x('created DbIndex', inRoot.cid)
162
194
  return inRoot
163
195
  } else {
164
- // load existing index
165
- // console.x('loading index', inRoot.cid)
166
- const index = await load({ cid: inRoot.cid, get: getBlock, ...opts })
196
+ // load existing DbIndex
197
+ // console.x('loading DbIndex', inRoot.cid)
198
+ const DbIndex = await load({ cid: inRoot.cid, get: getBlock, ...opts })
167
199
  // console.log('new indexEntries', indexEntries)
168
- const { root, blocks } = await index.bulk(indexEntries)
200
+ const { root, blocks } = await DbIndex.bulk(indexEntries)
169
201
  for await (const block of blocks) {
170
202
  await putBlock(block.cid, block.bytes)
171
203
  }
172
- // console.x('updated index', root.block.cid)
204
+ // console.x('updated DbIndex', root.block.cid)
173
205
  return await root.block // if we hold the root we won't have to load every time
174
206
  }
175
207
  }
176
208
 
177
- /**
178
- * Query the index for the given range
179
- * @param {Blockstore} blocks
180
- * @param {import('multiformats/block').Block} inRoot
181
- * @param {import('prolly-trees/db-index').Query} query
182
- * @returns {Promise<import('prolly-trees/db-index').QueryResult>}
183
- **/
184
209
  async function doIndexQuery (blocks, root, query) {
185
210
  const cid = root && root.cid
186
211
  if (!cid) return { result: [] }
187
212
  const getBlock = makeGetBlock(blocks)
188
- const index = await load({ cid, get: getBlock, ...opts })
213
+ const DbIndex = await load({ cid, get: getBlock, ...opts })
189
214
  if (query.range) {
190
215
  const encodedRange = query.range.map((key) => charwise.encode(key))
191
- return index.range(...encodedRange)
216
+ return DbIndex.range(...encodedRange)
192
217
  } else if (query.key) {
193
218
  const encodedKey = charwise.encode(query.key)
194
- return index.get(encodedKey)
219
+ return DbIndex.get(encodedKey)
195
220
  }
196
221
  }