@fireproof/core 0.5.12 → 0.5.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5497,17 +5497,17 @@ class CIDCounter {
5497
5497
 
5498
5498
  /**
5499
5499
  * @typedef {{
5500
- * type: 'put'|'del'
5501
- * key: string
5502
- * value: import('./link').AnyLink
5503
- * root: import('./link').AnyLink
5504
- * }} EventData
5505
- * @typedef {{
5506
- * root: import('./link').AnyLink
5507
- * head: import('./clock').EventLink<EventData>[]
5508
- * event: import('./clock').EventBlockView<EventData>
5509
- * }} Result
5510
- */
5500
+ * type: 'put'|'del'
5501
+ * key: string
5502
+ * value: import('./link').AnyLink
5503
+ * root: import('./link').AnyLink
5504
+ * }} EventData
5505
+ * @typedef {{
5506
+ * root: import('./link').AnyLink
5507
+ * head: import('./clock').EventLink<EventData>[]
5508
+ * event: import('./clock').EventBlockView<EventData>
5509
+ * }} Result
5510
+ */
5511
5511
 
5512
5512
  /**
5513
5513
  * Advance the clock by adding an event.
@@ -5521,7 +5521,7 @@ class CIDCounter {
5521
5521
  async function advance (blocks, head, event) {
5522
5522
  /** @type {EventFetcher<T>} */
5523
5523
  const events = new EventFetcher(blocks);
5524
- const headmap = new Map(head.map((cid) => [cid.toString(), cid]));
5524
+ const headmap = new Map(head.map(cid => [cid.toString(), cid]));
5525
5525
 
5526
5526
  // Check if the headmap already includes the event, return head if it does
5527
5527
  if (headmap.has(event.toString())) return { head, cids: await events.all() }
@@ -5643,14 +5643,16 @@ async function decodeEventBlock (bytes) {
5643
5643
  async function contains (events, a, b) {
5644
5644
  if (a.toString() === b.toString()) return true
5645
5645
  const [{ value: aevent }, { value: bevent }] = await Promise.all([events.get(a), events.get(b)]);
5646
- const links = [...aevent.parents];
5646
+ // const links = [...aevent.parents]
5647
+ // console.log('aevent', aevent.parents)
5648
+ const links = [...(aevent.parents || [])];
5647
5649
  while (links.length) {
5648
5650
  const link = links.shift();
5649
5651
  if (!link) break
5650
5652
  if (link.toString() === b.toString()) return true
5651
5653
  // if any of b's parents are this link, then b cannot exist in any of the
5652
5654
  // tree below, since that would create a cycle.
5653
- if (bevent.parents.some((p) => link.toString() === p.toString())) continue
5655
+ if (bevent.parents.some(p => link.toString() === p.toString())) continue
5654
5656
  const { value: event } = await events.get(link);
5655
5657
  links.push(...event.parents);
5656
5658
  }
@@ -5666,15 +5668,19 @@ async function contains (events, a, b) {
5666
5668
  */
5667
5669
  async function * vis$1 (blocks, head, options = {}) {
5668
5670
  // @ts-ignore
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
- });
5671
+ const renderNodeLabel =
5672
+ options.renderNodeLabel ??
5673
+ (b => {
5674
+ // @ts-ignore
5675
+ const { key, root, type } = b.value.data;
5676
+ return (
5677
+ b.cid.toString() + '\n' + JSON.stringify({ key, root: root.cid.toString(), type }, null, 2).replace(/"/g, "'")
5678
+ )
5679
+ });
5674
5680
  const events = new EventFetcher(blocks);
5675
5681
  yield 'digraph clock {';
5676
5682
  yield ' node [shape=point fontname="Courier"]; head;';
5677
- const hevents = await Promise.all(head.map((link) => events.get(link)));
5683
+ const hevents = await Promise.all(head.map(link => events.get(link)));
5678
5684
  const links = [];
5679
5685
  const nodes = new Set();
5680
5686
  for (const e of hevents) {
@@ -5707,17 +5713,18 @@ async function findEventsToSync (blocks, head) {
5707
5713
  // console.time(callTag + '.findCommonAncestorWithSortedEvents')
5708
5714
  const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head);
5709
5715
  // console.timeEnd(callTag + '.findCommonAncestorWithSortedEvents')
5710
- // console.log('sorted', sorted.length)
5716
+ // console.log('sorted', !!ancestor, sorted.length)
5711
5717
  // console.time(callTag + '.contains')
5712
- const toSync = await asyncFilter(sorted, async (uks) => !(await contains(events, ancestor, uks.cid)));
5718
+
5719
+ const toSync = ancestor ? await asyncFilter(sorted, async uks => !(await contains(events, ancestor, uks.cid))) : sorted;
5713
5720
  // console.timeEnd(callTag + '.contains')
5714
- // console.log('toSync.contains', toSync.length)
5721
+ console.log('toSync', !!ancestor, sorted.length - toSync.length);
5715
5722
 
5716
5723
  return { cids: events, events: toSync }
5717
5724
  }
5718
5725
 
5719
5726
  const asyncFilter = async (arr, predicate) =>
5720
- Promise.all(arr.map(predicate)).then((results) => arr.filter((_v, index) => results[index]));
5727
+ Promise.all(arr.map(predicate)).then(results => arr.filter((_v, index) => results[index]));
5721
5728
 
5722
5729
  async function findCommonAncestorWithSortedEvents (events, children, doFull = false) {
5723
5730
  // console.trace('findCommonAncestorWithSortedEvents')
@@ -5728,12 +5735,16 @@ async function findCommonAncestorWithSortedEvents (events, children, doFull = fa
5728
5735
  // console.timeEnd(callTag + '.findCommonAncestor')
5729
5736
  // console.log('ancestor', ancestor.toString())
5730
5737
  if (!ancestor) {
5731
- throw new Error('failed to find common ancestor event')
5738
+ console.log('no common ancestor', children);
5739
+ // throw new Error('no common ancestor')
5740
+ const sorted = await findSortedEvents(events, children, children, doFull);
5741
+ return { ancestor: null, sorted }
5732
5742
  }
5733
5743
  // console.time(callTag + '.findSortedEvents')
5734
- const sorted = await findSortedEvents(events, children, ancestor, doFull);
5744
+ const sorted = await findSortedEvents(events, children, [ancestor], doFull);
5735
5745
  // console.timeEnd(callTag + '.findSortedEvents')
5736
5746
  // console.log('sorted', sorted.length)
5747
+ // console.log('ancestor', JSON.stringify(ancestor, null, 2))
5737
5748
  return { ancestor, sorted }
5738
5749
  }
5739
5750
 
@@ -5744,17 +5755,58 @@ async function findCommonAncestorWithSortedEvents (events, children, doFull = fa
5744
5755
  * @param {import('./clock').EventFetcher} events
5745
5756
  * @param {import('./clock').EventLink<EventData>[]} children
5746
5757
  */
5758
+ // async function NEWfindCommonAncestor (events, children) {
5759
+ // if (!children.length) return
5760
+ // if (children.length === 1) return children[0]
5761
+
5762
+ // const candidates = children.map(c => [c])
5763
+ // const visited = new Set()
5764
+
5765
+ // while (true) {
5766
+ // let changed = false
5767
+ // for (const c of candidates) {
5768
+ // const candidate = await findAncestorCandidate(events, c[c.length - 1])
5769
+
5770
+ // if (!candidate) continue
5771
+
5772
+ // if (visited.has(candidate)) {
5773
+ // return candidate // Common ancestor found
5774
+ // }
5775
+
5776
+ // visited.add(candidate)
5777
+ // changed = true
5778
+ // c.push(candidate)
5779
+ // }
5780
+
5781
+ // if (!changed) {
5782
+ // // No common ancestor found, exhausted candidates
5783
+ // return null
5784
+ // }
5785
+ // }
5786
+ // }
5787
+
5747
5788
  async function findCommonAncestor (events, children) {
5748
5789
  if (!children.length) return
5790
+ children = [...new Set(children)];
5749
5791
  if (children.length === 1) return children[0]
5750
5792
  const candidates = children.map((c) => [c]);
5793
+ // console.log(
5794
+ // 'og candidates',
5795
+ // candidates.map((c) => c.toString())
5796
+ // )
5751
5797
  while (true) {
5752
5798
  let changed = false;
5753
5799
  for (const c of candidates) {
5754
5800
  const candidate = await findAncestorCandidate(events, c[c.length - 1]);
5755
5801
  if (!candidate) continue
5802
+
5803
+ // Check if the candidate is already in the list, and if so, skip it.
5804
+ if (c.includes(candidate)) continue
5805
+
5806
+ // if set size is all cids, then no common ancestor
5756
5807
  changed = true;
5757
- c.push(candidate);
5808
+ c.push(candidate); // make set?
5809
+ // console.log('candidate', candidates.map((c) => c.toString()))
5758
5810
  const ancestor = findCommonString(candidates);
5759
5811
  if (ancestor) return ancestor
5760
5812
  }
@@ -5762,12 +5814,45 @@ async function findCommonAncestor (events, children) {
5762
5814
  }
5763
5815
  }
5764
5816
 
5817
+ // async function OGfindCommonAncestor (events, children) {
5818
+ // if (!children.length) return
5819
+ // if (children.length === 1) return children[0]
5820
+ // const candidates = children.map(c => [c])
5821
+ // console.log(
5822
+ // 'og candidates',
5823
+ // candidates.map(c => c.toString())
5824
+ // )
5825
+ // while (true) {
5826
+ // let changed = false
5827
+ // for (const c of candidates) {
5828
+ // const candidate = await findAncestorCandidate(events, c[c.length - 1])
5829
+ // if (!candidate) continue
5830
+ // // if set size is all cids, then no common ancestor
5831
+ // changed = true
5832
+ // c.push(candidate) // make set?
5833
+ // console.log(
5834
+ // 'candidate',
5835
+ // candidates.map(c => c.toString())
5836
+ // )
5837
+ // const ancestor = findCommonString(candidates)
5838
+ // if (ancestor) return ancestor
5839
+ // }
5840
+ // if (!changed) return
5841
+ // }
5842
+ // }
5843
+
5765
5844
  /**
5766
5845
  * @param {import('./clock').EventFetcher} events
5767
5846
  * @param {import('./clock').EventLink<EventData>} root
5768
5847
  */
5769
5848
  async function findAncestorCandidate (events, root) {
5770
- const { value: event } = await events.get(root);// .catch(() => ({ value: { parents: [] } }))
5849
+ const { value: event } = await events.get(root); // .catch(() => ({ value: { parents: [] } }))
5850
+ // console.log(
5851
+ // 'findAncestorCandidate',
5852
+ // root.toString(),
5853
+ // 'parents',
5854
+ // event.parents.map(p => p.toString())
5855
+ // )
5771
5856
  if (!event.parents.length) return root
5772
5857
  return event.parents.length === 1 ? event.parents[0] : findCommonAncestor(events, event.parents)
5773
5858
  }
@@ -5778,13 +5863,13 @@ async function findAncestorCandidate (events, root) {
5778
5863
  */
5779
5864
  function findCommonString (arrays) {
5780
5865
  // console.log('findCommonString', arrays.map((a) => a.map((i) => String(i))))
5781
- arrays = arrays.map((a) => [...a]);
5866
+ arrays = arrays.map(a => [...a]);
5782
5867
  for (const arr of arrays) {
5783
5868
  for (const item of arr) {
5784
5869
  let matched = true;
5785
5870
  for (const other of arrays) {
5786
5871
  if (arr === other) continue
5787
- matched = other.some((i) => String(i) === String(item));
5872
+ matched = other.some(i => String(i) === String(item));
5788
5873
  if (!matched) break
5789
5874
  }
5790
5875
  if (matched) return item
@@ -5796,19 +5881,19 @@ function findCommonString (arrays) {
5796
5881
  * Find and sort events between the head(s) and the tail.
5797
5882
  * @param {import('./clock').EventFetcher} events
5798
5883
  * @param {any[]} head
5799
- * @param {import('./clock').EventLink<EventData>} tail
5884
+ * @param {import('./clock').EventLink<EventData>[]} tails
5800
5885
  */
5801
- async function findSortedEvents (events, head, tail, doFull) {
5886
+ async function findSortedEvents (events, head, tails, doFull) {
5802
5887
  // const callTag = Math.random().toString(36).substring(7)
5803
5888
  // get weighted events - heavier events happened first
5804
5889
  // const callTag = Math.random().toString(36).substring(7)
5805
5890
 
5806
5891
  /** @type {Map<string, { event: import('./clock').EventBlockView<EventData>, weight: number }>} */
5807
5892
  const weights = new Map();
5808
- head = [...new Set([...head.map((h) => h.toString())])];
5893
+ head = [...new Set([...head.map(h => h.toString())])];
5809
5894
  // console.log(callTag + '.head', head.length)
5810
5895
 
5811
- const allEvents = new Set([tail.toString(), ...head]);
5896
+ const allEvents = new Set([tails.map((t) => t.toString()).toString(), ...head]);
5812
5897
  if (!doFull && allEvents.size === 1) {
5813
5898
  // console.log('head contains tail', tail.toString())
5814
5899
  return []
@@ -5820,7 +5905,8 @@ async function findSortedEvents (events, head, tail, doFull) {
5820
5905
  // console.log(callTag + '.head', head.length, [...head.map((h) => h.toString())], tail.toString())
5821
5906
 
5822
5907
  // console.time(callTag + '.findEvents')
5823
- const all = await Promise.all(head.map((h) => findEvents(events, h, tail)));
5908
+ const all = await (await Promise.all(tails.map((t) => Promise.all(head.map(h => findEvents(events, h, t)))))).flat();
5909
+ // console.log('all', all.length)
5824
5910
  // console.timeEnd(callTag + '.findEvents')
5825
5911
  for (const arr of all) {
5826
5912
  for (const { event, depth } of arr) {
@@ -5868,9 +5954,9 @@ async function findEvents (events, start, end, depth = 0) {
5868
5954
  const acc = [{ event, depth }];
5869
5955
  const { parents } = event.value;
5870
5956
  // if (parents.length === 1 && String(parents[0]) === send) return acc
5871
- if (parents.findIndex((p) => String(p) === send) !== -1) return acc
5957
+ if (parents.findIndex(p => String(p) === send) !== -1) return acc
5872
5958
  // if (parents.length === 1) return acc
5873
- const rest = await Promise.all(parents.map((p) => findEvents(events, p, end, depth + 1)));
5959
+ const rest = await Promise.all(parents.map(p => findEvents(events, p, end, depth + 1)));
5874
5960
  return acc.concat(...rest)
5875
5961
  }
5876
5962
 
@@ -36826,7 +36912,7 @@ const decrypt = async function * ({ root, get, key, cache, chunker, hasher }) {
36826
36912
  const { result: nodes } = await cidset.getAllEntries();
36827
36913
  const unwrap = async (eblock) => {
36828
36914
  const { bytes, cid } = await decrypt$1({ ...eblock, key }).catch(e => {
36829
- console.log('ekey', e);
36915
+ // console.log('ekey', e)
36830
36916
  throw new Error('bad key: ' + key.toString('hex'))
36831
36917
  });
36832
36918
  const block = await createBlock(bytes, cid);
@@ -36947,11 +37033,11 @@ class Valet {
36947
37033
  this.name = name;
36948
37034
  this.setKeyMaterial(keyMaterial);
36949
37035
  this.uploadQueue = cargoQueue(async (tasks, callback) => {
36950
- console.log(
36951
- 'queue worker',
36952
- tasks.length,
36953
- tasks.reduce((acc, t) => acc + t.value.length, 0)
36954
- );
37036
+ // console.log(
37037
+ // 'queue worker',
37038
+ // tasks.length,
37039
+ // tasks.reduce((acc, t) => acc + t.value.length, 0)
37040
+ // )
36955
37041
  if (this.uploadFunction) {
36956
37042
  // todo we can coalesce these into a single car file
36957
37043
  return await this.withDB(async db => {
@@ -37373,6 +37459,7 @@ class TransactionBlockstore {
37373
37459
  await this.doCommit(innerBlockstore);
37374
37460
  if (doSync) {
37375
37461
  // const all =
37462
+ // console.log('syncing', innerBlockstore.label)
37376
37463
  await Promise.all([...this.syncs].map(async sync => sync.sendUpdate(innerBlockstore).catch(e => {
37377
37464
  console.error('sync error, cancelling', e);
37378
37465
  sync.destroy();
@@ -37485,6 +37572,8 @@ class InnerBlockstore {
37485
37572
 
37486
37573
  const blockOpts = { cache: nocache, chunker: bf(30), codec: codec$1, hasher: sha256$2, compare: simpleCompare };
37487
37574
 
37575
+ // const SYNC_ROOT = 'fireproof' // change this if you want to break sync
37576
+
37488
37577
  /**
37489
37578
  * @typedef {import('./blockstore.js').TransactionBlockstore} TransactionBlockstore
37490
37579
  */
@@ -37518,13 +37607,11 @@ const makeGetBlock = blocks => {
37518
37607
  async function createAndSaveNewEvent ({ inBlocks, bigPut, root, event: inEvent, head, additions, removals = [] }) {
37519
37608
  let cids;
37520
37609
  const { key, value, del } = inEvent;
37610
+ // console.log('createAndSaveNewEvent', root.constructor.name, root.entryList)
37611
+ // root = await root.block
37521
37612
  const data = {
37522
37613
  root: root
37523
- ? {
37524
- cid: root.cid,
37525
- bytes: root.bytes, // can we remove this?
37526
- value: root.value // can we remove this?
37527
- }
37614
+ ? (await root.address)
37528
37615
  : null,
37529
37616
  key
37530
37617
  };
@@ -37536,6 +37623,29 @@ async function createAndSaveNewEvent ({ inBlocks, bigPut, root, event: inEvent,
37536
37623
  data.value = value;
37537
37624
  data.type = 'put';
37538
37625
  }
37626
+ // console.log('head', head)
37627
+ // if (head.length === 0) {
37628
+ // // create an empty prolly root
37629
+ // let emptyRoot
37630
+
37631
+ // for await (const node of create({ get: getBlock, list: [{ key: '_sync', value: SYNC_ROOT }], ...blockOpts })) {
37632
+ // emptyRoot = await node.block
37633
+ // bigPut(emptyRoot)
37634
+ // }
37635
+ // console.log('emptyRoot', emptyRoot)
37636
+ // const first = await EventBlock.create(
37637
+ // {
37638
+ // root: emptyRoot.cid,
37639
+ // key: null,
37640
+ // value: null,
37641
+ // type: 'del'
37642
+ // },
37643
+ // []
37644
+ // )
37645
+ // bigPut(first)
37646
+ // head = [first.cid]
37647
+ // }
37648
+
37539
37649
  /** @type {import('./clock').EventData} */
37540
37650
  // @ts-ignore
37541
37651
  const event = await EventBlock.create(data, head);
@@ -37604,16 +37714,23 @@ const prollyRootFromAncestor = async (events, ancestor, getBlock) => {
37604
37714
  // console.log('prollyRootFromAncestor', ancestor)
37605
37715
  const event = await events.get(ancestor);
37606
37716
  const { root } = event.value.data;
37607
- // console.log('prollyRootFromAncestor', root.cid, JSON.stringify(root.value))
37608
37717
  if (root) {
37609
- return load$2({ cid: root.cid, get: getBlock, ...blockOpts })
37718
+ return load$2({ cid: root, get: getBlock, ...blockOpts })
37610
37719
  } else {
37611
- return null
37720
+ // console.log('no root', root) // false means no common ancestor. null means empty database.
37721
+ return root
37612
37722
  }
37613
37723
  };
37614
37724
 
37725
+ // async function bigMerge (events, head, getBlock) {
37726
+ // const allRoots = await Promise.all(head.map(async h => prollyRootFromAncestor(events, h, getBlock)))
37727
+ // console.log('allRoots', allRoots)
37728
+ // // todo query over all roots and merge them, but how do they not have a common ancestor? they all start with the _sync root
37729
+ // throw new Error('not implemented')
37730
+ // }
37731
+
37615
37732
  const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
37616
- const { getBlock, blocks } = makeGetAndPutBlock(inBlocks);
37733
+ const { getBlock, blocks } = makeGetAndPutBlock(inBlocks); // this is doubled with eventfetcher
37617
37734
  let bulkSorted = [];
37618
37735
  let prollyRootNode = null;
37619
37736
  const events = new EventFetcher(blocks);
@@ -37621,14 +37738,22 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
37621
37738
  if (!doFull && head.length === 1) {
37622
37739
  prollyRootNode = await prollyRootFromAncestor(events, head[0], getBlock);
37623
37740
  } else {
37624
- // Otherwise, we find the common ancestor and update the root and other blocks
37625
- // todo this is returning more events than necessary, lets define the desired semantics from the top down
37626
- // good semantics mean we can cache the results of this call
37741
+ // Otherwise, we find the common ancestor and update the root and other blocks
37742
+ // todo this is returning more events than necessary, lets define the desired semantics from the top down
37743
+ // good semantics mean we can cache the results of this call
37744
+ // const {cids, events : bulkSorted } = await findEventsToSync(blocks, head)
37627
37745
  const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head, doFull);
37746
+
37628
37747
  bulkSorted = sorted;
37629
- // console.log('sorted', JSON.stringify(sorted.map(({ value: { data: { key, value } } }) => ({ key, value }))))
37630
- prollyRootNode = await prollyRootFromAncestor(events, ancestor, getBlock);
37631
- // console.log('event', event)
37748
+ // console.log('sorted', !!ancestor, JSON.stringify(sorted.map(({ value: { data: { key, value } } }) => ({ key, value }))))
37749
+ if (ancestor) {
37750
+ prollyRootNode = await prollyRootFromAncestor(events, ancestor, getBlock);
37751
+ // if (!prollyRootNode) {
37752
+ // prollyRootNode = await bigMerge(events, head, getBlock)
37753
+ // // throw new Error('no common ancestor')
37754
+ // }
37755
+ }
37756
+ // console.log('event', event)
37632
37757
  }
37633
37758
  }
37634
37759
 
@@ -37636,16 +37761,23 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
37636
37761
 
37637
37762
  // if prolly root node is null, we need to create a new one
37638
37763
  if (!prollyRootNode) {
37764
+ // console.log('make new root', bulkOperations.length)
37639
37765
  let root;
37766
+ // let rootNode
37640
37767
  const newBlocks = [];
37641
37768
  // if all operations are deletes, we can just return an empty root
37642
37769
  if (bulkOperations.every(op => op.del)) {
37643
37770
  return { root: null, blocks: [], clockCIDs: await events.all() }
37644
37771
  }
37645
37772
  for await (const node of create$3({ get: getBlock, list: bulkOperations, ...blockOpts })) {
37646
- root = await node.block;
37647
- newBlocks.push(root);
37773
+ // root = await node.block
37774
+ root = node;
37775
+ newBlocks.push(await node.block);
37648
37776
  }
37777
+ // throw new Error('not root time')
37778
+ // root.isThisOne = 'yes'
37779
+ // console.log('made new root', root.constructor.name, root.block.cid.toString())
37780
+
37649
37781
  return { root, blocks: newBlocks, clockCIDs: await events.all() }
37650
37782
  } else {
37651
37783
  const writeResp = await prollyRootNode.bulk(bulkOperations); // { root: newProllyRootNode, blocks: newBlocks }
@@ -37665,7 +37797,7 @@ const doProllyBulk = async (inBlocks, head, event, doFull = false) => {
37665
37797
  */
37666
37798
  async function put (inBlocks, head, event, options) {
37667
37799
  const { bigPut } = makeGetAndPutBlock(inBlocks);
37668
-
37800
+ // console.log('major put')
37669
37801
  // If the head is empty, we create a new event and return the root and addition blocks
37670
37802
  if (!head.length) {
37671
37803
  const additions = new Map();
@@ -37697,7 +37829,7 @@ async function put (inBlocks, head, event, options) {
37697
37829
  return createAndSaveNewEvent({
37698
37830
  inBlocks,
37699
37831
  bigPut,
37700
- root: prollyRootBlock,
37832
+ root: newProllyRootNode, // Block
37701
37833
  event,
37702
37834
  head,
37703
37835
  additions: Array.from(additions.values()) /*, todo? Array.from(removals.values()) */
@@ -37716,20 +37848,25 @@ async function root (inBlocks, head, doFull = false) {
37716
37848
  throw new Error('no head')
37717
37849
  }
37718
37850
  // console.log('root', head.map(h => h.toString()))
37719
- const { root: newProllyRootNode, blocks: newBlocks, clockCIDs } = await doProllyBulk(inBlocks, head, null, doFull);
37720
37851
  // todo maybe these should go to a temp blockstore?
37721
- await doTransaction(
37852
+ return await doTransaction(
37722
37853
  'root',
37723
37854
  inBlocks,
37724
37855
  async transactionBlocks => {
37725
37856
  const { bigPut } = makeGetAndPutBlock(transactionBlocks);
37857
+ const { root: newProllyRootNode, blocks: newBlocks, clockCIDs } = await doProllyBulk(inBlocks, head, null, doFull);
37858
+ //
37859
+ // const rootBlock = await newProllyRootNode.block
37860
+ // bigPut(rootBlock)
37726
37861
  for (const nb of newBlocks) {
37727
37862
  bigPut(nb);
37728
37863
  }
37864
+ // console.log('root root', newProllyRootNode.constructor.name, newProllyRootNode)
37865
+ return { clockCIDs, node: newProllyRootNode }
37729
37866
  },
37730
37867
  false
37731
- );
37732
- return { clockCIDs, node: newProllyRootNode }
37868
+ )
37869
+ // return { clockCIDs, node: newProllyRootNode }
37733
37870
  }
37734
37871
 
37735
37872
  /**
@@ -37745,7 +37882,8 @@ async function eventsSince (blocks, head, since) {
37745
37882
  return { clockCIDs: [], result: [] }
37746
37883
  }
37747
37884
  // @ts-ignore
37748
- const sinceHead = [...since, ...head]; // ?
37885
+ const sinceHead = [...since, ...head].map(h => h.toString()); // ?
37886
+ // console.log('eventsSince', sinceHead.map(h => h.toString()))
37749
37887
  const { cids, events: unknownSorted3 } = await findEventsToSync(blocks, sinceHead);
37750
37888
  return { clockCIDs: cids, result: unknownSorted3.map(({ value: { data } }) => data) }
37751
37889
  }
@@ -37782,8 +37920,12 @@ async function rootOrCache (blocks, head, rootCache, doFull = false) {
37782
37920
  clockCIDs = rootCache.clockCIDs;
37783
37921
  } else {
37784
37922
  ({ node, clockCIDs } = await root(blocks, head, doFull));
37923
+
37924
+ // this.applyClock(prevClock, result.head)
37925
+ // await this.notifyListeners([decodedEvent])
37926
+
37785
37927
  // console.timeEnd(callTag + '.root')
37786
- // console.log('found root')
37928
+ // console.log('found root', node.entryList)
37787
37929
  }
37788
37930
  return { node, clockCIDs }
37789
37931
  }
@@ -38151,8 +38293,8 @@ class Database {
38151
38293
  * @memberof Fireproof
38152
38294
  * @instance
38153
38295
  */
38154
- clockToJSON () {
38155
- return this.clock.map(cid => cid.toString())
38296
+ clockToJSON (clock = null) {
38297
+ return (clock || this.clock).map(cid => cid.toString())
38156
38298
  }
38157
38299
 
38158
38300
  hydrate ({ clock, name, key }) {
@@ -38192,21 +38334,21 @@ class Database {
38192
38334
  * @memberof Fireproof
38193
38335
  * @instance
38194
38336
  */
38195
- async changesSince (event) {
38196
- // console.log('events for', this.instanceId, event.constructor.name)
38197
- // console.log('changesSince', this.instanceId, event, this.clock)
38337
+ async changesSince (aClock) {
38338
+ // console.log('events for', this.instanceId, aClock?.constructor.name)
38339
+ // console.log('changesSince', this.instanceId, this.clockToJSON(aClock), this.clockToJSON())
38198
38340
  let rows, dataCIDs, clockCIDs;
38199
- // if (!event) event = []
38200
- if (event) {
38201
- event = event.map((cid) => cid.toString());
38202
- const eventKey = JSON.stringify([...event, ...this.clockToJSON()]);
38341
+ // if (!aClock) aClock = []
38342
+ if (aClock && aClock.length > 0) {
38343
+ aClock = aClock.map((cid) => cid.toString());
38344
+ const eventKey = JSON.stringify([...this.clockToJSON(aClock), ...this.clockToJSON()]);
38203
38345
 
38204
38346
  let resp;
38205
38347
  if (this.eventsCache.has(eventKey)) {
38206
- console.log('events from cache');
38348
+ // console.log('events from cache')
38207
38349
  resp = this.eventsCache.get(eventKey);
38208
38350
  } else {
38209
- resp = await eventsSince(this.blocks, this.clock, event);
38351
+ resp = await eventsSince(this.blocks, this.clock, aClock);
38210
38352
  this.eventsCache.set(eventKey, resp);
38211
38353
  }
38212
38354
  const docsMap = new Map();
@@ -38367,7 +38509,9 @@ class Database {
38367
38509
  */
38368
38510
  async putToProllyTree (decodedEvent, clock = null) {
38369
38511
  const event = encodeEvent(decodedEvent);
38370
- if (clock && JSON.stringify(clock) !== JSON.stringify(this.clockToJSON())) {
38512
+ if (clock && JSON.stringify(this.clockToJSON(clock)) !== JSON.stringify(this.clockToJSON())) {
38513
+ // console.log('this.clock', this.clockToJSON())
38514
+ // console.log('that.clock', this.clockToJSON(clock))
38371
38515
  // we need to check and see what version of the document exists at the clock specified
38372
38516
  // if it is the same as the one we are trying to put, then we can proceed
38373
38517
  const resp = await eventsSince(this.blocks, this.clock, event.value._clock);
@@ -38377,6 +38521,7 @@ class Database {
38377
38521
  }
38378
38522
  }
38379
38523
  const prevClock = [...this.clock];
38524
+ // console.log('putToProllyTree', this.clockToJSON(), decodedEvent)
38380
38525
  const result = await doTransaction(
38381
38526
  'putToProllyTree',
38382
38527
  this.blocks,
@@ -39066,7 +39211,7 @@ class DbIndex {
39066
39211
  );
39067
39212
  this.indexByKey = await bulkIndex(blocks, this.indexByKey, oldIndexEntries.concat(indexEntries), dbIndexOpts);
39068
39213
  this.dbHead = result.clock;
39069
- });
39214
+ }, false /* don't sync transaction -- maybe move this flag to database.indexBlocks? */);
39070
39215
  // todo index subscriptions
39071
39216
  // this.database.notifyExternal('dbIndex')
39072
39217
  // console.timeEnd(callTag + '.doTransactionupdateIndex')
@@ -41021,10 +41166,15 @@ class Sync {
41021
41166
  this.pushBacklogResolve = resolve;
41022
41167
  this.pushBacklogReject = reject;
41023
41168
  });
41169
+ this.isReady = false;
41024
41170
  // this.pushBacklog.then(() => {
41025
41171
  // // console.log('sync backlog resolved')
41026
41172
  // this.database.notifyReset()
41027
41173
  // })
41174
+ // this.connected = new Promise((resolve, reject) => {
41175
+ // this.readyResolve = resolve
41176
+ // this.readyReject = reject
41177
+ // })
41028
41178
  }
41029
41179
 
41030
41180
  async offer () {
@@ -41073,6 +41223,7 @@ class Sync {
41073
41223
  // console.log('not a car', data.toString())
41074
41224
  }
41075
41225
  if (reader) {
41226
+ // console.log('got car')
41076
41227
  this.status = 'parking car';
41077
41228
  const blz = new Set();
41078
41229
  for await (const block of reader.blocks()) {
@@ -41085,7 +41236,7 @@ class Sync {
41085
41236
  // this.database.clock.map(c => c.toString())
41086
41237
  // )
41087
41238
  // console.log(
41088
- // 'got blocks',
41239
+ // 'got blocks!',
41089
41240
  // [...blz].map(({ cid }) => cid.toString())
41090
41241
  // )
41091
41242
  // @ts-ignore
@@ -41126,7 +41277,7 @@ class Sync {
41126
41277
  } else if (message.clock) {
41127
41278
  const reqCidDiff = message;
41128
41279
  // this might be a CID diff
41129
- console.log('got diff', reqCidDiff);
41280
+ // console.log('got diff', reqCidDiff)
41130
41281
  const carBlock = await Sync.makeCar(this.database, null, reqCidDiff.cids);
41131
41282
  if (!carBlock) {
41132
41283
  // we are full synced
@@ -41135,9 +41286,10 @@ class Sync {
41135
41286
  this.peer.send(JSON.stringify({ ok: true }));
41136
41287
  // this.pushBacklogResolve({ ok: true })
41137
41288
  } else {
41138
- // console.log('do send', carBlock.bytes.length)
41289
+ // console.log('do send diff', carBlock.bytes.length)
41139
41290
  this.status = 'sending diff car';
41140
41291
  this.peer.send(carBlock.bytes);
41292
+ // console.log('sent diff car')
41141
41293
  // this.pushBacklogResolve({ ok: true })
41142
41294
  }
41143
41295
  }
@@ -41151,7 +41303,7 @@ class Sync {
41151
41303
  }
41152
41304
 
41153
41305
  async sendUpdate (blockstore) {
41154
- if (!this.peer) return
41306
+ if (!this.peer || !this.isReady) return
41155
41307
  // console.log('send update from', this.database.instanceId)
41156
41308
  // todo should send updates since last sync
41157
41309
  const newCar = await blocksToCarBlock(blockstore.lastCid, blockstore);
@@ -41161,6 +41313,7 @@ class Sync {
41161
41313
 
41162
41314
  async startSync () {
41163
41315
  // console.log('start sync', this.peer.initiator)
41316
+ this.isReady = true;
41164
41317
  const allCIDs = await this.database.allStoredCIDs();
41165
41318
  // console.log('allCIDs', allCIDs)
41166
41319
  const reqCidDiff = {