@fireproof/core 0.5.7 → 0.5.8

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.
@@ -5666,7 +5666,11 @@ async function contains (events, a, b) {
5666
5666
  */
5667
5667
  async function * vis$1 (blocks, head, options = {}) {
5668
5668
  // @ts-ignore
5669
- const renderNodeLabel = options.renderNodeLabel ?? ((b) => b.value.data.value);
5669
+ const renderNodeLabel = options.renderNodeLabel ?? ((b) => {
5670
+ // @ts-ignore
5671
+ const { key, root, type } = b.value.data;
5672
+ return b.cid.toString() + '\n' + JSON.stringify({ key, root: root.cid.toString(), type }, null, 2).replace(/"/g, '\'')
5673
+ });
5670
5674
  const events = new EventFetcher(blocks);
5671
5675
  yield 'digraph clock {';
5672
5676
  yield ' node [shape=point fontname="Courier"]; head;';
@@ -5707,6 +5711,7 @@ async function findEventsToSync (blocks, head) {
5707
5711
  // console.time(callTag + '.contains')
5708
5712
  const toSync = await asyncFilter(sorted, async (uks) => !(await contains(events, ancestor, uks.cid)));
5709
5713
  // console.timeEnd(callTag + '.contains')
5714
+ // console.log('toSync.contains', toSync.length)
5710
5715
 
5711
5716
  return { cids: events, events: toSync }
5712
5717
  }
@@ -5714,17 +5719,21 @@ async function findEventsToSync (blocks, head) {
5714
5719
  const asyncFilter = async (arr, predicate) =>
5715
5720
  Promise.all(arr.map(predicate)).then((results) => arr.filter((_v, index) => results[index]));
5716
5721
 
5717
- async function findCommonAncestorWithSortedEvents (events, children) {
5722
+ async function findCommonAncestorWithSortedEvents (events, children, doFull = false) {
5723
+ // console.trace('findCommonAncestorWithSortedEvents')
5718
5724
  // const callTag = Math.random().toString(36).substring(7)
5725
+ // console.log(callTag + '.children', children.map((c) => c.toString()))
5719
5726
  // console.time(callTag + '.findCommonAncestor')
5720
5727
  const ancestor = await findCommonAncestor(events, children);
5721
5728
  // console.timeEnd(callTag + '.findCommonAncestor')
5729
+ // console.log('ancestor', ancestor.toString())
5722
5730
  if (!ancestor) {
5723
5731
  throw new Error('failed to find common ancestor event')
5724
5732
  }
5725
5733
  // console.time(callTag + '.findSortedEvents')
5726
- const sorted = await findSortedEvents(events, children, ancestor);
5734
+ const sorted = await findSortedEvents(events, children, ancestor, doFull);
5727
5735
  // console.timeEnd(callTag + '.findSortedEvents')
5736
+ // console.log('sorted', sorted.length)
5728
5737
  return { ancestor, sorted }
5729
5738
  }
5730
5739
 
@@ -5737,6 +5746,7 @@ async function findCommonAncestorWithSortedEvents (events, children) {
5737
5746
  */
5738
5747
  async function findCommonAncestor (events, children) {
5739
5748
  if (!children.length) return
5749
+ if (children.length === 1) return children[0]
5740
5750
  const candidates = children.map((c) => [c]);
5741
5751
  while (true) {
5742
5752
  let changed = false;
@@ -5757,7 +5767,7 @@ async function findCommonAncestor (events, children) {
5757
5767
  * @param {import('./clock').EventLink<EventData>} root
5758
5768
  */
5759
5769
  async function findAncestorCandidate (events, root) {
5760
- const { value: event } = await events.get(root);
5770
+ const { value: event } = await events.get(root);// .catch(() => ({ value: { parents: [] } }))
5761
5771
  if (!event.parents.length) return root
5762
5772
  return event.parents.length === 1 ? event.parents[0] : findCommonAncestor(events, event.parents)
5763
5773
  }
@@ -5767,6 +5777,7 @@ async function findAncestorCandidate (events, root) {
5767
5777
  * @param {Array<T[]>} arrays
5768
5778
  */
5769
5779
  function findCommonString (arrays) {
5780
+ // console.log('findCommonString', arrays.map((a) => a.map((i) => String(i))))
5770
5781
  arrays = arrays.map((a) => [...a]);
5771
5782
  for (const arr of arrays) {
5772
5783
  for (const item of arr) {
@@ -5784,15 +5795,33 @@ function findCommonString (arrays) {
5784
5795
  /**
5785
5796
  * Find and sort events between the head(s) and the tail.
5786
5797
  * @param {import('./clock').EventFetcher} events
5787
- * @param {import('./clock').EventLink<EventData>[]} head
5798
+ * @param {any[]} head
5788
5799
  * @param {import('./clock').EventLink<EventData>} tail
5789
5800
  */
5790
- async function findSortedEvents (events, head, tail) {
5801
+ async function findSortedEvents (events, head, tail, doFull) {
5791
5802
  // const callTag = Math.random().toString(36).substring(7)
5792
5803
  // get weighted events - heavier events happened first
5804
+ // const callTag = Math.random().toString(36).substring(7)
5805
+
5793
5806
  /** @type {Map<string, { event: import('./clock').EventBlockView<EventData>, weight: number }>} */
5794
5807
  const weights = new Map();
5808
+ head = [...new Set([...head.map((h) => h.toString())])];
5809
+ // console.log(callTag + '.head', head.length)
5810
+
5811
+ const allEvents = new Set([tail.toString(), ...head]);
5812
+ if (!doFull && allEvents.size === 1) {
5813
+ // console.log('head contains tail', tail.toString())
5814
+ return []
5815
+ // const event = await events.get(tail)
5816
+ // return [event]
5817
+ }
5818
+
5819
+ // console.log('finding events')
5820
+ // console.log(callTag + '.head', head.length, [...head.map((h) => h.toString())], tail.toString())
5821
+
5822
+ // console.time(callTag + '.findEvents')
5795
5823
  const all = await Promise.all(head.map((h) => findEvents(events, h, tail)));
5824
+ // console.timeEnd(callTag + '.findEvents')
5796
5825
  for (const arr of all) {
5797
5826
  for (const { event, depth } of arr) {
5798
5827
  // console.log('event value', event.value.data.value)
@@ -5821,7 +5850,7 @@ async function findSortedEvents (events, head, tail) {
5821
5850
  const sorted = Array.from(buckets)
5822
5851
  .sort((a, b) => b[0] - a[0])
5823
5852
  .flatMap(([, es]) => es.sort((a, b) => (String(a.cid) < String(b.cid) ? -1 : 1)));
5824
- // console.log('sorted', sorted.map(s => s.value.data.value))
5853
+ // console.log('sorted', sorted.map(s => s.cid))
5825
5854
 
5826
5855
  return sorted
5827
5856
  }
@@ -5833,11 +5862,14 @@ async function findSortedEvents (events, head, tail) {
5833
5862
  * @returns {Promise<Array<{ event: EventBlockView<EventData>, depth: number }>>}
5834
5863
  */
5835
5864
  async function findEvents (events, start, end, depth = 0) {
5836
- // console.log('findEvents', start)
5865
+ // console.log('findEvents', start.toString(), end.toString(), depth)
5837
5866
  const event = await events.get(start);
5867
+ const send = String(end);
5838
5868
  const acc = [{ event, depth }];
5839
5869
  const { parents } = event.value;
5840
- if (parents.length === 1 && String(parents[0]) === String(end)) return acc
5870
+ // if (parents.length === 1 && String(parents[0]) === send) return acc
5871
+ if (parents.findIndex((p) => String(p) === send) !== -1) return acc
5872
+ // if (parents.length === 1) return acc
5841
5873
  const rest = await Promise.all(parents.map((p) => findEvents(events, p, end, depth + 1)));
5842
5874
  return acc.concat(...rest)
5843
5875
  }
@@ -36926,7 +36958,7 @@ function rawSha1 (b) {
36926
36958
  return new Uint8Array(H.buffer, H.byteOffset, H.byteLength)
36927
36959
  }
36928
36960
 
36929
- const chunker = bf(3);
36961
+ const chunker = bf(30);
36930
36962
 
36931
36963
  const NO_ENCRYPT = typeof process !== 'undefined' && !!process.env?.NO_ENCRYPT;
36932
36964
  // ? process.env.NO_ENCRYPT : import.meta && import.meta.env.VITE_NO_ENCRYPT
@@ -37375,7 +37407,10 @@ class TransactionBlockstore {
37375
37407
  await this.doCommit(innerBlockstore);
37376
37408
  if (doSync) {
37377
37409
  // const all =
37378
- await Promise.all([...this.syncs].map(async sync => sync.sendUpdate(innerBlockstore)));
37410
+ await Promise.all([...this.syncs].map(async sync => sync.sendUpdate(innerBlockstore).catch(e => {
37411
+ console.error('sync error', e);
37412
+ this.syncs.delete(sync);
37413
+ })));
37379
37414
  }
37380
37415
  }
37381
37416
 
@@ -37482,23 +37517,24 @@ class InnerBlockstore {
37482
37517
  }
37483
37518
  }
37484
37519
 
37485
- const blockOpts = { cache: nocache, chunker: bf(3), codec: codec$1, hasher: sha256$2, compare: simpleCompare };
37520
+ const blockOpts = { cache: nocache, chunker: bf(30), codec: codec$1, hasher: sha256$2, compare: simpleCompare };
37486
37521
 
37487
37522
  /**
37488
37523
  * @typedef {import('./blockstore.js').TransactionBlockstore} TransactionBlockstore
37489
37524
  */
37490
37525
 
37491
- const withLog = async (label, fn) => {
37492
- const resp = await fn();
37493
- // console.log('withLog', label, !!resp)
37494
- return resp
37495
- };
37526
+ // const withLog = async (label, fn) => {
37527
+ // const resp = await fn()
37528
+ // // console.log('withLog', label, !!resp)
37529
+ // return resp
37530
+ // }
37496
37531
 
37497
37532
  // should also return a CIDCounter
37498
- const makeGetBlock = (blocks) => {
37533
+ const makeGetBlock = blocks => {
37499
37534
  // const cids = new CIDCounter() // this could be used for proofs of mutations
37500
- const getBlockFn = async (address) => {
37501
- const { cid, bytes } = await withLog(address, () => blocks.get(address));
37535
+ const getBlockFn = async address => {
37536
+ // const { cid, bytes } = await withLog(address, () => blocks.get(address))
37537
+ const { cid, bytes } = await blocks.get(address);
37502
37538
  // cids.add({ address: cid })
37503
37539
  return create$5({ cid, bytes, hasher: sha256$2, codec: codec$1 })
37504
37540
  };
@@ -37513,25 +37549,17 @@ const makeGetBlock = (blocks) => {
37513
37549
  * @param {*} param0
37514
37550
  * @returns
37515
37551
  */
37516
- async function createAndSaveNewEvent ({
37517
- inBlocks,
37518
- bigPut,
37519
- root,
37520
- event: inEvent,
37521
- head,
37522
- additions,
37523
- removals = []
37524
- }) {
37552
+ async function createAndSaveNewEvent ({ inBlocks, bigPut, root, event: inEvent, head, additions, removals = [] }) {
37525
37553
  let cids;
37526
37554
  const { key, value, del } = inEvent;
37527
37555
  const data = {
37528
- root: (root
37556
+ root: root
37529
37557
  ? {
37530
37558
  cid: root.cid,
37531
37559
  bytes: root.bytes, // can we remove this?
37532
37560
  value: root.value // can we remove this?
37533
37561
  }
37534
- : null),
37562
+ : null,
37535
37563
  key
37536
37564
  };
37537
37565
  // import('./clock').EventLink<import('./clock').EventData>
@@ -37559,7 +37587,7 @@ async function createAndSaveNewEvent ({
37559
37587
  }
37560
37588
  }
37561
37589
 
37562
- const makeGetAndPutBlock = (inBlocks) => {
37590
+ const makeGetAndPutBlock = inBlocks => {
37563
37591
  // const mblocks = new MemoryBlockstore()
37564
37592
  // const blocks = new MultiBlockFetcher(mblocks, inBlocks)
37565
37593
  const { getBlock, cids } = makeGetBlock(inBlocks);
@@ -37618,20 +37646,24 @@ const prollyRootFromAncestor = async (events, ancestor, getBlock) => {
37618
37646
  }
37619
37647
  };
37620
37648
 
37621
- const doProllyBulk = async (inBlocks, head, event) => {
37649
+ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
37622
37650
  const { getBlock, blocks } = makeGetAndPutBlock(inBlocks);
37623
37651
  let bulkSorted = [];
37624
37652
  let prollyRootNode = null;
37625
37653
  const events = new EventFetcher(blocks);
37626
37654
  if (head.length) {
37627
- // Otherwise, we find the common ancestor and update the root and other blocks
37655
+ if (!doFull && head.length === 1) {
37656
+ prollyRootNode = await prollyRootFromAncestor(events, head[0], getBlock);
37657
+ } else {
37658
+ // Otherwise, we find the common ancestor and update the root and other blocks
37628
37659
  // todo this is returning more events than necessary, lets define the desired semantics from the top down
37629
37660
  // good semantics mean we can cache the results of this call
37630
- const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head);
37631
- bulkSorted = sorted;
37632
- // console.log('sorted', JSON.stringify(sorted.map(({ value: { data: { key, value } } }) => ({ key, value }))))
37633
- prollyRootNode = await prollyRootFromAncestor(events, ancestor, getBlock);
37661
+ const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head, doFull);
37662
+ bulkSorted = sorted;
37663
+ // console.log('sorted', JSON.stringify(sorted.map(({ value: { data: { key, value } } }) => ({ key, value }))))
37664
+ prollyRootNode = await prollyRootFromAncestor(events, ancestor, getBlock);
37634
37665
  // console.log('event', event)
37666
+ }
37635
37667
  }
37636
37668
 
37637
37669
  const bulkOperations = bulkFromEvents(bulkSorted, event);
@@ -37641,7 +37673,7 @@ const doProllyBulk = async (inBlocks, head, event) => {
37641
37673
  let root;
37642
37674
  const newBlocks = [];
37643
37675
  // if all operations are deletes, we can just return an empty root
37644
- if (bulkOperations.every((op) => op.del)) {
37676
+ if (bulkOperations.every(op => op.del)) {
37645
37677
  return { root: null, blocks: [], clockCIDs: await events.all() }
37646
37678
  }
37647
37679
  for await (const node of create$3({ get: getBlock, list: bulkOperations, ...blockOpts })) {
@@ -37661,7 +37693,7 @@ const doProllyBulk = async (inBlocks, head, event) => {
37661
37693
  *
37662
37694
  * @param {import('./blockstore.js').Blockstore} inBlocks Bucket block storage.
37663
37695
  * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
37664
- * @param {{key: string, value: import('./clock').EventLink<import('./clock').EventData>}} event The key of the value to put.
37696
+ * @param {{key: string, value: import('./clock').EventLink<import('./clock').EventData>}} event The key of the value to put.
37665
37697
  * @param {object} [options]
37666
37698
  * @returns {Promise<any>}
37667
37699
  */
@@ -37713,18 +37745,24 @@ async function put (inBlocks, head, event, options) {
37713
37745
  * @param {TransactionBlockstore} inBlocks Bucket block storage.
37714
37746
  * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
37715
37747
  */
37716
- async function root (inBlocks, head) {
37748
+ async function root (inBlocks, head, doFull = false) {
37717
37749
  if (!head.length) {
37718
37750
  throw new Error('no head')
37719
37751
  }
37720
- const { root: newProllyRootNode, blocks: newBlocks, clockCIDs } = await doProllyBulk(inBlocks, head);
37752
+ // console.log('root', head.map(h => h.toString()))
37753
+ const { root: newProllyRootNode, blocks: newBlocks, clockCIDs } = await doProllyBulk(inBlocks, head, null, doFull);
37721
37754
  // todo maybe these should go to a temp blockstore?
37722
- await doTransaction('root', inBlocks, async (transactionBlocks) => {
37723
- const { bigPut } = makeGetAndPutBlock(transactionBlocks);
37724
- for (const nb of newBlocks) {
37725
- bigPut(nb);
37726
- }
37727
- }, false);
37755
+ await doTransaction(
37756
+ 'root',
37757
+ inBlocks,
37758
+ async transactionBlocks => {
37759
+ const { bigPut } = makeGetAndPutBlock(transactionBlocks);
37760
+ for (const nb of newBlocks) {
37761
+ bigPut(nb);
37762
+ }
37763
+ },
37764
+ false
37765
+ );
37728
37766
  return { clockCIDs, node: newProllyRootNode }
37729
37767
  }
37730
37768
 
@@ -37751,22 +37789,37 @@ async function eventsSince (blocks, head, since) {
37751
37789
  * @param {TransactionBlockstore} blocks Bucket block storage.
37752
37790
  * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
37753
37791
  *
37754
- * @returns {Promise<{cids: CIDCounter, clockCIDs: CIDCounter, result: import('./clock').EventData[]}>}
37792
+ * @returns {Promise<{root: any, cids: CIDCounter, clockCIDs: CIDCounter, result: import('./clock').EventData[]}>}
37755
37793
  *
37756
37794
  */
37757
- async function getAll (blocks, head) {
37795
+ async function getAll (blocks, head, rootCache = null, doFull = false) {
37758
37796
  // todo use the root node left around from put, etc
37759
37797
  // move load to a central place
37760
37798
  if (!head.length) {
37761
- return { clockCIDs: new CIDCounter(), cids: new CIDCounter(), result: [] }
37799
+ return { root: null, clockCIDs: new CIDCounter(), cids: new CIDCounter(), result: [] }
37762
37800
  }
37763
- const { node: prollyRootNode, clockCIDs } = await root(blocks, head);
37801
+ const { node: prollyRootNode, clockCIDs } = await rootOrCache(blocks, head, rootCache, doFull);
37764
37802
 
37765
37803
  if (!prollyRootNode) {
37766
- return { clockCIDs, cids: new CIDCounter(), result: [] }
37804
+ return { root: null, clockCIDs, cids: new CIDCounter(), result: [] }
37767
37805
  }
37768
37806
  const { result, cids } = await prollyRootNode.getAllEntries(); // todo params
37769
- return { clockCIDs, cids, result: result.map(({ key, value }) => ({ key, value })) }
37807
+ return { root: prollyRootNode, clockCIDs, cids, result: result.map(({ key, value }) => ({ key, value })) }
37808
+ }
37809
+
37810
+ async function rootOrCache (blocks, head, rootCache, doFull = false) {
37811
+ let node;
37812
+ let clockCIDs;
37813
+ if (!doFull && rootCache && rootCache.root) {
37814
+ // console.log('get root from cache', rootCache)
37815
+ node = rootCache.root;
37816
+ clockCIDs = rootCache.clockCIDs;
37817
+ } else {
37818
+ ({ node, clockCIDs } = await root(blocks, head, doFull));
37819
+ // console.timeEnd(callTag + '.root')
37820
+ // console.log('found root')
37821
+ }
37822
+ return { node, clockCIDs }
37770
37823
  }
37771
37824
 
37772
37825
  /**
@@ -37774,17 +37827,19 @@ async function getAll (blocks, head) {
37774
37827
  * @param {import('./clock').EventLink<import('./clock').EventData>[]} head Merkle clock head.
37775
37828
  * @param {string} key The key of the value to retrieve.
37776
37829
  */
37777
- async function get (blocks, head, key) {
37830
+ async function get (blocks, head, key, rootCache = null) {
37778
37831
  // instead pass root from db? and always update on change
37779
37832
  if (!head.length) {
37780
37833
  return { cids: new CIDCounter(), result: null }
37781
37834
  }
37782
- const { node: prollyRootNode, cids: clockCIDs } = await root(blocks, head);
37835
+
37836
+ const { node: prollyRootNode, clockCIDs } = await rootOrCache(blocks, head, rootCache);
37837
+
37783
37838
  if (!prollyRootNode) {
37784
37839
  return { clockCIDs, cids: new CIDCounter(), result: null }
37785
37840
  }
37786
37841
  const { result, cids } = await prollyRootNode.get(key);
37787
- return { result, cids, clockCIDs }
37842
+ return { result, cids, clockCIDs, root: prollyRootNode }
37788
37843
  }
37789
37844
 
37790
37845
  async function * vis (blocks, head) {
@@ -37801,8 +37856,19 @@ async function * vis (blocks, head) {
37801
37856
  }
37802
37857
 
37803
37858
  async function visMerkleTree (blocks, head) {
37804
- if (!head.length) {
37805
- return { cids: new CIDCounter(), result: null }
37859
+ // if (!head) return
37860
+ if (head && !Array.isArray(head)) {
37861
+ const getBl = makeGetBlock(blocks);
37862
+ const prollyRootNode = await load$2({
37863
+ cid: head,
37864
+ get: getBl.getBlock,
37865
+ ...blockOpts
37866
+ });
37867
+ const lines = [];
37868
+ for await (const line of prollyRootNode.vis()) {
37869
+ lines.push(line);
37870
+ }
37871
+ return { vis: lines.join('\n'), cids: new CIDCounter() }
37806
37872
  }
37807
37873
  const { node: prollyRootNode, cids } = await root(blocks, head);
37808
37874
  const lines = [];
@@ -38085,15 +38151,16 @@ const parseCID = cid => (typeof cid === 'string' ? CID$1.parse(cid) : cid);
38085
38151
  */
38086
38152
  class Database {
38087
38153
  listeners = new Set()
38154
+ indexes = new Map()
38155
+ rootCache = null
38156
+ eventsCache = new Map()
38088
38157
 
38089
- // todo refactor this for the next version
38090
38158
  constructor (blocks, clock, config = {}) {
38091
38159
  this.name = config.name;
38092
38160
  this.instanceId = `fp.${this.name}.${Math.random().toString(36).substring(2, 7)}`;
38093
38161
  this.blocks = blocks;
38094
38162
  this.clock = clock;
38095
38163
  this.config = config;
38096
- this.indexes = new Map();
38097
38164
  }
38098
38165
 
38099
38166
  /**
@@ -38160,11 +38227,22 @@ class Database {
38160
38227
  * @instance
38161
38228
  */
38162
38229
  async changesSince (event) {
38230
+ // console.log('events for', this.instanceId, event.constructor.name)
38163
38231
  // console.log('changesSince', this.instanceId, event, this.clock)
38164
38232
  let rows, dataCIDs, clockCIDs;
38165
38233
  // if (!event) event = []
38166
38234
  if (event) {
38167
- const resp = await eventsSince(this.blocks, this.clock, event);
38235
+ event = event.map((cid) => cid.toString());
38236
+ const eventKey = JSON.stringify([...event, ...this.clockToJSON()]);
38237
+
38238
+ let resp;
38239
+ if (this.eventsCache.has(eventKey)) {
38240
+ console.log('events from cache');
38241
+ resp = this.eventsCache.get(eventKey);
38242
+ } else {
38243
+ resp = await eventsSince(this.blocks, this.clock, event);
38244
+ this.eventsCache.set(eventKey, resp);
38245
+ }
38168
38246
  const docsMap = new Map();
38169
38247
  for (const { key, type, value } of resp.result.map(decodeEvent)) {
38170
38248
  if (type === 'del') {
@@ -38177,7 +38255,9 @@ class Database {
38177
38255
  clockCIDs = resp.clockCIDs;
38178
38256
  // console.log('change rows', this.instanceId, rows)
38179
38257
  } else {
38180
- const allResp = await getAll(this.blocks, this.clock);
38258
+ const allResp = await getAll(this.blocks, this.clock, this.rootCache);
38259
+ this.rootCache = { root: allResp.root, clockCIDs: allResp.clockCIDs };
38260
+
38181
38261
  rows = allResp.result.map(({ key, value }) => decodeEvent({ key, value }));
38182
38262
  dataCIDs = allResp.cids;
38183
38263
  // console.log('dbdoc rows', this.instanceId, rows)
@@ -38190,7 +38270,9 @@ class Database {
38190
38270
  }
38191
38271
 
38192
38272
  async allDocuments () {
38193
- const allResp = await getAll(this.blocks, this.clock);
38273
+ const allResp = await getAll(this.blocks, this.clock, this.rootCache);
38274
+ this.rootCache = { root: allResp.root, clockCIDs: allResp.clockCIDs };
38275
+
38194
38276
  const rows = allResp.result
38195
38277
  .map(({ key, value }) => decodeEvent({ key, value }))
38196
38278
  .map(({ key, value }) => ({ key, value: { _id: key, ...value } }));
@@ -38202,7 +38284,8 @@ class Database {
38202
38284
  }
38203
38285
 
38204
38286
  async allCIDs () {
38205
- const allResp = await getAll(this.blocks, this.clock);
38287
+ const allResp = await getAll(this.blocks, this.clock, this.rootCache, true);
38288
+ this.rootCache = { root: allResp.root, clockCIDs: allResp.clockCIDs };
38206
38289
  // console.log('allcids', allResp.cids, allResp.clockCIDs)
38207
38290
  const cids = await cidsToProof(allResp.cids);
38208
38291
  const clockCids = await cidsToProof(allResp.clockCIDs);
@@ -38248,13 +38331,13 @@ class Database {
38248
38331
  */
38249
38332
  async get (key, opts = {}) {
38250
38333
  const clock = opts.clock || this.clock;
38251
- const resp = await get(this.blocks, clock, charwise.encode(key));
38252
-
38334
+ const resp = await get(this.blocks, clock, charwise.encode(key), this.rootCache);
38335
+ this.rootCache = { root: resp.root, clockCIDs: resp.clockCIDs };
38253
38336
  // this tombstone is temporary until we can get the prolly tree to delete
38254
38337
  if (!resp || resp.result === null) {
38255
38338
  throw new Error('Not found')
38256
38339
  }
38257
- const doc = resp.result;
38340
+ const doc = { ...resp.result };
38258
38341
  if (opts.mvcc === true) {
38259
38342
  doc._clock = this.clockToJSON();
38260
38343
  }
@@ -38348,7 +38431,9 @@ class Database {
38348
38431
  }
38349
38432
 
38350
38433
  applyClock (prevClock, newClock) {
38351
- // console.log('applyClock', prevClock, newClock, this.clock)
38434
+ // console.log('prevClock', prevClock.length, prevClock.map((cid) => cid.toString()))
38435
+ // console.log('newClock', newClock.length, newClock.map((cid) => cid.toString()))
38436
+ // console.log('this.clock', this.clock.length, this.clockToJSON())
38352
38437
  const stPrev = prevClock.map(cid => cid.toString());
38353
38438
  const keptPrevClock = this.clock.filter(cid => stPrev.indexOf(cid.toString()) === -1);
38354
38439
  const merged = keptPrevClock.concat(newClock);
@@ -38356,8 +38441,10 @@ class Database {
38356
38441
  for (const cid of merged) {
38357
38442
  uniquebyCid.set(cid.toString(), cid);
38358
38443
  }
38359
- this.clock = Array.from(uniquebyCid.values());
38360
- // console.log('afterClock', this.clock)
38444
+ this.clock = Array.from(uniquebyCid.values()).sort((a, b) => a.toString().localeCompare(b.toString()));
38445
+ this.rootCache = null;
38446
+ this.eventsCache.clear();
38447
+ // console.log('afterClock', this.clock.length, this.clockToJSON())
38361
38448
  }
38362
38449
 
38363
38450
  // /**
@@ -38693,8 +38780,8 @@ const refCompare = (aRef, bRef) => {
38693
38780
  return simpleCompare(aRef, bRef)
38694
38781
  };
38695
38782
 
38696
- const dbIndexOpts = { cache: nocache, chunker: bf(3), codec: codec$1, hasher: sha256$2, compare };
38697
- const idIndexOpts = { cache: nocache, chunker: bf(3), codec: codec$1, hasher: sha256$2, compare: simpleCompare };
38783
+ const dbIndexOpts = { cache: nocache, chunker: bf(30), codec: codec$1, hasher: sha256$2, compare };
38784
+ const idIndexOpts = { cache: nocache, chunker: bf(30), codec: codec$1, hasher: sha256$2, compare: simpleCompare };
38698
38785
 
38699
38786
  const makeDoc = ({ key, value }) => ({ _id: key, ...value });
38700
38787
 
@@ -38751,6 +38838,9 @@ const indexEntriesForChanges = (changes, mapFn) => {
38751
38838
  *
38752
38839
  */
38753
38840
  class DbIndex {
38841
+ /**
38842
+ * @param {Database} database
38843
+ */
38754
38844
  constructor (database, name, mapFn, clock = null, opts = {}) {
38755
38845
  this.database = database;
38756
38846
  if (!database.indexBlocks) {
@@ -38822,6 +38912,14 @@ class DbIndex {
38822
38912
  return new DbIndex(database, name, code, clock)
38823
38913
  }
38824
38914
 
38915
+ async visKeyTree () {
38916
+ return await visMerkleTree(this.database.indexBlocks, this.indexById.cid)
38917
+ }
38918
+
38919
+ async visIdTree () {
38920
+ return await visMerkleTree(this.database.indexBlocks, this.indexByKey.cid)
38921
+ }
38922
+
38825
38923
  /**
38826
38924
  * JSDoc for Query type.
38827
38925
  * @typedef {Object} DbQuery
@@ -40875,7 +40973,7 @@ class Sync {
40875
40973
  */
40876
40974
  constructor (database, PeerClass = simplePeer) {
40877
40975
  this.database = database;
40878
- this.database.blocks.syncs.add(this);
40976
+ this.database.blocks.syncs.add(this); // should this happen during setup?
40879
40977
  this.PeerClass = PeerClass;
40880
40978
  this.pushBacklog = new Promise((resolve, reject) => {
40881
40979
  this.pushBacklogResolve = resolve;
@@ -40923,8 +41021,13 @@ class Sync {
40923
41021
 
40924
41022
  async gotData (data) {
40925
41023
  // console.log('got data', data.toString())
41024
+ let reader = null;
40926
41025
  try {
40927
- const reader = await CarReader.fromBytes(data);
41026
+ reader = await CarReader.fromBytes(data);
41027
+ } catch (e) {
41028
+ // console.log('not a car', data.toString())
41029
+ }
41030
+ if (reader) {
40928
41031
  const blz = new Set();
40929
41032
  for await (const block of reader.blocks()) {
40930
41033
  blz.add(block);
@@ -40947,17 +41050,18 @@ class Sync {
40947
41050
  get: async cid => await reader.get(cid),
40948
41051
  lastCid: [...blz][0].cid // doesn't matter
40949
41052
  }, false);
40950
- this.database.applyClock([], roots);
41053
+ // first arg could be the roots parents?
41054
+ // get the roots parents
41055
+ const parents = await Promise.all(roots.map(async (cid) => {
41056
+ const rbl = await reader.get(cid);
41057
+ const block = await decodeEventBlock(rbl.bytes);
41058
+ return block.value.parents
41059
+ }));
41060
+ this.database.applyClock(parents.flat(), roots);
40951
41061
  this.database.notifyReset();
40952
41062
  // console.log('after', this.database.clockToJSON())
40953
41063
  this.pushBacklogResolve({ ok: true });
40954
- } catch (e) {
40955
- // console.error(e)
40956
- // if e.message matche 'CBOR' we can ignore it
40957
- if (!e.message.match(/CBOR|fromBytes/)) {
40958
- throw e
40959
- }
40960
-
41064
+ } else {
40961
41065
  // data is a json string, parse it
40962
41066
  const message = JSON.parse(data.toString());
40963
41067
  // console.log('got message', message)
@@ -40983,7 +41087,7 @@ class Sync {
40983
41087
  }
40984
41088
 
40985
41089
  async sendUpdate (blockstore) {
40986
- console.log('send update from', this.database.instanceId);
41090
+ // console.log('send update from', this.database.instanceId)
40987
41091
  // todo should send updates since last sync
40988
41092
  const newCar = await blocksToCarBlock(blockstore.lastCid, blockstore);
40989
41093
  this.peer.send(newCar.bytes);