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