@fireproof/core 0.6.3-dev2 → 0.6.4
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/src/database.js +3 -3
- package/dist/src/fireproof.d.ts +2 -26
- package/dist/src/fireproof.js +533 -763
- package/dist/src/fireproof.js.map +1 -1
- package/dist/src/fireproof.mjs +533 -763
- package/dist/src/fireproof.mjs.map +1 -1
- package/dist/src/prolly.js +0 -1
- package/dist/src/valet.js +33 -18
- package/package.json +1 -3
- package/src/database.js +3 -3
- package/src/fireproof.js +3 -4
- package/src/prolly.js +0 -2
- package/src/utils.js +16 -0
- package/src/valet.js +36 -21
- package/src/loader.js +0 -168
package/dist/src/prolly.js
CHANGED
@@ -8,7 +8,6 @@ import { nocache as cache } from 'prolly-trees/cache';
|
|
8
8
|
import { CIDCounter, bf, simpleCompare as compare } from 'prolly-trees/utils';
|
9
9
|
import * as codec from '@ipld/dag-cbor';
|
10
10
|
import { sha256 as hasher } from 'multiformats/hashes/sha2';
|
11
|
-
// import { blake2b256 as hasher } from '@multiformats/blake2/blake2b'
|
12
11
|
import { doTransaction } from './blockstore.js';
|
13
12
|
import { create as createBlock } from 'multiformats/block';
|
14
13
|
const blockOpts = { cache, chunker: bf(30), codec, hasher, compare };
|
package/dist/src/valet.js
CHANGED
@@ -6,8 +6,8 @@ import * as CBW from '@ipld/car/buffer-writer';
|
|
6
6
|
import * as raw from 'multiformats/codecs/raw';
|
7
7
|
import * as Block from 'multiformats/block';
|
8
8
|
import * as dagcbor from '@ipld/dag-cbor';
|
9
|
+
import { openDB } from 'idb';
|
9
10
|
import cargoQueue from 'async/cargoQueue.js';
|
10
|
-
import { Loader } from './loader.js';
|
11
11
|
// @ts-ignore
|
12
12
|
// @ts-ignore
|
13
13
|
import { bf, simpleCompare as compare } from 'prolly-trees/utils';
|
@@ -44,7 +44,6 @@ export class Valet {
|
|
44
44
|
constructor(name = 'default', keyMaterial) {
|
45
45
|
this.name = name;
|
46
46
|
this.setKeyMaterial(keyMaterial);
|
47
|
-
this.loader = new Loader(name, this.keyId); // todo send this config.loader, if we ever need it
|
48
47
|
this.uploadQueue = cargoQueue(async (tasks, callback) => {
|
49
48
|
// console.log(
|
50
49
|
// 'queue worker',
|
@@ -77,9 +76,6 @@ export class Valet {
|
|
77
76
|
// })
|
78
77
|
});
|
79
78
|
}
|
80
|
-
saveHeader(header) {
|
81
|
-
return this.loader.saveHeader(header);
|
82
|
-
}
|
83
79
|
getKeyMaterial() {
|
84
80
|
return this.keyMaterial;
|
85
81
|
}
|
@@ -120,6 +116,18 @@ export class Valet {
|
|
120
116
|
throw new Error('missing lastCid for car header');
|
121
117
|
}
|
122
118
|
}
|
119
|
+
withDB = async (dbWorkFun) => {
|
120
|
+
if (!this.idb) {
|
121
|
+
this.idb = await openDB(`fp.${this.keyId}.${this.name}.valet`, 3, {
|
122
|
+
upgrade(db, oldVersion, newVersion, transaction) {
|
123
|
+
if (oldVersion < 1) {
|
124
|
+
db.createObjectStore('cars');
|
125
|
+
}
|
126
|
+
}
|
127
|
+
});
|
128
|
+
}
|
129
|
+
return await dbWorkFun(this.idb);
|
130
|
+
};
|
123
131
|
/**
|
124
132
|
* Iterate over all blocks in the store.
|
125
133
|
*
|
@@ -159,7 +167,6 @@ export class Valet {
|
|
159
167
|
blockHasher: blockOpts.hasher,
|
160
168
|
blockCodec: blockOpts.codec
|
161
169
|
});
|
162
|
-
this.valetRoot = indexNode;
|
163
170
|
}
|
164
171
|
const got = await indexNode.get(cid);
|
165
172
|
// console.log('getCarCIDForCID', cid, got)
|
@@ -204,14 +211,13 @@ export class Valet {
|
|
204
211
|
* @param {*} value
|
205
212
|
*/
|
206
213
|
async parkCar(carCid, value, cids) {
|
207
|
-
// const callId = Math.random().toString(36).substring(7)
|
208
214
|
// console.log('parkCar', this.instanceId, this.name, carCid, cids)
|
209
215
|
const combinedReader = await this.getCombinedReader(carCid);
|
210
216
|
const mapNode = await addCidsToCarIndex(combinedReader, this.valetRoot, this.valetRootCid, Array.from(cids).map(cid => ({ key: cid.toString(), value: carCid.toString() })));
|
211
217
|
this.valetRoot = mapNode;
|
212
218
|
this.valetRootCid = mapNode.cid;
|
213
219
|
// make a block set with all the cids of the map
|
214
|
-
const saveValetBlocks = new VMemoryBlockstore();
|
220
|
+
const saveValetBlocks = new VMemoryBlockstore(); // todo this blockstore should read from the last valetCid car also
|
215
221
|
for await (const cidx of mapNode.cids()) {
|
216
222
|
const bytes = await combinedReader.get(cidx);
|
217
223
|
saveValetBlocks.put(cidx, bytes);
|
@@ -224,8 +230,7 @@ export class Valet {
|
|
224
230
|
newValetCidCar = await blocksToCarBlock(this.valetRootCid, saveValetBlocks);
|
225
231
|
}
|
226
232
|
// console.log('newValetCidCar', this.name, Math.floor(newValetCidCar.bytes.length / 1024))
|
227
|
-
|
228
|
-
await this.loader.writeCars([
|
233
|
+
await this.writeCars([
|
229
234
|
{
|
230
235
|
cid: carCid,
|
231
236
|
bytes: value,
|
@@ -239,7 +244,6 @@ export class Valet {
|
|
239
244
|
}
|
240
245
|
]);
|
241
246
|
this.valetRootCarCid = newValetCidCar.cid; // goes to clock
|
242
|
-
// console.log('wroteCars', callId, carCid.toString(), newValetCidCar.cid.toString())
|
243
247
|
// console.log('parked car', carCid, value.length, Array.from(cids))
|
244
248
|
// upload to web3.storage if we have credentials
|
245
249
|
if (this.uploadFunction) {
|
@@ -256,12 +260,27 @@ export class Valet {
|
|
256
260
|
// console.log('no upload function', carCid, value.length, this.uploadFunction)
|
257
261
|
}
|
258
262
|
}
|
263
|
+
async writeCars(cars) {
|
264
|
+
return await this.withDB(async (db) => {
|
265
|
+
const tx = db.transaction(['cars'], 'readwrite');
|
266
|
+
for (const { cid, bytes, replaces } of cars) {
|
267
|
+
await tx.objectStore('cars').put(bytes, cid.toString());
|
268
|
+
// todo remove old maps
|
269
|
+
if (replaces) {
|
270
|
+
await tx.objectStore('cars').delete(replaces.toString());
|
271
|
+
}
|
272
|
+
}
|
273
|
+
return await tx.done;
|
274
|
+
});
|
275
|
+
}
|
259
276
|
remoteBlockFunction = null;
|
260
277
|
async getCarReader(carCid) {
|
261
278
|
carCid = carCid.toString();
|
262
|
-
const carBytes = await this.
|
263
|
-
|
264
|
-
|
279
|
+
const carBytes = await this.withDB(async (db) => {
|
280
|
+
const tx = db.transaction(['cars'], 'readonly');
|
281
|
+
// console.log('getCarReader', carCid)
|
282
|
+
return await tx.objectStore('cars').get(carCid);
|
283
|
+
});
|
265
284
|
const reader = await CarReader.fromBytes(carBytes);
|
266
285
|
if (this.keyMaterial) {
|
267
286
|
const roots = await reader.getRoots();
|
@@ -284,7 +303,6 @@ export class Valet {
|
|
284
303
|
const { blocks } = await blocksFromEncryptedCarBlock(roots[0], readerGetWithCodec, this.keyMaterial);
|
285
304
|
// last block is the root ??? todo
|
286
305
|
const rootBlock = blocks[blocks.length - 1];
|
287
|
-
// console.log('got reader', callID, carCid)
|
288
306
|
return {
|
289
307
|
root: rootBlock,
|
290
308
|
get: async (dataCID) => {
|
@@ -406,8 +424,6 @@ const blocksFromEncryptedCarBlock = async (cid, get, keyMaterial) => {
|
|
406
424
|
};
|
407
425
|
const addCidsToCarIndex = async (blockstore, valetRoot, valetRootCid, bulkOperations) => {
|
408
426
|
let indexNode;
|
409
|
-
// const callID = Math.random().toString(32).substring(2, 8)
|
410
|
-
// console.log('addCidsToCarIndex', callID, valetRootCid, bulkOperations.length)
|
411
427
|
if (valetRootCid) {
|
412
428
|
if (valetRoot) {
|
413
429
|
indexNode = valetRoot;
|
@@ -429,7 +445,6 @@ const addCidsToCarIndex = async (blockstore, valetRoot, valetRootCid, bulkOperat
|
|
429
445
|
// console.log('adding', key, value)
|
430
446
|
await indexNode.set(key, value);
|
431
447
|
}
|
432
|
-
// console.log('newCidsToCarIndex', callID, indexNode.cid, bulkOperations.length)
|
433
448
|
return indexNode;
|
434
449
|
};
|
435
450
|
export class VMemoryBlockstore {
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@fireproof/core",
|
3
|
-
"version": "0.6.
|
3
|
+
"version": "0.6.4",
|
4
4
|
"description": "Live data for React, accelerated by proofs, powered by IPFS",
|
5
5
|
"main": "dist/src/fireproof.js",
|
6
6
|
"module": "dist/src/fireproof.mjs",
|
@@ -40,8 +40,6 @@
|
|
40
40
|
"dependencies": {
|
41
41
|
"@ipld/car": "^5.1.0",
|
42
42
|
"@ipld/dag-cbor": "^9.0.0",
|
43
|
-
"@jsonlines/core": "^1.0.2",
|
44
|
-
"@multiformats/blake2": "^1.0.13",
|
45
43
|
"@rollup/plugin-commonjs": "^24.0.1",
|
46
44
|
"archy": "^1.0.0",
|
47
45
|
"async": "^3.2.4",
|
package/src/database.js
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
import { visMerkleClock, visMerkleTree, vis, put, get, getAll, eventsSince } from './prolly.js'
|
3
3
|
import { doTransaction, TransactionBlockstore } from './blockstore.js'
|
4
4
|
import charwise from 'charwise'
|
5
|
+
import { localSet } from './utils.js'
|
5
6
|
import { CID } from 'multiformats'
|
6
7
|
|
7
8
|
// TypeScript Types
|
@@ -33,7 +34,7 @@ export class Database {
|
|
33
34
|
this.name = name
|
34
35
|
this.instanceId = `fp.${this.name}.${Math.random().toString(36).substring(2, 7)}`
|
35
36
|
this.blocks = new TransactionBlockstore(name, config.key)
|
36
|
-
this.indexBlocks = new TransactionBlockstore(name
|
37
|
+
this.indexBlocks = new TransactionBlockstore(name + '.indexes', config.key)
|
37
38
|
this.clock = clock
|
38
39
|
this.config = config
|
39
40
|
}
|
@@ -77,7 +78,7 @@ export class Database {
|
|
77
78
|
|
78
79
|
maybeSaveClock () {
|
79
80
|
if (this.name && this.blocks.valet) {
|
80
|
-
this.
|
81
|
+
localSet('fp.' + this.name, JSON.stringify(this))
|
81
82
|
}
|
82
83
|
}
|
83
84
|
|
@@ -313,7 +314,6 @@ export class Database {
|
|
313
314
|
console.error('failed', event)
|
314
315
|
throw new Error('failed to put at storage layer')
|
315
316
|
}
|
316
|
-
// await new Promise(resolve => setTimeout(resolve, 10)) // makes concurrent tests work
|
317
317
|
this.applyClock(prevClock, result.head)
|
318
318
|
await this.notifyListeners([decodedEvent]) // this type is odd
|
319
319
|
return {
|
package/src/fireproof.js
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
import randomBytes from 'randombytes'
|
2
|
-
// import { randomBytes } from 'crypto'
|
3
2
|
import { Database, parseCID } from './database.js'
|
4
3
|
import { Listener } from './listener.js'
|
5
4
|
import { DbIndex as Index } from './db-index.js'
|
6
5
|
// import { TransactionBlockstore } from './blockstore.js'
|
7
|
-
import {
|
6
|
+
import { localGet } from './utils.js'
|
8
7
|
import { Sync } from './sync.js'
|
9
8
|
|
10
9
|
// todo remove Listener in 0.7.0
|
@@ -22,8 +21,8 @@ export class Fireproof {
|
|
22
21
|
static storage = (name = null, opts = {}) => {
|
23
22
|
if (name) {
|
24
23
|
opts.name = name
|
25
|
-
|
26
|
-
const existing =
|
24
|
+
// todo this can come from a registry also eg remote database / config, etc
|
25
|
+
const existing = localGet('fp.' + name)
|
27
26
|
if (existing) {
|
28
27
|
const existingConfig = JSON.parse(existing)
|
29
28
|
return Fireproof.fromConfig(name, existingConfig, opts)
|
package/src/prolly.js
CHANGED
@@ -15,8 +15,6 @@ import { nocache as cache } from 'prolly-trees/cache'
|
|
15
15
|
import { CIDCounter, bf, simpleCompare as compare } from 'prolly-trees/utils'
|
16
16
|
import * as codec from '@ipld/dag-cbor'
|
17
17
|
import { sha256 as hasher } from 'multiformats/hashes/sha2'
|
18
|
-
// import { blake2b256 as hasher } from '@multiformats/blake2/blake2b'
|
19
|
-
|
20
18
|
import { doTransaction } from './blockstore.js'
|
21
19
|
import { create as createBlock } from 'multiformats/block'
|
22
20
|
const blockOpts = { cache, chunker: bf(30), codec, hasher, compare }
|
package/src/utils.js
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
/* global localStorage */
|
3
|
+
let storageSupported = false
|
4
|
+
try {
|
5
|
+
storageSupported = window.localStorage && true
|
6
|
+
} catch (e) {}
|
7
|
+
export function localGet (key) {
|
8
|
+
if (storageSupported) {
|
9
|
+
return localStorage && localStorage.getItem(key)
|
10
|
+
}
|
11
|
+
}
|
12
|
+
export function localSet (key, value) {
|
13
|
+
if (storageSupported) {
|
14
|
+
return localStorage && localStorage.setItem(key, value)
|
15
|
+
}
|
16
|
+
}
|
package/src/valet.js
CHANGED
@@ -6,9 +6,8 @@ import * as CBW from '@ipld/car/buffer-writer'
|
|
6
6
|
import * as raw from 'multiformats/codecs/raw'
|
7
7
|
import * as Block from 'multiformats/block'
|
8
8
|
import * as dagcbor from '@ipld/dag-cbor'
|
9
|
+
import { openDB } from 'idb'
|
9
10
|
import cargoQueue from 'async/cargoQueue.js'
|
10
|
-
import { Loader } from './loader.js'
|
11
|
-
|
12
11
|
// @ts-ignore
|
13
12
|
|
14
13
|
// @ts-ignore
|
@@ -54,7 +53,6 @@ export class Valet {
|
|
54
53
|
constructor (name = 'default', keyMaterial) {
|
55
54
|
this.name = name
|
56
55
|
this.setKeyMaterial(keyMaterial)
|
57
|
-
this.loader = new Loader(name, this.keyId) // todo send this config.loader, if we ever need it
|
58
56
|
this.uploadQueue = cargoQueue(async (tasks, callback) => {
|
59
57
|
// console.log(
|
60
58
|
// 'queue worker',
|
@@ -89,10 +87,6 @@ export class Valet {
|
|
89
87
|
})
|
90
88
|
}
|
91
89
|
|
92
|
-
saveHeader (header) {
|
93
|
-
return this.loader.saveHeader(header)
|
94
|
-
}
|
95
|
-
|
96
90
|
getKeyMaterial () {
|
97
91
|
return this.keyMaterial
|
98
92
|
}
|
@@ -133,6 +127,19 @@ export class Valet {
|
|
133
127
|
}
|
134
128
|
}
|
135
129
|
|
130
|
+
withDB = async dbWorkFun => {
|
131
|
+
if (!this.idb) {
|
132
|
+
this.idb = await openDB(`fp.${this.keyId}.${this.name}.valet`, 3, {
|
133
|
+
upgrade (db, oldVersion, newVersion, transaction) {
|
134
|
+
if (oldVersion < 1) {
|
135
|
+
db.createObjectStore('cars')
|
136
|
+
}
|
137
|
+
}
|
138
|
+
})
|
139
|
+
}
|
140
|
+
return await dbWorkFun(this.idb)
|
141
|
+
}
|
142
|
+
|
136
143
|
/**
|
137
144
|
* Iterate over all blocks in the store.
|
138
145
|
*
|
@@ -173,7 +180,6 @@ export class Valet {
|
|
173
180
|
blockHasher: blockOpts.hasher,
|
174
181
|
blockCodec: blockOpts.codec
|
175
182
|
})
|
176
|
-
this.valetRoot = indexNode
|
177
183
|
}
|
178
184
|
|
179
185
|
const got = await indexNode.get(cid)
|
@@ -220,7 +226,6 @@ export class Valet {
|
|
220
226
|
* @param {*} value
|
221
227
|
*/
|
222
228
|
async parkCar (carCid, value, cids) {
|
223
|
-
// const callId = Math.random().toString(36).substring(7)
|
224
229
|
// console.log('parkCar', this.instanceId, this.name, carCid, cids)
|
225
230
|
const combinedReader = await this.getCombinedReader(carCid)
|
226
231
|
const mapNode = await addCidsToCarIndex(
|
@@ -233,7 +238,7 @@ export class Valet {
|
|
233
238
|
this.valetRoot = mapNode
|
234
239
|
this.valetRootCid = mapNode.cid
|
235
240
|
// make a block set with all the cids of the map
|
236
|
-
const saveValetBlocks = new VMemoryBlockstore()
|
241
|
+
const saveValetBlocks = new VMemoryBlockstore() // todo this blockstore should read from the last valetCid car also
|
237
242
|
|
238
243
|
for await (const cidx of mapNode.cids()) {
|
239
244
|
const bytes = await combinedReader.get(cidx)
|
@@ -246,8 +251,7 @@ export class Valet {
|
|
246
251
|
newValetCidCar = await blocksToCarBlock(this.valetRootCid, saveValetBlocks)
|
247
252
|
}
|
248
253
|
// console.log('newValetCidCar', this.name, Math.floor(newValetCidCar.bytes.length / 1024))
|
249
|
-
|
250
|
-
await this.loader.writeCars([
|
254
|
+
await this.writeCars([
|
251
255
|
{
|
252
256
|
cid: carCid,
|
253
257
|
bytes: value,
|
@@ -263,8 +267,6 @@ export class Valet {
|
|
263
267
|
|
264
268
|
this.valetRootCarCid = newValetCidCar.cid // goes to clock
|
265
269
|
|
266
|
-
// console.log('wroteCars', callId, carCid.toString(), newValetCidCar.cid.toString())
|
267
|
-
|
268
270
|
// console.log('parked car', carCid, value.length, Array.from(cids))
|
269
271
|
// upload to web3.storage if we have credentials
|
270
272
|
if (this.uploadFunction) {
|
@@ -281,13 +283,29 @@ export class Valet {
|
|
281
283
|
}
|
282
284
|
}
|
283
285
|
|
286
|
+
async writeCars (cars) {
|
287
|
+
return await this.withDB(async db => {
|
288
|
+
const tx = db.transaction(['cars'], 'readwrite')
|
289
|
+
for (const { cid, bytes, replaces } of cars) {
|
290
|
+
await tx.objectStore('cars').put(bytes, cid.toString())
|
291
|
+
// todo remove old maps
|
292
|
+
if (replaces) {
|
293
|
+
await tx.objectStore('cars').delete(replaces.toString())
|
294
|
+
}
|
295
|
+
}
|
296
|
+
return await tx.done
|
297
|
+
})
|
298
|
+
}
|
299
|
+
|
284
300
|
remoteBlockFunction = null
|
285
301
|
|
286
302
|
async getCarReader (carCid) {
|
287
303
|
carCid = carCid.toString()
|
288
|
-
const carBytes = await this.
|
289
|
-
|
290
|
-
|
304
|
+
const carBytes = await this.withDB(async db => {
|
305
|
+
const tx = db.transaction(['cars'], 'readonly')
|
306
|
+
// console.log('getCarReader', carCid)
|
307
|
+
return await tx.objectStore('cars').get(carCid)
|
308
|
+
})
|
291
309
|
const reader = await CarReader.fromBytes(carBytes)
|
292
310
|
if (this.keyMaterial) {
|
293
311
|
const roots = await reader.getRoots()
|
@@ -311,7 +329,7 @@ export class Valet {
|
|
311
329
|
|
312
330
|
// last block is the root ??? todo
|
313
331
|
const rootBlock = blocks[blocks.length - 1]
|
314
|
-
|
332
|
+
|
315
333
|
return {
|
316
334
|
root: rootBlock,
|
317
335
|
get: async dataCID => {
|
@@ -438,8 +456,6 @@ const blocksFromEncryptedCarBlock = async (cid, get, keyMaterial) => {
|
|
438
456
|
|
439
457
|
const addCidsToCarIndex = async (blockstore, valetRoot, valetRootCid, bulkOperations) => {
|
440
458
|
let indexNode
|
441
|
-
// const callID = Math.random().toString(32).substring(2, 8)
|
442
|
-
// console.log('addCidsToCarIndex', callID, valetRootCid, bulkOperations.length)
|
443
459
|
if (valetRootCid) {
|
444
460
|
if (valetRoot) {
|
445
461
|
indexNode = valetRoot
|
@@ -459,7 +475,6 @@ const addCidsToCarIndex = async (blockstore, valetRoot, valetRootCid, bulkOperat
|
|
459
475
|
// console.log('adding', key, value)
|
460
476
|
await indexNode.set(key, value)
|
461
477
|
}
|
462
|
-
// console.log('newCidsToCarIndex', callID, indexNode.cid, bulkOperations.length)
|
463
478
|
return indexNode
|
464
479
|
}
|
465
480
|
|
package/src/loader.js
DELETED
@@ -1,168 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
readFileSync
|
3
|
-
// createReadStream
|
4
|
-
} from 'node:fs'
|
5
|
-
import { mkdir, writeFile } from 'node:fs/promises'
|
6
|
-
import { openDB } from 'idb'
|
7
|
-
import { join, dirname } from 'path'
|
8
|
-
// import { parse } from '@jsonlines/core'
|
9
|
-
// import cargoQueue from 'async/cargoQueue.js'
|
10
|
-
import { homedir } from 'os'
|
11
|
-
|
12
|
-
const defaultConfig = {
|
13
|
-
dataDir: join(homedir(), '.fireproof'),
|
14
|
-
headerKeyPrefix: 'fp.'
|
15
|
-
}
|
16
|
-
|
17
|
-
const FORCE_IDB = typeof process !== 'undefined' && !!process.env?.FORCE_IDB
|
18
|
-
|
19
|
-
/* global localStorage */
|
20
|
-
|
21
|
-
export class Loader {
|
22
|
-
constructor (name, keyId, config = defaultConfig) {
|
23
|
-
this.name = name
|
24
|
-
this.keyId = keyId
|
25
|
-
this.config = config
|
26
|
-
this.isBrowser = false
|
27
|
-
try {
|
28
|
-
this.isBrowser = window.localStorage && true
|
29
|
-
} catch (e) {}
|
30
|
-
}
|
31
|
-
|
32
|
-
withDB = async (dbWorkFun) => {
|
33
|
-
if (!this.idb) {
|
34
|
-
this.idb = await openDB(`fp.${this.keyId}.${this.name}.valet`, 3, {
|
35
|
-
upgrade (db, oldVersion, newVersion, transaction) {
|
36
|
-
if (oldVersion < 1) {
|
37
|
-
db.createObjectStore('cars')
|
38
|
-
}
|
39
|
-
}
|
40
|
-
})
|
41
|
-
}
|
42
|
-
return await dbWorkFun(this.idb)
|
43
|
-
}
|
44
|
-
|
45
|
-
async writeCars (cars) {
|
46
|
-
// console.log('writeCars', this.config.dataDir, this.name, cars.map(c => c.cid.toString()))
|
47
|
-
// console.log('writeCars', cars.length)
|
48
|
-
|
49
|
-
if (FORCE_IDB || this.isBrowser) {
|
50
|
-
await this.writeCarsIDB(cars)
|
51
|
-
} else {
|
52
|
-
const writes = []
|
53
|
-
for (const { cid, bytes } of cars) {
|
54
|
-
const carFilename = join(this.config.dataDir, this.name, `${cid.toString()}.car`)
|
55
|
-
// console.log('writeCars', carFilename)
|
56
|
-
writes.push(writeSync(carFilename, bytes))
|
57
|
-
}
|
58
|
-
await Promise.all(writes)
|
59
|
-
}
|
60
|
-
}
|
61
|
-
|
62
|
-
async writeCarsIDB (cars) {
|
63
|
-
return await this.withDB(async db => {
|
64
|
-
const tx = db.transaction(['cars'], 'readwrite')
|
65
|
-
for (const { cid, bytes, replaces } of cars) {
|
66
|
-
await tx.objectStore('cars').put(bytes, cid.toString())
|
67
|
-
// todo remove old maps
|
68
|
-
if (replaces) {
|
69
|
-
await tx.objectStore('cars').delete(replaces.toString())
|
70
|
-
}
|
71
|
-
}
|
72
|
-
return await tx.done
|
73
|
-
})
|
74
|
-
}
|
75
|
-
|
76
|
-
async readCar (carCid) {
|
77
|
-
if (FORCE_IDB || this.isBrowser) {
|
78
|
-
return await this.readCarIDB(carCid)
|
79
|
-
} else {
|
80
|
-
const carFilename = join(this.config.dataDir, this.name, `${carCid.toString()}.car`)
|
81
|
-
const got = readFileSync(carFilename)
|
82
|
-
// console.log('readCar', carFilename, got.constructor.name)
|
83
|
-
return got
|
84
|
-
}
|
85
|
-
}
|
86
|
-
|
87
|
-
async readCarIDB (carCid) {
|
88
|
-
return await this.withDB(async db => {
|
89
|
-
const tx = db.transaction(['cars'], 'readonly')
|
90
|
-
// console.log('getCarReader', carCid)
|
91
|
-
return await tx.objectStore('cars').get(carCid)
|
92
|
-
})
|
93
|
-
}
|
94
|
-
|
95
|
-
getHeader () {
|
96
|
-
if (this.isBrowser) {
|
97
|
-
return localStorage.getItem(this.config.headerKeyPrefix + this.name)
|
98
|
-
} else {
|
99
|
-
return loadSync(this.headerFilename())
|
100
|
-
// return null
|
101
|
-
}
|
102
|
-
}
|
103
|
-
|
104
|
-
async saveHeader (stringValue) {
|
105
|
-
// console.log('saveHeader', this.isBrowser)
|
106
|
-
if (this.isBrowser) {
|
107
|
-
// console.log('localStorage!', this.config.headerKeyPrefix)
|
108
|
-
return localStorage.setItem(this.config.headerKeyPrefix + this.name, stringValue)
|
109
|
-
} else {
|
110
|
-
// console.log('no localStorage', this.config.dataDir, this.name)
|
111
|
-
// console.log('saving clock to', this.headerFilename(), stringValue)
|
112
|
-
|
113
|
-
try {
|
114
|
-
await writeSync(this.headerFilename(), stringValue)
|
115
|
-
} catch (error) {
|
116
|
-
console.log('error', error)
|
117
|
-
}
|
118
|
-
|
119
|
-
// console.log('saved clock to', this.headerFilename())
|
120
|
-
}
|
121
|
-
}
|
122
|
-
|
123
|
-
headerFilename () {
|
124
|
-
// console.log('headerFilename', this.config.dataDir, this.name)
|
125
|
-
return join(this.config.dataDir, this.name, 'header.json')
|
126
|
-
}
|
127
|
-
|
128
|
-
// async loadData (database, filename) {
|
129
|
-
// const fullFilePath = join(process.cwd(), filename)
|
130
|
-
// const readableStream = createReadStream(fullFilePath)
|
131
|
-
// const parseStream = parse()
|
132
|
-
// readableStream.pipe(parseStream)
|
133
|
-
|
134
|
-
// const saveQueue = cargoQueue(async (tasks, callback) => {
|
135
|
-
// for (const t of tasks) {
|
136
|
-
// await database.put(t)
|
137
|
-
// }
|
138
|
-
// callback()
|
139
|
-
// })
|
140
|
-
|
141
|
-
// parseStream.on('data', async (data) => {
|
142
|
-
// saveQueue.push(data)
|
143
|
-
// })
|
144
|
-
// let res
|
145
|
-
// const p = new Promise((resolve, reject) => {
|
146
|
-
// res = resolve
|
147
|
-
// })
|
148
|
-
// saveQueue.drain(async (x) => {
|
149
|
-
// res()
|
150
|
-
// })
|
151
|
-
// return p
|
152
|
-
// }
|
153
|
-
}
|
154
|
-
|
155
|
-
function loadSync (filename) {
|
156
|
-
try {
|
157
|
-
return readFileSync(filename, 'utf8').toString()
|
158
|
-
} catch (error) {
|
159
|
-
// console.log('error', error)
|
160
|
-
return null
|
161
|
-
}
|
162
|
-
}
|
163
|
-
|
164
|
-
async function writeSync (fullpath, stringValue) {
|
165
|
-
await mkdir(dirname(fullpath), { recursive: true })
|
166
|
-
// writeFileSync(fullpath, stringValue)
|
167
|
-
await writeFile(fullpath, stringValue)
|
168
|
-
}
|