Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: error objects and handling #203

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
"datastore-fs": "~0.9.0",
"datastore-level": "~0.12.0",
"debug": "^4.1.0",
"err-code": "^1.1.2",
"interface-datastore": "~0.7.0",
"ipfs-block": "~0.8.1",
"just-safe-get": "^1.3.0",
Expand Down
8 changes: 4 additions & 4 deletions src/blockstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const Key = require('interface-datastore').Key
const base32 = require('base32.js')
const Block = require('ipfs-block')
const CID = require('cids')
const errcode = require('err-code')
const { ERR_INVALID_CID } = require('./errors')

/**
* Transform a raw buffer to a base32 encoded key.
Expand Down Expand Up @@ -63,7 +63,7 @@ function createBaseStore (store) {
*/
async get (cid) {
if (!CID.isCID(cid)) {
throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID')
throw new ERR_INVALID_CID('Not a valid CID')
}
const key = cidToDsKey(cid)
let blockData
Expand Down Expand Up @@ -138,7 +138,7 @@ function createBaseStore (store) {
*/
async has (cid) {
if (!CID.isCID(cid)) {
throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID')
throw new ERR_INVALID_CID('Not a valid CID')
}

const exists = await store.has(cidToDsKey(cid))
Expand All @@ -155,7 +155,7 @@ function createBaseStore (store) {
*/
async delete (cid) { // eslint-disable-line require-await
if (!CID.isCID(cid)) {
throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID')
throw new ERR_INVALID_CID('Not a valid CID')
}
return store.delete(cidToDsKey(cid))
},
Expand Down
9 changes: 4 additions & 5 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ const Queue = require('p-queue')
const _get = require('just-safe-get')
const _set = require('just-safe-set')
const _has = require('lodash.has')
const errcode = require('err-code')
const errors = require('./errors')
const { ERR_NOT_FOUND, ERR_INVALID_VALUE, ERR_INVALID_KEY } = require('./errors')

const configKey = new Key('config')

Expand All @@ -28,7 +27,7 @@ module.exports = (store) => {
const encodedValue = await store.get(configKey)
const config = JSON.parse(encodedValue.toString())
if (key !== undefined && !_has(config, key)) {
throw new errors.NotFoundError(`Key ${key} does not exist in config`)
throw new ERR_NOT_FOUND(`Key ${key} does not exist in config`)
}

const value = key !== undefined ? _get(config, key) : config
Expand All @@ -47,11 +46,11 @@ module.exports = (store) => {
value = key
key = undefined
} else if (!key || typeof key !== 'string') {
throw errcode(new Error('Invalid key type: ' + typeof key), 'ERR_INVALID_KEY')
throw new ERR_INVALID_KEY('Invalid key type: ' + typeof key)
}

if (value === undefined || Buffer.isBuffer(value)) {
throw errcode(new Error('Invalid value type: ' + typeof value), 'ERR_INVALID_VALUE')
throw new ERR_INVALID_VALUE('Invalid value type: ' + typeof value)
}

return setQueue.add(() => _doSet({
Expand Down
129 changes: 124 additions & 5 deletions src/errors/index.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use strict'

// TODO: Should be refactored when https://github.com/ipfs/js-ipfs/pull/1746/ is adopted.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the PR there are some utils to ease the creation of the Error's class, but since I believe it will be moved out to some general package to be used across js land, I did not copy&pasted it directly here and just created the Error's classes manually. Once it will land this can be adopted here.


/**
* Error raised when there is lock already in place when repo is being opened.
*/
Expand All @@ -13,7 +15,7 @@ class LockExistsError extends Error {
}

LockExistsError.code = 'ERR_LOCK_EXISTS'
exports.LockExistsError = LockExistsError
exports.ERR_LOCK_EXISTS = LockExistsError

/**
* Error raised when requested item is not found.
Expand All @@ -28,8 +30,125 @@ class NotFoundError extends Error {
}

NotFoundError.code = 'ERR_NOT_FOUND'
exports.NotFoundError = NotFoundError
exports.ERR_NOT_FOUND = NotFoundError

/**
* Error raised when repo was not initialized.
*/
class RepoNotInitializedError extends Error {
constructor (message, path) {
super(message)
this.name = 'RepoNotInitializedError'
this.code = 'ERR_REPO_NOT_INITIALIZED'
this.message = message
this.path = path
}
}

RepoNotInitializedError.code = 'ERR_REPO_NOT_INITIALIZED'
exports.ERR_REPO_NOT_INITIALIZED = RepoNotInitializedError

/**
* Error raised while opening repo when repo is already opened.
*/
class RepoAlreadyOpenError extends Error {
constructor (message) {
super(message)
this.name = 'RepoAlreadyOpenError'
this.code = 'ERR_REPO_ALREADY_OPEN'
this.message = message
}
}

RepoAlreadyOpenError.code = 'ERR_REPO_ALREADY_OPEN'
exports.ERR_REPO_ALREADY_OPEN = RepoAlreadyOpenError

/**
* Error raised while opening repo when repo is already opened.
*/
class RepoAlreadyClosedError extends Error {
constructor (message) {
super(message)
this.name = 'RepoAlreadyClosedError'
this.code = 'ERR_REPO_ALREADY_CLOSED'
this.message = message
}
}

RepoAlreadyClosedError.code = 'ERR_REPO_ALREADY_CLOSED'
exports.ERR_REPO_ALREADY_CLOSED = RepoAlreadyClosedError

/**
* Error raised when lock object is returned that does not have close() function.
*/
class NoCloseFunctionError extends Error {
constructor (message) {
super(message)
this.name = 'NoCloseFunctionError'
this.code = 'ERR_NO_CLOSE_FUNCTION'
this.message = message
}
}

NoCloseFunctionError.code = 'ERR_NO_CLOSE_FUNCTION'
exports.ERR_NO_CLOSE_FUNCTION = NoCloseFunctionError

/**
* Error raised when the version of repo is not as expected.
*/
class InvalidRepoVersionError extends Error {
constructor (message) {
super(message)
this.name = 'InvalidRepoVersionError'
this.code = 'ERR_INVALID_REPO_VERSION'
this.message = message
}
}

InvalidRepoVersionError.code = 'ERR_INVALID_REPO_VERSION'
exports.ERR_INVALID_REPO_VERSION = InvalidRepoVersionError

/**
* Error raised when the config's key is of invalid type.
*/
class InvalidKeyError extends Error {
constructor (message) {
super(message)
this.name = 'InvalidKeyError'
this.code = 'ERR_INVALID_KEY'
this.message = message
}
}

InvalidKeyError.code = 'ERR_INVALID_KEY'
exports.ERR_INVALID_KEY = InvalidKeyError

/**
* Error raised when the config's value is of invalid type.
*/
class InvalidValueError extends Error {
constructor (message) {
super(message)
this.name = 'InvalidValueError'
this.code = 'ERR_INVALID_VALUE'
this.message = message
}
}

InvalidValueError.code = 'ERR_INVALID_VALUE'
exports.ERR_INVALID_VALUE = InvalidValueError

/**
* Error raised when CID is not valid.
*/
class InvalidCidError extends Error {
constructor (message) {
super(message)
this.name = 'InvalidCidError'
this.code = 'ERR_INVALID_CID'
this.message = message
}
}

exports.ERR_REPO_NOT_INITIALIZED = 'ERR_REPO_NOT_INITIALIZED'
exports.ERR_REPO_ALREADY_OPEN = 'ERR_REPO_ALREADY_OPEN'
exports.ERR_REPO_ALREADY_CLOSED = 'ERR_REPO_ALREADY_CLOSED'
InvalidCidError.code = 'ERR_INVALID_CID'
exports.ERR_INVALID_CID = InvalidCidError
21 changes: 8 additions & 13 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ const assert = require('assert')
const path = require('path')
const debug = require('debug')
const Big = require('bignumber.js')
const errcode = require('err-code')

const backends = require('./backends')
const version = require('./version')
Expand All @@ -15,7 +14,7 @@ const apiAddr = require('./api-addr')
const blockstore = require('./blockstore')
const defaultOptions = require('./default-options')
const defaultDatastore = require('./default-datastore')
const ERRORS = require('./errors')
const errors = require('./errors')

const log = debug('repo')

Expand Down Expand Up @@ -75,7 +74,7 @@ class IpfsRepo {
*/
async open () {
if (!this.closed) {
throw errcode(new Error('repo is already open'), ERRORS.ERR_REPO_ALREADY_OPEN)
throw new errors.ERR_REPO_ALREADY_OPEN('Repo is already open')
}
log('opening at: %s', this.path)

Expand Down Expand Up @@ -149,7 +148,7 @@ class IpfsRepo {
const lockfile = await this._locker.lock(path)

if (typeof lockfile.close !== 'function') {
throw errcode(new Error('Locks must have a close method'), 'ERR_NO_CLOSE_FUNCTION')
throw new errors.ERR_NO_CLOSE_FUNCTION('Locks must have a close method')
}

return lockfile
Expand Down Expand Up @@ -180,18 +179,14 @@ class IpfsRepo {
])
} catch (err) {
if (err.code === 'ERR_NOT_FOUND') {
throw errcode(new Error('repo is not initialized yet'), ERRORS.ERR_REPO_NOT_INITIALIZED, {
path: this.path
})
throw new errors.ERR_REPO_NOT_INITIALIZED('Repo is not initialized yet', this.path)
}

throw err
}

if (!config) {
throw errcode(new Error('repo is not initialized yet'), ERRORS.ERR_REPO_NOT_INITIALIZED, {
path: this.path
})
throw new errors.ERR_REPO_NOT_INITIALIZED('Repo is not initialized yet', this.path)
}
}

Expand All @@ -202,15 +197,15 @@ class IpfsRepo {
*/
async close () {
if (this.closed) {
throw errcode(new Error('repo is already closed'), ERRORS.ERR_REPO_ALREADY_CLOSED)
throw new errors.ERR_REPO_ALREADY_CLOSED('Repo is already closed')
}
log('closing at: %s', this.path)

try {
// Delete api, ignoring irrelevant errors
await this.apiAddr.delete()
} catch (err) {
if (err.code !== ERRORS.ERR_REPO_NOT_INITIALIZED && !err.message.startsWith('ENOENT')) {
if (err.code !== errors.ERR_REPO_NOT_INITIALIZED.code && !err.message.startsWith('ENOENT')) {
throw err
}
}
Expand Down Expand Up @@ -299,7 +294,7 @@ async function getSize (queryFn) {

module.exports = IpfsRepo
module.exports.repoVersion = repoVersion
module.exports.errors = ERRORS
module.exports.errors = errors

function buildOptions (_options) {
const options = Object.assign({}, defaultOptions, _options)
Expand Down
4 changes: 2 additions & 2 deletions src/lock-memory.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict'

const errors = require('./errors')
const { ERR_LOCK_EXISTS } = require('./errors')
const debug = require('debug')

const log = debug('repo:lock')
Expand All @@ -20,7 +20,7 @@ exports.lock = async (dir) => { // eslint-disable-line require-await
log('locking %s', file)

if (LOCKS[file] === true) {
throw new errors.LockExistsError(`Lock already being held for file: ${file}`)
throw new ERR_LOCK_EXISTS(`Lock already being held for file: ${file}`)
}

LOCKS[file] = true
Expand Down
4 changes: 2 additions & 2 deletions src/version.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const Key = require('interface-datastore').Key
const debug = require('debug')
const log = debug('repo:version')
const errcode = require('err-code')
const { ERR_INVALID_REPO_VERSION } = require('./errors')

const versionKey = new Key('version')

Expand Down Expand Up @@ -48,7 +48,7 @@ module.exports = (store) => {
const compatibleVersion = (version === 6 && expected === 7) || (expected === 6 && version === 7)

if (version !== expected && !compatibleVersion) {
throw errcode(new Error(`ipfs repo needs migration: expected version v${expected}, found version v${version}`), 'ERR_INVALID_REPO_VERSION')
throw new ERR_INVALID_REPO_VERSION(`Ipfs repo needs migration: expected version v${expected}, found version v${version}`)
}
}
}
Expand Down
7 changes: 4 additions & 3 deletions test/blockstore-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const path = require('path')
const Key = require('interface-datastore').Key
const base32 = require('base32.js')
const IPFSRepo = require('../')
const errors = IPFSRepo.errors

module.exports = (repo) => {
describe('blockstore', () => {
Expand Down Expand Up @@ -187,7 +188,7 @@ module.exports = (repo) => {
await repo.blocks.get('foo')
throw new Error('Should have thrown')
} catch (err) {
expect(err.code).to.equal('ERR_INVALID_CID')
expect(err.code).to.equal(errors.ERR_INVALID_CID.code)
}
})

Expand Down Expand Up @@ -278,7 +279,7 @@ module.exports = (repo) => {
await repo.blocks.has('foo')
throw new Error('Should have thrown')
} catch (err) {
expect(err.code).to.equal('ERR_INVALID_CID')
expect(err.code).to.equal(errors.ERR_INVALID_CID.code)
}
})

Expand All @@ -304,7 +305,7 @@ module.exports = (repo) => {
await repo.blocks.delete('foo')
throw new Error('Should have thrown')
} catch (err) {
expect(err.code).to.equal('ERR_INVALID_CID')
expect(err.code).to.equal(errors.ERR_INVALID_CID.code)
}
})
})
Expand Down
Loading