@fireproof/core 0.7.3-dev.2 → 0.8.0-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.
- package/dist/blockstore.js +6 -0
- package/dist/database.js +6 -3
- package/dist/fireproof.js +1 -0
- package/dist/loader.js +0 -4
- package/dist/prolly.js +1 -1
- package/dist/remote.js +46 -0
- package/dist/src/fireproof.d.ts +2 -2
- package/dist/src/fireproof.js +74 -69
- package/dist/src/fireproof.js.map +1 -1
- package/dist/src/fireproof.mjs +74 -69
- package/dist/src/fireproof.mjs.map +1 -1
- package/dist/storage/base.js +53 -15
- package/dist/storage/ucan.js +0 -40
- package/package.json +1 -5
- package/src/blockstore.js +4 -0
- package/src/database.js +5 -3
- package/src/fireproof.js +1 -0
- package/src/loader.js +0 -5
- package/src/prolly.js +1 -1
- package/src/storage/base.js +61 -15
- package/src/storage/ucan.js +0 -45
    
        package/dist/storage/base.js
    CHANGED
    
    | @@ -91,10 +91,11 @@ export class Base { | |
| 91 91 | 
             
                    }
         | 
| 92 92 | 
             
                    cidMap.clear();
         | 
| 93 93 | 
             
                    const blocks = {
         | 
| 94 | 
            +
                        head: clock,
         | 
| 94 95 | 
             
                        lastCid: clock[0],
         | 
| 95 96 | 
             
                        get: cid => allBlocks.get(cid.toString())
         | 
| 96 97 | 
             
                    };
         | 
| 97 | 
            -
                    console.log('compact', this.instanceId, this.name, blocks.lastCid.toString(), dataCids.length) | 
| 98 | 
            +
                    // console.log('compact', this.instanceId, this.name, blocks.lastCid.toString(), dataCids.length)
         | 
| 98 99 | 
             
                    await this.parkCar(blocks, dataCids);
         | 
| 99 100 | 
             
                }
         | 
| 100 101 | 
             
                async parkCar(innerBlockstore, cids) {
         | 
| @@ -111,10 +112,10 @@ export class Base { | |
| 111 112 | 
             
                        newCar = await blocksToCarBlock(innerBlockstore.lastCid, innerBlockstore);
         | 
| 112 113 | 
             
                    }
         | 
| 113 114 | 
             
                    // console.log('new car', newCar.cid.toString())
         | 
| 114 | 
            -
                    return await this.saveCar(newCar.cid.toString(), newCar.bytes, cids);
         | 
| 115 | 
            +
                    return await this.saveCar(newCar.cid.toString(), newCar.bytes, cids, innerBlockstore.head);
         | 
| 115 116 | 
             
                }
         | 
| 116 | 
            -
                async saveCar(carCid, value, cids) {
         | 
| 117 | 
            -
                    const newValetCidCar = await this.updateCarCidMap(carCid, cids);
         | 
| 117 | 
            +
                async saveCar(carCid, value, cids, head = null) {
         | 
| 118 | 
            +
                    const newValetCidCar = await this.updateCarCidMap(carCid, cids, head);
         | 
| 118 119 | 
             
                    // console.log('writeCars', carCid.toString(), newValetCidCar.cid.toString())
         | 
| 119 120 | 
             
                    const carList = [
         | 
| 120 121 | 
             
                        {
         | 
| @@ -134,7 +135,7 @@ export class Base { | |
| 134 135 | 
             
                    // console.trace('saved car', this.instanceId, this.name, newValetCidCar.cid.toString())
         | 
| 135 136 | 
             
                    return newValetCidCar;
         | 
| 136 137 | 
             
                }
         | 
| 137 | 
            -
                applyHeaders(headers) {
         | 
| 138 | 
            +
                async applyHeaders(headers) {
         | 
| 138 139 | 
             
                    // console.log('applyHeaders', headers.index)
         | 
| 139 140 | 
             
                    this.headers = headers;
         | 
| 140 141 | 
             
                    // console.log('before applied', this.instanceId, this.name, this.keyMaterial, this.valetRootCarCid)
         | 
| @@ -143,6 +144,9 @@ export class Base { | |
| 143 144 | 
             
                            // console.log('applyHeaders', this.instanceId, this.name, header.key, header.car)
         | 
| 144 145 | 
             
                            header.key && this.setKeyMaterial(header.key);
         | 
| 145 146 | 
             
                            this.setCarCidMapCarCid(header.car);
         | 
| 147 | 
            +
                            const { clock } = await this.readHeaderCar(header.car);
         | 
| 148 | 
            +
                            // console.log('stored clock', this.name, branch, clock, header)
         | 
| 149 | 
            +
                            header.clock = clock.map(c => c.toString());
         | 
| 146 150 | 
             
                        }
         | 
| 147 151 | 
             
                    }
         | 
| 148 152 | 
             
                    if (!this.valetRootCarCid) {
         | 
| @@ -163,18 +167,28 @@ export class Base { | |
| 163 167 | 
             
                    const headers = {};
         | 
| 164 168 | 
             
                    for (const [branch] of Object.entries(this.config.branches)) {
         | 
| 165 169 | 
             
                        const got = await this.loadHeader(branch);
         | 
| 170 | 
            +
                        // const carCid = got.car
         | 
| 166 171 | 
             
                        // console.log('getHeaders', this.name, branch, got)
         | 
| 172 | 
            +
                        // if (got && got.car) {
         | 
| 173 | 
            +
                        // const { clock } = await this.readHeaderCar(got.car)
         | 
| 174 | 
            +
                        // console.log('stored clock', this.name, branch, clock)
         | 
| 175 | 
            +
                        // }
         | 
| 167 176 | 
             
                        headers[branch] = got;
         | 
| 168 177 | 
             
                    }
         | 
| 169 | 
            -
                    this.applyHeaders(headers);
         | 
| 178 | 
            +
                    await this.applyHeaders(headers);
         | 
| 170 179 | 
             
                    return headers;
         | 
| 171 180 | 
             
                }
         | 
| 172 181 | 
             
                loadHeader(branch = 'main') {
         | 
| 173 | 
            -
                     | 
| 182 | 
            +
                    if (NOT_IMPL)
         | 
| 183 | 
            +
                        throw new Error('not implemented');
         | 
| 184 | 
            +
                    return {};
         | 
| 185 | 
            +
                }
         | 
| 186 | 
            +
                async getStoredClock(carCid) {
         | 
| 174 187 | 
             
                }
         | 
| 175 188 | 
             
                async saveHeader(header) {
         | 
| 189 | 
            +
                    // this.clock = header.clock
         | 
| 176 190 | 
             
                    // for each branch, save the header
         | 
| 177 | 
            -
                    // console.log('saveHeader',  | 
| 191 | 
            +
                    // console.log('saveHeader', header.clock)
         | 
| 178 192 | 
             
                    //  for (const branch of this.branches) {
         | 
| 179 193 | 
             
                    //    await this.saveBranchHeader(branch)
         | 
| 180 194 | 
             
                    //  }
         | 
| @@ -233,8 +247,10 @@ export class Base { | |
| 233 247 | 
             
                async mapForIPLDHashmapCarCid(carCid) {
         | 
| 234 248 | 
             
                    // console.log('mapForIPLDHashmapCarCid', carCid)
         | 
| 235 249 | 
             
                    // todo why is this writeable?
         | 
| 236 | 
            -
                    const carMapReader = await this. | 
| 237 | 
            -
                     | 
| 250 | 
            +
                    const { cars, reader: carMapReader } = await this.readHeaderCar(carCid);
         | 
| 251 | 
            +
                    // this.clock = clock
         | 
| 252 | 
            +
                    // console.log('mapForIPLDHashmapCarCid', cars)
         | 
| 253 | 
            +
                    const indexNode = await load(carMapReader, cars, {
         | 
| 238 254 | 
             
                        blockHasher: blockOpts.hasher,
         | 
| 239 255 | 
             
                        blockCodec: blockOpts.codec
         | 
| 240 256 | 
             
                    });
         | 
| @@ -245,9 +261,20 @@ export class Base { | |
| 245 261 | 
             
                    }
         | 
| 246 262 | 
             
                    return theCarMap;
         | 
| 247 263 | 
             
                }
         | 
| 264 | 
            +
                async readHeaderCar(carCid) {
         | 
| 265 | 
            +
                    const carMapReader = await this.getWriteableCarReader(carCid);
         | 
| 266 | 
            +
                    // console.log('readHeaderCar', carCid, carMapReader)
         | 
| 267 | 
            +
                    // now when we load the root cid from the car, we get our new custom root node
         | 
| 268 | 
            +
                    const bytes = await carMapReader.get(carMapReader.root.cid);
         | 
| 269 | 
            +
                    const decoded = await Block.decode({ bytes, hasher: blockOpts.hasher, codec: blockOpts.codec });
         | 
| 270 | 
            +
                    // @ts-ignore
         | 
| 271 | 
            +
                    const { fp: { cars, clock } } = decoded.value;
         | 
| 272 | 
            +
                    return { cars, clock, reader: carMapReader };
         | 
| 273 | 
            +
                }
         | 
| 248 274 | 
             
                async getWriteableCarReader(carCid) {
         | 
| 249 275 | 
             
                    // console.log('getWriteableCarReader', carCid)
         | 
| 250 276 | 
             
                    const carMapReader = await this.getCarReader(carCid);
         | 
| 277 | 
            +
                    // console.log('getWriteableCarReader', carCid, carMapReader)
         | 
| 251 278 | 
             
                    const theseWriteableBlocks = new VMemoryBlockstore();
         | 
| 252 279 | 
             
                    const combinedReader = {
         | 
| 253 280 | 
             
                        blocks: theseWriteableBlocks,
         | 
| @@ -283,12 +310,16 @@ export class Base { | |
| 283 310 | 
             
                }
         | 
| 284 311 | 
             
                async getCarReaderImpl(carCid) {
         | 
| 285 312 | 
             
                    carCid = carCid.toString();
         | 
| 313 | 
            +
                    // console.log('getCarReaderImpl', carCid)
         | 
| 286 314 | 
             
                    const carBytes = await this.readCar(carCid);
         | 
| 287 315 | 
             
                    // console.log('getCarReader', this.constructor.name, carCid, carBytes.length)
         | 
| 288 316 | 
             
                    const reader = await CarReader.fromBytes(carBytes);
         | 
| 317 | 
            +
                    // console.log('getCarReader', carCid, reader._header)
         | 
| 289 318 | 
             
                    if (this.keyMaterial) {
         | 
| 290 319 | 
             
                        const roots = await reader.getRoots();
         | 
| 320 | 
            +
                        // let count = 0
         | 
| 291 321 | 
             
                        const readerGetWithCodec = async (cid) => {
         | 
| 322 | 
            +
                            // console.log('readerGetWithCodec', count++, cid)
         | 
| 292 323 | 
             
                            const got = await reader.get(cid);
         | 
| 293 324 | 
             
                            let useCodec = codec;
         | 
| 294 325 | 
             
                            if (cid.toString().indexOf('bafy') === 0) {
         | 
| @@ -343,16 +374,16 @@ export class Base { | |
| 343 374 | 
             
                    }
         | 
| 344 375 | 
             
                }
         | 
| 345 376 | 
             
                writeCars(cars) { }
         | 
| 346 | 
            -
                async updateCarCidMap(carCid, cids) {
         | 
| 377 | 
            +
                async updateCarCidMap(carCid, cids, head) {
         | 
| 347 378 | 
             
                    // this hydrates the map if it has not been hydrated
         | 
| 348 379 | 
             
                    const theCarMap = await this.getCidCarMap();
         | 
| 349 380 | 
             
                    for (const cid of cids) {
         | 
| 350 381 | 
             
                        theCarMap.set(cid, carCid);
         | 
| 351 382 | 
             
                    }
         | 
| 352 383 | 
             
                    // todo can we debounce this? -- maybe put it into a queue so we can batch it
         | 
| 353 | 
            -
                    return await this.persistCarMap(theCarMap);
         | 
| 384 | 
            +
                    return await this.persistCarMap(theCarMap, head);
         | 
| 354 385 | 
             
                }
         | 
| 355 | 
            -
                async persistCarMap(theCarMap) {
         | 
| 386 | 
            +
                async persistCarMap(theCarMap, head) {
         | 
| 356 387 | 
             
                    const ipldLoader = await getEmptyLoader();
         | 
| 357 388 | 
             
                    const indexNode = await create(ipldLoader, {
         | 
| 358 389 | 
             
                        bitWidth: 4,
         | 
| @@ -363,14 +394,20 @@ export class Base { | |
| 363 394 | 
             
                    for (const [key, value] of theCarMap.entries()) {
         | 
| 364 395 | 
             
                        await indexNode.set(key, value);
         | 
| 365 396 | 
             
                    }
         | 
| 397 | 
            +
                    // console.log('persistCarMap', indexNode.cid, head)
         | 
| 398 | 
            +
                    const value = { fp: { cars: indexNode.cid, clock: head } };
         | 
| 399 | 
            +
                    const header = await Block.encode({ value, hasher: blockOpts.hasher, codec: blockOpts.codec });
         | 
| 400 | 
            +
                    ipldLoader.blocks.put(header.cid, header.bytes);
         | 
| 366 401 | 
             
                    let newValetCidCar;
         | 
| 367 402 | 
             
                    if (this.keyMaterial) {
         | 
| 368 403 | 
             
                        const cids = [...ipldLoader.blocks.blocks.keys()];
         | 
| 369 404 | 
             
                        // console.log('persistCarMap', cids)
         | 
| 370 | 
            -
                         | 
| 405 | 
            +
                        // store the clock head and a link to the indexNode.cid in a custom root?
         | 
| 406 | 
            +
                        newValetCidCar = await blocksToEncryptedCarBlock(header.cid, ipldLoader.blocks, this.keyMaterial, cids);
         | 
| 407 | 
            +
                        // then put this carcid into the header / w3clock
         | 
| 371 408 | 
             
                    }
         | 
| 372 409 | 
             
                    else {
         | 
| 373 | 
            -
                        newValetCidCar = await blocksToCarBlock( | 
| 410 | 
            +
                        newValetCidCar = await blocksToCarBlock(header.cid, ipldLoader.blocks);
         | 
| 374 411 | 
             
                    }
         | 
| 375 412 | 
             
                    return newValetCidCar;
         | 
| 376 413 | 
             
                }
         | 
| @@ -497,6 +534,7 @@ export const blocksFromEncryptedCarBlock = async (cid, get, keyMaterial) => { | |
| 497 534 | 
             
                            cache
         | 
| 498 535 | 
             
                            // codec: dagcbor
         | 
| 499 536 | 
             
                        })) {
         | 
| 537 | 
            +
                            // console.log('decrypted', block.cid.toString())
         | 
| 500 538 | 
             
                            decryptedBlocks.push(block);
         | 
| 501 539 | 
             
                            cids.add(block.cid.toString());
         | 
| 502 540 | 
             
                        }
         | 
    
        package/dist/storage/ucan.js
    CHANGED
    
    | @@ -1,40 +0,0 @@ | |
| 1 | 
            -
            import fetch from 'cross-fetch';
         | 
| 2 | 
            -
            import { Base } from './base.js';
         | 
| 3 | 
            -
            const defaultConfig = {
         | 
| 4 | 
            -
                upload: () => { },
         | 
| 5 | 
            -
                url: (cid) => `https://${cid}.ipfs.w3s.link/`
         | 
| 6 | 
            -
            };
         | 
| 7 | 
            -
            export class UCAN extends Base {
         | 
| 8 | 
            -
                constructor(name, config = {}) {
         | 
| 9 | 
            -
                    super(name, Object.assign({}, defaultConfig, config));
         | 
| 10 | 
            -
                }
         | 
| 11 | 
            -
                async writeCars(cars) {
         | 
| 12 | 
            -
                    if (this.config.readonly)
         | 
| 13 | 
            -
                        return;
         | 
| 14 | 
            -
                    for (const { cid, bytes } of cars) {
         | 
| 15 | 
            -
                        console.log(`write UCAN ${cid}, ${bytes.length} bytes`);
         | 
| 16 | 
            -
                        const upCid = await this.config.upload(bytes);
         | 
| 17 | 
            -
                        console.log(`wrote UCAN ${cid}, ${upCid}`);
         | 
| 18 | 
            -
                        // if (!response.ok) throw new Error(`An error occurred: ${response.statusText}`)
         | 
| 19 | 
            -
                    }
         | 
| 20 | 
            -
                }
         | 
| 21 | 
            -
                async readCar(carCid) {
         | 
| 22 | 
            -
                    const carURL = this.config.url(carCid);
         | 
| 23 | 
            -
                    const response = await fetch(carURL);
         | 
| 24 | 
            -
                    if (!response.ok)
         | 
| 25 | 
            -
                        throw new Error(`An error occurred: ${response.statusText}`);
         | 
| 26 | 
            -
                    const got = await response.arrayBuffer();
         | 
| 27 | 
            -
                    return new Uint8Array(got);
         | 
| 28 | 
            -
                }
         | 
| 29 | 
            -
                async loadHeader(branch = 'main') {
         | 
| 30 | 
            -
                    return headerMock.get(branch);
         | 
| 31 | 
            -
                }
         | 
| 32 | 
            -
                async writeHeader(branch, header) {
         | 
| 33 | 
            -
                    if (this.config.readonly)
         | 
| 34 | 
            -
                        return;
         | 
| 35 | 
            -
                    const pHeader = this.prepareHeader(header);
         | 
| 36 | 
            -
                    // console.log('writeHeader rt', branch, pHeader)
         | 
| 37 | 
            -
                    headerMock.set(branch, pHeader);
         | 
| 38 | 
            -
                }
         | 
| 39 | 
            -
            }
         | 
| 40 | 
            -
            const headerMock = new Map();
         | 
    
        package/package.json
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            {
         | 
| 2 2 | 
             
              "name": "@fireproof/core",
         | 
| 3 | 
            -
              "version": "0. | 
| 3 | 
            +
              "version": "0.8.0-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",
         | 
| @@ -42,10 +42,6 @@ | |
| 42 42 | 
             
                "@ipld/car": "^5.1.0",
         | 
| 43 43 | 
             
                "@ipld/dag-cbor": "^9.0.0",
         | 
| 44 44 | 
             
                "@jsonlines/core": "^1.0.2",
         | 
| 45 | 
            -
                "@ucanto/principal": "^8.0.0",
         | 
| 46 | 
            -
                "@ucanto/server": "^8.0.1",
         | 
| 47 | 
            -
                "@ucanto/transport": "^8.0.0",
         | 
| 48 | 
            -
                "@ucanto/validator": "^8.0.0",
         | 
| 49 45 | 
             
                "async": "^3.2.4",
         | 
| 50 46 | 
             
                "charwise": "^3.0.1",
         | 
| 51 47 | 
             
                "cross-fetch": "^3.1.6",
         | 
    
        package/src/blockstore.js
    CHANGED
    
    | @@ -221,6 +221,9 @@ export const doTransaction = async (label, blockstore, doFun, doSync = true) => | |
| 221 221 | 
             
              const innerBlockstore = blockstore.begin(label)
         | 
| 222 222 | 
             
              try {
         | 
| 223 223 | 
             
                const result = await doFun(innerBlockstore)
         | 
| 224 | 
            +
                // console.log('doTransaction', label, 'result', result.head)
         | 
| 225 | 
            +
                if (result && result.head) { innerBlockstore.head = result.head }
         | 
| 226 | 
            +
                // pass the latest clock head for writing to the valet
         | 
| 224 227 | 
             
                // @ts-ignore
         | 
| 225 228 | 
             
                await blockstore.commit(innerBlockstore, doSync)
         | 
| 226 229 | 
             
                return result
         | 
| @@ -236,6 +239,7 @@ export const doTransaction = async (label, blockstore, doFun, doSync = true) => | |
| 236 239 | 
             
            export class InnerBlockstore {
         | 
| 237 240 | 
             
              /** @type {Map<string, Uint8Array>} */
         | 
| 238 241 | 
             
              blocks = new Map()
         | 
| 242 | 
            +
              head = []
         | 
| 239 243 | 
             
              lastCid = null
         | 
| 240 244 | 
             
              label = ''
         | 
| 241 245 | 
             
              parentBlockstore = null
         | 
    
        package/src/database.js
    CHANGED
    
    | @@ -92,7 +92,7 @@ export class Database { | |
| 92 92 |  | 
| 93 93 | 
             
              toHeader () {
         | 
| 94 94 | 
             
                return {
         | 
| 95 | 
            -
                  clock: this.clockToJSON(),
         | 
| 95 | 
            +
                  // clock: this.clockToJSON(),
         | 
| 96 96 | 
             
                  name: this.name,
         | 
| 97 97 | 
             
                  index: {
         | 
| 98 98 | 
             
                    key: this.indexBlocks.valet?.primary.keyMaterial,
         | 
| @@ -277,11 +277,13 @@ export class Database { | |
| 277 277 | 
             
               * @memberof Fireproof
         | 
| 278 278 | 
             
               * @instance
         | 
| 279 279 | 
             
               */
         | 
| 280 | 
            -
              async put ({ _id, _proof, ...doc }) {
         | 
| 280 | 
            +
              async put ({ _id, _proof, _clock, ...doc }) {
         | 
| 281 281 | 
             
                await this.ready
         | 
| 282 282 | 
             
                const id = _id || 'f' + Math.random().toString(36).slice(2)
         | 
| 283 | 
            +
                doc = JSON.parse(JSON.stringify(doc))
         | 
| 284 | 
            +
                if (_clock) doc._clock = _clock
         | 
| 283 285 | 
             
                await this.runValidation({ _id: id, ...doc })
         | 
| 284 | 
            -
                return await this.putToProllyTree({ key: id, value: doc },  | 
| 286 | 
            +
                return await this.putToProllyTree({ key: id, value: doc }, _clock)
         | 
| 285 287 | 
             
              }
         | 
| 286 288 |  | 
| 287 289 | 
             
              /**
         | 
    
        package/src/fireproof.js
    CHANGED
    
    
    
        package/src/loader.js
    CHANGED
    
    | @@ -1,6 +1,5 @@ | |
| 1 1 | 
             
            import { Browser } from './storage/browser.js'
         | 
| 2 2 | 
             
            import { Rest } from './storage/rest.js'
         | 
| 3 | 
            -
            import { UCAN } from './storage/ucan.js'
         | 
| 4 3 |  | 
| 5 4 | 
             
            export const Loader = {
         | 
| 6 5 | 
             
              appropriate: (name, config = {}) => {
         | 
| @@ -12,10 +11,6 @@ export const Loader = { | |
| 12 11 | 
             
                  return new Rest(name, config)
         | 
| 13 12 | 
             
                }
         | 
| 14 13 |  | 
| 15 | 
            -
                if (config.type === 'ucan') {
         | 
| 16 | 
            -
                  return new UCAN(name, config)
         | 
| 17 | 
            -
                }
         | 
| 18 | 
            -
             | 
| 19 14 | 
             
                return new Browser(name, config)
         | 
| 20 15 | 
             
              }
         | 
| 21 16 | 
             
            }
         | 
    
        package/src/prolly.js
    CHANGED
    
    | @@ -307,7 +307,7 @@ export async function root (inBlocks, head, doFull = false) { | |
| 307 307 | 
             
                    bigPut(nb)
         | 
| 308 308 | 
             
                  }
         | 
| 309 309 | 
             
                  // console.log('root root', newProllyRootNode.constructor.name, newProllyRootNode)
         | 
| 310 | 
            -
                  return { clockCIDs, node: newProllyRootNode }
         | 
| 310 | 
            +
                  return { clockCIDs, node: newProllyRootNode, head }
         | 
| 311 311 | 
             
                },
         | 
| 312 312 | 
             
                false
         | 
| 313 313 | 
             
              )
         | 
    
        package/src/storage/base.js
    CHANGED
    
    | @@ -101,10 +101,11 @@ export class Base { | |
| 101 101 | 
             
                }
         | 
| 102 102 | 
             
                cidMap.clear()
         | 
| 103 103 | 
             
                const blocks = {
         | 
| 104 | 
            +
                  head: clock,
         | 
| 104 105 | 
             
                  lastCid: clock[0],
         | 
| 105 106 | 
             
                  get: cid => allBlocks.get(cid.toString())
         | 
| 106 107 | 
             
                }
         | 
| 107 | 
            -
                console.log('compact', this.instanceId, this.name, blocks.lastCid.toString(), dataCids.length)
         | 
| 108 | 
            +
                // console.log('compact', this.instanceId, this.name, blocks.lastCid.toString(), dataCids.length)
         | 
| 108 109 | 
             
                await this.parkCar(blocks, dataCids)
         | 
| 109 110 | 
             
              }
         | 
| 110 111 |  | 
| @@ -120,11 +121,11 @@ export class Base { | |
| 120 121 | 
             
                  newCar = await blocksToCarBlock(innerBlockstore.lastCid, innerBlockstore)
         | 
| 121 122 | 
             
                }
         | 
| 122 123 | 
             
                // console.log('new car', newCar.cid.toString())
         | 
| 123 | 
            -
                return await this.saveCar(newCar.cid.toString(), newCar.bytes, cids)
         | 
| 124 | 
            +
                return await this.saveCar(newCar.cid.toString(), newCar.bytes, cids, innerBlockstore.head)
         | 
| 124 125 | 
             
              }
         | 
| 125 126 |  | 
| 126 | 
            -
              async saveCar (carCid, value, cids) {
         | 
| 127 | 
            -
                const newValetCidCar = await this.updateCarCidMap(carCid, cids)
         | 
| 127 | 
            +
              async saveCar (carCid, value, cids, head = null) {
         | 
| 128 | 
            +
                const newValetCidCar = await this.updateCarCidMap(carCid, cids, head)
         | 
| 128 129 | 
             
                // console.log('writeCars', carCid.toString(), newValetCidCar.cid.toString())
         | 
| 129 130 | 
             
                const carList = [
         | 
| 130 131 | 
             
                  {
         | 
| @@ -146,7 +147,7 @@ export class Base { | |
| 146 147 | 
             
                return newValetCidCar
         | 
| 147 148 | 
             
              }
         | 
| 148 149 |  | 
| 149 | 
            -
              applyHeaders (headers) {
         | 
| 150 | 
            +
              async applyHeaders (headers) {
         | 
| 150 151 | 
             
                // console.log('applyHeaders', headers.index)
         | 
| 151 152 | 
             
                this.headers = headers
         | 
| 152 153 | 
             
                // console.log('before applied', this.instanceId, this.name, this.keyMaterial, this.valetRootCarCid)
         | 
| @@ -155,6 +156,9 @@ export class Base { | |
| 155 156 | 
             
                    // console.log('applyHeaders', this.instanceId, this.name, header.key, header.car)
         | 
| 156 157 | 
             
                    header.key && this.setKeyMaterial(header.key)
         | 
| 157 158 | 
             
                    this.setCarCidMapCarCid(header.car)
         | 
| 159 | 
            +
                    const { clock } = await this.readHeaderCar(header.car)
         | 
| 160 | 
            +
                    // console.log('stored clock', this.name, branch, clock, header)
         | 
| 161 | 
            +
                    header.clock = clock.map(c => c.toString())
         | 
| 158 162 | 
             
                  }
         | 
| 159 163 | 
             
                }
         | 
| 160 164 | 
             
                if (!this.valetRootCarCid) {
         | 
| @@ -175,20 +179,32 @@ export class Base { | |
| 175 179 | 
             
                const headers = {}
         | 
| 176 180 | 
             
                for (const [branch] of Object.entries(this.config.branches)) {
         | 
| 177 181 | 
             
                  const got = await this.loadHeader(branch)
         | 
| 182 | 
            +
                  // const carCid = got.car
         | 
| 178 183 | 
             
                  // console.log('getHeaders', this.name, branch, got)
         | 
| 184 | 
            +
                  // if (got && got.car) {
         | 
| 185 | 
            +
                  // const { clock } = await this.readHeaderCar(got.car)
         | 
| 186 | 
            +
                  // console.log('stored clock', this.name, branch, clock)
         | 
| 187 | 
            +
                  // }
         | 
| 188 | 
            +
             | 
| 179 189 | 
             
                  headers[branch] = got
         | 
| 180 190 | 
             
                }
         | 
| 181 | 
            -
                this.applyHeaders(headers)
         | 
| 191 | 
            +
                await this.applyHeaders(headers)
         | 
| 182 192 | 
             
                return headers
         | 
| 183 193 | 
             
              }
         | 
| 184 194 |  | 
| 185 195 | 
             
              loadHeader (branch = 'main') {
         | 
| 186 | 
            -
                throw new Error('not implemented')
         | 
| 196 | 
            +
                if (NOT_IMPL) throw new Error('not implemented')
         | 
| 197 | 
            +
                return {}
         | 
| 198 | 
            +
              }
         | 
| 199 | 
            +
             | 
| 200 | 
            +
              async getStoredClock (carCid) {
         | 
| 201 | 
            +
             | 
| 187 202 | 
             
              }
         | 
| 188 203 |  | 
| 189 204 | 
             
              async saveHeader (header) {
         | 
| 205 | 
            +
                // this.clock = header.clock
         | 
| 190 206 | 
             
                // for each branch, save the header
         | 
| 191 | 
            -
                // console.log('saveHeader',  | 
| 207 | 
            +
                // console.log('saveHeader', header.clock)
         | 
| 192 208 | 
             
                //  for (const branch of this.branches) {
         | 
| 193 209 | 
             
                //    await this.saveBranchHeader(branch)
         | 
| 194 210 | 
             
                //  }
         | 
| @@ -251,8 +267,13 @@ export class Base { | |
| 251 267 | 
             
              async mapForIPLDHashmapCarCid (carCid) {
         | 
| 252 268 | 
             
                // console.log('mapForIPLDHashmapCarCid', carCid)
         | 
| 253 269 | 
             
                // todo why is this writeable?
         | 
| 254 | 
            -
                const carMapReader = await this. | 
| 255 | 
            -
             | 
| 270 | 
            +
                const { cars, reader: carMapReader } = await this.readHeaderCar(carCid)
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                // this.clock = clock
         | 
| 273 | 
            +
             | 
| 274 | 
            +
                // console.log('mapForIPLDHashmapCarCid', cars)
         | 
| 275 | 
            +
             | 
| 276 | 
            +
                const indexNode = await load(carMapReader, cars, {
         | 
| 256 277 | 
             
                  blockHasher: blockOpts.hasher,
         | 
| 257 278 | 
             
                  blockCodec: blockOpts.codec
         | 
| 258 279 | 
             
                })
         | 
| @@ -264,9 +285,21 @@ export class Base { | |
| 264 285 | 
             
                return theCarMap
         | 
| 265 286 | 
             
              }
         | 
| 266 287 |  | 
| 288 | 
            +
              async readHeaderCar (carCid) {
         | 
| 289 | 
            +
                const carMapReader = await this.getWriteableCarReader(carCid)
         | 
| 290 | 
            +
                // console.log('readHeaderCar', carCid, carMapReader)
         | 
| 291 | 
            +
                // now when we load the root cid from the car, we get our new custom root node
         | 
| 292 | 
            +
                const bytes = await carMapReader.get(carMapReader.root.cid)
         | 
| 293 | 
            +
                const decoded = await Block.decode({ bytes, hasher: blockOpts.hasher, codec: blockOpts.codec })
         | 
| 294 | 
            +
                // @ts-ignore
         | 
| 295 | 
            +
                const { fp: { cars, clock } } = decoded.value
         | 
| 296 | 
            +
                return { cars, clock, reader: carMapReader }
         | 
| 297 | 
            +
              }
         | 
| 298 | 
            +
             | 
| 267 299 | 
             
              async getWriteableCarReader (carCid) {
         | 
| 268 300 | 
             
                // console.log('getWriteableCarReader', carCid)
         | 
| 269 301 | 
             
                const carMapReader = await this.getCarReader(carCid)
         | 
| 302 | 
            +
                // console.log('getWriteableCarReader', carCid, carMapReader)
         | 
| 270 303 | 
             
                const theseWriteableBlocks = new VMemoryBlockstore()
         | 
| 271 304 | 
             
                const combinedReader = {
         | 
| 272 305 | 
             
                  blocks: theseWriteableBlocks,
         | 
| @@ -303,12 +336,16 @@ export class Base { | |
| 303 336 |  | 
| 304 337 | 
             
              async getCarReaderImpl (carCid) {
         | 
| 305 338 | 
             
                carCid = carCid.toString()
         | 
| 339 | 
            +
                // console.log('getCarReaderImpl', carCid)
         | 
| 306 340 | 
             
                const carBytes = await this.readCar(carCid)
         | 
| 307 341 | 
             
                // console.log('getCarReader', this.constructor.name, carCid, carBytes.length)
         | 
| 308 342 | 
             
                const reader = await CarReader.fromBytes(carBytes)
         | 
| 343 | 
            +
                // console.log('getCarReader', carCid, reader._header)
         | 
| 309 344 | 
             
                if (this.keyMaterial) {
         | 
| 310 345 | 
             
                  const roots = await reader.getRoots()
         | 
| 346 | 
            +
                  // let count = 0
         | 
| 311 347 | 
             
                  const readerGetWithCodec = async cid => {
         | 
| 348 | 
            +
                    // console.log('readerGetWithCodec', count++, cid)
         | 
| 312 349 | 
             
                    const got = await reader.get(cid)
         | 
| 313 350 | 
             
                    let useCodec = codec
         | 
| 314 351 | 
             
                    if (cid.toString().indexOf('bafy') === 0) {
         | 
| @@ -365,17 +402,17 @@ export class Base { | |
| 365 402 |  | 
| 366 403 | 
             
              writeCars (cars) {}
         | 
| 367 404 |  | 
| 368 | 
            -
              async updateCarCidMap (carCid, cids) {
         | 
| 405 | 
            +
              async updateCarCidMap (carCid, cids, head) {
         | 
| 369 406 | 
             
                // this hydrates the map if it has not been hydrated
         | 
| 370 407 | 
             
                const theCarMap = await this.getCidCarMap()
         | 
| 371 408 | 
             
                for (const cid of cids) {
         | 
| 372 409 | 
             
                  theCarMap.set(cid, carCid)
         | 
| 373 410 | 
             
                }
         | 
| 374 411 | 
             
                // todo can we debounce this? -- maybe put it into a queue so we can batch it
         | 
| 375 | 
            -
                return await this.persistCarMap(theCarMap)
         | 
| 412 | 
            +
                return await this.persistCarMap(theCarMap, head)
         | 
| 376 413 | 
             
              }
         | 
| 377 414 |  | 
| 378 | 
            -
              async persistCarMap (theCarMap) {
         | 
| 415 | 
            +
              async persistCarMap (theCarMap, head) {
         | 
| 379 416 | 
             
                const ipldLoader = await getEmptyLoader()
         | 
| 380 417 | 
             
                const indexNode = await create(ipldLoader, {
         | 
| 381 418 | 
             
                  bitWidth: 4,
         | 
| @@ -388,13 +425,21 @@ export class Base { | |
| 388 425 | 
             
                  await indexNode.set(key, value)
         | 
| 389 426 | 
             
                }
         | 
| 390 427 |  | 
| 428 | 
            +
                // console.log('persistCarMap', indexNode.cid, head)
         | 
| 429 | 
            +
                const value = { fp: { cars: indexNode.cid, clock: head } }
         | 
| 430 | 
            +
                const header = await Block.encode({ value, hasher: blockOpts.hasher, codec: blockOpts.codec })
         | 
| 431 | 
            +
                ipldLoader.blocks.put(header.cid, header.bytes)
         | 
| 432 | 
            +
             | 
| 391 433 | 
             
                let newValetCidCar
         | 
| 392 434 | 
             
                if (this.keyMaterial) {
         | 
| 393 435 | 
             
                  const cids = [...ipldLoader.blocks.blocks.keys()]
         | 
| 394 436 | 
             
                  // console.log('persistCarMap', cids)
         | 
| 395 | 
            -
                   | 
| 437 | 
            +
                  // store the clock head and a link to the indexNode.cid in a custom root?
         | 
| 438 | 
            +
             | 
| 439 | 
            +
                  newValetCidCar = await blocksToEncryptedCarBlock(header.cid, ipldLoader.blocks, this.keyMaterial, cids)
         | 
| 440 | 
            +
                  // then put this carcid into the header / w3clock
         | 
| 396 441 | 
             
                } else {
         | 
| 397 | 
            -
                  newValetCidCar = await blocksToCarBlock( | 
| 442 | 
            +
                  newValetCidCar = await blocksToCarBlock(header.cid, ipldLoader.blocks)
         | 
| 398 443 | 
             
                }
         | 
| 399 444 | 
             
                return newValetCidCar
         | 
| 400 445 | 
             
              }
         | 
| @@ -529,6 +574,7 @@ export const blocksFromEncryptedCarBlock = async (cid, get, keyMaterial) => { | |
| 529 574 | 
             
                    cache
         | 
| 530 575 | 
             
                    // codec: dagcbor
         | 
| 531 576 | 
             
                  })) {
         | 
| 577 | 
            +
                    // console.log('decrypted', block.cid.toString())
         | 
| 532 578 | 
             
                    decryptedBlocks.push(block)
         | 
| 533 579 | 
             
                    cids.add(block.cid.toString())
         | 
| 534 580 | 
             
                  }
         | 
    
        package/src/storage/ucan.js
    CHANGED
    
    | @@ -1,45 +0,0 @@ | |
| 1 | 
            -
            import fetch from 'cross-fetch'
         | 
| 2 | 
            -
            import { Base } from './base.js'
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            const defaultConfig = {
         | 
| 5 | 
            -
              upload: () => {},
         | 
| 6 | 
            -
              url: (cid) => `https://${cid}.ipfs.w3s.link/`
         | 
| 7 | 
            -
            }
         | 
| 8 | 
            -
             | 
| 9 | 
            -
            export class UCAN extends Base {
         | 
| 10 | 
            -
              constructor (name, config = {}) {
         | 
| 11 | 
            -
                super(name, Object.assign({}, defaultConfig, config))
         | 
| 12 | 
            -
              }
         | 
| 13 | 
            -
             | 
| 14 | 
            -
              async writeCars (cars) {
         | 
| 15 | 
            -
                if (this.config.readonly) return
         | 
| 16 | 
            -
                for (const { cid, bytes } of cars) {
         | 
| 17 | 
            -
                  console.log(`write UCAN ${cid}, ${bytes.length} bytes`)
         | 
| 18 | 
            -
                  const upCid = await this.config.upload(bytes)
         | 
| 19 | 
            -
                  console.log(`wrote UCAN ${cid}, ${upCid}`)
         | 
| 20 | 
            -
                  // if (!response.ok) throw new Error(`An error occurred: ${response.statusText}`)
         | 
| 21 | 
            -
                }
         | 
| 22 | 
            -
              }
         | 
| 23 | 
            -
             | 
| 24 | 
            -
              async readCar (carCid) {
         | 
| 25 | 
            -
                const carURL = this.config.url(carCid)
         | 
| 26 | 
            -
                const response = await fetch(carURL)
         | 
| 27 | 
            -
                if (!response.ok) throw new Error(`An error occurred: ${response.statusText}`)
         | 
| 28 | 
            -
                const got = await response.arrayBuffer()
         | 
| 29 | 
            -
                return new Uint8Array(got)
         | 
| 30 | 
            -
              }
         | 
| 31 | 
            -
             | 
| 32 | 
            -
              async loadHeader (branch = 'main') {
         | 
| 33 | 
            -
                return headerMock.get(branch)
         | 
| 34 | 
            -
              }
         | 
| 35 | 
            -
             | 
| 36 | 
            -
              async writeHeader (branch, header) {
         | 
| 37 | 
            -
                if (this.config.readonly) return
         | 
| 38 | 
            -
                const pHeader = this.prepareHeader(header)
         | 
| 39 | 
            -
                // console.log('writeHeader rt', branch, pHeader)
         | 
| 40 | 
            -
             | 
| 41 | 
            -
                headerMock.set(branch, pHeader)
         | 
| 42 | 
            -
              }
         | 
| 43 | 
            -
            }
         | 
| 44 | 
            -
             | 
| 45 | 
            -
            const headerMock = new Map()
         |