@fireproof/core 0.6.2 → 0.6.3-dev

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