@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.
- package/dist/hooks/use-fireproof.js +2 -1
- package/dist/src/blockstore.js +4 -4
- package/dist/src/clock.js +109 -37
- package/dist/src/crypto.js +1 -1
- package/dist/src/database.js +20 -19
- package/dist/src/db-index.js +6 -6
- package/dist/src/fireproof.d.ts +3 -2
- package/dist/src/fireproof.js +238 -85
- package/dist/src/fireproof.js.map +1 -1
- package/dist/src/fireproof.mjs +238 -85
- package/dist/src/fireproof.mjs.map +1 -1
- package/dist/src/listener.js +2 -3
- package/dist/src/prolly.js +74 -25
- package/dist/src/sha1.js +2 -1
- package/dist/src/sync.js +28 -9
- package/dist/src/valet.js +5 -1
- package/package.json +2 -2
- package/src/blockstore.js +1 -0
- package/src/clock.js +123 -37
- package/src/crypto.js +1 -1
- package/src/database.js +15 -12
- package/src/db-index.js +1 -1
- package/src/prolly.js +82 -24
- package/src/sync.js +12 -4
- package/src/valet.js +5 -5
@@ -29,6 +29,7 @@ const initializeDatabase = name => {
|
|
29
29
|
@function useFireproof
|
30
30
|
React hook to initialize a Fireproof database, automatically saving and loading the clock.
|
31
31
|
You might need to import { nodePolyfills } from 'vite-plugin-node-polyfills' in your vite.config.ts
|
32
|
+
@deprecated - npm install @fireproof/react instead
|
32
33
|
@param {string} name - The path to the database file
|
33
34
|
@param {function(database): void} [defineDatabaseFn] - Synchronous function that defines the database, run this before any async calls
|
34
35
|
@param {function(database): Promise<void>} [setupDatabaseFn] - Asynchronous function that sets up the database, run this to load fixture data etc
|
@@ -42,7 +43,7 @@ export function useFireproof(name = 'useFireproof', defineDatabaseFn = () => { }
|
|
42
43
|
*/
|
43
44
|
const addSubscriber = (label, fn) => {
|
44
45
|
// todo test that the label is not needed
|
45
|
-
return database.
|
46
|
+
return database.registerListener(fn);
|
46
47
|
// inboundSubscriberQueue.set(label, fn)
|
47
48
|
};
|
48
49
|
useEffect(() => {
|
package/dist/src/blockstore.js
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
import { parse } from 'multiformats/link';
|
3
2
|
import { CID } from 'multiformats';
|
4
|
-
import { Valet } from './valet';
|
3
|
+
import { Valet } from './valet.js';
|
5
4
|
// const sleep = ms => new Promise(r => setTimeout(r, ms))
|
6
5
|
const husherMap = new Map();
|
7
6
|
const husher = (id, workFn) => {
|
@@ -150,9 +149,10 @@ export class TransactionBlockstore {
|
|
150
149
|
await this.doCommit(innerBlockstore);
|
151
150
|
if (doSync) {
|
152
151
|
// const all =
|
152
|
+
// console.log('syncing', innerBlockstore.label)
|
153
153
|
await Promise.all([...this.syncs].map(async (sync) => sync.sendUpdate(innerBlockstore).catch(e => {
|
154
|
-
console.error('sync error', e);
|
155
|
-
|
154
|
+
console.error('sync error, cancelling', e);
|
155
|
+
sync.destroy();
|
156
156
|
})));
|
157
157
|
}
|
158
158
|
}
|
package/dist/src/clock.js
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
// @ts-nocheck
|
2
1
|
import { Block, encode, decode } from 'multiformats/block';
|
3
2
|
import { sha256 } from 'multiformats/hashes/sha2';
|
4
3
|
import * as cbor from '@ipld/dag-cbor';
|
@@ -18,17 +17,17 @@ import { CIDCounter } from 'prolly-trees/utils';
|
|
18
17
|
*/
|
19
18
|
/**
|
20
19
|
* @typedef {{
|
21
|
-
* type: 'put'|'del'
|
22
|
-
* key: string
|
23
|
-
* value: import('./link').AnyLink
|
24
|
-
* root: import('./link').AnyLink
|
25
|
-
* }} EventData
|
26
|
-
* @typedef {{
|
27
|
-
* root: import('./link').AnyLink
|
28
|
-
* head: import('./clock').EventLink<EventData>[]
|
29
|
-
* event: import('./clock').EventBlockView<EventData>
|
30
|
-
* }} Result
|
31
|
-
*/
|
20
|
+
* type: 'put'|'del'
|
21
|
+
* key: string
|
22
|
+
* value: import('./link').AnyLink
|
23
|
+
* root: import('./link').AnyLink
|
24
|
+
* }} EventData
|
25
|
+
* @typedef {{
|
26
|
+
* root: import('./link').AnyLink
|
27
|
+
* head: import('./clock').EventLink<EventData>[]
|
28
|
+
* event: import('./clock').EventBlockView<EventData>
|
29
|
+
* }} Result
|
30
|
+
*/
|
32
31
|
/**
|
33
32
|
* Advance the clock by adding an event.
|
34
33
|
*
|
@@ -41,7 +40,7 @@ import { CIDCounter } from 'prolly-trees/utils';
|
|
41
40
|
export async function advance(blocks, head, event) {
|
42
41
|
/** @type {EventFetcher<T>} */
|
43
42
|
const events = new EventFetcher(blocks);
|
44
|
-
const headmap = new Map(head.map(
|
43
|
+
const headmap = new Map(head.map(cid => [cid.toString(), cid]));
|
45
44
|
// Check if the headmap already includes the event, return head if it does
|
46
45
|
if (headmap.has(event.toString()))
|
47
46
|
return { head, cids: await events.all() };
|
@@ -154,7 +153,9 @@ async function contains(events, a, b) {
|
|
154
153
|
if (a.toString() === b.toString())
|
155
154
|
return true;
|
156
155
|
const [{ value: aevent }, { value: bevent }] = await Promise.all([events.get(a), events.get(b)]);
|
157
|
-
const links = [...aevent.parents]
|
156
|
+
// const links = [...aevent.parents]
|
157
|
+
// console.log('aevent', aevent.parents)
|
158
|
+
const links = [...(aevent.parents || [])];
|
158
159
|
while (links.length) {
|
159
160
|
const link = links.shift();
|
160
161
|
if (!link)
|
@@ -163,7 +164,7 @@ async function contains(events, a, b) {
|
|
163
164
|
return true;
|
164
165
|
// if any of b's parents are this link, then b cannot exist in any of the
|
165
166
|
// tree below, since that would create a cycle.
|
166
|
-
if (bevent.parents.some(
|
167
|
+
if (bevent.parents.some(p => link.toString() === p.toString()))
|
167
168
|
continue;
|
168
169
|
const { value: event } = await events.get(link);
|
169
170
|
links.push(...event.parents);
|
@@ -179,15 +180,16 @@ async function contains(events, a, b) {
|
|
179
180
|
*/
|
180
181
|
export async function* vis(blocks, head, options = {}) {
|
181
182
|
// @ts-ignore
|
182
|
-
const renderNodeLabel = options.renderNodeLabel ??
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
183
|
+
const renderNodeLabel = options.renderNodeLabel ??
|
184
|
+
(b => {
|
185
|
+
// @ts-ignore
|
186
|
+
const { key, root, type } = b.value.data;
|
187
|
+
return (b.cid.toString() + '\n' + JSON.stringify({ key, root: root.cid.toString(), type }, null, 2).replace(/"/g, "'"));
|
188
|
+
});
|
187
189
|
const events = new EventFetcher(blocks);
|
188
190
|
yield 'digraph clock {';
|
189
191
|
yield ' node [shape=point fontname="Courier"]; head;';
|
190
|
-
const hevents = await Promise.all(head.map(
|
192
|
+
const hevents = await Promise.all(head.map(link => events.get(link)));
|
191
193
|
const links = [];
|
192
194
|
const nodes = new Set();
|
193
195
|
for (const e of hevents) {
|
@@ -221,14 +223,14 @@ export async function findEventsToSync(blocks, head) {
|
|
221
223
|
// console.time(callTag + '.findCommonAncestorWithSortedEvents')
|
222
224
|
const { ancestor, sorted } = await findCommonAncestorWithSortedEvents(events, head);
|
223
225
|
// console.timeEnd(callTag + '.findCommonAncestorWithSortedEvents')
|
224
|
-
// console.log('sorted', sorted.length)
|
226
|
+
// console.log('sorted', !!ancestor, sorted.length)
|
225
227
|
// console.time(callTag + '.contains')
|
226
|
-
const toSync = await asyncFilter(sorted, async (uks) => !(await contains(events, ancestor, uks.cid)));
|
228
|
+
const toSync = ancestor ? await asyncFilter(sorted, async (uks) => !(await contains(events, ancestor, uks.cid))) : sorted;
|
227
229
|
// console.timeEnd(callTag + '.contains')
|
228
|
-
|
230
|
+
console.log('toSync', !!ancestor, sorted.length - toSync.length);
|
229
231
|
return { cids: events, events: toSync };
|
230
232
|
}
|
231
|
-
const asyncFilter = async (arr, predicate) => Promise.all(arr.map(predicate)).then(
|
233
|
+
const asyncFilter = async (arr, predicate) => Promise.all(arr.map(predicate)).then(results => arr.filter((_v, index) => results[index]));
|
232
234
|
export async function findCommonAncestorWithSortedEvents(events, children, doFull = false) {
|
233
235
|
// console.trace('findCommonAncestorWithSortedEvents')
|
234
236
|
// const callTag = Math.random().toString(36).substring(7)
|
@@ -238,12 +240,16 @@ export async function findCommonAncestorWithSortedEvents(events, children, doFul
|
|
238
240
|
// console.timeEnd(callTag + '.findCommonAncestor')
|
239
241
|
// console.log('ancestor', ancestor.toString())
|
240
242
|
if (!ancestor) {
|
241
|
-
|
243
|
+
console.log('no common ancestor', children);
|
244
|
+
// throw new Error('no common ancestor')
|
245
|
+
const sorted = await findSortedEvents(events, children, children, doFull);
|
246
|
+
return { ancestor: null, sorted };
|
242
247
|
}
|
243
248
|
// console.time(callTag + '.findSortedEvents')
|
244
|
-
const sorted = await findSortedEvents(events, children, ancestor, doFull);
|
249
|
+
const sorted = await findSortedEvents(events, children, [ancestor], doFull);
|
245
250
|
// console.timeEnd(callTag + '.findSortedEvents')
|
246
251
|
// console.log('sorted', sorted.length)
|
252
|
+
// console.log('ancestor', JSON.stringify(ancestor, null, 2))
|
247
253
|
return { ancestor, sorted };
|
248
254
|
}
|
249
255
|
/**
|
@@ -253,20 +259,53 @@ export async function findCommonAncestorWithSortedEvents(events, children, doFul
|
|
253
259
|
* @param {import('./clock').EventFetcher} events
|
254
260
|
* @param {import('./clock').EventLink<EventData>[]} children
|
255
261
|
*/
|
262
|
+
// async function NEWfindCommonAncestor (events, children) {
|
263
|
+
// if (!children.length) return
|
264
|
+
// if (children.length === 1) return children[0]
|
265
|
+
// const candidates = children.map(c => [c])
|
266
|
+
// const visited = new Set()
|
267
|
+
// while (true) {
|
268
|
+
// let changed = false
|
269
|
+
// for (const c of candidates) {
|
270
|
+
// const candidate = await findAncestorCandidate(events, c[c.length - 1])
|
271
|
+
// if (!candidate) continue
|
272
|
+
// if (visited.has(candidate)) {
|
273
|
+
// return candidate // Common ancestor found
|
274
|
+
// }
|
275
|
+
// visited.add(candidate)
|
276
|
+
// changed = true
|
277
|
+
// c.push(candidate)
|
278
|
+
// }
|
279
|
+
// if (!changed) {
|
280
|
+
// // No common ancestor found, exhausted candidates
|
281
|
+
// return null
|
282
|
+
// }
|
283
|
+
// }
|
284
|
+
// }
|
256
285
|
async function findCommonAncestor(events, children) {
|
257
286
|
if (!children.length)
|
258
287
|
return;
|
288
|
+
children = [...new Set(children)];
|
259
289
|
if (children.length === 1)
|
260
290
|
return children[0];
|
261
291
|
const candidates = children.map((c) => [c]);
|
292
|
+
// console.log(
|
293
|
+
// 'og candidates',
|
294
|
+
// candidates.map((c) => c.toString())
|
295
|
+
// )
|
262
296
|
while (true) {
|
263
297
|
let changed = false;
|
264
298
|
for (const c of candidates) {
|
265
299
|
const candidate = await findAncestorCandidate(events, c[c.length - 1]);
|
266
300
|
if (!candidate)
|
267
301
|
continue;
|
302
|
+
// Check if the candidate is already in the list, and if so, skip it.
|
303
|
+
if (c.includes(candidate))
|
304
|
+
continue;
|
305
|
+
// if set size is all cids, then no common ancestor
|
268
306
|
changed = true;
|
269
|
-
c.push(candidate);
|
307
|
+
c.push(candidate); // make set?
|
308
|
+
// console.log('candidate', candidates.map((c) => c.toString()))
|
270
309
|
const ancestor = findCommonString(candidates);
|
271
310
|
if (ancestor)
|
272
311
|
return ancestor;
|
@@ -275,12 +314,44 @@ async function findCommonAncestor(events, children) {
|
|
275
314
|
return;
|
276
315
|
}
|
277
316
|
}
|
317
|
+
// async function OGfindCommonAncestor (events, children) {
|
318
|
+
// if (!children.length) return
|
319
|
+
// if (children.length === 1) return children[0]
|
320
|
+
// const candidates = children.map(c => [c])
|
321
|
+
// console.log(
|
322
|
+
// 'og candidates',
|
323
|
+
// candidates.map(c => c.toString())
|
324
|
+
// )
|
325
|
+
// while (true) {
|
326
|
+
// let changed = false
|
327
|
+
// for (const c of candidates) {
|
328
|
+
// const candidate = await findAncestorCandidate(events, c[c.length - 1])
|
329
|
+
// if (!candidate) continue
|
330
|
+
// // if set size is all cids, then no common ancestor
|
331
|
+
// changed = true
|
332
|
+
// c.push(candidate) // make set?
|
333
|
+
// console.log(
|
334
|
+
// 'candidate',
|
335
|
+
// candidates.map(c => c.toString())
|
336
|
+
// )
|
337
|
+
// const ancestor = findCommonString(candidates)
|
338
|
+
// if (ancestor) return ancestor
|
339
|
+
// }
|
340
|
+
// if (!changed) return
|
341
|
+
// }
|
342
|
+
// }
|
278
343
|
/**
|
279
344
|
* @param {import('./clock').EventFetcher} events
|
280
345
|
* @param {import('./clock').EventLink<EventData>} root
|
281
346
|
*/
|
282
347
|
async function findAncestorCandidate(events, root) {
|
283
348
|
const { value: event } = await events.get(root); // .catch(() => ({ value: { parents: [] } }))
|
349
|
+
// console.log(
|
350
|
+
// 'findAncestorCandidate',
|
351
|
+
// root.toString(),
|
352
|
+
// 'parents',
|
353
|
+
// event.parents.map(p => p.toString())
|
354
|
+
// )
|
284
355
|
if (!event.parents.length)
|
285
356
|
return root;
|
286
357
|
return event.parents.length === 1 ? event.parents[0] : findCommonAncestor(events, event.parents);
|
@@ -291,14 +362,14 @@ async function findAncestorCandidate(events, root) {
|
|
291
362
|
*/
|
292
363
|
function findCommonString(arrays) {
|
293
364
|
// console.log('findCommonString', arrays.map((a) => a.map((i) => String(i))))
|
294
|
-
arrays = arrays.map(
|
365
|
+
arrays = arrays.map(a => [...a]);
|
295
366
|
for (const arr of arrays) {
|
296
367
|
for (const item of arr) {
|
297
368
|
let matched = true;
|
298
369
|
for (const other of arrays) {
|
299
370
|
if (arr === other)
|
300
371
|
continue;
|
301
|
-
matched = other.some(
|
372
|
+
matched = other.some(i => String(i) === String(item));
|
302
373
|
if (!matched)
|
303
374
|
break;
|
304
375
|
}
|
@@ -311,17 +382,17 @@ function findCommonString(arrays) {
|
|
311
382
|
* Find and sort events between the head(s) and the tail.
|
312
383
|
* @param {import('./clock').EventFetcher} events
|
313
384
|
* @param {any[]} head
|
314
|
-
* @param {import('./clock').EventLink<EventData>}
|
385
|
+
* @param {import('./clock').EventLink<EventData>[]} tails
|
315
386
|
*/
|
316
|
-
async function findSortedEvents(events, head,
|
387
|
+
async function findSortedEvents(events, head, tails, doFull) {
|
317
388
|
// const callTag = Math.random().toString(36).substring(7)
|
318
389
|
// get weighted events - heavier events happened first
|
319
390
|
// const callTag = Math.random().toString(36).substring(7)
|
320
391
|
/** @type {Map<string, { event: import('./clock').EventBlockView<EventData>, weight: number }>} */
|
321
392
|
const weights = new Map();
|
322
|
-
head = [...new Set([...head.map(
|
393
|
+
head = [...new Set([...head.map(h => h.toString())])];
|
323
394
|
// console.log(callTag + '.head', head.length)
|
324
|
-
const allEvents = new Set([
|
395
|
+
const allEvents = new Set([tails.map((t) => t.toString()).toString(), ...head]);
|
325
396
|
if (!doFull && allEvents.size === 1) {
|
326
397
|
// console.log('head contains tail', tail.toString())
|
327
398
|
return [];
|
@@ -331,7 +402,8 @@ async function findSortedEvents(events, head, tail, doFull) {
|
|
331
402
|
// console.log('finding events')
|
332
403
|
// console.log(callTag + '.head', head.length, [...head.map((h) => h.toString())], tail.toString())
|
333
404
|
// console.time(callTag + '.findEvents')
|
334
|
-
const all = await Promise.all(
|
405
|
+
const all = await (await Promise.all(tails.map((t) => Promise.all(head.map(h => findEvents(events, h, t)))))).flat();
|
406
|
+
// console.log('all', all.length)
|
335
407
|
// console.timeEnd(callTag + '.findEvents')
|
336
408
|
for (const arr of all) {
|
337
409
|
for (const { event, depth } of arr) {
|
@@ -377,9 +449,9 @@ async function findEvents(events, start, end, depth = 0) {
|
|
377
449
|
const acc = [{ event, depth }];
|
378
450
|
const { parents } = event.value;
|
379
451
|
// if (parents.length === 1 && String(parents[0]) === send) return acc
|
380
|
-
if (parents.findIndex(
|
452
|
+
if (parents.findIndex(p => String(p) === send) !== -1)
|
381
453
|
return acc;
|
382
454
|
// if (parents.length === 1) return acc
|
383
|
-
const rest = await Promise.all(parents.map(
|
455
|
+
const rest = await Promise.all(parents.map(p => findEvents(events, p, end, depth + 1)));
|
384
456
|
return acc.concat(...rest);
|
385
457
|
}
|
package/dist/src/crypto.js
CHANGED
@@ -42,7 +42,7 @@ const decrypt = async function* ({ root, get, key, cache, chunker, hasher }) {
|
|
42
42
|
const { result: nodes } = await cidset.getAllEntries();
|
43
43
|
const unwrap = async (eblock) => {
|
44
44
|
const { bytes, cid } = await codec.decrypt({ ...eblock, key }).catch(e => {
|
45
|
-
console.log('ekey', e)
|
45
|
+
// console.log('ekey', e)
|
46
46
|
throw new Error('bad key: ' + key.toString('hex'));
|
47
47
|
});
|
48
48
|
const block = await createBlock(bytes, cid);
|
package/dist/src/database.js
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
// @ts-nocheck
|
2
|
-
import { visMerkleClock, visMerkleTree, vis, put, get, getAll, eventsSince } from './prolly';
|
3
|
-
import { doTransaction } from './blockstore';
|
2
|
+
import { visMerkleClock, visMerkleTree, vis, put, get, getAll, eventsSince } from './prolly.js';
|
3
|
+
import { doTransaction } from './blockstore.js';
|
4
4
|
import charwise from 'charwise';
|
5
|
-
import { localSet } from './utils';
|
5
|
+
import { localSet } from './utils.js';
|
6
6
|
import { CID } from 'multiformats';
|
7
7
|
// TypeScript Types
|
8
8
|
// eslint-disable-next-line no-unused-vars
|
9
|
-
// import { CID } from 'multiformats/dist/types/src/cid'
|
9
|
+
// import { CID } from 'multiformats/dist/types/src/cid.js'
|
10
10
|
// eslint-disable-next-line no-unused-vars
|
11
11
|
class Proof {
|
12
12
|
}
|
@@ -17,7 +17,7 @@ export const parseCID = cid => (typeof cid === 'string' ? CID.parse(cid) : cid);
|
|
17
17
|
* This is the main class for saving and loading JSON and other documents with the database. You can find additional examples and
|
18
18
|
* usage guides in the repository README.
|
19
19
|
*
|
20
|
-
* @param {import('./blockstore').TransactionBlockstore} blocks - The block storage instance to use documents and indexes
|
20
|
+
* @param {import('./blockstore.js').TransactionBlockstore} blocks - The block storage instance to use documents and indexes
|
21
21
|
* @param {CID[]} clock - The Merkle clock head to use for the Fireproof instance.
|
22
22
|
* @param {object} [config] - Optional configuration options for the Fireproof instance.
|
23
23
|
* @param {object} [authCtx] - Optional authorization context object to use for any authentication checks.
|
@@ -28,8 +28,6 @@ export class Database {
|
|
28
28
|
indexes = new Map();
|
29
29
|
rootCache = null;
|
30
30
|
eventsCache = new Map();
|
31
|
-
blocks;
|
32
|
-
clock;
|
33
31
|
constructor(blocks, clock, config = {}) {
|
34
32
|
this.name = config.name;
|
35
33
|
this.instanceId = `fp.${this.name}.${Math.random().toString(36).substring(2, 7)}`;
|
@@ -58,8 +56,8 @@ export class Database {
|
|
58
56
|
* @memberof Fireproof
|
59
57
|
* @instance
|
60
58
|
*/
|
61
|
-
clockToJSON() {
|
62
|
-
return this.clock.map(cid => cid.toString());
|
59
|
+
clockToJSON(clock = null) {
|
60
|
+
return (clock || this.clock).map(cid => cid.toString());
|
63
61
|
}
|
64
62
|
hydrate({ clock, name, key }) {
|
65
63
|
this.name = name;
|
@@ -94,21 +92,21 @@ export class Database {
|
|
94
92
|
* @memberof Fireproof
|
95
93
|
* @instance
|
96
94
|
*/
|
97
|
-
async changesSince(
|
98
|
-
// console.log('events for', this.instanceId,
|
99
|
-
// console.log('changesSince', this.instanceId,
|
95
|
+
async changesSince(aClock) {
|
96
|
+
// console.log('events for', this.instanceId, aClock?.constructor.name)
|
97
|
+
// console.log('changesSince', this.instanceId, this.clockToJSON(aClock), this.clockToJSON())
|
100
98
|
let rows, dataCIDs, clockCIDs;
|
101
|
-
// if (!
|
102
|
-
if (
|
103
|
-
|
104
|
-
const eventKey = JSON.stringify([...
|
99
|
+
// if (!aClock) aClock = []
|
100
|
+
if (aClock && aClock.length > 0) {
|
101
|
+
aClock = aClock.map((cid) => cid.toString());
|
102
|
+
const eventKey = JSON.stringify([...this.clockToJSON(aClock), ...this.clockToJSON()]);
|
105
103
|
let resp;
|
106
104
|
if (this.eventsCache.has(eventKey)) {
|
107
|
-
console.log('events from cache')
|
105
|
+
// console.log('events from cache')
|
108
106
|
resp = this.eventsCache.get(eventKey);
|
109
107
|
}
|
110
108
|
else {
|
111
|
-
resp = await eventsSince(this.blocks, this.clock,
|
109
|
+
resp = await eventsSince(this.blocks, this.clock, aClock);
|
112
110
|
this.eventsCache.set(eventKey, resp);
|
113
111
|
}
|
114
112
|
const docsMap = new Map();
|
@@ -262,7 +260,9 @@ export class Database {
|
|
262
260
|
*/
|
263
261
|
async putToProllyTree(decodedEvent, clock = null) {
|
264
262
|
const event = encodeEvent(decodedEvent);
|
265
|
-
if (clock && JSON.stringify(clock) !== JSON.stringify(this.clockToJSON())) {
|
263
|
+
if (clock && JSON.stringify(this.clockToJSON(clock)) !== JSON.stringify(this.clockToJSON())) {
|
264
|
+
// console.log('this.clock', this.clockToJSON())
|
265
|
+
// console.log('that.clock', this.clockToJSON(clock))
|
266
266
|
// we need to check and see what version of the document exists at the clock specified
|
267
267
|
// if it is the same as the one we are trying to put, then we can proceed
|
268
268
|
const resp = await eventsSince(this.blocks, this.clock, event.value._clock);
|
@@ -272,6 +272,7 @@ export class Database {
|
|
272
272
|
}
|
273
273
|
}
|
274
274
|
const prevClock = [...this.clock];
|
275
|
+
// console.log('putToProllyTree', this.clockToJSON(), decodedEvent)
|
275
276
|
const result = await doTransaction('putToProllyTree', this.blocks, async (blocks) => await put(blocks, this.clock, event));
|
276
277
|
if (!result) {
|
277
278
|
console.error('failed', event);
|
package/dist/src/db-index.js
CHANGED
@@ -8,7 +8,7 @@ import { nocache as cache } from 'prolly-trees/cache';
|
|
8
8
|
import { bf, simpleCompare } from 'prolly-trees/utils';
|
9
9
|
import { makeGetBlock, visMerkleTree } from './prolly.js';
|
10
10
|
// eslint-disable-next-line no-unused-vars
|
11
|
-
import { cidsToProof } from './database.js';
|
11
|
+
import { Database, cidsToProof } from './database.js';
|
12
12
|
import * as codec from '@ipld/dag-cbor';
|
13
13
|
// import { create as createBlock } from 'multiformats/block'
|
14
14
|
import { TransactionBlockstore, doTransaction } from './blockstore.js';
|
@@ -143,7 +143,7 @@ export class DbIndex {
|
|
143
143
|
if (matches.length === 0) {
|
144
144
|
matches = /=>\s*(.*)/.exec(this.mapFnString);
|
145
145
|
}
|
146
|
-
if (matches
|
146
|
+
if (matches === null) {
|
147
147
|
return this.mapFnString;
|
148
148
|
}
|
149
149
|
else {
|
@@ -200,7 +200,7 @@ export class DbIndex {
|
|
200
200
|
/**
|
201
201
|
* Query object can have {range}
|
202
202
|
* @param {DbQuery} query - the query range to use
|
203
|
-
* @returns {Promise<{proof: {}, rows: Array<{id: string, key: string, value: any}>}>}
|
203
|
+
* @returns {Promise<{proof: {}, rows: Array<{id: string, key: string, value: any, doc?: any}>}>}
|
204
204
|
* @memberof DbIndex
|
205
205
|
* @instance
|
206
206
|
*/
|
@@ -282,8 +282,8 @@ export class DbIndex {
|
|
282
282
|
return this.updateIndexPromise;
|
283
283
|
}
|
284
284
|
async innerUpdateIndex(inBlocks) {
|
285
|
-
const callTag = Math.random().toString(36).substring(4)
|
286
|
-
console.log(`updateIndex ${callTag} >`, this.instanceId, this.dbHead?.toString(), this.indexByKey.cid?.toString(), this.indexById.cid?.toString())
|
285
|
+
// const callTag = Math.random().toString(36).substring(4)
|
286
|
+
// console.log(`updateIndex ${callTag} >`, this.instanceId, this.dbHead?.toString(), this.indexByKey.cid?.toString(), this.indexById.cid?.toString())
|
287
287
|
// todo remove this hack
|
288
288
|
if (ALWAYS_REBUILD) {
|
289
289
|
this.indexById = { root: null, cid: null };
|
@@ -322,7 +322,7 @@ export class DbIndex {
|
|
322
322
|
this.indexById = await bulkIndex(blocks, this.indexById, removeByIdIndexEntries.concat(byIdIndexEntries), idIndexOpts);
|
323
323
|
this.indexByKey = await bulkIndex(blocks, this.indexByKey, oldIndexEntries.concat(indexEntries), dbIndexOpts);
|
324
324
|
this.dbHead = result.clock;
|
325
|
-
});
|
325
|
+
}, false /* don't sync transaction -- maybe move this flag to database.indexBlocks? */);
|
326
326
|
// todo index subscriptions
|
327
327
|
// this.database.notifyExternal('dbIndex')
|
328
328
|
// console.timeEnd(callTag + '.doTransactionupdateIndex')
|
package/dist/src/fireproof.d.ts
CHANGED
@@ -37,7 +37,7 @@ declare class Database {
|
|
37
37
|
* @memberof Fireproof
|
38
38
|
* @instance
|
39
39
|
*/
|
40
|
-
clockToJSON(): string[];
|
40
|
+
clockToJSON(clock?: any): string[];
|
41
41
|
hydrate({ clock, name, key }: {
|
42
42
|
clock: any;
|
43
43
|
name: any;
|
@@ -61,7 +61,7 @@ declare class Database {
|
|
61
61
|
* @memberof Fireproof
|
62
62
|
* @instance
|
63
63
|
*/
|
64
|
-
changesSince(
|
64
|
+
changesSince(aClock: any): Promise<{
|
65
65
|
rows: any[];
|
66
66
|
clock: CID[];
|
67
67
|
proof: {};
|
@@ -382,6 +382,7 @@ declare class Sync {
|
|
382
382
|
pushBacklog: Promise<any>;
|
383
383
|
pushBacklogResolve: (value: any) => void;
|
384
384
|
pushBacklogReject: (reason?: any) => void;
|
385
|
+
isReady: boolean;
|
385
386
|
offer(): Promise<string>;
|
386
387
|
accept(base64offer: any): Promise<string>;
|
387
388
|
connect(base64accept: any): void;
|