@fireproof/core 0.5.8 → 0.5.10

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.
@@ -38216,9 +38216,9 @@ class Database {
38216
38216
  }
38217
38217
 
38218
38218
  // used be indexes etc to notify database listeners of new availability
38219
- async notifyExternal (source = 'unknown') {
38220
- await this.notifyListeners({ _external: source, _clock: this.clockToJSON() });
38221
- }
38219
+ // async notifyExternal (source = 'unknown') {
38220
+ // // await this.notifyListeners({ _external: source, _clock: this.clockToJSON() })
38221
+ // }
38222
38222
 
38223
38223
  /**
38224
38224
  * Returns the changes made to the Fireproof instance since the specified event.
@@ -38478,13 +38478,23 @@ class Database {
38478
38478
  * @returns {Function} - A function that can be called to unregister the listener.
38479
38479
  * @memberof Fireproof
38480
38480
  */
38481
- registerListener (listener) {
38481
+ subscribe (listener) {
38482
38482
  this.listeners.add(listener);
38483
38483
  return () => {
38484
38484
  this.listeners.delete(listener);
38485
38485
  }
38486
38486
  }
38487
38487
 
38488
+ /**
38489
+ * @deprecated 0.7.0 - renamed subscribe(listener)
38490
+ * @param {Function} listener - The listener to be called when the clock is updated.
38491
+ * @returns {Function} - A function that can be called to unregister the listener.
38492
+ * @memberof Fireproof
38493
+ */
38494
+ registerListener (listener) {
38495
+ return this.subscribe(listener)
38496
+ }
38497
+
38488
38498
  async notifyListeners (changes) {
38489
38499
  // await sleep(10)
38490
38500
  await this.maybeSaveClock();
@@ -38533,7 +38543,9 @@ function encodeEvent (event) {
38533
38543
  * @param {Function} routingFn - The routing function to apply to each entry in the database.
38534
38544
  */
38535
38545
  // import { ChangeEvent } from './db-index'
38536
-
38546
+ /**
38547
+ * @deprecated since version 0.7.0
38548
+ */
38537
38549
  class Listener {
38538
38550
  subcribers = new Map()
38539
38551
  doStopListening = null
@@ -38817,14 +38829,23 @@ const makeDoc = ({ key, value }) => ({ _id: key, ...value });
38817
38829
  const indexEntriesForChanges = (changes, mapFn) => {
38818
38830
  const indexEntries = [];
38819
38831
  changes.forEach(({ key, value, del }) => {
38832
+ // key is _id, value is the document
38820
38833
  if (del || !value) return
38821
- mapFn(makeDoc({ key, value }), (k, v) => {
38834
+ let mapCalled = false;
38835
+ const mapReturn = mapFn(makeDoc({ key, value }), (k, v) => {
38836
+ mapCalled = true;
38822
38837
  if (typeof k === 'undefined') return
38823
38838
  indexEntries.push({
38824
38839
  key: [charwise.encode(k), key],
38825
38840
  value: v || null
38826
38841
  });
38827
38842
  });
38843
+ if (!mapCalled && mapReturn) {
38844
+ indexEntries.push({
38845
+ key: [charwise.encode(mapReturn), key],
38846
+ value: null
38847
+ });
38848
+ }
38828
38849
  });
38829
38850
  return indexEntries
38830
38851
  };
@@ -38846,7 +38867,10 @@ class DbIndex {
38846
38867
  constructor (database, name, mapFn, clock = null, opts = {}) {
38847
38868
  this.database = database;
38848
38869
  if (!database.indexBlocks) {
38849
- database.indexBlocks = new TransactionBlockstore(database?.name + '.indexes', database.blocks.valet?.getKeyMaterial());
38870
+ database.indexBlocks = new TransactionBlockstore(
38871
+ database?.name + '.indexes',
38872
+ database.blocks.valet?.getKeyMaterial()
38873
+ );
38850
38874
  }
38851
38875
  if (typeof name === 'function') {
38852
38876
  // app is using deprecated API, remove in 0.7
@@ -38855,13 +38879,8 @@ class DbIndex {
38855
38879
  mapFn = name;
38856
38880
  name = null;
38857
38881
  }
38858
- if (typeof mapFn === 'string') {
38859
- this.mapFnString = mapFn;
38860
- } else {
38861
- this.mapFn = mapFn;
38862
- this.mapFnString = mapFn.toString();
38863
- }
38864
- this.name = name || this.makeName();
38882
+ this.applyMapFn(mapFn, name);
38883
+
38865
38884
  this.indexById = { root: null, cid: null };
38866
38885
  this.indexByKey = { root: null, cid: null };
38867
38886
  this.dbHead = null;
@@ -38872,13 +38891,34 @@ class DbIndex {
38872
38891
  }
38873
38892
  this.instanceId = this.database.instanceId + `.DbIndex.${Math.random().toString(36).substring(2, 7)}`;
38874
38893
  this.updateIndexPromise = null;
38875
- if (!opts.temporary) { DbIndex.registerWithDatabase(this, this.database); }
38894
+ if (!opts.temporary) {
38895
+ DbIndex.registerWithDatabase(this, this.database);
38896
+ }
38897
+ }
38898
+
38899
+ applyMapFn (mapFn, name) {
38900
+ if (typeof mapFn === 'string') {
38901
+ this.mapFnString = mapFn;
38902
+ } else {
38903
+ this.mapFn = mapFn;
38904
+ this.mapFnString = mapFn.toString();
38905
+ }
38906
+ this.name = name || this.makeName();
38876
38907
  }
38877
38908
 
38878
38909
  makeName () {
38879
38910
  const regex = /\(([^,()]+,\s*[^,()]+|\[[^\]]+\],\s*[^,()]+)\)/g;
38880
- const matches = Array.from(this.mapFnString.matchAll(regex), match => match[1].trim());
38881
- return matches[1]
38911
+ let matches = Array.from(this.mapFnString.matchAll(regex), match => match[1].trim());
38912
+ if (matches.length === 0) {
38913
+ matches = /=>\s*(.*)/.exec(this.mapFnString);
38914
+ }
38915
+ if (matches.length === 0) {
38916
+ return this.mapFnString
38917
+ } else {
38918
+ // it's a consise arrow function, match everythign after the arrow
38919
+ this.includeDocsDefault = true;
38920
+ return matches[1]
38921
+ }
38882
38922
  }
38883
38923
 
38884
38924
  static registerWithDatabase (inIndex, database) {
@@ -38888,7 +38928,8 @@ class DbIndex {
38888
38928
  // merge our inIndex code with the inIndex clock or vice versa
38889
38929
  const existingIndex = database.indexes.get(inIndex.mapFnString);
38890
38930
  // keep the code instance, discard the clock instance
38891
- if (existingIndex.mapFn) { // this one also has other config
38931
+ if (existingIndex.mapFn) {
38932
+ // this one also has other config
38892
38933
  existingIndex.dbHead = inIndex.dbHead;
38893
38934
  existingIndex.indexById.cid = inIndex.indexById.cid;
38894
38935
  existingIndex.indexByKey.cid = inIndex.indexByKey.cid;
@@ -38932,7 +38973,7 @@ class DbIndex {
38932
38973
  /**
38933
38974
  * Query object can have {range}
38934
38975
  * @param {DbQuery} query - the query range to use
38935
- * @returns {Promise<{proof: {}, rows: Array<{id: string, key: string, value: any}>}>}
38976
+ * @returns {Promise<{proof: {}, rows: Array<{id: string, key: string, value: any, doc?: any}>}>}
38936
38977
  * @memberof DbIndex
38937
38978
  * @instance
38938
38979
  */
@@ -38940,20 +38981,63 @@ class DbIndex {
38940
38981
  // const callId = Math.random().toString(36).substring(2, 7)
38941
38982
  // todo pass a root to query a snapshot
38942
38983
  // console.time(callId + '.updateIndex')
38943
- update && await this.updateIndex(this.database.indexBlocks);
38984
+ update && (await this.updateIndex(this.database.indexBlocks));
38944
38985
  // console.timeEnd(callId + '.updateIndex')
38945
38986
  // console.time(callId + '.doIndexQuery')
38946
38987
  // console.log('query', query)
38947
- const response = await doIndexQuery(this.database.indexBlocks, this.indexByKey, query);
38988
+ const response = await this.doIndexQuery(query);
38948
38989
  // console.timeEnd(callId + '.doIndexQuery')
38949
38990
  return {
38950
38991
  proof: { index: await cidsToProof(response.cids) },
38951
- rows: response.result.map(({ id, key, row }) => {
38952
- return ({ id, key: charwise.decode(key), value: row })
38992
+ rows: response.result.map(({ id, key, row, doc }) => {
38993
+ return { id, key: charwise.decode(key), value: row, doc }
38953
38994
  })
38954
38995
  }
38955
38996
  }
38956
38997
 
38998
+ /**
38999
+ *
39000
+ * @param {any} resp
39001
+ * @param {any} query
39002
+ * @returns
39003
+ */
39004
+ async applyQuery (resp, query) {
39005
+ if (query.descending) {
39006
+ resp.result = resp.result.reverse();
39007
+ }
39008
+ if (query.limit) {
39009
+ resp.result = resp.result.slice(0, query.limit);
39010
+ }
39011
+ if (query.includeDocs) {
39012
+ resp.result = await Promise.all(
39013
+ resp.result.map(async row => {
39014
+ const doc = await this.database.get(row.id);
39015
+ return { ...row, doc }
39016
+ })
39017
+ );
39018
+ }
39019
+ return resp
39020
+ }
39021
+
39022
+ async doIndexQuery (query = {}) {
39023
+ await loadIndex(this.database.indexBlocks, this.indexByKey, dbIndexOpts);
39024
+ if (!this.indexByKey.root) return { result: [] }
39025
+ if (query.includeDocs === undefined) query.includeDocs = this.includeDocsDefault;
39026
+ if (query.range) {
39027
+ const encodedRange = query.range.map(key => charwise.encode(key));
39028
+ return await this.applyQuery(await this.indexByKey.root.range(...encodedRange), query)
39029
+ } else if (query.key) {
39030
+ const encodedKey = charwise.encode(query.key);
39031
+ return await this.applyQuery(this.indexByKey.root.get(encodedKey), query)
39032
+ } else {
39033
+ const { result, ...all } = await this.indexByKey.root.getAllEntries();
39034
+ return await this.applyQuery(
39035
+ { result: result.map(({ key: [k, id], value }) => ({ key: k, id, row: value })), ...all },
39036
+ query
39037
+ )
39038
+ }
39039
+ }
39040
+
38957
39041
  /**
38958
39042
  * Update the DbIndex with the latest changes
38959
39043
  * @private
@@ -38970,7 +39054,9 @@ class DbIndex {
38970
39054
  })
38971
39055
  }
38972
39056
  this.updateIndexPromise = this.innerUpdateIndex(blocks);
38973
- this.updateIndexPromise.finally(() => { this.updateIndexPromise = null; });
39057
+ this.updateIndexPromise.finally(() => {
39058
+ this.updateIndexPromise = null;
39059
+ });
38974
39060
  return this.updateIndexPromise
38975
39061
  }
38976
39062
 
@@ -38989,7 +39075,7 @@ class DbIndex {
38989
39075
  this.dbHead = result.clock;
38990
39076
  return
38991
39077
  }
38992
- const didT = await doTransaction('updateIndex', inBlocks, async (blocks) => {
39078
+ const didT = await doTransaction('updateIndex', inBlocks, async blocks => {
38993
39079
  let oldIndexEntries = [];
38994
39080
  let removeByIdIndexEntries = [];
38995
39081
  await loadIndex(blocks, this.indexById, idIndexOpts);
@@ -38997,19 +39083,28 @@ class DbIndex {
38997
39083
  // console.log('head', this.dbHead, this.indexById)
38998
39084
  if (this.indexById.root) {
38999
39085
  const oldChangeEntries = await this.indexById.root.getMany(result.rows.map(({ key }) => key));
39000
- oldIndexEntries = oldChangeEntries.result.map((key) => ({ key, del: true }));
39086
+ oldIndexEntries = oldChangeEntries.result.map(key => ({ key, del: true }));
39001
39087
  removeByIdIndexEntries = oldIndexEntries.map(({ key }) => ({ key: key[1], del: true }));
39002
39088
  }
39003
39089
  if (!this.mapFn) {
39004
- throw new Error('No live map function installed for index, cannot update. Make sure your index definition runs before any queries.' + (this.mapFnString ? ' Your code should match the stored map function source:\n' + this.mapFnString : ''))
39090
+ throw new Error(
39091
+ 'No live map function installed for index, cannot update. Make sure your index definition runs before any queries.' +
39092
+ (this.mapFnString ? ' Your code should match the stored map function source:\n' + this.mapFnString : '')
39093
+ )
39005
39094
  }
39006
39095
  const indexEntries = indexEntriesForChanges(result.rows, this.mapFn);
39007
39096
  const byIdIndexEntries = indexEntries.map(({ key }) => ({ key: key[1], value: key }));
39008
- this.indexById = await bulkIndex(blocks, this.indexById, removeByIdIndexEntries.concat(byIdIndexEntries), idIndexOpts);
39097
+ this.indexById = await bulkIndex(
39098
+ blocks,
39099
+ this.indexById,
39100
+ removeByIdIndexEntries.concat(byIdIndexEntries),
39101
+ idIndexOpts
39102
+ );
39009
39103
  this.indexByKey = await bulkIndex(blocks, this.indexByKey, oldIndexEntries.concat(indexEntries), dbIndexOpts);
39010
39104
  this.dbHead = result.clock;
39011
39105
  });
39012
- this.database.notifyExternal('dbIndex');
39106
+ // todo index subscriptions
39107
+ // this.database.notifyExternal('dbIndex')
39013
39108
  // console.timeEnd(callTag + '.doTransactionupdateIndex')
39014
39109
  // console.log(`updateIndex ${callTag} <`, this.instanceId, this.dbHead?.toString(), this.indexByKey.cid?.toString(), this.indexById.cid?.toString())
39015
39110
  return didT
@@ -39071,26 +39166,6 @@ async function loadIndex (blocks, index, indexOpts) {
39071
39166
  return index.root
39072
39167
  }
39073
39168
 
39074
- async function applyLimit (results, limit) {
39075
- results.result = results.result.slice(0, limit);
39076
- return results
39077
- }
39078
-
39079
- async function doIndexQuery (blocks, indexByKey, query = {}) {
39080
- await loadIndex(blocks, indexByKey, dbIndexOpts);
39081
- if (!indexByKey.root) return { result: [] }
39082
- if (query.range) {
39083
- const encodedRange = query.range.map((key) => charwise.encode(key));
39084
- return applyLimit(await indexByKey.root.range(...encodedRange), query.limit)
39085
- } else if (query.key) {
39086
- const encodedKey = charwise.encode(query.key);
39087
- return indexByKey.root.get(encodedKey)
39088
- } else {
39089
- const { result, ...all } = await indexByKey.root.getAllEntries();
39090
- return applyLimit({ result: result.map(({ key: [k, id], value }) => ({ key: k, id, row: value })), ...all }, query.limit)
39091
- }
39092
- }
39093
-
39094
39169
  var browserExports = {};
39095
39170
  var browser = {
39096
39171
  get exports(){ return browserExports; },
@@ -41056,6 +41131,10 @@ class Sync {
41056
41131
  // get the roots parents
41057
41132
  const parents = await Promise.all(roots.map(async (cid) => {
41058
41133
  const rbl = await reader.get(cid);
41134
+ if (!rbl) {
41135
+ console.log('missing root block', cid.toString(), reader);
41136
+ throw new Error('missing root block')
41137
+ }
41059
41138
  const block = await decodeEventBlock(rbl.bytes);
41060
41139
  return block.value.parents
41061
41140
  }));
@@ -41072,7 +41151,7 @@ class Sync {
41072
41151
  } else if (message.clock) {
41073
41152
  const reqCidDiff = message;
41074
41153
  // this might be a CID diff
41075
- // console.log('got diff', reqCidDiff)
41154
+ console.log('got diff', reqCidDiff);
41076
41155
  const carBlock = await Sync.makeCar(this.database, null, reqCidDiff.cids);
41077
41156
  if (!carBlock) {
41078
41157
  // we are full synced
@@ -41175,7 +41254,7 @@ class Fireproof {
41175
41254
  if (existing) {
41176
41255
  const existingConfig = JSON.parse(existing);
41177
41256
  const fp = new Database(new TransactionBlockstore(name, existingConfig.key), [], opts);
41178
- return this.fromJSON(existingConfig, fp)
41257
+ return Fireproof.fromJSON(existingConfig, fp)
41179
41258
  } else {
41180
41259
  const instanceKey = browserExports$1(32).toString('hex'); // pass null to disable encryption
41181
41260
  return new Database(new TransactionBlockstore(name, instanceKey), [], opts)
@@ -41218,7 +41297,7 @@ class Fireproof {
41218
41297
  index.clock.db = null;
41219
41298
  });
41220
41299
  }
41221
- const snappedDb = this.fromJSON(definition, withBlocks)
41300
+ const snappedDb = Fireproof.fromJSON(definition, withBlocks)
41222
41301
  ;[...database.indexes.values()].forEach(index => {
41223
41302
  snappedDb.indexes.get(index.mapFnString).mapFn = index.mapFn;
41224
41303
  });