Skip to content

Commit

Permalink
Merge pull request #25 from Raynos/full-info
Browse files Browse the repository at this point in the history
add getInfo() method
  • Loading branch information
Raynos committed May 21, 2020
2 parents 59a70bf + e18b638 commit 68a29c9
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 29 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,8 @@ the type name.
- `fullStack`; Take a wrapped error and compute a full stack.
- `wrapf`; Utility function to quickly wrap
- `errorf`; Utility function to quickly create an error
- `getInfo`; Utility function to get the info for any error
object. Calls `err.info()` if the method exists.

### `WError`

Expand Down Expand Up @@ -326,6 +328,15 @@ and an info object.
It will use [string-template][string-template] to apply the
template with the `info` object as a parameter.

### `SError.getInfo(error)`

Static method to `getInfo` on a maybe error. The `error` can
be `null` or `undefined`, it can be a plain `new Error()` or
it can be a structured or wrapped error.

Will return `err.info()` if it exists, returns `{}` if its `null`
and returns `{ ...err }` if its a plain vanilla error.

### `serr.type`

Returns the type field. The `err.type` field is machine readable.
Expand Down
59 changes: 44 additions & 15 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,15 @@

const assert = require('assert')

/**
* @typedef {import('./interfaces').CustomError} CustomError
/** @typedef {{
type?: string;
errno?: string;
syscall?: string;
cause?(): Error;
fullType?(this: CustomError): string;
info?(): Record<string, unknown>;
toJSON?(): Record<string, unknown>;
} & Error} CustomError
*/

const nargs = /\{([0-9a-zA-Z_]+)\}/g
Expand Down Expand Up @@ -52,12 +59,12 @@ class StructuredError extends Error {
this.__info = info
}

/** @returns {{ [k: string]: unknown }} */
/** @returns {Record<string, unknown>} */
info () {
return { ...this.__info }
}

/** @returns {{ [k: string]: unknown }} */
/** @returns {Record<string, unknown>} */
toJSON () {
return {
...this.__info,
Expand All @@ -73,9 +80,22 @@ class StructuredError extends Error {
return getTypeNameCached(this.name)
}

/**
* @param {CustomError | null} error
* @returns {Record<string, unknown>}
*/
static getInfo (error) {
if (!error) return {}
if (typeof error.info !== 'function') {
return { ...error }
}

return error.info()
}

/**
* @param {string} messageTmpl
* @param {{ [k: string]: unknown }} [info]
* @param {Record<string, unknown>} [info]
* @returns {StructuredError}
*/
static create (messageTmpl, info) {
Expand Down Expand Up @@ -133,14 +153,14 @@ class WrappedError extends Error {
return this.__cause
}

/** @returns {{ [k: string]: unknown }} */
/** @returns {Record<string, unknown>} */
info () {
return WrappedError.fullInfo(this.cause(), this.__info)
}

/** @returns {{ [k: string]: unknown }} */
/** @returns {Record<string, unknown>} */
toJSON () {
/** @type {{ [k: string]: unknown }} */
/** @type {Record<string, unknown>} */
let causeJSON
if (typeof this.__cause.toJSON === 'function') {
causeJSON = this.__cause.toJSON()
Expand Down Expand Up @@ -188,10 +208,10 @@ class WrappedError extends Error {
/**
* @param {CustomError | null} cause
* @param {object} [info]
* @returns {{ [k: string]: unknown }}
* @returns {Record<string, unknown>}
*/
static fullInfo (cause, info) {
/** @type {{ [k: string]: unknown } | undefined} */
/** @type {Record<string, unknown> | undefined} */
let existing
if (cause && typeof cause.info === 'function') {
existing = cause.info()
Expand Down Expand Up @@ -351,6 +371,15 @@ function fullStack (err) {
}
exports.fullStack = fullStack

/**
* @param {CustomError | null} error
* @returns {Record<string, unknown>}
*/
function getInfo (error) {
return StructuredError.getInfo(error)
}
exports.getInfo = getInfo

/**
* @param {string} messageTmpl
* @param {Error} cause
Expand All @@ -364,7 +393,7 @@ exports.wrapf = wrapf

/**
* @param {string} messageTmpl
* @param {{ [k: string]: unknown }} [info]
* @param {Record<string, unknown>} [info]
* @returns {StructuredError}
*/
function errorf (messageTmpl, info) {
Expand Down Expand Up @@ -407,10 +436,10 @@ function createTypeStr (name) {

/**
* @param {CustomError} cause
* @returns {{ [k: string]: unknown }}
* @returns {Record<string, unknown>}
*/
function getInfoForPlainError (cause) {
/** @type {{ [k: string]: unknown }} */
/** @type {Record<string, unknown>} */
const info = {}
for (const field of PLAIN_ERROR_FIELDS) {
const v = reflectGet(cause, field)
Expand All @@ -431,7 +460,7 @@ function isError (err) {

/**
* @param {Error} err
* @returns {{ [k: string]: unknown }}
* @returns {Record<string, unknown>}
*/
function getJSONForPlainError (err) {
const obj = getInfoForPlainError(err)
Expand All @@ -449,7 +478,7 @@ function getJSONForPlainError (err) {
*/
/**
* @param {string} string
* @param {{ [k: string]: unknown }} [object]
* @param {Record<string, unknown>} [object]
* @returns {string}
*/
function stringTemplate (string, object) {
Expand Down
11 changes: 0 additions & 11 deletions interfaces.d.ts

This file was deleted.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"devDependencies": {
"@pre-bundled/tape": "5.0.0",
"@types/node": "13.13.4",
"npm-bin-deps": "1.7.0"
"npm-bin-deps": "1.8.2"
},
"licenses": [
{
Expand Down
4 changes: 2 additions & 2 deletions test/wrapped.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ test('can create a wrapped error', function t (assert) {
class ServerListenFailedError extends WError {}

/** @type {Error & { code?: string }} */
var err = new Error('listen EADDRINUSE')
const err = new Error('listen EADDRINUSE')
err.code = 'EADDRINUSE'

var err2 = ServerListenFailedError.wrap(
const err2 = ServerListenFailedError.wrap(
'server failed', err, {
requestedPort: 3426,
host: 'localhost'
Expand Down

0 comments on commit 68a29c9

Please sign in to comment.