From ab37d40c62875a976eb55054e0d604e237d5a8aa Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 25 Jun 2021 17:15:45 +0100 Subject: [PATCH] feat: add in-memory blockstore implementation (#1) A simple blockstore that's good for testing. --- packages/interface-blockstore/package.json | 1 + packages/interface-blockstore/src/errors.js | 15 ++++ packages/interface-blockstore/src/index.js | 4 +- packages/interface-blockstore/src/memory.js | 78 +++++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 packages/interface-blockstore/src/errors.js create mode 100644 packages/interface-blockstore/src/memory.js diff --git a/packages/interface-blockstore/package.json b/packages/interface-blockstore/package.json index ee29c5f3..cb72b752 100644 --- a/packages/interface-blockstore/package.json +++ b/packages/interface-blockstore/package.json @@ -17,6 +17,7 @@ "url": "git+https://github.com/ipfs/js-ipfs-interfaces.git" }, "dependencies": { + "err-code": "^3.0.1", "interface-store": "^0.0.2", "it-all": "^1.0.5", "it-drain": "^1.0.4", diff --git a/packages/interface-blockstore/src/errors.js b/packages/interface-blockstore/src/errors.js new file mode 100644 index 00000000..5436deb9 --- /dev/null +++ b/packages/interface-blockstore/src/errors.js @@ -0,0 +1,15 @@ +'use strict' + +const errCode = require('err-code') + +/** + * @param {Error} [err] + */ +function notFoundError (err) { + err = err || new Error('Not Found') + return errCode(err, 'ERR_NOT_FOUND') +} + +module.exports = { + notFoundError +} diff --git a/packages/interface-blockstore/src/index.js b/packages/interface-blockstore/src/index.js index 322a3178..87034558 100644 --- a/packages/interface-blockstore/src/index.js +++ b/packages/interface-blockstore/src/index.js @@ -1,6 +1,7 @@ 'use strict' const BlockstoreAdapter = require('./adapter') +const MemoryBlockstore = require('./memory') /** * @typedef {import('./types').Options} Options @@ -16,5 +17,6 @@ const BlockstoreAdapter = require('./adapter') */ module.exports = { - BlockstoreAdapter + BlockstoreAdapter, + MemoryBlockstore } diff --git a/packages/interface-blockstore/src/memory.js b/packages/interface-blockstore/src/memory.js new file mode 100644 index 00000000..c3223f9f --- /dev/null +++ b/packages/interface-blockstore/src/memory.js @@ -0,0 +1,78 @@ +'use strict' + +const Adapter = require('./adapter') +const { base32 } = require('multiformats/bases/base32') +const raw = require('multiformats/codecs/raw') +const { CID } = require('multiformats/cid') +const Digest = require('multiformats/hashes/digest') +const Errors = require('./errors') + +/** + * @typedef {import('./types').Pair} Pair + * @typedef {import('./types').Blockstore} Blockstore + * @typedef {import('interface-store').Options} Options + */ + +/** + * @class MemoryBlockstore + * @implements {Blockstore} + */ +class MemoryBlockstore extends Adapter { + constructor () { + super() + + /** @type {Record} */ + this.data = {} + } + + open () { + return Promise.resolve() + } + + close () { + return Promise.resolve() + } + + /** + * @param {CID} key + * @param {Uint8Array} val + */ + async put (key, val) { // eslint-disable-line require-await + this.data[base32.encode(key.multihash.bytes)] = val + } + + /** + * @param {CID} key + */ + async get (key) { + const exists = await this.has(key) + if (!exists) throw Errors.notFoundError() + return this.data[base32.encode(key.multihash.bytes)] + } + + /** + * @param {CID} key + */ + async has (key) { // eslint-disable-line require-await + return this.data[base32.encode(key.multihash.bytes)] !== undefined + } + + /** + * @param {CID} key + */ + async delete (key) { // eslint-disable-line require-await + delete this.data[base32.encode(key.multihash.bytes)] + } + + async * _all () { + yield * Object.entries(this.data) + .map(([key, value]) => ({ key: CID.createV1(raw.code, Digest.decode(base32.decode(key))), value })) + } + + async * _allKeys () { + yield * Object.entries(this.data) + .map(([key]) => CID.createV1(raw.code, Digest.decode(base32.decode(key)))) + } +} + +module.exports = MemoryBlockstore