@fireproof/core 0.4.1 → 0.5.0
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/README.md +20 -22
- package/dist/src/fireproof.d.ts +20 -15
- package/dist/src/fireproof.js +97 -28
- package/dist/src/fireproof.js.map +1 -1
- package/dist/src/fireproof.mjs +97 -29
- package/dist/src/fireproof.mjs.map +1 -1
- package/package.json +2 -2
- package/src/database.js +31 -14
- package/src/db-index.js +19 -9
- package/src/fireproof.js +45 -5
- package/src/prolly.js +2 -1
- package/src/valet.js +3 -2
package/dist/src/fireproof.mjs
CHANGED
@@ -37116,6 +37116,7 @@ const blocksToCarBlock = async (lastCid, blocks) => {
|
|
37116
37116
|
blocks = Array.from(blocks.entries());
|
37117
37117
|
}
|
37118
37118
|
for (const { cid, bytes } of blocks) {
|
37119
|
+
// console.log(cid, bytes)
|
37119
37120
|
size += blockLength({ cid, bytes });
|
37120
37121
|
}
|
37121
37122
|
const buffer = new Uint8Array(size);
|
@@ -37695,7 +37696,8 @@ async function root (inBlocks, head) {
|
|
37695
37696
|
*/
|
37696
37697
|
async function eventsSince (blocks, head, since) {
|
37697
37698
|
if (!head.length) {
|
37698
|
-
throw new Error('no head')
|
37699
|
+
// throw new Error('no head')
|
37700
|
+
return { clockCIDs: [], result: [] }
|
37699
37701
|
}
|
37700
37702
|
// @ts-ignore
|
37701
37703
|
const sinceHead = [...since, ...head]; // ?
|
@@ -38133,7 +38135,7 @@ class Database {
|
|
38133
38135
|
// console.log('change rows', this.instanceId, rows)
|
38134
38136
|
} else {
|
38135
38137
|
const allResp = await getAll(this.blocks, this.clock);
|
38136
|
-
rows = allResp.result.map(({ key, value }) =>
|
38138
|
+
rows = allResp.result.map(({ key, value }) => decodeEvent({ key, value }));
|
38137
38139
|
dataCIDs = allResp.cids;
|
38138
38140
|
// console.log('dbdoc rows', this.instanceId, rows)
|
38139
38141
|
}
|
@@ -38146,7 +38148,9 @@ class Database {
|
|
38146
38148
|
|
38147
38149
|
async allDocuments () {
|
38148
38150
|
const allResp = await getAll(this.blocks, this.clock);
|
38149
|
-
const rows = allResp.result
|
38151
|
+
const rows = allResp.result
|
38152
|
+
.map(({ key, value }) => decodeEvent({ key, value }))
|
38153
|
+
.map(({ key, value }) => ({ key, value: { _id: key, ...value } }));
|
38150
38154
|
return {
|
38151
38155
|
rows,
|
38152
38156
|
clock: this.clockToJSON(),
|
@@ -38154,6 +38158,15 @@ class Database {
|
|
38154
38158
|
}
|
38155
38159
|
}
|
38156
38160
|
|
38161
|
+
async allCIDs () {
|
38162
|
+
const allResp = await getAll(this.blocks, this.clock);
|
38163
|
+
const cids = await cidsToProof(allResp.cids);
|
38164
|
+
const clockCids = await cidsToProof(allResp.clockCIDs);
|
38165
|
+
// console.log('allcids', cids, clockCids)
|
38166
|
+
// todo we need to put the clock head as the last block in the encrypted car
|
38167
|
+
return [...cids, ...clockCids] // need a single block version of clock head, maybe an encoded block for it
|
38168
|
+
}
|
38169
|
+
|
38157
38170
|
/**
|
38158
38171
|
* Runs validation on the specified document using the Fireproof instance's configuration. Throws an error if the document is invalid.
|
38159
38172
|
*
|
@@ -38166,7 +38179,7 @@ class Database {
|
|
38166
38179
|
async runValidation (doc) {
|
38167
38180
|
if (this.config && this.config.validateChange) {
|
38168
38181
|
const oldDoc = await this.get(doc._id)
|
38169
|
-
.then(
|
38182
|
+
.then(doc => doc)
|
38170
38183
|
.catch(() => ({}));
|
38171
38184
|
this.config.validateChange(doc, oldDoc, this.authCtx);
|
38172
38185
|
}
|
@@ -38201,13 +38214,13 @@ class Database {
|
|
38201
38214
|
return doc
|
38202
38215
|
}
|
38203
38216
|
/**
|
38204
|
-
|
38205
|
-
|
38206
|
-
|
38207
|
-
|
38208
|
-
|
38209
|
-
|
38210
|
-
|
38217
|
+
* @typedef {Object} Document
|
38218
|
+
* @property {string} _id - The ID of the document (required)
|
38219
|
+
* @property {string} [_proof] - The proof of the document (optional)
|
38220
|
+
* @property {string} [_clock] - The clock of the document (optional)
|
38221
|
+
* @property {any} [key: string] - Index signature notation to allow any other unknown fields
|
38222
|
+
* * @property {Object.<string, any>} [otherProperties] - Any other unknown properties (optional)
|
38223
|
+
*/
|
38211
38224
|
|
38212
38225
|
/**
|
38213
38226
|
* Adds a new document to the database, or updates an existing document. Returns the ID of the document and the new clock head.
|
@@ -38262,17 +38275,17 @@ class Database {
|
|
38262
38275
|
throw new Error('MVCC conflict, document is changed, please reload the document and try again.')
|
38263
38276
|
}
|
38264
38277
|
}
|
38278
|
+
const prevClock = [...this.clock];
|
38265
38279
|
const result = await doTransaction(
|
38266
38280
|
'putToProllyTree',
|
38267
38281
|
this.blocks,
|
38268
|
-
async
|
38282
|
+
async blocks => await put(blocks, this.clock, event)
|
38269
38283
|
);
|
38270
38284
|
if (!result) {
|
38271
38285
|
console.error('failed', event);
|
38272
38286
|
throw new Error('failed to put at storage layer')
|
38273
38287
|
}
|
38274
|
-
|
38275
|
-
this.clock = result.head; // do we want to do this as a finally block
|
38288
|
+
this.applyClock(prevClock, result.head);
|
38276
38289
|
await this.notifyListeners([decodedEvent]); // this type is odd
|
38277
38290
|
return {
|
38278
38291
|
id: decodedEvent.key,
|
@@ -38282,6 +38295,12 @@ class Database {
|
|
38282
38295
|
// todo should include additions (or split clock)
|
38283
38296
|
}
|
38284
38297
|
|
38298
|
+
applyClock (prevClock, newClock) {
|
38299
|
+
// console.log('applyClock', prevClock, newClock, this.clock)
|
38300
|
+
const removedprevCIDs = this.clock.filter(cid => prevClock.indexOf(cid) === -1);
|
38301
|
+
this.clock = removedprevCIDs.concat(newClock);
|
38302
|
+
}
|
38303
|
+
|
38285
38304
|
// /**
|
38286
38305
|
// * Advances the clock to the specified event and updates the root CID
|
38287
38306
|
// * Will be used by replication
|
@@ -38340,7 +38359,7 @@ class Database {
|
|
38340
38359
|
async function cidsToProof (cids) {
|
38341
38360
|
if (!cids || !cids.all) return []
|
38342
38361
|
const all = await cids.all();
|
38343
|
-
return [...all].map(
|
38362
|
+
return [...all].map(cid => cid.toString())
|
38344
38363
|
}
|
38345
38364
|
|
38346
38365
|
function decodeEvent (event) {
|
@@ -38650,10 +38669,10 @@ const indexEntriesForChanges = (changes, mapFn) => {
|
|
38650
38669
|
changes.forEach(({ key, value, del }) => {
|
38651
38670
|
if (del || !value) return
|
38652
38671
|
mapFn(makeDoc({ key, value }), (k, v) => {
|
38653
|
-
if (typeof
|
38672
|
+
if (typeof k === 'undefined') return
|
38654
38673
|
indexEntries.push({
|
38655
38674
|
key: [charwise.encode(k), key],
|
38656
|
-
value: v
|
38675
|
+
value: v || null
|
38657
38676
|
});
|
38658
38677
|
});
|
38659
38678
|
});
|
@@ -38671,7 +38690,7 @@ const indexEntriesForChanges = (changes, mapFn) => {
|
|
38671
38690
|
*
|
38672
38691
|
*/
|
38673
38692
|
class DbIndex {
|
38674
|
-
constructor (database, mapFn, clock, opts = {}) {
|
38693
|
+
constructor (database, name, mapFn, clock = null, opts = {}) {
|
38675
38694
|
this.database = database;
|
38676
38695
|
if (!database.indexBlocks) {
|
38677
38696
|
database.indexBlocks = new TransactionBlockstore(database?.name + '.indexes', database.blocks.valet?.getKeyMaterial());
|
@@ -38687,7 +38706,7 @@ class DbIndex {
|
|
38687
38706
|
this.mapFn = mapFn;
|
38688
38707
|
this.mapFnString = mapFn.toString();
|
38689
38708
|
}
|
38690
|
-
this.name =
|
38709
|
+
this.name = name || this.makeName();
|
38691
38710
|
this.indexById = { root: null, cid: null };
|
38692
38711
|
this.indexByKey = { root: null, cid: null };
|
38693
38712
|
this.dbHead = null;
|
@@ -38737,7 +38756,7 @@ class DbIndex {
|
|
38737
38756
|
|
38738
38757
|
static fromJSON (database, { code, clock, name }) {
|
38739
38758
|
// console.log('DbIndex.fromJSON', database.constructor.name, code, clock)
|
38740
|
-
return new DbIndex(database, code, clock
|
38759
|
+
return new DbIndex(database, name, code, clock)
|
38741
38760
|
}
|
38742
38761
|
|
38743
38762
|
/**
|
@@ -38754,7 +38773,7 @@ class DbIndex {
|
|
38754
38773
|
* @memberof DbIndex
|
38755
38774
|
* @instance
|
38756
38775
|
*/
|
38757
|
-
async query (query, update = true) {
|
38776
|
+
async query (query = {}, update = true) {
|
38758
38777
|
// const callId = Math.random().toString(36).substring(2, 7)
|
38759
38778
|
// todo pass a root to query a snapshot
|
38760
38779
|
// console.time(callId + '.updateIndex')
|
@@ -38781,7 +38800,12 @@ class DbIndex {
|
|
38781
38800
|
async updateIndex (blocks) {
|
38782
38801
|
// todo this could enqueue the request and give fresh ones to all second comers -- right now it gives out stale promises while working
|
38783
38802
|
// what would it do in a world where all indexes provide a database snapshot to query?
|
38784
|
-
if (this.updateIndexPromise)
|
38803
|
+
if (this.updateIndexPromise) {
|
38804
|
+
return this.updateIndexPromise.then(() => {
|
38805
|
+
this.updateIndexPromise = null;
|
38806
|
+
return this.updateIndex(blocks)
|
38807
|
+
})
|
38808
|
+
}
|
38785
38809
|
this.updateIndexPromise = this.innerUpdateIndex(blocks);
|
38786
38810
|
this.updateIndexPromise.finally(() => { this.updateIndexPromise = null; });
|
38787
38811
|
return this.updateIndexPromise
|
@@ -38802,7 +38826,7 @@ class DbIndex {
|
|
38802
38826
|
this.dbHead = result.clock;
|
38803
38827
|
return
|
38804
38828
|
}
|
38805
|
-
await doTransaction('updateIndex', inBlocks, async (blocks) => {
|
38829
|
+
const didT = await doTransaction('updateIndex', inBlocks, async (blocks) => {
|
38806
38830
|
let oldIndexEntries = [];
|
38807
38831
|
let removeByIdIndexEntries = [];
|
38808
38832
|
await loadIndex(blocks, this.indexById, idIndexOpts);
|
@@ -38824,6 +38848,7 @@ class DbIndex {
|
|
38824
38848
|
this.database.notifyExternal('dbIndex');
|
38825
38849
|
// console.timeEnd(callTag + '.doTransactionupdateIndex')
|
38826
38850
|
// console.log(`updateIndex ${callTag} <`, this.instanceId, this.dbHead?.toString(), this.indexByKey.cid?.toString(), this.indexById.cid?.toString())
|
38851
|
+
return didT
|
38827
38852
|
}
|
38828
38853
|
}
|
38829
38854
|
|
@@ -38866,7 +38891,11 @@ async function bulkIndex (blocks, inIndex, indexEntries, opts) {
|
|
38866
38891
|
async function loadIndex (blocks, index, indexOpts) {
|
38867
38892
|
if (!index.root) {
|
38868
38893
|
const cid = index.cid;
|
38869
|
-
if (!cid)
|
38894
|
+
if (!cid) {
|
38895
|
+
// console.log('no cid', index)
|
38896
|
+
// throw new Error('cannot load index')
|
38897
|
+
return null
|
38898
|
+
}
|
38870
38899
|
const { getBlock } = makeGetBlock(blocks);
|
38871
38900
|
index.root = await load({ cid, get: getBlock, ...indexOpts });
|
38872
38901
|
}
|
@@ -38893,7 +38922,7 @@ async function doIndexQuery (blocks, indexByKey, query = {}) {
|
|
38893
38922
|
}
|
38894
38923
|
}
|
38895
38924
|
|
38896
|
-
const parseCID = cid => typeof cid === 'string' ? CID$1.parse(cid) : cid;
|
38925
|
+
const parseCID = cid => (typeof cid === 'string' ? CID$1.parse(cid) : cid);
|
38897
38926
|
|
38898
38927
|
class Fireproof {
|
38899
38928
|
/**
|
@@ -38924,7 +38953,11 @@ class Fireproof {
|
|
38924
38953
|
static fromJSON (json, database) {
|
38925
38954
|
database.hydrate({ clock: json.clock.map(c => parseCID(c)), name: json.name, key: json.key });
|
38926
38955
|
if (json.indexes) {
|
38927
|
-
for (const {
|
38956
|
+
for (const {
|
38957
|
+
name,
|
38958
|
+
code,
|
38959
|
+
clock: { byId, byKey, db }
|
38960
|
+
} of json.indexes) {
|
38928
38961
|
DbIndex.fromJSON(database, {
|
38929
38962
|
clock: {
|
38930
38963
|
byId: byId ? parseCID(byId) : null,
|
@@ -38951,14 +38984,14 @@ class Fireproof {
|
|
38951
38984
|
});
|
38952
38985
|
}
|
38953
38986
|
const snappedDb = this.fromJSON(definition, withBlocks)
|
38954
|
-
;
|
38987
|
+
;[...database.indexes.values()].forEach(index => {
|
38955
38988
|
snappedDb.indexes.get(index.mapFnString).mapFn = index.mapFn;
|
38956
38989
|
});
|
38957
38990
|
return snappedDb
|
38958
38991
|
}
|
38959
38992
|
|
38960
38993
|
static async zoom (database, clock) {
|
38961
|
-
|
38994
|
+
[...database.indexes.values()].forEach(index => {
|
38962
38995
|
index.indexById = { root: null, cid: null };
|
38963
38996
|
index.indexByKey = { root: null, cid: null };
|
38964
38997
|
index.dbHead = null;
|
@@ -38967,7 +39000,42 @@ class Fireproof {
|
|
38967
39000
|
await database.notifyReset(); // hmm... indexes should listen to this? might be more complex than worth it. so far this is the only caller
|
38968
39001
|
return database
|
38969
39002
|
}
|
39003
|
+
|
39004
|
+
// get all the cids
|
39005
|
+
// tell valet to make a file
|
39006
|
+
static async makeCar (database, key) {
|
39007
|
+
const allCIDs = await database.allCIDs();
|
39008
|
+
const blocks = database.blocks;
|
39009
|
+
|
39010
|
+
const rootCid = CID$1.parse(allCIDs[allCIDs.length - 1]);
|
39011
|
+
if (typeof key === 'undefined') {
|
39012
|
+
key = blocks.valet?.getKeyMaterial();
|
39013
|
+
}
|
39014
|
+
if (key) {
|
39015
|
+
return blocksToEncryptedCarBlock(
|
39016
|
+
rootCid,
|
39017
|
+
{
|
39018
|
+
entries: () => allCIDs.map(cid => ({ cid })),
|
39019
|
+
get: async cid => await blocks.get(cid)
|
39020
|
+
},
|
39021
|
+
key
|
39022
|
+
)
|
39023
|
+
} else {
|
39024
|
+
const carBlocks = await Promise.all(
|
39025
|
+
allCIDs.map(async c => {
|
39026
|
+
const b = await blocks.get(c);
|
39027
|
+
// console.log('block', b)
|
39028
|
+
if (typeof b.cid === 'string') { b.cid = CID$1.parse(b.cid); }
|
39029
|
+
// if (b.bytes.constructor.name === 'Buffer') console.log('conver vbuff')
|
39030
|
+
return b
|
39031
|
+
})
|
39032
|
+
);
|
39033
|
+
return blocksToCarBlock(rootCid, {
|
39034
|
+
entries: () => carBlocks
|
39035
|
+
})
|
39036
|
+
}
|
39037
|
+
}
|
38970
39038
|
}
|
38971
39039
|
|
38972
|
-
export { Fireproof, DbIndex as Index, Listener };
|
39040
|
+
export { Database, Fireproof, DbIndex as Index, Listener };
|
38973
39041
|
//# sourceMappingURL=fireproof.mjs.map
|