From 742973a3beffcf3bad938afd58f93976d78f8ac4 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 14 Apr 2021 16:00:40 +0100 Subject: [PATCH 1/3] chore: update types - Updates deps - Changes Blockstore.query return type based on query arg - Exports Blockstore type from index.js - Moves Config types from ipfs-core-types to ipfs-repo - Removes bignumber.js dep in favour of using `BigInt`s - Normalises type import style - Removes ts-ignores from modules with types --- package.json | 7 ++- src/api-addr.js | 2 +- src/backends.js | 6 +-- src/blockstore.js | 9 ++-- src/config.js | 27 +++++----- src/default-options.js | 2 +- src/idstore.js | 8 +-- src/index.js | 41 +++++++------- src/lock-memory.js | 2 +- src/lock.js | 2 +- src/spec.js | 2 +- src/types.d.ts | 115 +++++++++++++++++++++++++++++++++++----- src/version.js | 2 +- test/blockstore-test.js | 8 +-- test/datastore-test.js | 2 +- test/interop-test.js | 2 +- test/is-initialized.js | 2 +- test/keystore-test.js | 2 +- test/lock-test.js | 2 +- test/migrations-test.js | 2 +- test/node.js | 2 +- test/pins-test.js | 2 +- test/repo-test.js | 4 +- test/stat-test.js | 8 +-- tsconfig.json | 4 +- 25 files changed, 177 insertions(+), 88 deletions(-) diff --git a/package.json b/package.json index 2a1febff..9ad6c655 100644 --- a/package.json +++ b/package.json @@ -51,25 +51,24 @@ "@types/ncp": "^2.0.4", "@types/proper-lockfile": "^4.1.1", "@types/rimraf": "^3.0.0", - "aegir": "^31.0.1", + "aegir": "^33.1.0", "assert": "^2.0.0", "events": "^3.3.0", "it-all": "^1.0.2", "it-drain": "^1.0.1", "it-first": "^1.0.2", "just-range": "^2.1.0", - "memdown": "^5.1.0", + "memdown": "^6.0.0", "multihashing-async": "^2.1.0", "ncp": "^2.0.0", "process": "^0.11.10", "readable-stream": "^3.6.0", "rimraf": "^3.0.0", - "sinon": "^9.0.2", + "sinon": "^10.0.0", "url": "^0.11.0", "util": "^0.12.3" }, "dependencies": { - "bignumber.js": "^9.0.0", "bytes": "^3.1.0", "cids": "^1.1.6", "datastore-core": "^3.0.0", diff --git a/src/api-addr.js b/src/api-addr.js index db347aa9..007ecb1c 100644 --- a/src/api-addr.js +++ b/src/api-addr.js @@ -7,7 +7,7 @@ const apiFile = new Key('api') /** * - * @param {import("interface-datastore").Datastore} store + * @param {import('interface-datastore').Datastore} store */ module.exports = (store) => { return { diff --git a/src/backends.js b/src/backends.js index 26f6e77c..f711d448 100644 --- a/src/backends.js +++ b/src/backends.js @@ -1,9 +1,9 @@ 'use strict' /** - * @typedef {import("interface-datastore").Datastore} Datastore - * @typedef {import("./types").Backends} Backends - * @typedef {Required} Options + * @typedef {import('interface-datastore').Datastore} Datastore + * @typedef {import('./types').Backends} Backends + * @typedef {Required} Options */ /** diff --git a/src/blockstore.js b/src/blockstore.js index cf52aa3b..4c40359f 100644 --- a/src/blockstore.js +++ b/src/blockstore.js @@ -7,10 +7,10 @@ const map = require('it-map') const drain = require('it-drain') const pushable = require('it-pushable') /** - * @typedef {import("interface-datastore").Query} Query - * @typedef {import("interface-datastore").Datastore} Datastore - * @typedef {import("interface-datastore").Options} DatastoreOptions - * @typedef {import("cids")} CID + * @typedef {import('interface-datastore').Query} Query + * @typedef {import('interface-datastore').Datastore} Datastore + * @typedef {import('interface-datastore').Options} DatastoreOptions + * @typedef {import('cids')} CID * @typedef {import('./types').Blockstore} Blockstore */ @@ -45,6 +45,7 @@ function createBaseStore (store) { return store.open() }, + // @ts-ignore TODO: how to not have ts freak out about this async * query (query, options) { for await (const { key, value } of store.query(query, options)) { // TODO: we should make this a different method diff --git a/src/config.js b/src/config.js index 83657b02..6dceb6a1 100644 --- a/src/config.js +++ b/src/config.js @@ -2,9 +2,7 @@ const { Key } = require('interface-datastore') const { default: Queue } = require('p-queue') -// @ts-ignore const _get = require('just-safe-get') -// @ts-ignore const _set = require('just-safe-set') const errcode = require('err-code') const errors = require('./errors') @@ -19,8 +17,11 @@ const { const configKey = new Key('config') /** - * - * @param {import("interface-datastore").Datastore} store + * @typedef {import('./types').Config} Config + */ + +/** + * @param {import('interface-datastore').Datastore} store */ module.exports = (store) => { const setQueue = new Queue({ concurrency: 1 }) @@ -31,7 +32,7 @@ module.exports = (store) => { * * @param {Object} [options] - options * @param {AbortSignal} [options.signal] - abort this config read - * @returns {Promise} + * @returns {Promise} */ getAll (options = {}) { // eslint-disable-line require-await return configStore.get(undefined, options) @@ -43,7 +44,7 @@ module.exports = (store) => { * @param {string} [key] - the config key to get * @param {Object} [options] - options * @param {AbortSignal} [options.signal] - abort this config read - * @returns {Promise} + * @returns {Promise} */ async get (key, options = {}) { if (!key) { @@ -53,11 +54,9 @@ module.exports = (store) => { // level-js@5.x cannot read keys from level-js@4.x dbs so fall back to // using IndexedDB API with string keys - only necessary until we do // the migratiion to v10 or above - const encodedValue = await getWithFallback(configKey, store.get.bind(store), store.has.bind(store), store) - - if (options.signal && options.signal.aborted) { - return - } + const encodedValue = await getWithFallback(configKey, store.get.bind(store), store.has.bind(store), store, { + signal: options.signal + }) const config = JSON.parse(uint8ArrayToString(encodedValue)) if (key !== undefined && _get(config, key) === undefined) { @@ -71,8 +70,8 @@ module.exports = (store) => { /** * Set the current configuration for this repo. * - * @param {string | unknown} [key] - the config key to be written - * @param {unknown} [value] - the config value to be written + * @param {string} [key] - the config key to be written + * @param {any} [value] - the config value to be written * @param {Object} [options] - options * @param {AbortSignal} [options.signal] - abort this config write */ @@ -97,7 +96,7 @@ module.exports = (store) => { /** * Set the current configuration for this repo. * - * @param {Object} [value] - the config value to be written + * @param {Config} [value] - the config value to be written * @param {Object} [options] - options * @param {AbortSignal} [options.signal] - abort this config write */ diff --git a/src/default-options.js b/src/default-options.js index dcb357c2..19089ffc 100644 --- a/src/default-options.js +++ b/src/default-options.js @@ -3,7 +3,7 @@ // Default configuration for a repo in node.js /** - * @type {Required} + * @type {Required} */ module.exports = { autoMigrate: true, diff --git a/src/idstore.js b/src/idstore.js index cbcfd940..41619d19 100644 --- a/src/idstore.js +++ b/src/idstore.js @@ -9,9 +9,9 @@ const CID = require('cids') const errcode = require('err-code') /** - * @typedef {import("interface-datastore").Query} Query - * @typedef {import("interface-datastore").Datastore} Datastore - * @typedef {import("interface-datastore").Options} DatastoreOptions + * @typedef {import('interface-datastore').Query} Query + * @typedef {import('interface-datastore').Datastore} Datastore + * @typedef {import('interface-datastore').Options} DatastoreOptions * @typedef {import('./types').Blockstore} Blockstore */ @@ -30,6 +30,8 @@ function createIdStore (store) { open () { return store.open() }, + + // @ts-ignore TODO: how to not have ts freak out about this query (query, options) { return store.query(query, options) }, diff --git a/src/index.js b/src/index.js index d625bf9c..b3b2ecd8 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,7 @@ 'use strict' -// @ts-ignore const _get = require('just-safe-get') const debug = require('debug') -const Big = require('bignumber.js').BigNumber const errcode = require('err-code') const migrator = require('ipfs-repo-migrations') const bytes = require('bytes') @@ -33,12 +31,14 @@ const lockers = { } /** - * @typedef {import("./types").Options} Options - * @typedef {import("./types").Lock} Lock - * @typedef {import("./types").LockCloser} LockCloser - * @typedef {import("./types").Stat} Stat - * @typedef {import("ipld-block")} Block - * @typedef {import("interface-datastore").Datastore} Datastore + * @typedef {import('./types').Options} Options + * @typedef {import('./types').Lock} Lock + * @typedef {import('./types').LockCloser} LockCloser + * @typedef {import('./types').Stat} Stat + * @typedef {import('./types').Blockstore} Blockstore + * @typedef {import('./types').Config} Config + * @typedef {import('ipld-block')} Block + * @typedef {import('interface-datastore').Datastore} Datastore */ /** @@ -319,9 +319,7 @@ class IpfsRepo { getSize(this.datastore), getSize(this.keys) ]) - const size = blocks.size - .plus(datastore) - .plus(keys) + const size = blocks.size + datastore + keys return { repoPath: this.path, @@ -389,9 +387,9 @@ class IpfsRepo { async _storageMaxStat () { try { const max = /** @type {number} */(await this.config.get('Datastore.StorageMax')) - return new Big(bytes(max)) + return BigInt(bytes(max)) } catch (err) { - return new Big(noLimit) + return BigInt(noLimit) } } @@ -399,16 +397,15 @@ class IpfsRepo { * @private */ async _blockStat () { - let count = new Big(0) - let size = new Big(0) + let count = BigInt(0) + let size = BigInt(0) if (this.blocks) { for await (const blockOrCid of this.blocks.query({})) { const block = /** @type {Block} */(blockOrCid) - count = count.plus(1) - size = size - .plus(block.data.byteLength) - .plus(block.cid.bytes.byteLength) + count += BigInt(1) + size += BigInt(block.data.byteLength) + size += BigInt(block.cid.bytes.byteLength) } } @@ -420,10 +417,10 @@ class IpfsRepo { * @param {Datastore} datastore */ async function getSize (datastore) { - const sum = new Big(0) + let sum = BigInt(0) for await (const block of datastore.query({})) { - sum.plus(block.value.byteLength) - .plus(block.key.uint8Array().byteLength) + sum += BigInt(block.value.byteLength) + sum += BigInt(block.key.uint8Array().byteLength) } return sum } diff --git a/src/lock-memory.js b/src/lock-memory.js index 0fb5fc05..f2047857 100644 --- a/src/lock-memory.js +++ b/src/lock-memory.js @@ -11,7 +11,7 @@ const lockFile = 'repo.lock' const LOCKS = {} /** - * @typedef {import("./types").LockCloser} LockCloser + * @typedef {import('./types').LockCloser} LockCloser */ /** diff --git a/src/lock.js b/src/lock.js index fa72523c..a505c218 100644 --- a/src/lock.js +++ b/src/lock.js @@ -9,7 +9,7 @@ const log = debug('ipfs:repo:lock') const lockFile = 'repo.lock' /** - * @typedef {import("./types").LockCloser} LockCloser + * @typedef {import('./types').LockCloser} LockCloser */ /** diff --git a/src/spec.js b/src/spec.js index d0d5302d..a9503b5b 100644 --- a/src/spec.js +++ b/src/spec.js @@ -9,7 +9,7 @@ const specKey = new Key('datastore_spec') /** * - * @param {import("interface-datastore").Datastore} store + * @param {import('interface-datastore').Datastore} store */ module.exports = (store) => { return { diff --git a/src/types.d.ts b/src/types.d.ts index e81753de..f344d5a6 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,7 +1,7 @@ -import type { Datastore, Options as DatastoreOptions, Query } from 'interface-datastore' -import type { BigNumber } from 'bignumber.js' +import type { Datastore, Options as DatastoreOptions, Query, Key } from 'interface-datastore' import type CID from 'cids' +import type Block from 'ipld-block' export type AwaitIterable = Iterable | AsyncIterable export type Await = Promise | T @@ -53,23 +53,19 @@ export interface LockCloser { export interface Stat { repoPath: string - storageMax: BigNumber + storageMax: BigInt version: number - numObjects: BigNumber - repoSize: BigNumber -} - -export interface Block { - cid: CID - data: Uint8Array + numObjects: BigInt + repoSize: BigInt } export interface Blockstore { open: () => Promise + /** * Query the store */ - query: (query: Query, options?: DatastoreOptions) => AsyncIterable + query: ((query: Query & { keysOnly: true }, options?: DatastoreOptions) => AsyncIterable) & ((query: Query, options?: DatastoreOptions) => AsyncIterable) /** * Get a single block by CID @@ -110,4 +106,99 @@ export interface Blockstore { * Close the store */ close: () => Promise -} \ No newline at end of file +} + +export interface Config { + Addresses: AddressConfig + API?: APIConfig, + Profiles?: string + Bootstrap: string[] + Discovery: DiscoveryConfig + Datastore?: DatastoreConfig + Identity?: IdentityConfig + Keychain?: KeychainConfig + Pubsub?: PubsubConfig + Swarm?: SwarmConfig + Routing?: RoutingConfig +} + +/** + * Contains information about various listener addresses to be used by this node + */ +export interface AddressConfig { + API?: string + RPC?: string + Delegates?: string[] + Gateway?: string + Swarm: string[] +} + +export interface APIConfig { + HTTPHeaders?: Record +} + +export interface DiscoveryConfig { + MDNS: MDNSDiscovery + webRTCStar: WebRTCStarDiscovery +} + +export interface MDNSDiscovery { + Enabled?: boolean + Interval?: number +} + +export interface WebRTCStarDiscovery { + Enabled?: boolean +} + +export interface DatastoreConfig { + Spec?: DatastoreSpec +} + +export interface DatastoreSpec { + +} + +export interface IdentityConfig { + /** + * The unique PKI identity label for this configs peer. Set on init and never + * read, its merely here for convenience. IPFS will always generate the peerID + * from its keypair at runtime. + */ + PeerID: string + + /** + * The base64 encoded protobuf describing (and containing) the nodes private key. + */ + PrivateKey: string +} + +export interface KeychainConfig { + DEK?: DEK +} + +export interface DEK { + keyLength?: number + iterationCount?: number + salt?: string + hash?: string +} + +export interface PubsubConfig { + PubSubRouter?: 'gossipsub' | 'floodsub' + Enabled?: boolean +} + +export interface SwarmConfig { + ConnMgr?: ConnMgrConfig + DisableNatPortMap?: boolean +} + +export interface ConnMgrConfig { + LowWater?: number + HighWater?: number +} + +export interface RoutingConfig { + Type?: string +} diff --git a/src/version.js b/src/version.js index ffe732e6..6edcd79c 100644 --- a/src/version.js +++ b/src/version.js @@ -15,7 +15,7 @@ const versionKey = new Key('version') /** * - * @param {import("interface-datastore").Datastore} store + * @param {import('interface-datastore').Datastore} store */ module.exports = (store) => { return { diff --git a/test/blockstore-test.js b/test/blockstore-test.js index 0838b862..ccb0fa2d 100644 --- a/test/blockstore-test.js +++ b/test/blockstore-test.js @@ -25,7 +25,7 @@ async function makeBlock () { } /** - * @typedef {import("interface-datastore").Key} Key + * @typedef {import('interface-datastore').Key} Key */ /** @@ -477,7 +477,7 @@ module.exports = (repo) => { }) it('returns key/values for block data', async () => { - const blocks = /** @type {Block[]} */(await all(repo.blocks.query({}))) + const blocks = await all(repo.blocks.query({})) const block = blocks.find(block => uint8ArrayToString(block.data, 'base64') === uint8ArrayToString(block1.data, 'base64')) expect(block).to.be.ok() @@ -486,9 +486,9 @@ module.exports = (repo) => { }) it('returns some of the blocks', async () => { - const blocksWithPrefix = /** @type {Block[]} */(await all(repo.blocks.query({ + const blocksWithPrefix = await all(repo.blocks.query({ prefix: cidToKey(block1.cid).toString().substring(0, 10) - }))) + })) const block = blocksWithPrefix.find(block => uint8ArrayToString(block.data, 'base64') === uint8ArrayToString(block1.data, 'base64')) expect(block).to.be.ok() diff --git a/test/datastore-test.js b/test/datastore-test.js index 83eb5569..27c9812f 100644 --- a/test/datastore-test.js +++ b/test/datastore-test.js @@ -7,7 +7,7 @@ const range = require('just-range') const Key = require('interface-datastore').Key const uint8ArrayFromString = require('uint8arrays/from-string') /** - * @typedef {import("../src/index")} Repo + * @typedef {import('../src/index')} Repo */ /** diff --git a/test/interop-test.js b/test/interop-test.js index c0e26774..c4324fd0 100644 --- a/test/interop-test.js +++ b/test/interop-test.js @@ -8,7 +8,7 @@ const Key = require('interface-datastore').Key const uint8ArrayToString = require('uint8arrays/to-string') /** - * @param {import("../src/index")} repo + * @param {import('../src/index')} repo */ module.exports = (repo) => { describe('interop', () => { diff --git a/test/is-initialized.js b/test/is-initialized.js index 15167b67..2a08b86a 100644 --- a/test/is-initialized.js +++ b/test/is-initialized.js @@ -7,7 +7,7 @@ const tempDir = require('ipfs-utils/src/temp-dir') const IPFSRepo = require('../src') /** - * @typedef {import("../src/index")} Repo + * @typedef {import('../src/index')} Repo */ describe('isInitialized', () => { diff --git a/test/keystore-test.js b/test/keystore-test.js index 077ed55b..f328b992 100644 --- a/test/keystore-test.js +++ b/test/keystore-test.js @@ -4,7 +4,7 @@ const { expect } = require('aegir/utils/chai') /** - * @typedef {import("../src/index")} Repo + * @typedef {import('../src/index')} Repo */ /** diff --git a/test/lock-test.js b/test/lock-test.js index 30bd4403..2bb99cea 100644 --- a/test/lock-test.js +++ b/test/lock-test.js @@ -7,7 +7,7 @@ const lockMemory = require('../src/lock-memory') const { LockExistsError } = require('./../src/errors') /** - * @param {import("../src/index")} repo + * @param {import('../src/index')} repo */ module.exports = (repo) => { describe('Repo lock tests', () => { diff --git a/test/migrations-test.js b/test/migrations-test.js index 703f1a53..e6d979fc 100644 --- a/test/migrations-test.js +++ b/test/migrations-test.js @@ -10,7 +10,7 @@ const constants = require('../src/constants') const errors = require('../src/errors') const IPFSRepo = require('../src') /** - * @typedef {import("../src/index")} Repo + * @typedef {import('../src/index')} Repo */ /** diff --git a/test/node.js b/test/node.js index 77b2eac1..5514ef43 100644 --- a/test/node.js +++ b/test/node.js @@ -16,7 +16,7 @@ const fsstat = promisify(fs.stat) const IPFSRepo = require('../src') /** - * @typedef {import("../src/types").Options} Options + * @typedef {import('../src/types').Options} Options */ async function createTempRepo (options = {}) { diff --git a/test/pins-test.js b/test/pins-test.js index a96f06ad..a2c78cc3 100644 --- a/test/pins-test.js +++ b/test/pins-test.js @@ -7,7 +7,7 @@ const range = require('just-range') const Key = require('interface-datastore').Key const uint8ArrayFromString = require('uint8arrays/from-string') /** - * @typedef {import("../src/index")} Repo + * @typedef {import('../src/index')} Repo */ /** diff --git a/test/repo-test.js b/test/repo-test.js index b6d38da1..ff4a20d5 100644 --- a/test/repo-test.js +++ b/test/repo-test.js @@ -13,7 +13,7 @@ const { Adapter } = require('interface-datastore') */ /** - * @param {import("../src/index")} repo + * @param {import('../src/index')} repo */ module.exports = (repo) => { describe('IPFS Repo Tests', () => { @@ -334,7 +334,7 @@ module.exports = (repo) => { const stat = await otherRepo.stat() expect(stat).to.have.property('storageMax') - expect(stat.storageMax.toNumber()).to.equal(bytes(maxStorage)) + expect(stat.storageMax).to.equal(BigInt(bytes(maxStorage))) }) it('should throw unexpected errors when closing', async () => { diff --git a/test/stat-test.js b/test/stat-test.js index 8a851d16..7ebf0cd9 100644 --- a/test/stat-test.js +++ b/test/stat-test.js @@ -6,7 +6,7 @@ const Block = require('ipld-block') const CID = require('cids') const uint8ArrayFromString = require('uint8arrays/from-string') /** - * @param {import("../src/index")} repo + * @param {import('../src/index')} repo */ module.exports = (repo) => { describe('stat', () => { @@ -27,10 +27,10 @@ module.exports = (repo) => { expect(stats).to.have.property('repoSize') expect(stats).to.have.property('storageMax') - expect(stats.numObjects.isGreaterThan(0)).to.eql(true) + expect(stats.numObjects > 0n).to.eql(true) expect(stats.version > 0).to.eql(true) - expect(stats.repoSize.isGreaterThan(0)).to.eql(true) - expect(stats.storageMax.isGreaterThan(0)).to.eql(true) + expect(stats.repoSize > 0n).to.eql(true) + expect(stats.storageMax > 0n).to.eql(true) }) }) } diff --git a/tsconfig.json b/tsconfig.json index 2a8e0472..5681ae6f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "./node_modules/aegir/src/config/tsconfig.aegir.json", + "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { "outDir": "dist", "baseUrl": "./", @@ -9,7 +9,7 @@ }, "include": [ "types", - "test", // remove this line if you don't want to type-check tests + "test", "src" ] } From de13f4747a5ab4e00c6227eb1e3a1a29073d3393 Mon Sep 17 00:00:00 2001 From: achingbrain Date: Wed, 14 Apr 2021 17:51:22 +0100 Subject: [PATCH 2/3] chore: make set and get require args and specify datastore spec types --- src/blockstore.js | 2 +- src/config.js | 40 +++++++++++++++++++--------------------- src/idstore.js | 2 +- src/index.js | 13 ++++++------- src/types.d.ts | 34 +++++++++++++++++++++++++--------- test/config-test.js | 7 ++++--- test/repo-test.js | 9 +++++---- 7 files changed, 61 insertions(+), 46 deletions(-) diff --git a/src/blockstore.js b/src/blockstore.js index 4c40359f..795b4ee9 100644 --- a/src/blockstore.js +++ b/src/blockstore.js @@ -45,7 +45,7 @@ function createBaseStore (store) { return store.open() }, - // @ts-ignore TODO: how to not have ts freak out about this + // @ts-ignore TODO: ts does not think we will yield only CIDs or only Blocks async * query (query, options) { for await (const { key, value } of store.query(query, options)) { // TODO: we should make this a different method diff --git a/src/config.js b/src/config.js index 6dceb6a1..cbd7606e 100644 --- a/src/config.js +++ b/src/config.js @@ -34,52 +34,50 @@ module.exports = (store) => { * @param {AbortSignal} [options.signal] - abort this config read * @returns {Promise} */ - getAll (options = {}) { // eslint-disable-line require-await - return configStore.get(undefined, options) + async getAll (options = {}) { // eslint-disable-line require-await + // level-js@5.x cannot read keys from level-js@4.x dbs so fall back to + // using IndexedDB API with string keys - only necessary until we do + // the migratiion to v10 or above + const encodedValue = await getWithFallback(configKey, store.get.bind(store), store.has.bind(store), store, { + signal: options.signal + }) + + return JSON.parse(uint8ArrayToString(encodedValue)) }, /** * Get the value for the passed configuration key from the repo. * - * @param {string} [key] - the config key to get + * @param {string} key - the config key to get * @param {Object} [options] - options * @param {AbortSignal} [options.signal] - abort this config read - * @returns {Promise} */ async get (key, options = {}) { - if (!key) { - key = undefined + if (key == null) { + throw new errors.NotFoundError(`Key ${key} does not exist in config`) } - // level-js@5.x cannot read keys from level-js@4.x dbs so fall back to - // using IndexedDB API with string keys - only necessary until we do - // the migratiion to v10 or above - const encodedValue = await getWithFallback(configKey, store.get.bind(store), store.has.bind(store), store, { - signal: options.signal - }) + const config = await this.getAll(options) + const value = _get(config, key) - const config = JSON.parse(uint8ArrayToString(encodedValue)) - if (key !== undefined && _get(config, key) === undefined) { + if (value === undefined) { throw new errors.NotFoundError(`Key ${key} does not exist in config`) } - const value = key !== undefined ? _get(config, key) : config return value }, /** * Set the current configuration for this repo. * - * @param {string} [key] - the config key to be written + * @param {string} key - the config key to be written * @param {any} [value] - the config value to be written * @param {Object} [options] - options * @param {AbortSignal} [options.signal] - abort this config write */ set (key, value, options = {}) { - if (arguments.length === 1) { - value = key - key = undefined - } else if (!key || typeof key !== 'string') { + // @ts-ignore ts thinks key will only be a string, but it may not be + if (typeof key !== 'string' && !(key instanceof String)) { throw errcode(new Error('Invalid key type: ' + typeof key), 'ERR_INVALID_KEY') } @@ -137,7 +135,7 @@ module.exports = (store) => { const key = m.key const value = m.value if (key) { - const config = await configStore.get() + const config = await configStore.getAll() if (typeof config === 'object' && config !== null) { _set(config, key, value) } diff --git a/src/idstore.js b/src/idstore.js index 41619d19..e25fd76a 100644 --- a/src/idstore.js +++ b/src/idstore.js @@ -31,7 +31,7 @@ function createIdStore (store) { return store.open() }, - // @ts-ignore TODO: how to not have ts freak out about this + // @ts-ignore TODO: ts does not think we will yield only CIDs or only Blocks query (query, options) { return store.query(query, options) }, diff --git a/src/index.js b/src/index.js index b3b2ecd8..b98b2033 100644 --- a/src/index.js +++ b/src/index.js @@ -78,13 +78,13 @@ class IpfsRepo { /** * Initialize a new repo. * - * @param {any} config - config to write into `config`. + * @param {import('./types').Config} config - config to write into `config`. * @returns {Promise} */ async init (config) { log('initializing at: %s', this.path) await this._openRoot() - await this.config.set(buildConfig(config)) + await this.config.replace(buildConfig(config)) await this.spec.set(buildDatastoreSpec(config)) await this.version.set(constants.repoVersion) } @@ -430,24 +430,23 @@ module.exports.utils = { blockstore: require('./blockstore-utils') } module.exports.repoVersion = constants.repoVersion module.exports.errors = ERRORS -// TODO this should come from js-ipfs instead /** - * @param {any} _config + * @param {import('./types').Config} _config */ function buildConfig (_config) { - _config.datastore = Object.assign({}, defaultDatastore, _get(_config, 'datastore')) + _config.Datastore = Object.assign({}, defaultDatastore, _get(_config, 'datastore')) return _config } /** - * @param {any} _config + * @param {import('./types').Config} _config */ function buildDatastoreSpec (_config) { /** @type { {type: string, mounts: Array<{mountpoint: string, type: string, prefix: string, child: {type: string, path: 'string', sync: boolean, shardFunc: string}}>}} */ const spec = { ...defaultDatastore.Spec, - ..._get(_config, 'datastore.Spec') + ..._get(_config, 'Datastore.Spec') } return { diff --git a/src/types.d.ts b/src/types.d.ts index f344d5a6..cb8679a0 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -109,11 +109,11 @@ export interface Blockstore { } export interface Config { - Addresses: AddressConfig + Addresses?: AddressConfig API?: APIConfig, Profiles?: string - Bootstrap: string[] - Discovery: DiscoveryConfig + Bootstrap?: string[] + Discovery?: DiscoveryConfig Datastore?: DatastoreConfig Identity?: IdentityConfig Keychain?: KeychainConfig @@ -130,7 +130,7 @@ export interface AddressConfig { RPC?: string Delegates?: string[] Gateway?: string - Swarm: string[] + Swarm?: string[] } export interface APIConfig { @@ -138,8 +138,8 @@ export interface APIConfig { } export interface DiscoveryConfig { - MDNS: MDNSDiscovery - webRTCStar: WebRTCStarDiscovery + MDNS?: MDNSDiscovery + webRTCStar?: WebRTCStarDiscovery } export interface MDNSDiscovery { @@ -155,15 +155,31 @@ export interface DatastoreConfig { Spec?: DatastoreSpec } -export interface DatastoreSpec { +export interface DatastoreType { + type: string, + path: string, + sync?: boolean, + shardFunc?: string, + compression?: string +} +export interface DatastoreMountPoint { + mountpoint: string, + type: string, + prefix: string, + child: DatastoreType +} + +export interface DatastoreSpec { + type?: string, + mounts?: DatastoreMountPoint[] } export interface IdentityConfig { /** * The unique PKI identity label for this configs peer. Set on init and never - * read, its merely here for convenience. IPFS will always generate the peerID - * from its keypair at runtime. + * read, its merely here for convenience. IPFS will always generate the peerID + * from its keypair at runtime. */ PeerID: string diff --git a/test/config-test.js b/test/config-test.js index 0df47282..f1aa482d 100644 --- a/test/config-test.js +++ b/test/config-test.js @@ -11,6 +11,7 @@ module.exports = (repo) => { describe('config', () => { describe('.set', () => { it('should throw when invalid key is passed', () => { + // @ts-expect-error key should be a string return expect(() => repo.config.set(5, 'value')) .to.throw() .with.property('code', 'ERR_INVALID_KEY') @@ -33,16 +34,16 @@ module.exports = (repo) => { it('should return the whole conifg', async () => { const thing = await repo.config.getAll() - expect(thing).to.deep.equal(await repo.config.get()) + expect(thing).to.deep.equal(await repo.config.getAll()) }) }) describe('.replace', () => { it('should replace the whole conifg', async () => { - expect({}).to.not.deep.equal(await repo.config.get()) + expect({}).to.not.deep.equal(await repo.config.getAll()) await repo.config.replace({}) - expect({}).to.deep.equal(await repo.config.get()) + expect({}).to.deep.equal(await repo.config.getAll()) }) }) }) diff --git a/test/repo-test.js b/test/repo-test.js index ff4a20d5..37922d69 100644 --- a/test/repo-test.js +++ b/test/repo-test.js @@ -28,13 +28,14 @@ module.exports = (repo) => { describe('config', () => { it('get config', async () => { - const config = await repo.config.get() + const config = await repo.config.getAll() expect(config).to.be.a('object') }) it('set config', async () => { - await repo.config.set({ a: 'b' }) - const config = await repo.config.get() + await repo.config.replace({}) + await repo.config.set('a', 'b') + const config = await repo.config.getAll() expect(config).to.deep.equal({ a: 'b' }) }) @@ -45,7 +46,7 @@ module.exports = (repo) => { it('set config key', async () => { await repo.config.set('c.x', 'd') - const config = await repo.config.get() + const config = await repo.config.getAll() expect(config).to.deep.equal({ a: 'b', c: { x: 'd' } }) }) }) From 81a536f3d18369bd81ba6bc68e7c30f42a7da5bd Mon Sep 17 00:00:00 2001 From: achingbrain Date: Thu, 15 Apr 2021 18:04:35 +0100 Subject: [PATCH 3/3] chore: update deps --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9ad6c655..da243546 100644 --- a/package.json +++ b/package.json @@ -71,13 +71,13 @@ "dependencies": { "bytes": "^3.1.0", "cids": "^1.1.6", - "datastore-core": "^3.0.0", - "datastore-fs": "^3.0.0", - "datastore-level": "^4.0.0", + "datastore-core": "^4.0.0", + "datastore-fs": "^4.0.0", + "datastore-level": "^5.0.0", "debug": "^4.1.0", "err-code": "^3.0.1", - "interface-datastore": "^3.0.3", - "ipfs-repo-migrations": "^7.0.1", + "interface-datastore": "^4.0.0", + "ipfs-repo-migrations": "^8.0.0", "ipfs-utils": "^6.0.0", "ipld-block": "^0.11.0", "it-filter": "^1.0.2",