@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.
- package/dist/hooks/use-fireproof.js +149 -0
- package/dist/src/blockstore.js +259 -0
- package/dist/src/clock.js +385 -0
- package/dist/src/crypto.js +59 -0
- package/dist/src/database.js +379 -0
- package/dist/src/db-index.js +387 -0
- package/dist/src/fireproof.d.ts +25 -5
- package/dist/src/fireproof.js +131 -52
- package/dist/src/fireproof.js.map +1 -1
- package/dist/src/fireproof.mjs +131 -52
- package/dist/src/fireproof.mjs.map +1 -1
- package/dist/src/link.js +1 -0
- package/dist/src/listener.js +112 -0
- package/dist/src/prolly.js +360 -0
- package/dist/src/sha1.js +73 -0
- package/dist/src/sync.js +198 -0
- package/dist/src/utils.js +16 -0
- package/dist/src/valet.js +291 -0
- package/hooks/use-fireproof.js +77 -14
- package/package.json +2 -1
- package/src/database.js +15 -4
- package/src/db-index.js +107 -44
- package/src/fireproof.js +2 -2
- package/src/listener.js +3 -1
- package/src/sync.js +5 -1
package/dist/src/fireproof.js
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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
|
-
|
38859
|
-
|
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) {
|
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
|
-
|
38881
|
-
|
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) {
|
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(
|
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
|
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(() => {
|
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
|
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(
|
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(
|
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(
|
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
|
-
|
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
|
-
|
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
|
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 =
|
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
|
});
|