@fireproof/core 0.6.4 → 0.7.0-alpha.0

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.
Files changed (48) hide show
  1. package/README.md +2 -2
  2. package/dist/{src/blockstore.js → blockstore.js} +7 -3
  3. package/dist/{src/database.js → database.js} +74 -48
  4. package/dist/{src/db-index.js → db-index.js} +13 -2
  5. package/dist/fireproof.js +92 -0
  6. package/dist/import.js +29 -0
  7. package/dist/loader.js +23 -0
  8. package/dist/{src/prolly.js → prolly.js} +1 -0
  9. package/dist/src/fireproof.d.ts +138 -137
  10. package/dist/src/fireproof.js +18183 -11479
  11. package/dist/src/fireproof.js.map +1 -1
  12. package/dist/src/fireproof.mjs +18184 -11479
  13. package/dist/src/fireproof.mjs.map +1 -1
  14. package/dist/storage/base.js +348 -0
  15. package/dist/storage/browser.js +61 -0
  16. package/dist/storage/filesystem.js +65 -0
  17. package/dist/storage/rest.js +58 -0
  18. package/dist/storage/ucan.js +0 -0
  19. package/dist/{src/sync.js → sync.js} +1 -1
  20. package/dist/valet.js +200 -0
  21. package/package.json +4 -5
  22. package/src/blockstore.js +6 -3
  23. package/src/database.js +80 -52
  24. package/src/db-index.js +12 -2
  25. package/src/fireproof.js +41 -30
  26. package/src/import.js +34 -0
  27. package/src/loader.js +26 -0
  28. package/src/prolly.js +2 -0
  29. package/src/storage/base.js +371 -0
  30. package/src/storage/browser.js +67 -0
  31. package/src/storage/filesystem.js +70 -0
  32. package/src/storage/rest.js +60 -0
  33. package/src/storage/ucan.js +0 -0
  34. package/src/sync.js +1 -1
  35. package/src/valet.js +57 -359
  36. package/dist/hooks/use-fireproof.js +0 -150
  37. package/dist/src/crypto-poly.js +0 -4
  38. package/dist/src/link.js +0 -1
  39. package/dist/src/loader.js +0 -131
  40. package/dist/src/valet.js +0 -476
  41. package/hooks/use-fireproof.js +0 -173
  42. package/src/listener.js +0 -119
  43. package/src/utils.js +0 -16
  44. /package/dist/{src/clock.js → clock.js} +0 -0
  45. /package/dist/{src/crypto.js → crypto.js} +0 -0
  46. /package/dist/{src/listener.js → listener.js} +0 -0
  47. /package/dist/{src/sha1.js → sha1.js} +0 -0
  48. /package/dist/{src/utils.js → utils.js} +0 -0
package/README.md CHANGED
@@ -38,14 +38,14 @@ With Fireproof, you **build first** and connect it to your cloud of choice when
38
38
  ```js
39
39
  const completedTodos = useLiveQuery((doc) => doc.completed, { key: true })
40
40
  ```
41
- This is the README for the core database technology. [The `useFireproof` hook documentation has features and a getting started guide](https://github.com/fireproof-storage/fireproof/blob/main/packages/react/README.md), like `useLiveDocument` and database setup helpers. Don't forget to star 🌟 this repo on the way over.
41
+ This is the README for the core database technology. [The `useFireproof` hook documentation has features and a getting started guide](https://github.com/fireproof-storage/fireproof/blob/main/packages/react/README.md), like `useDocument` and database setup helpers. Don't forget to star 🌟 this repo on the way over.
42
42
 
43
43
  ## AI Assistant Quick Start
44
44
 
45
45
  Because Fireproof is designed around the mantra of build-first, it's ideal for AI-assisted app development as you can get an app up and running before even considering the cloud. If you are using GPT-3.5, GPT-4, or Bard, you can [easily enable the AI to write React apps using Fireproof](https://hackernoon.com/get-chatgpt-to-focus-on-coding-on-the-right-apis-with-gptdoc-strings). Paste this line of code into your prompt, along with a detailed description of the app to build:
46
46
 
47
47
  ```
48
- Fireproof/React/Usage: import { useFireproof } from '@fireproof/react'; function App() { const { useLiveQuery, useLiveDocument, database } = useFireproof(); const result = useLiveQuery(doc => doc.word, { limit: 10 }); const [{ count }, saveCountDocument] = useLiveDocument({_id: 'count', count: 0}); return (<><p>{count} changes</p><input type='text' onChange={() => saveCountDocument({count: count + 1})} onSubmit={e => database.put({word: e.target.value})} /><ul>{result.map(row => (<li key={row.id}>{row.key}</li>))}</ul></>)}
48
+ Fireproof/React/Usage: import { useFireproof } from '@fireproof/react'; function App() { const { useLiveQuery, useDocument, database } = useFireproof(); const result = useLiveQuery(doc => doc.word, { limit: 10 }); const [{ count }, saveCountDocument] = useDocument({_id: 'count', count: 0}); return (<><p>{count} changes</p><input type='text' onChange={() => saveCountDocument({count: count + 1})} onSubmit={e => database.put({word: e.target.value})} /><ul>{result.map(row => (<li key={row.id}>{row.key}</li>))}</ul></>)}
49
49
  ```
50
50
 
51
51
  Here are some examples that worked for us:
@@ -31,9 +31,13 @@ export class TransactionBlockstore {
31
31
  instanceId = 'blkz.' + Math.random().toString(36).substring(2, 4);
32
32
  inflightTransactions = new Set();
33
33
  syncs = new Set();
34
- constructor(name, encryptionKey) {
34
+ constructor(name, config) {
35
35
  if (name) {
36
- this.valet = new Valet(name, encryptionKey);
36
+ this.valet = new Valet(name, config);
37
+ this.ready = this.valet.ready;
38
+ }
39
+ else {
40
+ this.ready = Promise.resolve();
37
41
  }
38
42
  this.remoteBlockFunction = null;
39
43
  }
@@ -47,7 +51,7 @@ export class TransactionBlockstore {
47
51
  const key = cid.toString();
48
52
  // it is safe to read from the in-flight transactions becauase they are immutable
49
53
  const bytes = await Promise.any([this.transactionsGet(key), this.committedGet(key)]).catch(e => {
50
- // console.log('networkGet', cid.toString(), e)
54
+ console.log('get error', cid.toString(), e);
51
55
  return this.networkGet(key);
52
56
  });
53
57
  if (!bytes)
@@ -2,8 +2,8 @@
2
2
  import { visMerkleClock, visMerkleTree, vis, put, get, getAll, eventsSince } from './prolly.js';
3
3
  import { doTransaction, TransactionBlockstore } from './blockstore.js';
4
4
  import charwise from 'charwise';
5
- import { localSet } from './utils.js';
6
5
  import { CID } from 'multiformats';
6
+ import { DbIndex as Index } from './db-index.js';
7
7
  // TypeScript Types
8
8
  // eslint-disable-next-line no-unused-vars
9
9
  // import { CID } from 'multiformats/dist/types/src/cid.js'
@@ -27,13 +27,49 @@ export class Database {
27
27
  indexes = new Map();
28
28
  rootCache = null;
29
29
  eventsCache = new Map();
30
- constructor(name, clock, config = {}) {
30
+ constructor(name, config = {}) {
31
31
  this.name = name;
32
+ this.clock = [];
32
33
  this.instanceId = `fp.${this.name}.${Math.random().toString(36).substring(2, 7)}`;
33
- this.blocks = new TransactionBlockstore(name, config.key);
34
- this.indexBlocks = new TransactionBlockstore(name + '.indexes', config.key);
35
- this.clock = clock;
34
+ this.blocks = new TransactionBlockstore(name, config);
35
+ this.indexBlocks = new TransactionBlockstore(name ? name + '.indexes' : null, { primary: config.index });
36
36
  this.config = config;
37
+ // todo we can wait for index blocks elsewhere
38
+ this.ready = Promise.all([this.blocks.ready, this.indexBlocks.ready]).then(([blocksReady, indexReady]) => {
39
+ const clock = new Set();
40
+ // console.log('blocksReady', blocksReady)
41
+ if (!blocksReady) {
42
+ return;
43
+ }
44
+ for (const headers of blocksReady) {
45
+ for (const [, header] of Object.entries(headers)) {
46
+ if (!header)
47
+ continue;
48
+ for (const cid of header.clock) {
49
+ clock.add(cid);
50
+ }
51
+ if (header.index) {
52
+ this.indexBlocks.valet.primary.setCarCidMapCarCid(header.index.car);
53
+ this.indexBlocks.valet.primary.setKeyMaterial(header.index.key);
54
+ }
55
+ if (header.indexes) {
56
+ for (const { name, code, clock: { byId, byKey, db } } of header.indexes) {
57
+ // console.log('index', name, code, { byId, byKey }, db, header.indexes)
58
+ Index.fromJSON(this, {
59
+ clock: {
60
+ byId: byId ? parseCID(byId) : null,
61
+ byKey: byKey ? parseCID(byKey) : null,
62
+ db: (db && db.length > 0) ? db.map(c => parseCID(c)) : null
63
+ },
64
+ code,
65
+ name
66
+ });
67
+ }
68
+ }
69
+ }
70
+ }
71
+ this.clock = [...clock];
72
+ });
37
73
  }
38
74
  /**
39
75
  * Renders the Fireproof instance as a JSON object.
@@ -42,12 +78,16 @@ export class Database {
42
78
  * @instance
43
79
  */
44
80
  toJSON() {
81
+ return this.blocks.valet ? this.blocks.valet.primary.prepareHeader(this.toHeader(), false) : this.toHeader(); // omg
82
+ }
83
+ toHeader() {
45
84
  return {
46
85
  clock: this.clockToJSON(),
47
86
  name: this.name,
48
- key: this.blocks.valet?.getKeyMaterial(),
49
- car: this.blocks.valet?.valetRootCarCid.toString(),
50
- indexCar: this.indexBlocks.valet?.valetRootCarCid?.toString(),
87
+ index: {
88
+ key: this.indexBlocks.valet?.primary.keyMaterial,
89
+ car: this.indexBlocks.valet?.primary.valetRootCarCid?.toString()
90
+ },
51
91
  indexes: [...this.indexes.values()].map(index => index.toJSON())
52
92
  };
53
93
  }
@@ -60,25 +100,12 @@ export class Database {
60
100
  clockToJSON(clock = null) {
61
101
  return (clock || this.clock).map(cid => cid.toString());
62
102
  }
63
- hydrate({ clock, name, key, car, indexCar }) {
64
- this.name = name;
65
- this.clock = clock;
66
- this.blocks.valet?.setKeyMaterial(key);
67
- this.blocks.valet?.setRootCarCid(car); // maybe
68
- this.indexBlocks.valet?.setKeyMaterial(key);
69
- this.indexBlocks.valet?.setRootCarCid(indexCar); // maybe
70
- // this.indexBlocks = null
71
- }
72
103
  maybeSaveClock() {
73
104
  if (this.name && this.blocks.valet) {
74
- localSet('fp.' + this.name, JSON.stringify(this));
105
+ this.blocks.valet.saveHeader(this.toHeader());
75
106
  }
76
107
  }
77
108
  index(name) {
78
- // iterate over the indexes and gather any with the same name
79
- // if there are more than one, throw an error
80
- // if there is one, return it
81
- // if there are none, return null
82
109
  const indexes = [...this.indexes.values()].filter(index => index.name === name);
83
110
  if (indexes.length > 1) {
84
111
  throw new Error(`Multiple indexes found with name ${name}`);
@@ -93,12 +120,9 @@ export class Database {
93
120
  * @instance
94
121
  */
95
122
  async notifyReset() {
123
+ await this.ready;
96
124
  await this.notifyListeners({ _reset: true, _clock: this.clockToJSON() });
97
125
  }
98
- // used be indexes etc to notify database listeners of new availability
99
- // async notifyExternal (source = 'unknown') {
100
- // // await this.notifyListeners({ _external: source, _clock: this.clockToJSON() })
101
- // }
102
126
  /**
103
127
  * Returns the changes made to the Fireproof instance since the specified event.
104
128
  * @function changesSince
@@ -108,6 +132,7 @@ export class Database {
108
132
  * @instance
109
133
  */
110
134
  async changesSince(aClock) {
135
+ await this.ready;
111
136
  // console.log('events for', this.instanceId, aClock?.constructor.name)
112
137
  // console.log('changesSince', this.instanceId, this.clockToJSON(aClock), this.clockToJSON())
113
138
  let rows, dataCIDs, clockCIDs;
@@ -151,6 +176,7 @@ export class Database {
151
176
  };
152
177
  }
153
178
  async allDocuments() {
179
+ await this.ready;
154
180
  const allResp = await getAll(this.blocks, this.clock, this.rootCache);
155
181
  this.rootCache = { root: allResp.root, clockCIDs: allResp.clockCIDs };
156
182
  const rows = allResp.result
@@ -163,6 +189,7 @@ export class Database {
163
189
  };
164
190
  }
165
191
  async allCIDs() {
192
+ await this.ready;
166
193
  const allResp = await getAll(this.blocks, this.clock, this.rootCache, true);
167
194
  this.rootCache = { root: allResp.root, clockCIDs: allResp.clockCIDs };
168
195
  // console.log('allcids', allResp.cids, allResp.clockCIDs)
@@ -172,29 +199,13 @@ export class Database {
172
199
  return [...cids, ...clockCids]; // clock CID last -- need to handle multiple entry clocks
173
200
  }
174
201
  async allStoredCIDs() {
202
+ await this.ready;
175
203
  const allCIDs = [];
176
204
  for await (const { cid } of this.blocks.entries()) {
177
205
  allCIDs.push(cid);
178
206
  }
179
207
  return allCIDs;
180
208
  }
181
- /**
182
- * Runs validation on the specified document using the Fireproof instance's configuration. Throws an error if the document is invalid.
183
- *
184
- * @param {Object} doc - The document to validate.
185
- * @returns {Promise<void>}
186
- * @throws {Error} - Throws an error if the document is invalid.
187
- * @memberof Fireproof
188
- * @instance
189
- */
190
- async runValidation(doc) {
191
- if (this.config && this.config.validateChange) {
192
- const oldDoc = await this.get(doc._id)
193
- .then(doc => doc)
194
- .catch(() => ({}));
195
- this.config.validateChange(doc, oldDoc, this.authCtx);
196
- }
197
- }
198
209
  /**
199
210
  * Retrieves the document with the specified ID from the database
200
211
  *
@@ -205,6 +216,7 @@ export class Database {
205
216
  * @instance
206
217
  */
207
218
  async get(key, opts = {}) {
219
+ await this.ready;
208
220
  const clock = opts.clock || this.clock;
209
221
  const resp = await get(this.blocks, clock, charwise.encode(key), this.rootCache);
210
222
  this.rootCache = { root: resp.root, clockCIDs: resp.clockCIDs };
@@ -239,6 +251,7 @@ export class Database {
239
251
  * @instance
240
252
  */
241
253
  async put({ _id, _proof, ...doc }) {
254
+ await this.ready;
242
255
  const id = _id || 'f' + Math.random().toString(36).slice(2);
243
256
  await this.runValidation({ _id: id, ...doc });
244
257
  return await this.putToProllyTree({ key: id, value: doc }, doc._clock);
@@ -251,6 +264,7 @@ export class Database {
251
264
  * @instance
252
265
  */
253
266
  async del(docOrId) {
267
+ await this.ready;
254
268
  let id;
255
269
  let clock = null;
256
270
  if (docOrId._id) {
@@ -265,6 +279,23 @@ export class Database {
265
279
  // this tombstone is temporary until we can get the prolly tree to delete
266
280
  // return await this.putToProllyTree({ key: id, value: null }, clock)
267
281
  }
282
+ /**
283
+ * Runs validation on the specified document using the Fireproof instance's configuration. Throws an error if the document is invalid.
284
+ *
285
+ * @param {Object} doc - The document to validate.
286
+ * @returns {Promise<void>}
287
+ * @throws {Error} - Throws an error if the document is invalid.
288
+ * @memberof Fireproof
289
+ * @instance
290
+ */
291
+ async runValidation(doc) {
292
+ if (this.config && this.config.validateChange) {
293
+ const oldDoc = await this.get(doc._id)
294
+ .then(doc => doc)
295
+ .catch(() => ({}));
296
+ this.config.validateChange(doc, oldDoc, this.authCtx);
297
+ }
298
+ }
268
299
  /**
269
300
  * Updates the underlying storage with the specified event.
270
301
  * @private
@@ -364,11 +395,6 @@ export class Database {
364
395
  await listener(changes);
365
396
  }
366
397
  }
367
- setCarUploader(carUploaderFn) {
368
- // console.log('registering car uploader')
369
- // https://en.wikipedia.org/wiki/Law_of_Demeter - this is a violation of the law of demeter
370
- this.blocks.valet.uploadFunction = carUploaderFn;
371
- }
372
398
  setRemoteBlockReader(remoteBlockReaderFn) {
373
399
  this.blocks.remoteBlockFunction = remoteBlockReaderFn;
374
400
  }
@@ -127,13 +127,23 @@ export class DbIndex {
127
127
  applyMapFn(mapFn, name) {
128
128
  if (typeof mapFn === 'string') {
129
129
  this.mapFnString = mapFn;
130
+ // make a regex that matches strings that only have letters, numbers, and spaces
131
+ const regex = /^[a-zA-Z0-9 ]+$/;
132
+ // if the string matches the regex, make a function that returns the value at that key
133
+ if (regex.test(mapFn)) {
134
+ this.mapFn = (doc, emit) => {
135
+ if (doc[mapFn])
136
+ emit(doc[mapFn]);
137
+ };
138
+ this.includeDocsDefault = true;
139
+ }
130
140
  }
131
141
  else {
132
142
  this.mapFn = mapFn;
133
143
  this.mapFnString = mapFn.toString();
134
144
  }
135
145
  const matches = /=>\s*(.*)/.exec(this.mapFnString);
136
- this.includeDocsDefault = matches && matches.length > 0;
146
+ this.includeDocsDefault = this.includeDocsDefault || (matches && matches.length > 0);
137
147
  this.name = name || this.makeName();
138
148
  }
139
149
  makeName() {
@@ -226,6 +236,7 @@ export class DbIndex {
226
236
  * @returns
227
237
  */
228
238
  async applyQuery(resp, query) {
239
+ // console.log('applyQuery', resp, query)
229
240
  if (query.descending) {
230
241
  resp.result = resp.result.reverse();
231
242
  }
@@ -261,7 +272,7 @@ export class DbIndex {
261
272
  }
262
273
  else if (query.key) {
263
274
  const encodedKey = charwise.encode(query.key);
264
- return await this.applyQuery(this.indexByKey.root.get(encodedKey), query);
275
+ return await this.applyQuery(await this.indexByKey.root.get(encodedKey), query);
265
276
  }
266
277
  else {
267
278
  const { result, ...all } = await this.indexByKey.root.getAllEntries();
@@ -0,0 +1,92 @@
1
+ import { Database, parseCID } from './database.js';
2
+ import { DbIndex as Index } from './db-index.js';
3
+ import { Sync } from './sync.js';
4
+ export { Index, Database, Sync };
5
+ class Fireproof {
6
+ /**
7
+ * @function storage
8
+ * @memberof Fireproof
9
+ * Creates a new Fireproof instance with default storage settings
10
+ * Most apps should use this and not worry about the details.
11
+ * @static
12
+ * @returns {Database|Promise<Database>} - a new Fireproof instance or a promise for remote loaders
13
+ */
14
+ static storage = (name = null, opts = {}) => {
15
+ if (!name) {
16
+ return new Database(null, opts);
17
+ }
18
+ else {
19
+ // const primaryLoader = Loader.appropriate(name, opts.primary, { key: null })
20
+ // const secondaryLoader = opts.secondary ? Loader.appropriate(name, opts.secondary, { key: null }) : null
21
+ const db = new Database(name, opts);
22
+ return db;
23
+ // const loaders = [pr]
24
+ // todo we need branch names here
25
+ // console.log('storage', name, opts, primaryLoader, secondaryLoader)
26
+ }
27
+ };
28
+ // static fromConfig (name, primary, secondary, opts = {}) {
29
+ // console.log('fromConfig', name, primary, secondary, opts)
30
+ // let clock = []
31
+ // if (primary && primary.clock) {
32
+ // clock = clock.concat(primary.clock)
33
+ // }
34
+ // if (secondary && secondary.clock) {
35
+ // clock = clock.concat(secondary.clock)
36
+ // }
37
+ // const mergedClock = [...new Set(clock)].map(c => parseCID(c))
38
+ // opts.primaryHeader = primary
39
+ // opts.secondaryHeader = secondary
40
+ // opts.index = primary ? primary.index : {}
41
+ // const fp = new Database(name, mergedClock, opts)
42
+ // return Fireproof.fromJSON(primary, secondary, fp)
43
+ // }
44
+ static fromJSON(primary, secondary, database) {
45
+ const json = primary && primary.indexes ? primary : secondary;
46
+ if (json.indexes) {
47
+ for (const { name, code, clock: { byId, byKey, db } } of json.indexes) {
48
+ Index.fromJSON(database, {
49
+ clock: {
50
+ byId: byId ? parseCID(byId) : null,
51
+ byKey: byKey ? parseCID(byKey) : null,
52
+ db: (db && db.length > 0) ? db.map(c => parseCID(c)) : null
53
+ },
54
+ code,
55
+ name
56
+ });
57
+ }
58
+ }
59
+ return database;
60
+ }
61
+ static snapshot(database, clock) {
62
+ const definition = database.toJSON();
63
+ if (clock) {
64
+ definition.clock = clock.map(c => parseCID(c));
65
+ definition.indexes.forEach(index => {
66
+ index.clock.byId = null;
67
+ index.clock.byKey = null;
68
+ index.clock.db = null;
69
+ });
70
+ }
71
+ const withBlocks = new Database(database.name);
72
+ withBlocks.blocks = database.blocks;
73
+ withBlocks.clock = definition.clock;
74
+ const snappedDb = Fireproof.fromJSON(definition, null, withBlocks);
75
+ [...database.indexes.values()].forEach(index => {
76
+ snappedDb.indexes.get(index.mapFnString).mapFn = index.mapFn;
77
+ });
78
+ return snappedDb;
79
+ }
80
+ static async zoom(database, clock) {
81
+ ;
82
+ [...database.indexes.values()].forEach(index => {
83
+ index.indexById = { root: null, cid: null };
84
+ index.indexByKey = { root: null, cid: null };
85
+ index.dbHead = null;
86
+ });
87
+ database.clock = clock.map(c => parseCID(c));
88
+ await database.notifyReset(); // hmm... indexes should listen to this? might be more complex than worth it. so far this is the only caller
89
+ return database;
90
+ }
91
+ }
92
+ export { Fireproof };
package/dist/import.js ADDED
@@ -0,0 +1,29 @@
1
+ import { createReadStream } from 'fs';
2
+ import { join } from 'path';
3
+ import { parse } from '@jsonlines/core';
4
+ import cargoQueue from 'async/cargoQueue.js';
5
+ // todo maybe this goes in a utils package for tree-shaking?
6
+ async function loadData(database, filename) {
7
+ const fullFilePath = join(process.cwd(), filename);
8
+ const readableStream = createReadStream(fullFilePath);
9
+ const parseStream = parse();
10
+ readableStream.pipe(parseStream);
11
+ const saveQueue = cargoQueue(async (tasks, callback) => {
12
+ for (const t of tasks) {
13
+ await database.put(t);
14
+ }
15
+ callback();
16
+ });
17
+ parseStream.on('data', async (data) => {
18
+ saveQueue.push(data);
19
+ });
20
+ let res;
21
+ const p = new Promise((resolve, reject) => {
22
+ res = resolve;
23
+ });
24
+ saveQueue.drain(async (x) => {
25
+ res();
26
+ });
27
+ return p;
28
+ }
29
+ export { loadData };
package/dist/loader.js ADDED
@@ -0,0 +1,23 @@
1
+ import { Browser } from './storage/browser.js';
2
+ import { Filesystem } from './storage/filesystem.js';
3
+ import { Rest } from './storage/rest.js';
4
+ const FORCE_IDB = typeof process !== 'undefined' && !!process.env?.FORCE_IDB;
5
+ /* global window */
6
+ export const Loader = {
7
+ appropriate: (name, config = {}) => {
8
+ let isBrowser = false;
9
+ try {
10
+ isBrowser = window.localStorage && true;
11
+ }
12
+ catch (e) { }
13
+ if (config.type === 'rest') {
14
+ return new Rest(name, config);
15
+ }
16
+ if (FORCE_IDB || isBrowser) {
17
+ return new Browser(name, config);
18
+ }
19
+ else {
20
+ return new Filesystem(name, config);
21
+ }
22
+ }
23
+ };
@@ -8,6 +8,7 @@ import { nocache as cache } from 'prolly-trees/cache';
8
8
  import { CIDCounter, bf, simpleCompare as compare } from 'prolly-trees/utils';
9
9
  import * as codec from '@ipld/dag-cbor';
10
10
  import { sha256 as hasher } from 'multiformats/hashes/sha2';
11
+ // import { blake2b256 as hasher } from '@multiformats/blake2/blake2b'
11
12
  import { doTransaction } from './blockstore.js';
12
13
  import { create as createBlock } from 'multiformats/block';
13
14
  const blockOpts = { cache, chunker: bf(30), codec, hasher, compare };