From dacd6ce6f325262f1bc1451f20789e9e7cd9b9fd Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Fri, 2 Aug 2024 17:49:09 +0100 Subject: [PATCH] feat!: use `.name` property for errors instead of `.code` (#315) Refactors thrown errors to have a `.name` property that describes the type of error, e.g. `NotFoundError` instead of a `.code` property like `ERR_NOT_FOUND`. This is more ideomatic JavaScript as `.code` is largely inherited from errors thrown by Node.js's fs module whereas `.name` reflects the [function (e.g. constructor) name](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name) of the error. Also removes the `err-code` dependency which is another CJS dep down. BREAKING CHANGE: To detect the type of error thrown, use `.name` instead of `.code` --- packages/blockstore-core/package.json | 1 - packages/blockstore-core/src/black-hole.ts | 4 +- packages/blockstore-core/src/errors.ts | 41 -------------- packages/blockstore-core/src/identity.ts | 4 +- packages/blockstore-core/src/index.ts | 6 -- packages/blockstore-core/src/memory.ts | 4 +- packages/blockstore-core/src/tiered.ts | 8 +-- packages/blockstore-fs/package.json | 1 - packages/blockstore-fs/src/index.ts | 18 +++--- packages/blockstore-fs/test/index.spec.ts | 9 ++- packages/blockstore-idb/src/index.ts | 21 ++++--- packages/blockstore-level/src/index.ts | 13 +++-- packages/blockstore-s3/src/index.ts | 17 +++--- packages/blockstore-s3/test/index.spec.ts | 10 ++-- packages/datastore-core/package.json | 1 - packages/datastore-core/src/black-hole.ts | 4 +- packages/datastore-core/src/errors.ts | 31 ----------- packages/datastore-core/src/index.ts | 2 - packages/datastore-core/src/memory.ts | 4 +- packages/datastore-core/src/mount.ts | 8 +-- packages/datastore-core/src/sharding.ts | 7 ++- packages/datastore-core/src/tiered.ts | 8 +-- packages/datastore-core/test/sharding.spec.ts | 2 +- packages/datastore-fs/src/index.ts | 20 +++---- packages/datastore-fs/test/index.spec.ts | 8 +-- packages/datastore-idb/package.json | 1 + packages/datastore-idb/src/index.ts | 17 +++--- packages/datastore-level/package.json | 1 + packages/datastore-level/src/index.ts | 13 +++-- packages/datastore-s3/src/index.ts | 22 ++++---- packages/datastore-s3/test/index.spec.ts | 10 ++-- .../interface-blockstore-tests/src/index.ts | 4 +- .../interface-datastore-tests/src/index.ts | 6 +- packages/interface-store/package.json | 8 ++- packages/interface-store/src/errors.ts | 55 +++++++++++++++++++ packages/interface-store/src/index.ts | 2 + packages/interface-store/tsconfig.json | 3 +- 37 files changed, 188 insertions(+), 206 deletions(-) delete mode 100644 packages/blockstore-core/src/errors.ts delete mode 100644 packages/datastore-core/src/errors.ts create mode 100644 packages/interface-store/src/errors.ts diff --git a/packages/blockstore-core/package.json b/packages/blockstore-core/package.json index ce215475..7cb046f3 100644 --- a/packages/blockstore-core/package.json +++ b/packages/blockstore-core/package.json @@ -98,7 +98,6 @@ }, "dependencies": { "@libp2p/logger": "^4.0.6", - "err-code": "^3.0.1", "interface-blockstore": "^5.0.0", "interface-store": "^5.0.0", "it-drain": "^3.0.5", diff --git a/packages/blockstore-core/src/black-hole.ts b/packages/blockstore-core/src/black-hole.ts index ab1b5a61..1d6664e5 100644 --- a/packages/blockstore-core/src/black-hole.ts +++ b/packages/blockstore-core/src/black-hole.ts @@ -1,5 +1,5 @@ +import { NotFoundError } from 'interface-store' import { BaseBlockstore } from './base.js' -import * as Errors from './errors.js' import type { Pair } from 'interface-blockstore' import type { Await, AwaitIterable } from 'interface-store' import type { CID } from 'multiformats/cid' @@ -10,7 +10,7 @@ export class BlackHoleBlockstore extends BaseBlockstore { } get (): Await { - throw Errors.notFoundError() + throw new NotFoundError() } has (): Await { diff --git a/packages/blockstore-core/src/errors.ts b/packages/blockstore-core/src/errors.ts deleted file mode 100644 index d4533c91..00000000 --- a/packages/blockstore-core/src/errors.ts +++ /dev/null @@ -1,41 +0,0 @@ -import errCode from 'err-code' - -export function openFailedError (err?: Error): Error { - err = err ?? new Error('Open failed') - return errCode(err, 'ERR_OPEN_FAILED') -} - -export function closeFailedError (err?: Error): Error { - err = err ?? new Error('Close failed') - return errCode(err, 'ERR_CLOSE_FAILED') -} - -export function putFailedError (err?: Error): Error { - err = err ?? new Error('Put failed') - return errCode(err, 'ERR_PUT_FAILED') -} - -export function getFailedError (err?: Error): Error { - err = err ?? new Error('Get failed') - return errCode(err, 'ERR_GET_FAILED') -} - -export function deleteFailedError (err?: Error): Error { - err = err ?? new Error('Delete failed') - return errCode(err, 'ERR_DELETE_FAILED') -} - -export function hasFailedError (err?: Error): Error { - err = err ?? new Error('Has failed') - return errCode(err, 'ERR_HAS_FAILED') -} - -export function notFoundError (err?: Error): Error { - err = err ?? new Error('Not Found') - return errCode(err, 'ERR_NOT_FOUND') -} - -export function abortedError (err?: Error): Error { - err = err ?? new Error('Aborted') - return errCode(err, 'ERR_ABORTED') -} diff --git a/packages/blockstore-core/src/identity.ts b/packages/blockstore-core/src/identity.ts index fdebafe4..bc61fcc2 100644 --- a/packages/blockstore-core/src/identity.ts +++ b/packages/blockstore-core/src/identity.ts @@ -1,5 +1,5 @@ +import { NotFoundError } from 'interface-store' import { BaseBlockstore } from './base.js' -import { Errors } from './index.js' import type { Blockstore, Pair } from 'interface-blockstore' import type { AbortOptions, Await, AwaitIterable } from 'interface-store' import type { CID } from 'multiformats/cid' @@ -34,7 +34,7 @@ export class IdentityBlockstore extends BaseBlockstore { } if (this.child == null) { - throw Errors.notFoundError() + throw new NotFoundError() } return this.child.get(key) diff --git a/packages/blockstore-core/src/index.ts b/packages/blockstore-core/src/index.ts index 0bab631f..c15b4ecd 100644 --- a/packages/blockstore-core/src/index.ts +++ b/packages/blockstore-core/src/index.ts @@ -82,13 +82,7 @@ * ``` */ -import * as ErrorsImport from './errors.js' - export { BaseBlockstore } from './base.js' export { MemoryBlockstore } from './memory.js' export { BlackHoleBlockstore } from './black-hole.js' export { TieredBlockstore } from './tiered.js' - -export const Errors = { - ...ErrorsImport -} diff --git a/packages/blockstore-core/src/memory.ts b/packages/blockstore-core/src/memory.ts index 72686d89..e56033a4 100644 --- a/packages/blockstore-core/src/memory.ts +++ b/packages/blockstore-core/src/memory.ts @@ -1,9 +1,9 @@ +import { NotFoundError } from 'interface-store' import { base32 } from 'multiformats/bases/base32' import { CID } from 'multiformats/cid' import * as raw from 'multiformats/codecs/raw' import * as Digest from 'multiformats/hashes/digest' import { BaseBlockstore } from './base.js' -import * as Errors from './errors.js' import type { Pair } from 'interface-blockstore' import type { Await, AwaitIterable } from 'interface-store' @@ -26,7 +26,7 @@ export class MemoryBlockstore extends BaseBlockstore { const buf = this.data.get(base32.encode(key.multihash.bytes)) if (buf == null) { - throw Errors.notFoundError() + throw new NotFoundError() } return buf diff --git a/packages/blockstore-core/src/tiered.ts b/packages/blockstore-core/src/tiered.ts index ce5c39f1..0062e02c 100644 --- a/packages/blockstore-core/src/tiered.ts +++ b/packages/blockstore-core/src/tiered.ts @@ -1,10 +1,10 @@ import { logger } from '@libp2p/logger' +import { DeleteFailedError, NotFoundError, PutFailedError } from 'interface-store' import drain from 'it-drain' import filter from 'it-filter' import merge from 'it-merge' import { pushable } from 'it-pushable' import { BaseBlockstore } from './base.js' -import * as Errors from './errors.js' import type { Blockstore, Pair } from 'interface-blockstore' import type { AbortOptions, AwaitIterable } from 'interface-store' import type { CID } from 'multiformats/cid' @@ -31,7 +31,7 @@ export class TieredBlockstore extends BaseBlockstore { await Promise.all(this.stores.map(async store => { await store.put(key, value, options) })) return key } catch (err: any) { - throw Errors.putFailedError(err) + throw new PutFailedError(String(err)) } } @@ -44,7 +44,7 @@ export class TieredBlockstore extends BaseBlockstore { log.error(err) } } - throw Errors.notFoundError() + throw new NotFoundError() } async has (key: CID, options?: AbortOptions): Promise { @@ -61,7 +61,7 @@ export class TieredBlockstore extends BaseBlockstore { try { await Promise.all(this.stores.map(async store => { await store.delete(key, options) })) } catch (err: any) { - throw Errors.deleteFailedError(err) + throw new DeleteFailedError(String(err)) } } diff --git a/packages/blockstore-fs/package.json b/packages/blockstore-fs/package.json index c532c84e..81aa8fca 100644 --- a/packages/blockstore-fs/package.json +++ b/packages/blockstore-fs/package.json @@ -76,7 +76,6 @@ "dep-check": "aegir dep-check" }, "dependencies": { - "blockstore-core": "^4.0.0", "fast-write-atomic": "^0.2.1", "interface-blockstore": "^5.0.0", "interface-store": "^5.0.0", diff --git a/packages/blockstore-fs/src/index.ts b/packages/blockstore-fs/src/index.ts index b2e0af65..dbe490e6 100644 --- a/packages/blockstore-fs/src/index.ts +++ b/packages/blockstore-fs/src/index.ts @@ -15,17 +15,15 @@ import fs from 'node:fs/promises' import path from 'node:path' import { promisify } from 'node:util' -import { - Errors -} from 'blockstore-core' // @ts-expect-error no types import fwa from 'fast-write-atomic' +import { OpenFailedError, type AwaitIterable, PutFailedError, NotFoundError, DeleteFailedError } from 'interface-store' import glob from 'it-glob' import map from 'it-map' import parallelBatch from 'it-parallel-batch' -import { NextToLast, type ShardingStrategy } from './sharding.js' +import { NextToLast } from './sharding.js' +import type { ShardingStrategy } from './sharding.js' import type { Blockstore, Pair } from 'interface-blockstore' -import type { AwaitIterable } from 'interface-store' import type { CID } from 'multiformats/cid' const writeAtomic = promisify(fwa) @@ -122,7 +120,7 @@ export class FsBlockstore implements Blockstore { await fs.access(this.path, fs.constants.F_OK | fs.constants.W_OK) if (this.errorIfExists) { - throw Errors.openFailedError(new Error(`Blockstore directory: ${this.path} already exists`)) + throw new OpenFailedError(`Blockstore directory: ${this.path} already exists`) } } catch (err: any) { if (err.code === 'ENOENT') { @@ -130,7 +128,7 @@ export class FsBlockstore implements Blockstore { await fs.mkdir(this.path, { recursive: true }) return } else { - throw Errors.openFailedError(new Error(`Blockstore directory: ${this.path} does not exist`)) + throw new OpenFailedError(`Blockstore directory: ${this.path} does not exist`) } } @@ -156,7 +154,7 @@ export class FsBlockstore implements Blockstore { return key } catch (err: any) { - throw Errors.putFailedError(err) + throw new PutFailedError(String(err)) } } @@ -179,7 +177,7 @@ export class FsBlockstore implements Blockstore { try { return await fs.readFile(path.join(this.path, dir, file)) } catch (err: any) { - throw Errors.notFoundError(err) + throw new NotFoundError(String(err)) } } @@ -207,7 +205,7 @@ export class FsBlockstore implements Blockstore { return } - throw Errors.deleteFailedError(err) + throw new DeleteFailedError(String(err)) } } diff --git a/packages/blockstore-fs/test/index.spec.ts b/packages/blockstore-fs/test/index.spec.ts index 696bacbc..7e327b33 100644 --- a/packages/blockstore-fs/test/index.spec.ts +++ b/packages/blockstore-fs/test/index.spec.ts @@ -1,4 +1,3 @@ -/* eslint-env mocha */ import fs from 'node:fs/promises' import os from 'node:os' import path from 'node:path' @@ -44,7 +43,7 @@ describe('FsBlockstore', () => { const dir = path.join(os.tmpdir(), `test-${Math.random()}`) const store = new FsBlockstore(dir, { createIfMissing: false }) await expect(store.open()).to.eventually.be.rejected - .with.property('code', 'ERR_OPEN_FAILED') + .with.property('name', 'OpenFailedError') }) it('errorIfExists: true - folder exists', async () => { @@ -54,7 +53,7 @@ describe('FsBlockstore', () => { }) const store = new FsBlockstore(dir, { errorIfExists: true }) await expect(store.open()).to.eventually.be.rejected - .with.property('code', 'ERR_OPEN_FAILED') + .with.property('name', 'OpenFailedError') }) }) @@ -68,7 +67,7 @@ describe('FsBlockstore', () => { await fs.delete(key) await expect(fs.get(key)).to.eventually.be.rejected - .with.property('code', 'ERR_NOT_FOUND') + .with.property('name', 'NotFoundError') }) it('deleting non-existent files', async () => { @@ -81,7 +80,7 @@ describe('FsBlockstore', () => { await fs.delete(key) await expect(fs.get(key)).to.eventually.be.rejected - .with.property('code', 'ERR_NOT_FOUND') + .with.property('name', 'NotFoundError') }) describe('interface-blockstore (flat directory)', () => { diff --git a/packages/blockstore-idb/src/index.ts b/packages/blockstore-idb/src/index.ts index 51048a1d..c181259d 100644 --- a/packages/blockstore-idb/src/index.ts +++ b/packages/blockstore-idb/src/index.ts @@ -12,15 +12,14 @@ * ``` */ -import { - BaseBlockstore, - Errors -} from 'blockstore-core' -import { openDB, type IDBPDatabase, deleteDB } from 'idb' +import { BaseBlockstore } from 'blockstore-core' +import { openDB, deleteDB } from 'idb' +import { OpenFailedError, PutFailedError, NotFoundError } from 'interface-store' import { base32upper } from 'multiformats/bases/base32' import { CID } from 'multiformats/cid' import * as raw from 'multiformats/codecs/raw' import * as Digest from 'multiformats/hashes/digest' +import type { IDBPDatabase } from 'idb' import type { Pair } from 'interface-blockstore' import type { AbortOptions, AwaitIterable } from 'interface-store' import type { MultibaseCodec } from 'multiformats/bases/interface' @@ -77,7 +76,7 @@ export class IDBBlockstore extends BaseBlockstore { } }) } catch (err: any) { - throw Errors.openFailedError(err) + throw new OpenFailedError(String(err)) } } @@ -95,7 +94,7 @@ export class IDBBlockstore extends BaseBlockstore { return key } catch (err: any) { - throw Errors.putFailedError(err) + throw new PutFailedError(String(err)) } } @@ -109,11 +108,11 @@ export class IDBBlockstore extends BaseBlockstore { try { val = await this.db.get(this.location, this.#encode(key)) } catch (err: any) { - throw Errors.putFailedError(err) + throw new PutFailedError(String(err)) } if (val === undefined) { - throw Errors.notFoundError() + throw new NotFoundError() } return val @@ -127,7 +126,7 @@ export class IDBBlockstore extends BaseBlockstore { try { await this.db.delete(this.location, this.#encode(key)) } catch (err: any) { - throw Errors.putFailedError(err) + throw new PutFailedError(String(err)) } } @@ -139,7 +138,7 @@ export class IDBBlockstore extends BaseBlockstore { try { return Boolean(await this.db.getKey(this.location, this.#encode(key))) } catch (err: any) { - throw Errors.putFailedError(err) + throw new PutFailedError(String(err)) } } diff --git a/packages/blockstore-level/src/index.ts b/packages/blockstore-level/src/index.ts index 21383ce3..404331f8 100644 --- a/packages/blockstore-level/src/index.ts +++ b/packages/blockstore-level/src/index.ts @@ -14,7 +14,8 @@ * ``` */ -import { BaseBlockstore, Errors } from 'blockstore-core' +import { BaseBlockstore } from 'blockstore-core' +import { DeleteFailedError, GetFailedError, NotFoundError, OpenFailedError, PutFailedError } from 'interface-store' import { Level } from 'level' import { base32upper } from 'multiformats/bases/base32' import { CID } from 'multiformats/cid' @@ -73,7 +74,7 @@ export class LevelBlockstore extends BaseBlockstore { try { await this.db.open(this.opts) } catch (err: any) { - throw Errors.openFailedError(err) + throw new OpenFailedError(String(err)) } } @@ -83,7 +84,7 @@ export class LevelBlockstore extends BaseBlockstore { return key } catch (err: any) { - throw Errors.putFailedError(err) + throw new PutFailedError(String(err)) } } @@ -93,10 +94,10 @@ export class LevelBlockstore extends BaseBlockstore { data = await this.db.get(this.#encode(key)) } catch (err: any) { if (err.notFound != null) { - throw Errors.notFoundError(err) + throw new NotFoundError(String(err)) } - throw Errors.getFailedError(err) + throw new GetFailedError(String(err)) } return data } @@ -118,7 +119,7 @@ export class LevelBlockstore extends BaseBlockstore { try { await this.db.del(this.#encode(key)) } catch (err: any) { - throw Errors.deleteFailedError(err) + throw new DeleteFailedError(String(err)) } } diff --git a/packages/blockstore-s3/src/index.ts b/packages/blockstore-s3/src/index.ts index c41b6397..f858e18f 100644 --- a/packages/blockstore-s3/src/index.ts +++ b/packages/blockstore-s3/src/index.ts @@ -40,7 +40,7 @@ import { ListObjectsV2Command } from '@aws-sdk/client-s3' import { BaseBlockstore } from 'blockstore-core/base' -import * as Errors from 'blockstore-core/errors' +import { DeleteFailedError, GetFailedError, HasFailedError, NotFoundError, OpenFailedError, PutFailedError } from 'interface-store' import toBuffer from 'it-to-buffer' import { fromString as unint8arrayFromString } from 'uint8arrays' import { NextToLast, type ShardingStrategy } from './sharding.js' @@ -106,7 +106,7 @@ export class S3Blockstore extends BaseBlockstore { return key } catch (err: any) { - throw Errors.putFailedError(err) + throw new PutFailedError(String(err)) } } @@ -147,9 +147,10 @@ export class S3Blockstore extends BaseBlockstore { return await toBuffer(data.Body) } catch (err: any) { if (err.statusCode === 404) { - throw Errors.notFoundError(err) + throw new NotFoundError(String(err)) } - throw err + + throw new GetFailedError(String(err)) } } @@ -179,7 +180,7 @@ export class S3Blockstore extends BaseBlockstore { return false } - throw err + throw new HasFailedError(String(err)) } } @@ -197,7 +198,7 @@ export class S3Blockstore extends BaseBlockstore { } ) } catch (err: any) { - throw Errors.deleteFailedError(err) + throw new DeleteFailedError(String(err)) } } @@ -249,7 +250,7 @@ export class S3Blockstore extends BaseBlockstore { break } } catch (err: any) { - throw new Error(err.code) + throw new GetFailedError(String(err)) } } @@ -279,7 +280,7 @@ export class S3Blockstore extends BaseBlockstore { return } - throw Errors.openFailedError(err) + throw new OpenFailedError(String(err)) } } } diff --git a/packages/blockstore-s3/test/index.spec.ts b/packages/blockstore-s3/test/index.spec.ts index 7e849e17..9298caa0 100644 --- a/packages/blockstore-s3/test/index.spec.ts +++ b/packages/blockstore-s3/test/index.spec.ts @@ -55,7 +55,7 @@ describe('S3Blockstore', () => { }) await expect(store.put(cid, new TextEncoder().encode('test data'))).to.eventually.rejected - .with.property('code', 'ERR_PUT_FAILED') + .with.property('name', 'PutFailedError') }) }) @@ -73,7 +73,7 @@ describe('S3Blockstore', () => { }) await expect(store.get(cid)).to.eventually.rejected - .with.property('code', 'ERR_NOT_FOUND') + .with.property('name', 'NotFoundError') }) }) @@ -91,7 +91,7 @@ describe('S3Blockstore', () => { }) await expect(store.delete(cid)).to.eventually.rejected - .with.property('code', 'ERR_DELETE_FAILED') + .with.property('name', 'DeleteFailedError') }) }) @@ -146,7 +146,7 @@ describe('S3Blockstore', () => { }) await expect(store.open()).to.eventually.rejected - .with.property('code', 'ERR_OPEN_FAILED') + .with.property('name', 'OpenFailedError') const headObjectCommand = await bucketTested.promise expect(headObjectCommand).to.have.nested.property('input.Bucket', 'test') @@ -165,7 +165,7 @@ describe('S3Blockstore', () => { }) await expect(store.open()).to.eventually.rejected - .with.property('code', 'ERR_OPEN_FAILED') + .with.property('name', 'OpenFailedError') }) }) diff --git a/packages/datastore-core/package.json b/packages/datastore-core/package.json index fb04ded2..b77609b6 100644 --- a/packages/datastore-core/package.json +++ b/packages/datastore-core/package.json @@ -114,7 +114,6 @@ }, "dependencies": { "@libp2p/logger": "^4.0.6", - "err-code": "^3.0.1", "interface-datastore": "^8.0.0", "interface-store": "^5.0.0", "it-drain": "^3.0.5", diff --git a/packages/datastore-core/src/black-hole.ts b/packages/datastore-core/src/black-hole.ts index 9c7b3d3e..f21ee823 100644 --- a/packages/datastore-core/src/black-hole.ts +++ b/packages/datastore-core/src/black-hole.ts @@ -1,5 +1,5 @@ +import { NotFoundError } from 'interface-store' import { BaseDatastore } from './base.js' -import * as Errors from './errors.js' import type { Pair } from 'interface-datastore' import type { Key } from 'interface-datastore/key' import type { Await, AwaitIterable } from 'interface-store' @@ -10,7 +10,7 @@ export class BlackHoleDatastore extends BaseDatastore { } get (): Await { - throw Errors.notFoundError() + throw new NotFoundError() } has (key: Key): Await { diff --git a/packages/datastore-core/src/errors.ts b/packages/datastore-core/src/errors.ts deleted file mode 100644 index 8009aff7..00000000 --- a/packages/datastore-core/src/errors.ts +++ /dev/null @@ -1,31 +0,0 @@ -import errCode from 'err-code' - -export function dbOpenFailedError (err?: Error): Error { - err = err ?? new Error('Cannot open database') - return errCode(err, 'ERR_DB_OPEN_FAILED') -} - -export function dbDeleteFailedError (err?: Error): Error { - err = err ?? new Error('Delete failed') - return errCode(err, 'ERR_DB_DELETE_FAILED') -} - -export function dbWriteFailedError (err?: Error): Error { - err = err ?? new Error('Write failed') - return errCode(err, 'ERR_DB_WRITE_FAILED') -} - -export function dbReadFailedError (err?: Error): Error { - err = err ?? new Error('Read failed') - return errCode(err, 'ERR_DB_READ_FAILED') -} - -export function notFoundError (err?: Error): Error { - err = err ?? new Error('Not Found') - return errCode(err, 'ERR_NOT_FOUND') -} - -export function abortedError (err?: Error): Error { - err = err ?? new Error('Aborted') - return errCode(err, 'ERR_ABORTED') -} diff --git a/packages/datastore-core/src/index.ts b/packages/datastore-core/src/index.ts index 5ec96a75..e3c75e81 100644 --- a/packages/datastore-core/src/index.ts +++ b/packages/datastore-core/src/index.ts @@ -61,7 +61,6 @@ * ``` */ -import * as Errors from './errors.js' import * as shard from './shard.js' import type { Key } from 'interface-datastore' @@ -73,7 +72,6 @@ export { MountDatastore } from './mount.js' export { TieredDatastore } from './tiered.js' export { NamespaceDatastore } from './namespace.js' -export { Errors } export { shard } export interface Shard { diff --git a/packages/datastore-core/src/memory.ts b/packages/datastore-core/src/memory.ts index df87fd4b..1d12931a 100644 --- a/packages/datastore-core/src/memory.ts +++ b/packages/datastore-core/src/memory.ts @@ -1,6 +1,6 @@ import { Key } from 'interface-datastore/key' +import { NotFoundError } from 'interface-store' import { BaseDatastore } from './base.js' -import * as Errors from './errors.js' import type { Pair } from 'interface-datastore' import type { Await, AwaitIterable } from 'interface-store' @@ -23,7 +23,7 @@ export class MemoryDatastore extends BaseDatastore { const result = this.data.get(key.toString()) if (result == null) { - throw Errors.notFoundError() + throw new NotFoundError() } return result diff --git a/packages/datastore-core/src/mount.ts b/packages/datastore-core/src/mount.ts index 15b74bfb..1e04de72 100644 --- a/packages/datastore-core/src/mount.ts +++ b/packages/datastore-core/src/mount.ts @@ -1,9 +1,9 @@ +import { DeleteFailedError, NotFoundError, PutFailedError } from 'interface-store' import filter from 'it-filter' import merge from 'it-merge' import sort from 'it-sort' import take from 'it-take' import { BaseDatastore } from './base.js' -import * as Errors from './errors.js' import type { Batch, Datastore, Key, KeyQuery, Pair, Query } from 'interface-datastore' import type { AbortOptions } from 'interface-store' @@ -37,7 +37,7 @@ export class MountDatastore extends BaseDatastore { async put (key: Key, value: Uint8Array, options?: AbortOptions): Promise { const match = this._lookup(key) if (match == null) { - throw Errors.dbWriteFailedError(new Error('No datastore mounted for this key')) + throw new PutFailedError('No datastore mounted for this key') } await match.datastore.put(key, value, options) @@ -52,7 +52,7 @@ export class MountDatastore extends BaseDatastore { async get (key: Key, options: AbortOptions = {}): Promise { const match = this._lookup(key) if (match == null) { - throw Errors.notFoundError(new Error('No datastore mounted for this key')) + throw new NotFoundError('No datastore mounted for this key') } return match.datastore.get(key, options) } @@ -68,7 +68,7 @@ export class MountDatastore extends BaseDatastore { async delete (key: Key, options?: AbortOptions): Promise { const match = this._lookup(key) if (match == null) { - throw Errors.dbDeleteFailedError(new Error('No datastore mounted for this key')) + throw new DeleteFailedError('No datastore mounted for this key') } await match.datastore.delete(key, options) diff --git a/packages/datastore-core/src/sharding.ts b/packages/datastore-core/src/sharding.ts index 6244bb2b..a58b4366 100644 --- a/packages/datastore-core/src/sharding.ts +++ b/packages/datastore-core/src/sharding.ts @@ -1,12 +1,13 @@ -import { type Batch, Key, type KeyQuery, type KeyQueryFilter, type Pair, type Query, type QueryFilter, type Datastore } from 'interface-datastore' +import { Key } from 'interface-datastore' +import { OpenFailedError } from 'interface-store' import { BaseDatastore } from './base.js' -import * as Errors from './errors.js' import { KeyTransformDatastore } from './keytransform.js' import { readShardFun, SHARDING_FN } from './shard.js' import type { Shard } from './index.js' +import type { Batch, KeyQuery, KeyQueryFilter, Pair, Query, QueryFilter, Datastore } from 'interface-datastore' import type { AbortOptions, AwaitIterable } from 'interface-store' const shardKey = new Key(SHARDING_FN) @@ -58,7 +59,7 @@ export class ShardingDatastore extends BaseDatastore { if (!hasShard) { if (shard == null) { - throw Errors.dbOpenFailedError(Error('Shard is required when datastore doesn\'t have a shard key already.')) + throw new OpenFailedError('Shard is required when datastore doesn\'t have a shard key already') } await store.put(shardKey, new TextEncoder().encode(shard.toString() + '\n')) diff --git a/packages/datastore-core/src/tiered.ts b/packages/datastore-core/src/tiered.ts index e76db6f1..be5a8de5 100644 --- a/packages/datastore-core/src/tiered.ts +++ b/packages/datastore-core/src/tiered.ts @@ -1,8 +1,8 @@ import { logger } from '@libp2p/logger' +import { PutFailedError, NotFoundError, DeleteFailedError } from 'interface-store' import drain from 'it-drain' import { pushable } from 'it-pushable' import { BaseDatastore } from './base.js' -import * as Errors from './errors.js' import type { Batch, Datastore, Key, KeyQuery, Pair, Query } from 'interface-datastore' import type { AbortOptions, AwaitIterable } from 'interface-store' @@ -29,7 +29,7 @@ export class TieredDatastore extends BaseDatastore { await Promise.all(this.stores.map(async store => { await store.put(key, value, options) })) return key } catch (err: any) { - throw Errors.dbWriteFailedError(err) + throw new PutFailedError(err.message) } } @@ -42,7 +42,7 @@ export class TieredDatastore extends BaseDatastore { log.error(err) } } - throw Errors.notFoundError() + throw new NotFoundError() } async has (key: Key, options?: AbortOptions): Promise { @@ -59,7 +59,7 @@ export class TieredDatastore extends BaseDatastore { try { await Promise.all(this.stores.map(async store => { await store.delete(key, options) })) } catch (err: any) { - throw Errors.dbDeleteFailedError(err) + throw new DeleteFailedError(err.message) } } diff --git a/packages/datastore-core/test/sharding.spec.ts b/packages/datastore-core/test/sharding.spec.ts index b4c8b2a6..b02f5bad 100644 --- a/packages/datastore-core/test/sharding.spec.ts +++ b/packages/datastore-core/test/sharding.spec.ts @@ -32,7 +32,7 @@ describe('ShardingDatastore', () => { const store = new ShardingDatastore(ms) return expect(store.open()) .to.eventually.be.rejected() - .with.property('code', 'ERR_DB_OPEN_FAILED') + .with.property('name', 'OpenFailedError') }) it('open - existing', () => { diff --git a/packages/datastore-fs/src/index.ts b/packages/datastore-fs/src/index.ts index bd19b657..0f6e2f0f 100644 --- a/packages/datastore-fs/src/index.ts +++ b/packages/datastore-fs/src/index.ts @@ -15,17 +15,15 @@ import fs from 'node:fs/promises' import path from 'node:path' import { promisify } from 'util' -import { - BaseDatastore, Errors -} from 'datastore-core' +import { BaseDatastore } from 'datastore-core' // @ts-expect-error no types import fwa from 'fast-write-atomic' -import { - Key, type KeyQuery, type Pair, type Query -} from 'interface-datastore' +import { Key } from 'interface-datastore' +import { OpenFailedError, NotFoundError, PutFailedError, DeleteFailedError } from 'interface-store' import glob from 'it-glob' import map from 'it-map' import parallel from 'it-parallel-batch' +import type { KeyQuery, Pair, Query } from 'interface-datastore' import type { AwaitIterable } from 'interface-store' const writeAtomic = promisify(fwa) @@ -94,7 +92,7 @@ export class FsDatastore extends BaseDatastore { await fs.access(this.path, fs.constants.F_OK | fs.constants.W_OK) if (this.errorIfExists) { - throw Errors.dbOpenFailedError(new Error(`Datastore directory: ${this.path} already exists`)) + throw new OpenFailedError(`Datastore directory: ${this.path} already exists`) } } catch (err: any) { if (err.code === 'ENOENT') { @@ -102,7 +100,7 @@ export class FsDatastore extends BaseDatastore { await fs.mkdir(this.path, { recursive: true }) return } else { - throw Errors.notFoundError(new Error(`Datastore directory: ${this.path} does not exist`)) + throw new NotFoundError(`Datastore directory: ${this.path} does not exist`) } } @@ -160,7 +158,7 @@ export class FsDatastore extends BaseDatastore { return key } catch (err: any) { - throw Errors.dbWriteFailedError(err) + throw new PutFailedError(String(err)) } } @@ -186,7 +184,7 @@ export class FsDatastore extends BaseDatastore { try { data = await fs.readFile(parts.file) } catch (err: any) { - throw Errors.notFoundError(err) + throw new NotFoundError(String(err)) } return data } @@ -244,7 +242,7 @@ export class FsDatastore extends BaseDatastore { return } - throw Errors.dbDeleteFailedError(err) + throw new DeleteFailedError(String(err)) } } diff --git a/packages/datastore-fs/test/index.spec.ts b/packages/datastore-fs/test/index.spec.ts index 273c30d8..39b74536 100644 --- a/packages/datastore-fs/test/index.spec.ts +++ b/packages/datastore-fs/test/index.spec.ts @@ -43,7 +43,7 @@ describe('FsDatastore', () => { const dir = tempdir() const store = new FsDatastore(dir, { createIfMissing: false }) await expect(store.open()).to.eventually.be.rejected - .with.property('code', 'ERR_NOT_FOUND') + .with.property('name', 'NotFoundError') }) it('errorIfExists: true - folder exists', async () => { @@ -53,7 +53,7 @@ describe('FsDatastore', () => { }) const store = new FsDatastore(dir, { errorIfExists: true }) await expect(store.open()).to.eventually.be.rejected - .with.property('code', 'ERR_DB_OPEN_FAILED') + .with.property('name', 'OpenFailedError') }) }) @@ -89,7 +89,7 @@ describe('FsDatastore', () => { await fs.get(key) throw new Error('Should have errored') } catch (err: any) { - expect(err.code).to.equal('ERR_NOT_FOUND') + expect(err).to.have.property('name', 'NotFoundError') } }) @@ -105,7 +105,7 @@ describe('FsDatastore', () => { await fs.get(key) throw new Error('Should have errored') } catch (err: any) { - expect(err.code).to.equal('ERR_NOT_FOUND') + expect(err).to.have.property('name', 'NotFoundError') } }) diff --git a/packages/datastore-idb/package.json b/packages/datastore-idb/package.json index 2334d138..dd42527a 100644 --- a/packages/datastore-idb/package.json +++ b/packages/datastore-idb/package.json @@ -61,6 +61,7 @@ "datastore-core": "^9.0.0", "idb": "^8.0.0", "interface-datastore": "^8.0.0", + "interface-store": "^5.1.8", "it-filter": "^3.0.4", "it-sort": "^3.0.4" }, diff --git a/packages/datastore-idb/src/index.ts b/packages/datastore-idb/src/index.ts index 02c3c7d8..b36c0b77 100644 --- a/packages/datastore-idb/src/index.ts +++ b/packages/datastore-idb/src/index.ts @@ -12,9 +12,10 @@ * ``` */ -import { Errors, BaseDatastore } from 'datastore-core' +import { BaseDatastore } from 'datastore-core' import { openDB, deleteDB, type IDBPDatabase } from 'idb' import { type Batch, Key, type KeyQuery, type Pair, type Query } from 'interface-datastore' +import { DeleteFailedError, GetFailedError, NotFoundError, OpenFailedError, PutFailedError } from 'interface-store' import filter from 'it-filter' import sort from 'it-sort' @@ -52,7 +53,7 @@ export class IDBDatastore extends BaseDatastore { } }) } catch (err: any) { - throw Errors.dbOpenFailedError(err) + throw new OpenFailedError(String(err)) } } @@ -70,7 +71,7 @@ export class IDBDatastore extends BaseDatastore { return key } catch (err: any) { - throw Errors.dbWriteFailedError(err) + throw new PutFailedError(String(err)) } } @@ -84,11 +85,11 @@ export class IDBDatastore extends BaseDatastore { try { val = await this.db.get(this.location, key.toString()) } catch (err: any) { - throw Errors.dbReadFailedError(err) + throw new GetFailedError(String(err)) } if (val === undefined) { - throw Errors.notFoundError() + throw new NotFoundError() } return val @@ -102,7 +103,7 @@ export class IDBDatastore extends BaseDatastore { try { return Boolean(await this.db.getKey(this.location, key.toString())) } catch (err: any) { - throw Errors.dbReadFailedError(err) + throw new GetFailedError(String(err)) } } @@ -114,7 +115,7 @@ export class IDBDatastore extends BaseDatastore { try { await this.db.delete(this.location, key.toString()) } catch (err: any) { - throw Errors.dbDeleteFailedError(err) + throw new DeleteFailedError(String(err)) } } @@ -222,7 +223,7 @@ export class IDBDatastore extends BaseDatastore { try { value = await this.get(k) } catch (err: any) { - if (err.code !== 'ERR_NOT_FOUND') { + if (err.name !== 'NotFoundError') { throw err } continue diff --git a/packages/datastore-level/package.json b/packages/datastore-level/package.json index 940d1fdb..7ae0717d 100644 --- a/packages/datastore-level/package.json +++ b/packages/datastore-level/package.json @@ -63,6 +63,7 @@ "dependencies": { "datastore-core": "^9.0.0", "interface-datastore": "^8.0.0", + "interface-store": "^5.1.8", "it-filter": "^3.0.4", "it-map": "^3.0.5", "it-sort": "^3.0.4", diff --git a/packages/datastore-level/src/index.ts b/packages/datastore-level/src/index.ts index b6368118..f08807d2 100644 --- a/packages/datastore-level/src/index.ts +++ b/packages/datastore-level/src/index.ts @@ -44,8 +44,9 @@ * More information: [https://github.com/Level/level-js/blob/master/UPGRADING.md#new-database-prefix](https://github.com/Level/level-js/blob/99831913e905d19e5f6dee56d512b7264fbed7bd/UPGRADING.md#new-database-prefix) */ -import { BaseDatastore, Errors } from 'datastore-core' +import { BaseDatastore } from 'datastore-core' import { type Batch, Key, type KeyQuery, type Pair, type Query } from 'interface-datastore' +import { DeleteFailedError, GetFailedError, NotFoundError, OpenFailedError, PutFailedError } from 'interface-store' import filter from 'it-filter' import map from 'it-map' import sort from 'it-sort' @@ -95,7 +96,7 @@ export class LevelDatastore extends BaseDatastore { try { await this.db.open(this.opts) } catch (err: any) { - throw Errors.dbOpenFailedError(err) + throw new OpenFailedError(String(err)) } } @@ -105,7 +106,7 @@ export class LevelDatastore extends BaseDatastore { return key } catch (err: any) { - throw Errors.dbWriteFailedError(err) + throw new PutFailedError(String(err)) } } @@ -115,10 +116,10 @@ export class LevelDatastore extends BaseDatastore { data = await this.db.get(key.toString()) } catch (err: any) { if (err.notFound != null) { - throw Errors.notFoundError(err) + throw new NotFoundError(String(err)) } - throw Errors.dbReadFailedError(err) + throw new GetFailedError(String(err)) } return data } @@ -140,7 +141,7 @@ export class LevelDatastore extends BaseDatastore { try { await this.db.del(key.toString()) } catch (err: any) { - throw Errors.dbDeleteFailedError(err) + throw new DeleteFailedError(String(err)) } } diff --git a/packages/datastore-s3/src/index.ts b/packages/datastore-s3/src/index.ts index 9d464f3f..cdd6d1d1 100644 --- a/packages/datastore-s3/src/index.ts +++ b/packages/datastore-s3/src/index.ts @@ -40,12 +40,13 @@ import { ListObjectsV2Command } from '@aws-sdk/client-s3' import { BaseDatastore } from 'datastore-core/base' -import * as Errors from 'datastore-core/errors' -import { Key, type KeyQuery, type Pair, type Query } from 'interface-datastore' +import { Key } from 'interface-datastore' +import { DeleteFailedError, GetFailedError, HasFailedError, NotFoundError, OpenFailedError, PutFailedError } from 'interface-store' import filter from 'it-filter' import toBuffer from 'it-to-buffer' import { fromString as unint8arrayFromString } from 'uint8arrays' import type { S3 } from '@aws-sdk/client-s3' +import type { KeyQuery, Pair, Query } from 'interface-datastore' import type { AbortOptions } from 'interface-store' export interface S3DatastoreInit { @@ -117,7 +118,7 @@ export class S3Datastore extends BaseDatastore { return key } catch (err: any) { - throw Errors.dbWriteFailedError(err) + throw new PutFailedError(String(err)) } } @@ -159,9 +160,10 @@ export class S3Datastore extends BaseDatastore { return await toBuffer(data.Body) } catch (err: any) { if (err.statusCode === 404) { - throw Errors.notFoundError(err) + throw new NotFoundError(String(err)) } - throw err + + throw new GetFailedError(String(err)) } } @@ -191,7 +193,7 @@ export class S3Datastore extends BaseDatastore { return false } - throw err + throw new HasFailedError(String(err)) } } @@ -209,7 +211,7 @@ export class S3Datastore extends BaseDatastore { } ) } catch (err: any) { - throw Errors.dbDeleteFailedError(err) + throw new DeleteFailedError(String(err)) } } @@ -253,7 +255,7 @@ export class S3Datastore extends BaseDatastore { yield * this._listKeys(params) } } catch (err: any) { - throw new Error(err.code) + throw new GetFailedError(String(err)) } } @@ -268,7 +270,7 @@ export class S3Datastore extends BaseDatastore { yield res } catch (err: any) { // key was deleted while we are iterating over the results - if (err.statusCode !== 404) { + if (err.name !== 'NotFoundError') { throw err } } @@ -316,7 +318,7 @@ export class S3Datastore extends BaseDatastore { return } - throw Errors.dbOpenFailedError(err) + throw new OpenFailedError(String(err)) } } } diff --git a/packages/datastore-s3/test/index.spec.ts b/packages/datastore-s3/test/index.spec.ts index 1fbd5d4e..837545d8 100644 --- a/packages/datastore-s3/test/index.spec.ts +++ b/packages/datastore-s3/test/index.spec.ts @@ -72,7 +72,7 @@ describe('S3Datastore', () => { }) await expect(store.put(new Key('/z/key'), new TextEncoder().encode('test data'))).to.eventually.rejected - .with.property('code', 'ERR_DB_WRITE_FAILED') + .with.property('name', 'PutFailedError') }) }) @@ -116,7 +116,7 @@ describe('S3Datastore', () => { }) await expect(store.get(new Key('/z/key'))).to.eventually.rejected - .with.property('code', 'ERR_NOT_FOUND') + .with.property('name', 'NotFoundError') }) }) @@ -134,7 +134,7 @@ describe('S3Datastore', () => { }) await expect(store.delete(new Key('/z/key'))).to.eventually.rejected - .with.property('code', 'ERR_DB_DELETE_FAILED') + .with.property('name', 'DeleteFailedError') }) }) @@ -189,7 +189,7 @@ describe('S3Datastore', () => { }) await expect(store.open()).to.eventually.rejected - .with.property('code', 'ERR_DB_OPEN_FAILED') + .with.property('name', 'OpenFailedError') const headObjectCommand = await bucketTested.promise expect(headObjectCommand).to.have.nested.property('input.Bucket', 'test') @@ -208,7 +208,7 @@ describe('S3Datastore', () => { }) await expect(store.open()).to.eventually.rejected - .with.property('code', 'ERR_DB_OPEN_FAILED') + .with.property('name', 'OpenFailedError') }) }) diff --git a/packages/interface-blockstore-tests/src/index.ts b/packages/interface-blockstore-tests/src/index.ts index 69a77146..069ddb4f 100644 --- a/packages/interface-blockstore-tests/src/index.ts +++ b/packages/interface-blockstore-tests/src/index.ts @@ -153,7 +153,7 @@ export function interfaceBlockstoreTests (te try { await store.get(cid) } catch (err) { - expect(err).to.have.property('code', 'ERR_NOT_FOUND') + expect(err).to.have.property('name', 'NotFoundError') return } @@ -194,7 +194,7 @@ export function interfaceBlockstoreTests (te try { await drain(store.getMany([cid])) } catch (err) { - expect(err).to.have.property('code', 'ERR_NOT_FOUND') + expect(err).to.have.property('name', 'NotFoundError') return } diff --git a/packages/interface-datastore-tests/src/index.ts b/packages/interface-datastore-tests/src/index.ts index 8076c214..a6fee810 100644 --- a/packages/interface-datastore-tests/src/index.ts +++ b/packages/interface-datastore-tests/src/index.ts @@ -124,7 +124,7 @@ export function interfaceDatastoreTests (test: try { await store.get(k) } catch (err) { - expect(err).to.have.property('code', 'ERR_NOT_FOUND') + expect(err).to.have.property('name', 'NotFoundError') return } @@ -158,7 +158,7 @@ export function interfaceDatastoreTests (test: try { await drain(store.getMany([k])) } catch (err) { - expect(err).to.have.property('code', 'ERR_NOT_FOUND') + expect(err).to.have.property('name', 'NotFoundError') return } @@ -476,7 +476,7 @@ export function interfaceDatastoreTests (test: } })) - it('allows mutating the datastore during a query', async () => { + it('allows mutating the datastore during a key query', async () => { const hello3 = { key: new Key('/z/4hello3'), value: uint8ArrayFromString('4') } let firstIteration = true diff --git a/packages/interface-store/package.json b/packages/interface-store/package.json index ba1690dc..aeaeb559 100644 --- a/packages/interface-store/package.json +++ b/packages/interface-store/package.json @@ -15,7 +15,7 @@ "access": "public", "provenance": true }, - "main": "src/index.js", + "type": "module", "types": "dist/src/index.d.ts", "typesVersions": { "*": { @@ -35,6 +35,12 @@ "src", "dist" ], + "exports": { + ".": { + "types": "./dist/src/index.d.ts", + "import": "./dist/src/index.js" + } + }, "eslintConfig": { "extends": "ipfs", "parserOptions": { diff --git a/packages/interface-store/src/errors.ts b/packages/interface-store/src/errors.ts new file mode 100644 index 00000000..c96c221b --- /dev/null +++ b/packages/interface-store/src/errors.ts @@ -0,0 +1,55 @@ +export class OpenFailedError extends Error { + constructor (message = 'Open failed') { + super(message) + this.name = 'OpenFailedError' + } +} + +export class CloseFailedError extends Error { + constructor (message = 'Close failed') { + super(message) + this.name = 'CloseFailedError' + } +} + +export class PutFailedError extends Error { + constructor (message = 'Put failed') { + super(message) + this.name = 'PutFailedError' + } +} + +export class GetFailedError extends Error { + constructor (message = 'Get failed') { + super(message) + this.name = 'GetFailedError' + } +} + +export class DeleteFailedError extends Error { + constructor (message = 'Delete failed') { + super(message) + this.name = 'DeleteFailedError' + } +} + +export class HasFailedError extends Error { + constructor (message = 'Has failed') { + super(message) + this.name = 'HasFailedError' + } +} + +export class NotFoundError extends Error { + constructor (message = 'Not Found') { + super(message) + this.name = 'NotFoundError' + } +} + +export class AbortError extends Error { + constructor (message = 'Aborted') { + super(message) + this.name = 'AbortError' + } +} diff --git a/packages/interface-store/src/index.ts b/packages/interface-store/src/index.ts index 5d84d4ca..9cf9a01e 100644 --- a/packages/interface-store/src/index.ts +++ b/packages/interface-store/src/index.ts @@ -133,3 +133,5 @@ export interface Store } + +export * from './errors.js' diff --git a/packages/interface-store/tsconfig.json b/packages/interface-store/tsconfig.json index 8988b1e0..5fe8ea40 100644 --- a/packages/interface-store/tsconfig.json +++ b/packages/interface-store/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "aegir/src/config/tsconfig.aegir.json", "compilerOptions": { - "outDir": "dist", - "emitDeclarationOnly": true + "outDir": "dist" }, "include": [ "src"