@fireproof/core 0.8.0 → 0.10.1-dev
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +5 -184
- package/dist/fireproof.browser.js +18879 -0
- package/dist/fireproof.browser.js.map +7 -0
- package/dist/fireproof.cjs.js +9305 -0
- package/dist/fireproof.cjs.js.map +7 -0
- package/dist/fireproof.esm.js +9295 -0
- package/dist/fireproof.esm.js.map +7 -0
- package/package.json +57 -105
- package/dist/blockstore.js +0 -268
- package/dist/clock.js +0 -459
- package/dist/crypto.js +0 -63
- package/dist/database.js +0 -434
- package/dist/db-index.js +0 -403
- package/dist/encrypted-block.js +0 -48
- package/dist/fireproof.js +0 -84
- package/dist/import.js +0 -29
- package/dist/listener.js +0 -111
- package/dist/loader.js +0 -13
- package/dist/prolly.js +0 -405
- package/dist/remote.js +0 -102
- package/dist/sha1.js +0 -74
- package/dist/src/fireproof.d.ts +0 -472
- package/dist/src/fireproof.js +0 -81191
- package/dist/src/fireproof.js.map +0 -1
- package/dist/src/fireproof.mjs +0 -81186
- package/dist/src/fireproof.mjs.map +0 -1
- package/dist/storage/base.js +0 -426
- package/dist/storage/blocksToEncryptedCarBlock.js +0 -144
- package/dist/storage/browser.js +0 -62
- package/dist/storage/filesystem.js +0 -67
- package/dist/storage/rest.js +0 -57
- package/dist/storage/ucan.js +0 -0
- package/dist/storage/utils.js +0 -144
- package/dist/sync.js +0 -218
- package/dist/utils.js +0 -16
- package/dist/valet.js +0 -102
- package/src/blockstore.js +0 -283
- package/src/clock.js +0 -486
- package/src/crypto.js +0 -70
- package/src/database.js +0 -469
- package/src/db-index.js +0 -426
- package/src/encrypted-block.js +0 -57
- package/src/fireproof.js +0 -98
- package/src/import.js +0 -34
- package/src/link.d.ts +0 -3
- package/src/loader.js +0 -16
- package/src/prolly.js +0 -445
- package/src/remote.js +0 -113
- package/src/sha1.js +0 -83
- package/src/storage/base.js +0 -463
- package/src/storage/browser.js +0 -67
- package/src/storage/filesystem.js +0 -73
- package/src/storage/rest.js +0 -59
- package/src/storage/ucan.js +0 -0
- package/src/storage/utils.js +0 -152
- package/src/sync.js +0 -237
- package/src/valet.js +0 -105
package/src/storage/base.js
DELETED
@@ -1,463 +0,0 @@
|
|
1
|
-
import randomBytes from 'randombytes'
|
2
|
-
// import { randomBytes } from 'crypto'
|
3
|
-
import { CarReader } from '@ipld/car'
|
4
|
-
import { CID } from 'multiformats/cid'
|
5
|
-
import { sha256 } from 'multiformats/hashes/sha2'
|
6
|
-
import * as Block from 'multiformats/block'
|
7
|
-
import * as dagcbor from '@ipld/dag-cbor'
|
8
|
-
// @ts-ignore
|
9
|
-
import { bf, simpleCompare as compare } from 'prolly-trees/utils'
|
10
|
-
// @ts-ignore
|
11
|
-
import { nocache as cache } from 'prolly-trees/cache'
|
12
|
-
import { Buffer } from 'buffer'
|
13
|
-
import { rawSha1 as sha1sync } from '../sha1.js'
|
14
|
-
// @ts-ignore
|
15
|
-
import * as codec from '../encrypted-block.js'
|
16
|
-
import {
|
17
|
-
blocksToEncryptedCarBlock,
|
18
|
-
blocksToCarBlock,
|
19
|
-
blocksFromEncryptedCarBlock,
|
20
|
-
VMemoryBlockstore
|
21
|
-
} from './utils.js'
|
22
|
-
|
23
|
-
const chunker = bf(30)
|
24
|
-
const blockOpts = { cache, chunker, codec: dagcbor, hasher: sha256, compare }
|
25
|
-
|
26
|
-
const NO_ENCRYPT = typeof process !== 'undefined' && !!process.env?.NO_ENCRYPT
|
27
|
-
const NOT_IMPL = true
|
28
|
-
|
29
|
-
export class Base {
|
30
|
-
static format = '0.8'
|
31
|
-
lastCar = null
|
32
|
-
carLog = []
|
33
|
-
keyMaterial = null
|
34
|
-
keyId = 'null'
|
35
|
-
readonly = false
|
36
|
-
instanceId = Math.random().toString(36).slice(2)
|
37
|
-
|
38
|
-
constructor (name, config = {}) {
|
39
|
-
this.name = name
|
40
|
-
this.config = config
|
41
|
-
|
42
|
-
if (!this.config.branches) {
|
43
|
-
this.config.branches = {
|
44
|
-
main: { readonly: false }
|
45
|
-
}
|
46
|
-
}
|
47
|
-
|
48
|
-
this.ready = this.getHeaders().then(blocksReady => {
|
49
|
-
// console.log('blocksReady base', this.name, blocksReady)
|
50
|
-
return blocksReady
|
51
|
-
})
|
52
|
-
}
|
53
|
-
|
54
|
-
setLastCar (car) {
|
55
|
-
this.lastCar = car
|
56
|
-
this.carLog.unshift(car)
|
57
|
-
}
|
58
|
-
|
59
|
-
setKeyMaterial (km) {
|
60
|
-
if (km && !NO_ENCRYPT) {
|
61
|
-
const hex = Uint8Array.from(Buffer.from(km, 'hex'))
|
62
|
-
this.keyMaterial = km
|
63
|
-
const hash = sha1sync(hex)
|
64
|
-
this.keyId = Buffer.from(hash).toString('hex')
|
65
|
-
} else {
|
66
|
-
this.keyMaterial = null
|
67
|
-
this.keyId = 'null'
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
async compact (clock) {
|
72
|
-
if (this.readonly) return
|
73
|
-
if (clock.length !== 1) {
|
74
|
-
throw new Error(
|
75
|
-
`Compacting with clock length ${clock.length} instead of 1. To merge the clock, apply an update to the database first.`
|
76
|
-
)
|
77
|
-
}
|
78
|
-
const cidMap = await this.getCidCarMap()
|
79
|
-
const dataCids = new Set([...cidMap.keys()].filter(cid => cid[0] !== '_').map(cid => CID.parse(cid)))
|
80
|
-
const allBlocks = new Map()
|
81
|
-
for (const cid of dataCids) {
|
82
|
-
const block = await this.getLoaderBlock(cid)
|
83
|
-
allBlocks.set(cid, block.block)
|
84
|
-
}
|
85
|
-
cidMap.clear()
|
86
|
-
let lastCid = clock[0]
|
87
|
-
const blocks = {
|
88
|
-
head: clock,
|
89
|
-
lastCid,
|
90
|
-
get: cid => allBlocks.get(cid.toString()),
|
91
|
-
put: async (cid, block) => {
|
92
|
-
allBlocks.set(cid.toString(), block)
|
93
|
-
lastCid = cid.toString()
|
94
|
-
}
|
95
|
-
}
|
96
|
-
// const lastCompactCar =
|
97
|
-
await this.parkCar(blocks, dataCids) // todo this should remove old cars from the cid car map
|
98
|
-
// console.log('compact', this.name, lastCompactCar.cid, blocks.lastCid.toString(), dataCids.length)
|
99
|
-
// await this.setLastCompact(lastCompactCar.cid)
|
100
|
-
}
|
101
|
-
|
102
|
-
async parkCar (innerBlockstore, cids) {
|
103
|
-
// console.log('parkCar', this.instanceId, this.name, this.readonly)
|
104
|
-
if (this.readonly) return
|
105
|
-
|
106
|
-
// console.log('parkCar', this.name, this.carLog, innerBlockstore.head)
|
107
|
-
|
108
|
-
const value = { fp: { last: innerBlockstore.lastCid, clock: innerBlockstore.head, cars: this.carLog } }
|
109
|
-
const header = await Block.encode({ value, hasher: blockOpts.hasher, codec: blockOpts.codec })
|
110
|
-
await innerBlockstore.put(header.cid, header.bytes)
|
111
|
-
cids.add(header.cid.toString())
|
112
|
-
|
113
|
-
let newCar
|
114
|
-
if (this.keyMaterial) {
|
115
|
-
// console.log('encrypting car', innerBlockstore.label)
|
116
|
-
newCar = await blocksToEncryptedCarBlock(innerBlockstore.lastCid, innerBlockstore, this.keyMaterial, [...cids])
|
117
|
-
} else {
|
118
|
-
// todo should we pass cids in instead of iterating innerBlockstore?
|
119
|
-
newCar = await blocksToCarBlock(innerBlockstore.lastCid, innerBlockstore)
|
120
|
-
}
|
121
|
-
return await this.saveCar(newCar.cid.toString(), newCar.bytes)
|
122
|
-
}
|
123
|
-
|
124
|
-
async saveCar (carCid, value) {
|
125
|
-
// add the car cid to our in memory car list
|
126
|
-
this.carLog.unshift(carCid)
|
127
|
-
this.lastCar = carCid
|
128
|
-
// console.log('saveCar', this.name, carCid, this.carLog.length)
|
129
|
-
await this.writeCars([
|
130
|
-
{
|
131
|
-
cid: carCid,
|
132
|
-
bytes: value
|
133
|
-
}
|
134
|
-
])
|
135
|
-
}
|
136
|
-
|
137
|
-
async applyHeaders (headers) {
|
138
|
-
// console.log('applyHeaders', headers.index)
|
139
|
-
this.headers = headers
|
140
|
-
// console.log('before applied', this.instanceId, this.name, this.keyMaterial, this.valetRootCarCid)
|
141
|
-
for (const [, header] of Object.entries(headers)) {
|
142
|
-
if (header) {
|
143
|
-
// console.log('applyHeaders', this.instanceId, this.name, header.key, header.car)
|
144
|
-
header.key && this.setKeyMaterial(header.key)
|
145
|
-
// this.setCarCidMapCarCid(header.car) // instead we should just extract the list of cars from the car
|
146
|
-
const carHeader = await this.readHeaderCar(header.car)
|
147
|
-
|
148
|
-
// console.log('carHeader', this.name, carHeader)
|
149
|
-
|
150
|
-
this.carLog = carHeader.cars || []
|
151
|
-
// console.log('stored carHeader', this.name, this.config.type, this.carLog)
|
152
|
-
|
153
|
-
// this.lastCar = header.car // ?
|
154
|
-
if (header.car) {
|
155
|
-
// console.log('header.car', header.car, this.blocks.valet.primary.carLog)
|
156
|
-
this.setLastCar(header.car)
|
157
|
-
}
|
158
|
-
header.clock = carHeader.clock.map(c => c.toString())
|
159
|
-
}
|
160
|
-
}
|
161
|
-
|
162
|
-
if (!this.keyMaterial) {
|
163
|
-
const nullKey = this.config.key === null
|
164
|
-
if (nullKey || this.config.key) {
|
165
|
-
this.setKeyMaterial(this.config.key)
|
166
|
-
} else {
|
167
|
-
this.setKeyMaterial(randomBytes(32).toString('hex'))
|
168
|
-
}
|
169
|
-
}
|
170
|
-
// console.log('applied', this.instanceId, this.name, this.keyMaterial, this.valetRootCarCid)
|
171
|
-
}
|
172
|
-
|
173
|
-
async getHeaders () {
|
174
|
-
const headers = {}
|
175
|
-
for (const [branch] of Object.entries(this.config.branches)) {
|
176
|
-
const got = await this.loadHeader(branch)
|
177
|
-
headers[branch] = got
|
178
|
-
}
|
179
|
-
await this.applyHeaders(headers)
|
180
|
-
return headers
|
181
|
-
}
|
182
|
-
|
183
|
-
loadHeader (branch = 'main') {
|
184
|
-
if (NOT_IMPL) throw new Error('not implemented')
|
185
|
-
return {}
|
186
|
-
}
|
187
|
-
|
188
|
-
async saveHeader (header) {
|
189
|
-
// this.clock = header.clock
|
190
|
-
// for each branch, save the header
|
191
|
-
// console.log('saveHeader', this.config.branches)
|
192
|
-
// for (const branch of this.branches) {
|
193
|
-
// await this.saveBranchHeader(branch)
|
194
|
-
// }
|
195
|
-
for (const [branch, { readonly }] of Object.entries(this.config.branches)) {
|
196
|
-
if (readonly) continue
|
197
|
-
// console.log('saveHeader', this.instanceId, this.name, branch, header)
|
198
|
-
await this.writeHeader(branch, this.prepareHeader(header))
|
199
|
-
}
|
200
|
-
}
|
201
|
-
|
202
|
-
prepareHeader (header, json = true) {
|
203
|
-
header.key = this.keyMaterial
|
204
|
-
header.car = this.lastCar?.toString()
|
205
|
-
// console.log('prepareHeader', this.instanceId, this.name, header)
|
206
|
-
return json ? JSON.stringify(header) : header
|
207
|
-
}
|
208
|
-
|
209
|
-
writeHeader (branch, header) {
|
210
|
-
throw new Error('not implemented')
|
211
|
-
}
|
212
|
-
|
213
|
-
async getCarCIDForCID (cid) { // todo combine with getLoaderBlock for one fetch not many
|
214
|
-
// console.log('getCarCIDForCID', cid, this.carLog, this.config.type)
|
215
|
-
// for each car in the car log
|
216
|
-
for (const carCid of this.carLog) {
|
217
|
-
const reader = await this.getCarReader(carCid)
|
218
|
-
// console.log('getCarCIDForCID', carCid, cid)
|
219
|
-
// if (reader.has(cid)) {
|
220
|
-
// console.log('getCarCIDForCID found', cid)
|
221
|
-
// return { result: carCid }
|
222
|
-
// }
|
223
|
-
|
224
|
-
for await (const block of reader.entries()) {
|
225
|
-
// console.log('getCarCIDForCID', cid, block.cid.toString())
|
226
|
-
// console.log('getCarCIDForCID', cid, block.cid.toString())
|
227
|
-
if (block.cid.toString() === cid.toString()) {
|
228
|
-
// console.log('getCarCIDForCID found', cid)
|
229
|
-
return { result: carCid }
|
230
|
-
}
|
231
|
-
}
|
232
|
-
}
|
233
|
-
// console.log('getCarCIDForCID not found', cid, this.config.type)
|
234
|
-
return { result: null }
|
235
|
-
// return this.carLog[0]
|
236
|
-
// const cidMap = await this.getCidCarMap()
|
237
|
-
// const carCid = cidMap.get(cid.toString())
|
238
|
-
// if (carCid) {
|
239
|
-
// return { result: carCid }
|
240
|
-
// }
|
241
|
-
// return { result: null }
|
242
|
-
}
|
243
|
-
|
244
|
-
async readCar (carCid) {
|
245
|
-
if (NOT_IMPL) throw new Error('not implemented')
|
246
|
-
return new Uint8Array(carCid)
|
247
|
-
}
|
248
|
-
|
249
|
-
async getLoaderBlock (dataCID) {
|
250
|
-
// console.log('getLoaderBlock', dataCID, this.config, this.carLog)
|
251
|
-
const { result: carCid } = await this.getCarCIDForCID(dataCID)
|
252
|
-
// console.log('gotLoaderBlock', dataCID, carCid)
|
253
|
-
if (!carCid) {
|
254
|
-
throw new Error('Missing car for: ' + dataCID)
|
255
|
-
}
|
256
|
-
const reader = await this.getCarReader(carCid)
|
257
|
-
const block = await reader.get(dataCID)
|
258
|
-
// console.log('gotLoaderBlock', dataCID, block.length)
|
259
|
-
return { block, reader, carCid }
|
260
|
-
}
|
261
|
-
|
262
|
-
// async getLastSynced () {
|
263
|
-
// const metadata = await this.getCidCarMap()
|
264
|
-
// if (metadata.has('_last_sync_head')) {
|
265
|
-
// return JSON.parse(metadata.get('_last_sync_head'))
|
266
|
-
// } else {
|
267
|
-
// return []
|
268
|
-
// }
|
269
|
-
// }
|
270
|
-
|
271
|
-
// async setLastSynced (lastSynced) {
|
272
|
-
// const metadata = await this.getCidCarMap()
|
273
|
-
// metadata.set('_last_sync_head', JSON.stringify(lastSynced))
|
274
|
-
// // await this.writeMetadata(metadata)
|
275
|
-
// }
|
276
|
-
|
277
|
-
// async getCompactSince (sinceHead) {
|
278
|
-
// // get the car for the head
|
279
|
-
// // find the location of the car in the metadata car sequence
|
280
|
-
// }
|
281
|
-
|
282
|
-
/** Private - internal **/
|
283
|
-
|
284
|
-
async getCidCarMap () {
|
285
|
-
if (this.valetCarCidMap) return this.valetCarCidMap
|
286
|
-
this.valetCarCidMap = new Map()
|
287
|
-
return this.valetCarCidMap
|
288
|
-
}
|
289
|
-
|
290
|
-
async readHeaderCar (carCid) {
|
291
|
-
const carMapReader = await this.getCarReader(carCid)
|
292
|
-
// await this.getWriteableCarReader(carCid)
|
293
|
-
// console.log('readHeaderCar', carCid, carMapReader)
|
294
|
-
// now when we load the root cid from the car, we get our new custom root node
|
295
|
-
const bytes = await carMapReader.get(carMapReader.root.cid)
|
296
|
-
const decoded = await Block.decode({ bytes, hasher: blockOpts.hasher, codec: blockOpts.codec })
|
297
|
-
// @ts-ignore
|
298
|
-
const { fp: { cars, clock } } = decoded.value
|
299
|
-
return { cars, clock, reader: carMapReader }
|
300
|
-
}
|
301
|
-
|
302
|
-
// todo this is only because parkCar wants a writable reader to put the metadata block
|
303
|
-
// parkCar should handle it's own writeable wrapper, and it should love to be called with
|
304
|
-
// a read only car reader
|
305
|
-
async getWriteableCarReader (carReader) {
|
306
|
-
// console.log('getWriteableCarReader')
|
307
|
-
// const carReader = await this.getCarReader(carCid)
|
308
|
-
// console.log('getWriteableCarReader', carCid, carReader)
|
309
|
-
const theseWriteableBlocks = new VMemoryBlockstore()
|
310
|
-
const combinedReader = {
|
311
|
-
blocks: theseWriteableBlocks,
|
312
|
-
root: carReader?.root,
|
313
|
-
put: async (cid, bytes) => {
|
314
|
-
return await theseWriteableBlocks.put(cid, bytes)
|
315
|
-
},
|
316
|
-
get: async cid => {
|
317
|
-
// console.log('getWriteableCarReader get', cid)
|
318
|
-
try {
|
319
|
-
const got = await theseWriteableBlocks.get(cid)
|
320
|
-
return got.bytes
|
321
|
-
} catch (e) {
|
322
|
-
if (!carReader) throw e
|
323
|
-
const bytes = await carReader.get(cid)
|
324
|
-
// console.log('getWriteableCarReader', cid, bytes)
|
325
|
-
await theseWriteableBlocks.put(cid, bytes)
|
326
|
-
return bytes
|
327
|
-
}
|
328
|
-
}
|
329
|
-
}
|
330
|
-
return combinedReader
|
331
|
-
}
|
332
|
-
|
333
|
-
carReaderCache = new Map()
|
334
|
-
async getCarReader (carCid) {
|
335
|
-
if (!this.carReaderCache.has(carCid)) {
|
336
|
-
this.carReaderCache.set(carCid, this.getCarReaderImpl(carCid))
|
337
|
-
}
|
338
|
-
return this.carReaderCache.get(carCid)
|
339
|
-
}
|
340
|
-
|
341
|
-
async getCarReaderImpl (carCid) {
|
342
|
-
carCid = carCid.toString()
|
343
|
-
const carBytes = await this.readCar(carCid)
|
344
|
-
// console.log('getCarReader', this.constructor.name, carCid, carBytes.length)
|
345
|
-
const reader = await CarReader.fromBytes(carBytes)
|
346
|
-
// console.log('getCarReader', carCid, reader._header)
|
347
|
-
if (this.keyMaterial) {
|
348
|
-
const roots = await reader.getRoots()
|
349
|
-
const readerGetWithCodec = async cid => {
|
350
|
-
const got = await reader.get(cid)
|
351
|
-
let useCodec = codec
|
352
|
-
if (cid.toString().indexOf('bafy') === 0) {
|
353
|
-
// @ts-ignore
|
354
|
-
useCodec = dagcbor // todo this is a dirty check
|
355
|
-
}
|
356
|
-
const decoded = await Block.decode({
|
357
|
-
...got,
|
358
|
-
codec: useCodec,
|
359
|
-
hasher: sha256
|
360
|
-
})
|
361
|
-
return decoded
|
362
|
-
}
|
363
|
-
const { blocks } = await blocksFromEncryptedCarBlock(roots[0], readerGetWithCodec, this.keyMaterial)
|
364
|
-
const rootBlock = blocks[blocks.length - 1]
|
365
|
-
const blocksIterable = function * () {
|
366
|
-
for (const block of blocks) yield block
|
367
|
-
}
|
368
|
-
|
369
|
-
const gat = async dataCID => {
|
370
|
-
dataCID = dataCID.toString()
|
371
|
-
return blocks.find(b => b.cid.toString() === dataCID)
|
372
|
-
}
|
373
|
-
|
374
|
-
return {
|
375
|
-
entries: blocksIterable,
|
376
|
-
root: rootBlock,
|
377
|
-
gat,
|
378
|
-
get: async dataCID => {
|
379
|
-
const block = await gat(dataCID)
|
380
|
-
if (block) {
|
381
|
-
return block.bytes
|
382
|
-
}
|
383
|
-
}
|
384
|
-
}
|
385
|
-
} else {
|
386
|
-
const gat = async dataCID => {
|
387
|
-
return await reader.get(CID.parse(dataCID))
|
388
|
-
}
|
389
|
-
return {
|
390
|
-
// blocks,
|
391
|
-
entries: reader.blocks.bind(reader),
|
392
|
-
root: reader.getRoots()[0],
|
393
|
-
gat,
|
394
|
-
get: async dataCID => {
|
395
|
-
const gotBlock = await gat(dataCID)
|
396
|
-
if (gotBlock) {
|
397
|
-
return gotBlock.bytes
|
398
|
-
}
|
399
|
-
}
|
400
|
-
}
|
401
|
-
}
|
402
|
-
}
|
403
|
-
|
404
|
-
writeCars (cars) {}
|
405
|
-
|
406
|
-
// sequenceCarMapAppend (theCarMap, carCid) {
|
407
|
-
// // _last_compact
|
408
|
-
// // _last_sync (map per clock? you can find this by looking at a clocks car and it's position in the map)
|
409
|
-
// const oldMark = theCarMap.get('_last_compact') // todo we can track _next_seq directly
|
410
|
-
// // console.log('sequenceCarMapAppend oldMark', oldMark)
|
411
|
-
// const lastCompact = oldMark ? charwise.decode(oldMark) : 0
|
412
|
-
// // start iterating from the last compact point and find the first missing entry.
|
413
|
-
// // then write the carCid to that entry
|
414
|
-
// let next = lastCompact
|
415
|
-
// while (true) {
|
416
|
-
// const key = `_${charwise.encode(next)}`
|
417
|
-
// if (!theCarMap.has(key)) {
|
418
|
-
// console.log('sequenceCarMapAppend', next, key, carCid)
|
419
|
-
// theCarMap.set(key, carCid.toString())
|
420
|
-
// break
|
421
|
-
// } else {
|
422
|
-
// // const got = theCarMap.get(key)
|
423
|
-
// next++
|
424
|
-
// }
|
425
|
-
// }
|
426
|
-
// }
|
427
|
-
|
428
|
-
// async setLastCompact (lastCompactCarCid) {
|
429
|
-
// console.log('setLastCompact', lastCompactCarCid)
|
430
|
-
// const theCarMap = await this.getCidCarMap()
|
431
|
-
// const oldMark = theCarMap.get('_last_compact')
|
432
|
-
// const lastCompact = oldMark ? charwise.decode(oldMark) : 0
|
433
|
-
|
434
|
-
// let next = lastCompact
|
435
|
-
// while (true) {
|
436
|
-
// const key = `_${charwise.encode(next)}`
|
437
|
-
// if (!theCarMap.has(key)) {
|
438
|
-
// if (next === 0) {
|
439
|
-
// theCarMap.set('_last_compact', charwise.encode(next))
|
440
|
-
// break
|
441
|
-
// } else {
|
442
|
-
// throw new Error(`last compact point not found ${next} ${key}`)
|
443
|
-
// }
|
444
|
-
// } else {
|
445
|
-
// const got = theCarMap.get(key)
|
446
|
-
// // console.log('setLastCompact', key, got)
|
447
|
-
// if (got === lastCompactCarCid) {
|
448
|
-
// theCarMap.set('_last_compact', charwise.encode(next))
|
449
|
-
// break
|
450
|
-
// }
|
451
|
-
// next++
|
452
|
-
// }
|
453
|
-
// }
|
454
|
-
// }
|
455
|
-
|
456
|
-
async updateCarCidMap (dataCarCid, cids, head) {
|
457
|
-
// this hydrates the map if it has not been hydrated
|
458
|
-
const theCarMap = await this.getCidCarMap()
|
459
|
-
for (const cid of cids) {
|
460
|
-
theCarMap.set(cid, dataCarCid)
|
461
|
-
}
|
462
|
-
}
|
463
|
-
}
|
package/src/storage/browser.js
DELETED
@@ -1,67 +0,0 @@
|
|
1
|
-
import { openDB } from 'idb'
|
2
|
-
import { Base } from './base.js'
|
3
|
-
|
4
|
-
const defaultConfig = {
|
5
|
-
headerKeyPrefix: 'fp.' + Base.format
|
6
|
-
}
|
7
|
-
|
8
|
-
/* global localStorage */
|
9
|
-
|
10
|
-
export class Browser extends Base {
|
11
|
-
constructor (name, config = {}) {
|
12
|
-
super(name, Object.assign({}, defaultConfig, config))
|
13
|
-
}
|
14
|
-
|
15
|
-
withDB = async dbWorkFun => {
|
16
|
-
if (!this.idb) {
|
17
|
-
this.idb = await openDB(`fp.${Base.format}.${this.keyId}.${this.name}.valet`, 3, {
|
18
|
-
upgrade (db, oldVersion, newVersion, transaction) {
|
19
|
-
if (oldVersion < 1) {
|
20
|
-
db.createObjectStore('cars')
|
21
|
-
}
|
22
|
-
}
|
23
|
-
})
|
24
|
-
}
|
25
|
-
return await dbWorkFun(this.idb)
|
26
|
-
}
|
27
|
-
|
28
|
-
async writeCars (cars) {
|
29
|
-
if (this.config.readonly) return
|
30
|
-
return await this.withDB(async db => {
|
31
|
-
const tx = db.transaction(['cars'], 'readwrite')
|
32
|
-
for (const { cid, bytes, replaces } of cars) {
|
33
|
-
await tx.objectStore('cars').put(bytes, cid.toString())
|
34
|
-
// todo remove old maps
|
35
|
-
if (replaces) {
|
36
|
-
await tx.objectStore('cars').delete(replaces.toString())
|
37
|
-
}
|
38
|
-
}
|
39
|
-
return await tx.done
|
40
|
-
})
|
41
|
-
}
|
42
|
-
|
43
|
-
async readCar (carCid) {
|
44
|
-
return await this.withDB(async db => {
|
45
|
-
const tx = db.transaction(['cars'], 'readonly')
|
46
|
-
// console.log('getCarReader', carCid)
|
47
|
-
return await tx.objectStore('cars').get(carCid)
|
48
|
-
})
|
49
|
-
}
|
50
|
-
|
51
|
-
loadHeader (branch = 'main') {
|
52
|
-
try {
|
53
|
-
return JSON.parse(localStorage.getItem(this.headerKey(branch)))
|
54
|
-
} catch (e) {}
|
55
|
-
}
|
56
|
-
|
57
|
-
async writeHeader (branch, header) {
|
58
|
-
if (this.config.readonly) return
|
59
|
-
try {
|
60
|
-
return localStorage.setItem(this.headerKey(branch), header)
|
61
|
-
} catch (e) {}
|
62
|
-
}
|
63
|
-
|
64
|
-
headerKey (branch = 'main') {
|
65
|
-
return this.config.headerKeyPrefix + this.name + '.' + branch
|
66
|
-
}
|
67
|
-
}
|
@@ -1,73 +0,0 @@
|
|
1
|
-
|
2
|
-
// import { mkdir, writeFile } from 'fs/promises'
|
3
|
-
import { join, dirname } from 'path'
|
4
|
-
import { homedir } from 'os'
|
5
|
-
import { Base } from './base.js'
|
6
|
-
// import { readFileSync } from 'node:fs'
|
7
|
-
// const { readFileSync } = require('fs')
|
8
|
-
import fs from 'fs'
|
9
|
-
const readFileSync = fs.readFileSync
|
10
|
-
|
11
|
-
export const defaultConfig = {
|
12
|
-
dataDir: join(homedir(), '.fireproof', 'v' + Base.format)
|
13
|
-
}
|
14
|
-
|
15
|
-
export class Filesystem extends Base {
|
16
|
-
constructor (name, config = {}) {
|
17
|
-
const mergedConfig = Object.assign({}, defaultConfig, config)
|
18
|
-
// console.log('Filesystem', name, mergedConfig, header)
|
19
|
-
super(name, mergedConfig)
|
20
|
-
}
|
21
|
-
|
22
|
-
async writeCars (cars) {
|
23
|
-
if (this.config.readonly) return
|
24
|
-
const writes = []
|
25
|
-
for (const { cid, bytes } of cars) {
|
26
|
-
const carFilename = join(this.config.dataDir, this.name, `${cid.toString()}.car`)
|
27
|
-
// console.log('writeCars', carFilename)
|
28
|
-
writes.push(writeSync(carFilename, bytes))
|
29
|
-
}
|
30
|
-
await Promise.all(writes)
|
31
|
-
}
|
32
|
-
|
33
|
-
async readCar (carCid) {
|
34
|
-
const carFilename = join(this.config.dataDir, this.name, `${carCid.toString()}.car`)
|
35
|
-
const got = readFileSync(carFilename)
|
36
|
-
// console.log('readCar', carFilename, got.constructor.name)
|
37
|
-
return got
|
38
|
-
}
|
39
|
-
|
40
|
-
loadHeader (branch = 'main') {
|
41
|
-
const header = loadSync(this.headerFilename(branch))
|
42
|
-
// console.log('fs getHeader', this.headerFilename(), header, typeof header)
|
43
|
-
if (!header) return null
|
44
|
-
return JSON.parse(header)
|
45
|
-
}
|
46
|
-
|
47
|
-
async writeHeader (branch, header) {
|
48
|
-
// console.log('saveHeader fs', header)
|
49
|
-
if (this.config.readonly) return
|
50
|
-
// console.log('writeHeader fs', branch, pHeader)
|
51
|
-
await writeSync(this.headerFilename(branch), header)
|
52
|
-
}
|
53
|
-
|
54
|
-
headerFilename (branch = 'main') {
|
55
|
-
// console.log('headerFilename', this.config.dataDir, this.name)
|
56
|
-
return join(this.config.dataDir, this.name, branch + '.json')
|
57
|
-
}
|
58
|
-
}
|
59
|
-
|
60
|
-
function loadSync (filename) {
|
61
|
-
try {
|
62
|
-
return readFileSync(filename, 'utf8').toString()
|
63
|
-
} catch (error) {
|
64
|
-
// console.log('error', error)
|
65
|
-
return null
|
66
|
-
}
|
67
|
-
}
|
68
|
-
|
69
|
-
async function writeSync (fullpath, stringValue) {
|
70
|
-
await fs.promises.mkdir(dirname(fullpath), { recursive: true })
|
71
|
-
// writeFileSync(fullpath, stringValue)
|
72
|
-
await fs.promises.writeFile(fullpath, stringValue)
|
73
|
-
}
|
package/src/storage/rest.js
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
import fetch from 'cross-fetch'
|
2
|
-
import { Base } from './base.js'
|
3
|
-
|
4
|
-
const defaultConfig = {
|
5
|
-
url: 'http://localhost:4000/v' + Base.format
|
6
|
-
}
|
7
|
-
|
8
|
-
export class Rest extends Base {
|
9
|
-
constructor (name, config = {}) {
|
10
|
-
super(name, Object.assign({}, defaultConfig, config))
|
11
|
-
// console.log('Rest', name, config)
|
12
|
-
}
|
13
|
-
|
14
|
-
headerURL (branch = 'main') {
|
15
|
-
return `${this.config.url}/${branch}.json`
|
16
|
-
}
|
17
|
-
|
18
|
-
async writeCars (cars) {
|
19
|
-
if (this.config.readonly) return
|
20
|
-
for (const { cid, bytes } of cars) {
|
21
|
-
const carURL = `${this.config.url}/${cid.toString()}.car`
|
22
|
-
const response = await fetch(carURL, {
|
23
|
-
method: 'PUT',
|
24
|
-
body: bytes,
|
25
|
-
headers: { 'Content-Type': 'application/car' }
|
26
|
-
})
|
27
|
-
if (!response.ok) throw new Error(`An error occurred: ${response.statusText}`)
|
28
|
-
}
|
29
|
-
}
|
30
|
-
|
31
|
-
async readCar (carCid) {
|
32
|
-
const carURL = `${this.config.url}/${carCid.toString()}.car`
|
33
|
-
const response = await fetch(carURL)
|
34
|
-
if (!response.ok) throw new Error(`An error occurred: ${response.statusText}`)
|
35
|
-
const got = await response.arrayBuffer()
|
36
|
-
return new Uint8Array(got)
|
37
|
-
}
|
38
|
-
|
39
|
-
async loadHeader (branch = 'main') {
|
40
|
-
const response = await fetch(this.headerURL(branch))
|
41
|
-
// console.log('rest getHeader', response.constructor.name)
|
42
|
-
if (!response.ok) return null
|
43
|
-
const got = await response.json()
|
44
|
-
// console.log('rest getHeader', got)
|
45
|
-
return got
|
46
|
-
}
|
47
|
-
|
48
|
-
async writeHeader (branch, header) {
|
49
|
-
if (this.config.readonly) return
|
50
|
-
// console.log('writeHeader rt', branch, pHeader)
|
51
|
-
|
52
|
-
const response = await fetch(this.headerURL(branch), {
|
53
|
-
method: 'PUT',
|
54
|
-
body: header,
|
55
|
-
headers: { 'Content-Type': 'application/json' }
|
56
|
-
})
|
57
|
-
if (!response.ok) throw new Error(`An error occurred: ${response.statusText}`)
|
58
|
-
}
|
59
|
-
}
|
package/src/storage/ucan.js
DELETED
File without changes
|