Comparing version 0.4.0 to 0.5.0
@@ -0,1 +1,38 @@ | ||
# [0.5.0](https://github.com/rafamel/errorish/compare/v0.4.0...v0.5.0) (2019-12-23) | ||
### Bug Fixes | ||
* **Errorish:** fixes static classes for inheriting classes ([ae9ecf2](https://github.com/rafamel/errorish/commit/ae9ecf2adedec9f66240d81f2dd1f0fcbacca399)) | ||
### chore | ||
* cleans up sources; begins complete rewrite ([f745eb9](https://github.com/rafamel/errorish/commit/f745eb957b3b69240075f16545c27d796161c1cb)) | ||
### Code Refactoring | ||
* removes I prefix from type interfaces ([122d668](https://github.com/rafamel/errorish/commit/122d66849bad51b9f7fcc49be2fa8df9501689d9)) | ||
### Features | ||
* **Errorish:** adds Errorish.raise; modifies recast arguments order ([ebb1f60](https://github.com/rafamel/errorish/commit/ebb1f602107ca2aad45e0c8d7148874d41ca2fbc)) | ||
* adds ensure ([6d0a537](https://github.com/rafamel/errorish/commit/6d0a5375d151c17cdec4e32a740cc2abb7606344)) | ||
* adds Errorish class ([e12df09](https://github.com/rafamel/errorish/commit/e12df0963b51ed5d7cedebbbe5a38bd3bd8f19b9)) | ||
* adds normalize ([a4994af](https://github.com/rafamel/errorish/commit/a4994af3c23dac39709baa2a686d275b9ea4e45f)) | ||
* adds rejects ([3b0c833](https://github.com/rafamel/errorish/commit/3b0c8335ccaf9f2a08dc29e10612dea97f13223a)) | ||
* adds throws ([e73d3d3](https://github.com/rafamel/errorish/commit/e73d3d30275088ebb22c95ac8c2f1b9c13096413)) | ||
* adds types ([3e8d28e](https://github.com/rafamel/errorish/commit/3e8d28ec6e1cd2bcfa74deefa5b83892c73043bc)) | ||
### BREAKING CHANGES | ||
* Errorish has been almost entirely rewritten. Please check the updated documentation | ||
-most of its functionality has suffered changes. | ||
* Type interfaces are no longer prefixed by "I" | ||
# [0.4.0](https://github.com/rafamel/errorish/compare/v0.3.0...v0.4.0) (2019-05-13) | ||
@@ -2,0 +39,0 @@ |
@@ -1,13 +0,1 @@ | ||
import normalize from "../normalize.js"; | ||
import defaults from "../scope/defaults.js"; | ||
import trunk from "./trunk.js"; | ||
/** | ||
* Will return `error` if it is an instance of `options.Error` -by default, and instance of `Error`. Otherwise, it will instantiate and return an `Error` of class `options.Errorish` -`Errorish` by default. This newly created error -if created- would have: | ||
* - whatever you passed as an `error` as its `source` field. | ||
* - whatever you passed as `data` as its `data` field. | ||
*/ | ||
export default function ensure(error, options, data) { | ||
const opts = Object.assign({}, defaults, options); | ||
return opts.normalize ? normalize(trunk(error, opts, data), opts) : trunk(error, opts, data); | ||
} | ||
export * from "./ensure.js"; |
@@ -1,2 +0,2 @@ | ||
export default function stringify(message, options) { | ||
export function stringify(message) { | ||
if (typeof message === 'string') return message; | ||
@@ -6,5 +6,3 @@ | ||
return JSON.stringify(message); | ||
} catch (e) { | ||
return options.message; | ||
} | ||
} catch (e) {} | ||
} |
@@ -1,13 +0,19 @@ | ||
import stringify from "./stringify.js"; | ||
export default function trunk(error, options, data) { | ||
if (error instanceof options.Error) return error; | ||
let message = error && typeof error === 'object' && error.hasOwnProperty('message') ? error.message : error; | ||
message = options.allow.includes(typeof message) ? stringify(message, options) : options.message; | ||
error = new options.Errorish(message, error, data); | ||
import { stringify } from "./stringify.js"; | ||
import { normalize } from "../normalize.js"; | ||
export function trunk(error, create, options) { | ||
if (!(error instanceof options.Error)) { | ||
if (typeof create === 'function') { | ||
error = create(error); | ||
} else { | ||
var message = error && typeof error === 'object' && Object.hasOwnProperty.call(error, 'message') ? error.message : error; | ||
message = create.allow.includes(typeof message) ? stringify(message) : undefined; | ||
error = new Error(message); | ||
} | ||
if (options.capture && Error.captureStackTrace) { | ||
Error.captureStackTrace(error, options.Errorish); | ||
if (error && options.capture && Error.captureStackTrace) { | ||
Error.captureStackTrace(error, error.constructor); | ||
} | ||
} | ||
return error; | ||
return options.normalize ? normalize(error, typeof options.normalize === 'boolean' ? null : options.normalize) : error; | ||
} |
@@ -0,20 +1,105 @@ | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
export default class Errorish extends Error { | ||
import { ensure } from "./ensure/index.js"; | ||
import { rejects } from "./rejects.js"; | ||
import { throws } from "./throws.js"; | ||
import { isPromise } from 'promist'; | ||
export class Errorish extends Error { | ||
/** | ||
* An optional `source` -should reference the object that originated the `Errorish`. | ||
* Returns `true` if `error` is an instance of the class with label `label`, if passed. | ||
*/ | ||
static is(error, label) { | ||
if (!(error instanceof this)) return false; | ||
if (label === undefined) return true; | ||
return Array.isArray(label) ? label.includes(error.label) : error.label === label; | ||
} | ||
/** | ||
* Runs and returns the result of `fn` only when `error` is an instance of the class and, optionally, has a specific `label`. | ||
*/ | ||
static recast(error, create, label) { | ||
return this.is(error, label) ? create(error) : error; | ||
} | ||
/** | ||
* An optional `data` field. | ||
* Calls `recast` and throws its response if `fn` throws or rejects, otherwise returns or throws the same result or error as `fn`. | ||
*/ | ||
constructor(message, source, data) { | ||
static raise(fn, create, label) { | ||
var _this = this; | ||
try { | ||
var response = fn(); | ||
if (isPromise(response)) { | ||
return response.catch( | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref = _asyncToGenerator(function* (err) { | ||
throw _this.recast(err, create, label); | ||
}); | ||
return function (_x) { | ||
return _ref.apply(this, arguments); | ||
}; | ||
}()); | ||
} | ||
return response; | ||
} catch (err) { | ||
throw this.recast(err, create, label); | ||
} | ||
} | ||
/** | ||
* See `ensure` function. | ||
*/ | ||
static ensure(error, create, options) { | ||
return ensure(error, create, Object.assign({}, options, { | ||
Error: this | ||
})); | ||
} | ||
/** | ||
* See `rejects` function. | ||
*/ | ||
static rejects(error, create, options) { | ||
return rejects(error, create, Object.assign({}, options, { | ||
Error: this | ||
})); | ||
} | ||
/** | ||
* See `throws` function. | ||
*/ | ||
static throws(fn, create, options) { | ||
return throws(fn, create, Object.assign({}, options, { | ||
Error: this | ||
})); | ||
} | ||
/** | ||
* A label for the Error. | ||
*/ | ||
constructor(message, label, data, source) { | ||
super(message || undefined); | ||
_defineProperty(this, "source", void 0); | ||
_defineProperty(this, "label", void 0); | ||
_defineProperty(this, "data", void 0); | ||
_defineProperty(this, "source", void 0); | ||
this.label = label || null; | ||
this.data = data || {}; | ||
this.source = source; | ||
this.data = data || {}; | ||
} | ||
@@ -30,26 +115,39 @@ /** | ||
/** | ||
* References `source.root` is an instance of `Errorish`; references `source` if it is an instance of `Error`; otherwise it references itself. | ||
* References the first `Errorish` in the `Errorish.source` chain. | ||
*/ | ||
get root() { | ||
if (this.source instanceof Errorish) return this.source.root; | ||
root() { | ||
return this.source instanceof Errorish && this.source !== this ? this.source.root() : this; | ||
} | ||
/** | ||
* Returns `Errorish.source` if it is an `Error`, otherwise it returns itself. | ||
*/ | ||
error() { | ||
return this.source instanceof Error ? this.source : this; | ||
} | ||
/** | ||
* Sets the `data` field and returns itself. | ||
* Clones the instance and assigns it a new `data` field. | ||
*/ | ||
set(data) { | ||
this.data = data; | ||
return this; | ||
reproduce(data) { | ||
var destination = Object.create(this); | ||
return Object.assign(destination, this, { | ||
data | ||
}); | ||
} | ||
/** | ||
* Assigns `data` to the `data` field and returns itself. | ||
* Runs `Error.captureStackTrace` if running in `V8` to clean up the error stack trace. | ||
*/ | ||
assign(data) { | ||
Object.assign(this.data, data); | ||
capture() { | ||
/* istanbul ignore next */ | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, this.constructor); | ||
} | ||
return this; | ||
@@ -56,0 +154,0 @@ } |
@@ -1,7 +0,6 @@ | ||
export { default as scope } from "./scope/index.js"; | ||
export { default as ensure } from "./ensure/index.js"; | ||
export { default as throws } from "./throws.js"; | ||
export { default as rejects } from "./rejects.js"; | ||
export { default as normalize } from "./normalize.js"; | ||
export { default as Errorish } from "./Errorish.js"; | ||
export * from "./types.js"; | ||
export * from "./normalize.js"; | ||
export * from "./ensure/index.js"; | ||
export * from "./rejects.js"; | ||
export * from "./throws.js"; | ||
export * from "./Errorish.js"; | ||
export * from "./types/index.js"; |
@@ -1,16 +0,13 @@ | ||
import defaults from "./scope/defaults.js"; | ||
/** | ||
* Normalizes an Error -it assumes an instance of Error is passed. It guarantees the error will have a `name`, `message`, and `stack` properties. | ||
*/ | ||
export default function normalize(error, options) { | ||
const opts = Object.assign({}, defaults, options); | ||
if (!error.name) { | ||
error.name = error.constructor && error.constructor.name || opts.name; | ||
} | ||
export function normalize(error, options) { | ||
var opts = Object.assign({ | ||
message: 'An error occurred', | ||
name: 'Error' | ||
}, options); | ||
if (!error.name) error.name = opts.name; | ||
if (!error.message) error.message = opts.message; | ||
if (!error.stack) error.stack = `Error: ${error.message}`; | ||
if (!error.stack) error.stack = "Error: ".concat(error.message); | ||
return error; | ||
} |
@@ -1,10 +0,19 @@ | ||
import ensure from "./ensure/index.js"; | ||
export default rejects; | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
import { ensure } from "./ensure/index.js"; | ||
/** | ||
* Returns a promise rejection with `error`, having called `ensure` on it. | ||
* Returns a `Promise` rejection with `error`, having called `ensure` on it. | ||
*/ | ||
async function rejects(error, options, data) { | ||
const condition = options && options.hasOwnProperty('case') ? options.case : true; | ||
if (condition) throw ensure(error, options, data); | ||
export function rejects(_x, _x2, _x3) { | ||
return _rejects.apply(this, arguments); | ||
} | ||
function _rejects() { | ||
_rejects = _asyncToGenerator(function* (error, create, options) { | ||
throw ensure(error, create, options); | ||
}); | ||
return _rejects.apply(this, arguments); | ||
} |
@@ -1,4 +0,4 @@ | ||
import ensure from "./ensure/index.js"; | ||
import rejects from "./rejects.js"; | ||
import { isPromise, lazy } from 'promist'; | ||
import { isPromise, LazyPromist } from 'promist'; | ||
import { ensure } from "./ensure/index.js"; | ||
import { rejects } from "./rejects.js"; | ||
@@ -8,14 +8,13 @@ /** | ||
*/ | ||
export default function throws(fn, options, data) { | ||
export function throws(fn, create, options) { | ||
try { | ||
const response = fn(); | ||
if (!isPromise(response)) return response; // if it is a promise | ||
// in case res was a lazy promise | ||
var response = fn(); | ||
if (!isPromise(response)) return response; // if it is a promise, in case response was a lazy promise | ||
return lazy.fn(() => { | ||
return response.catch(err => rejects(err, options, data)); | ||
}); | ||
return LazyPromist.from(() => { | ||
return response.catch(err => rejects(err, create, options)); | ||
}).then(value => value); | ||
} catch (err) { | ||
throw ensure(err, options, data); | ||
throw ensure(err, create, options); | ||
} | ||
} |
@@ -1,299 +0,242 @@ | ||
import { isPromise, lazy } from 'promist'; | ||
import { isPromise, LazyPromist } from 'promist'; | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { | ||
/** | ||
* Normalizes an Error -it assumes an instance of Error is passed. It guarantees the error will have a `name`, `message`, and `stack` properties. | ||
*/ | ||
function normalize(error, options) { | ||
var opts = Object.assign({ | ||
message: 'An error occurred', | ||
name: 'Error' | ||
}, options); | ||
if (!error.name) error.name = opts.name; | ||
if (!error.message) error.message = opts.message; | ||
if (!error.stack) error.stack = "Error: ".concat(error.message); | ||
return error; | ||
} | ||
function stringify(message) { | ||
if (typeof message === 'string') return message; | ||
try { | ||
var info = gen[key](arg); | ||
var value = info.value; | ||
} catch (error) { | ||
reject(error); | ||
return; | ||
return JSON.stringify(message); | ||
} catch (e) {} | ||
} | ||
function trunk(error, create, options) { | ||
if (!(error instanceof options.Error)) { | ||
if (typeof create === 'function') { | ||
error = create(error); | ||
} else { | ||
var message = error && typeof error === 'object' && Object.hasOwnProperty.call(error, 'message') ? error.message : error; | ||
message = create.allow.includes(typeof message) ? stringify(message) : undefined; | ||
error = new Error(message); | ||
} | ||
if (error && options.capture && Error.captureStackTrace) { | ||
Error.captureStackTrace(error, error.constructor); | ||
} | ||
} | ||
if (info.done) { | ||
resolve(value); | ||
} else { | ||
Promise.resolve(value).then(_next, _throw); | ||
} | ||
return options.normalize ? normalize(error, typeof options.normalize === 'boolean' ? null : options.normalize) : error; | ||
} | ||
function _asyncToGenerator(fn) { | ||
return function () { | ||
var self = this, | ||
args = arguments; | ||
return new Promise(function (resolve, reject) { | ||
var gen = fn.apply(self, args); | ||
/** | ||
* Will return `error` if it's an instance of `Error`; otherwise, it will instantiate and return one. | ||
*/ | ||
function ensure(error, create, options) { | ||
return trunk(error, typeof create === 'function' ? create : Object.assign({ | ||
allow: ['string'] | ||
}, create), Object.assign({ | ||
normalize: true, | ||
capture: true, | ||
Error: Error | ||
}, options)); | ||
} | ||
function _next(value) { | ||
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); | ||
} | ||
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _throw(err) { | ||
asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); | ||
} | ||
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
_next(undefined); | ||
}); | ||
}; | ||
/** | ||
* Returns a `Promise` rejection with `error`, having called `ensure` on it. | ||
*/ | ||
function rejects(_x, _x2, _x3) { | ||
return _rejects.apply(this, arguments); | ||
} | ||
function _defineProperty(obj, key, value) { | ||
if (key in obj) { | ||
Object.defineProperty(obj, key, { | ||
value: value, | ||
enumerable: true, | ||
configurable: true, | ||
writable: true | ||
}); | ||
} else { | ||
obj[key] = value; | ||
function _rejects() { | ||
_rejects = _asyncToGenerator(function* (error, create, options) { | ||
throw ensure(error, create, options); | ||
}); | ||
return _rejects.apply(this, arguments); | ||
} | ||
/** | ||
* Returns the result of `fn`; if it throws, it will call `ensure` on the thrown error and throw it. `fn` can be an *async* function -it will be automatically detected. | ||
*/ | ||
function throws(fn, create, options) { | ||
try { | ||
var response = fn(); | ||
if (!isPromise(response)) return response; // if it is a promise, in case response was a lazy promise | ||
return LazyPromist.from(() => { | ||
return response.catch(err => rejects(err, create, options)); | ||
}).then(value => value); | ||
} catch (err) { | ||
throw ensure(err, create, options); | ||
} | ||
return obj; | ||
} | ||
function asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } | ||
function _asyncToGenerator$1(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep$1(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
class Errorish extends Error { | ||
/** | ||
* An optional `source` -should reference the object that originated the `Errorish`. | ||
* Returns `true` if `error` is an instance of the class with label `label`, if passed. | ||
*/ | ||
static is(error, label) { | ||
if (!(error instanceof this)) return false; | ||
if (label === undefined) return true; | ||
return Array.isArray(label) ? label.includes(error.label) : error.label === label; | ||
} | ||
/** | ||
* An optional `data` field. | ||
* Runs and returns the result of `fn` only when `error` is an instance of the class and, optionally, has a specific `label`. | ||
*/ | ||
constructor(message, source, data) { | ||
super(message || undefined); | ||
_defineProperty(this, "source", void 0); | ||
_defineProperty(this, "data", void 0); | ||
this.source = source; | ||
this.data = data || {}; | ||
static recast(error, create, label) { | ||
return this.is(error, label) ? create(error) : error; | ||
} | ||
/** | ||
* Custom Error name: 'Errorish' | ||
* Calls `recast` and throws its response if `fn` throws or rejects, otherwise returns or throws the same result or error as `fn`. | ||
*/ | ||
get name() { | ||
return 'Errorish'; | ||
static raise(fn, create, label) { | ||
var _this = this; | ||
try { | ||
var response = fn(); | ||
if (isPromise(response)) { | ||
return response.catch( | ||
/*#__PURE__*/ | ||
function () { | ||
var _ref = _asyncToGenerator$1(function* (err) { | ||
throw _this.recast(err, create, label); | ||
}); | ||
return function (_x) { | ||
return _ref.apply(this, arguments); | ||
}; | ||
}()); | ||
} | ||
return response; | ||
} catch (err) { | ||
throw this.recast(err, create, label); | ||
} | ||
} | ||
/** | ||
* References `source.root` is an instance of `Errorish`; references `source` if it is an instance of `Error`; otherwise it references itself. | ||
* See `ensure` function. | ||
*/ | ||
get root() { | ||
if (this.source instanceof Errorish) return this.source.root; | ||
return this.source instanceof Error ? this.source : this; | ||
static ensure(error, create, options) { | ||
return ensure(error, create, Object.assign({}, options, { | ||
Error: this | ||
})); | ||
} | ||
/** | ||
* Sets the `data` field and returns itself. | ||
* See `rejects` function. | ||
*/ | ||
set(data) { | ||
this.data = data; | ||
return this; | ||
static rejects(error, create, options) { | ||
return rejects(error, create, Object.assign({}, options, { | ||
Error: this | ||
})); | ||
} | ||
/** | ||
* Assigns `data` to the `data` field and returns itself. | ||
* See `throws` function. | ||
*/ | ||
assign(data) { | ||
Object.assign(this.data, data); | ||
return this; | ||
static throws(fn, create, options) { | ||
return throws(fn, create, Object.assign({}, options, { | ||
Error: this | ||
})); | ||
} | ||
/** | ||
* A label for the Error. | ||
*/ | ||
} | ||
/** | ||
* Default values for error creation and normalization when an options object is not passed or lacks a particular property. They can be reset via `scope.set`. See `ICoreOptions`. | ||
*/ | ||
constructor(message, label, data, source) { | ||
super(message || undefined); | ||
const defaults = { | ||
name: 'Error', | ||
message: 'An error occurred', | ||
Errorish: Errorish, | ||
normalize: true, | ||
capture: true, | ||
allow: ['string'], | ||
Error: Error | ||
}; | ||
_defineProperty(this, "label", void 0); | ||
/** | ||
* Normalizes an Error -it assumes an instance of Error is passed. It guarantees the error will have a `name`, `message`, and `stack` properties. | ||
*/ | ||
_defineProperty(this, "data", void 0); | ||
function normalize(error, options) { | ||
const opts = Object.assign({}, defaults, options); | ||
_defineProperty(this, "source", void 0); | ||
if (!error.name) { | ||
error.name = error.constructor && error.constructor.name || opts.name; | ||
this.label = label || null; | ||
this.data = data || {}; | ||
this.source = source; | ||
} | ||
/** | ||
* Custom Error name: 'Errorish' | ||
*/ | ||
if (!error.message) error.message = opts.message; | ||
if (!error.stack) error.stack = "Error: ".concat(error.message); | ||
return error; | ||
} | ||
function stringify(message, options) { | ||
if (typeof message === 'string') return message; | ||
try { | ||
return JSON.stringify(message); | ||
} catch (e) { | ||
return options.message; | ||
get name() { | ||
return 'Errorish'; | ||
} | ||
} | ||
/** | ||
* References the first `Errorish` in the `Errorish.source` chain. | ||
*/ | ||
function trunk(error, options, data) { | ||
if (error instanceof options.Error) return error; | ||
let message = error && typeof error === 'object' && error.hasOwnProperty('message') ? error.message : error; | ||
message = options.allow.includes(typeof message) ? stringify(message, options) : options.message; | ||
error = new options.Errorish(message, error, data); | ||
if (options.capture && Error.captureStackTrace) { | ||
Error.captureStackTrace(error, options.Errorish); | ||
root() { | ||
return this.source instanceof Errorish && this.source !== this ? this.source.root() : this; | ||
} | ||
/** | ||
* Returns `Errorish.source` if it is an `Error`, otherwise it returns itself. | ||
*/ | ||
return error; | ||
} | ||
/** | ||
* Will return `error` if it is an instance of `options.Error` -by default, and instance of `Error`. Otherwise, it will instantiate and return an `Error` of class `options.Errorish` -`Errorish` by default. This newly created error -if created- would have: | ||
* - whatever you passed as an `error` as its `source` field. | ||
* - whatever you passed as `data` as its `data` field. | ||
*/ | ||
error() { | ||
return this.source instanceof Error ? this.source : this; | ||
} | ||
/** | ||
* Clones the instance and assigns it a new `data` field. | ||
*/ | ||
function ensure(error, options, data) { | ||
const opts = Object.assign({}, defaults, options); | ||
return opts.normalize ? normalize(trunk(error, opts, data), opts) : trunk(error, opts, data); | ||
} | ||
/** | ||
* Returns a promise rejection with `error`, having called `ensure` on it. | ||
*/ | ||
function rejects(_x, _x2, _x3) { | ||
return _rejects.apply(this, arguments); | ||
} | ||
function _rejects() { | ||
_rejects = _asyncToGenerator(function* (error, options, data) { | ||
const condition = options && options.hasOwnProperty('case') ? options.case : true; | ||
if (condition) throw ensure(error, options, data); | ||
}); | ||
return _rejects.apply(this, arguments); | ||
} | ||
/** | ||
* Returns the result of `fn`; if it throws, it will call `ensure` on the thrown error and throw it. `fn` can be an *async* function -it will be automatically detected. | ||
*/ | ||
function throws(fn, options, data) { | ||
try { | ||
const response = fn(); | ||
if (!isPromise(response)) return response; // if it is a promise | ||
// in case res was a lazy promise | ||
return lazy.fn(() => { | ||
return response.catch(err => rejects(err, options, data)); | ||
reproduce(data) { | ||
var destination = Object.create(this); | ||
return Object.assign(destination, this, { | ||
data | ||
}); | ||
} catch (err) { | ||
throw ensure(err, options, data); | ||
} | ||
} | ||
const root = { | ||
name: null, | ||
ensure, | ||
throws, | ||
rejects, | ||
normalize | ||
}; | ||
const scopes = {}; | ||
const values = {}; | ||
/** | ||
* Allows the creation of specific scopes with different sets of default options. If a particular option is nor defined for a scope, it will fall back to the root scope value for that option -the root scope is the one the `ensure`, `throws`, `rejects`, and `normalize` functions as exported from `errorish` entry point belong to by default. | ||
*/ | ||
const scope = { | ||
/** | ||
* Gets a scope by name -it is created if it doesn't exist. If no name is passed, the root scope will be returned. | ||
* Runs `Error.captureStackTrace` if running in `V8` to clean up the error stack trace. | ||
*/ | ||
get(name) { | ||
if (!name) return root; | ||
if (!scopes.hasOwnProperty(name)) { | ||
if (!values.hasOwnProperty(name)) values[name] = {}; | ||
const options = values[name]; | ||
scopes[name] = { | ||
name, | ||
ensure() { | ||
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { | ||
args[_key] = arguments[_key]; | ||
} | ||
args[1] = Object.assign({}, options, args[1]); | ||
return ensure(args[0], ...args.slice(1)); | ||
}, | ||
throws() { | ||
for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { | ||
args[_key2] = arguments[_key2]; | ||
} | ||
args[1] = Object.assign({}, options, args[1]); | ||
return throws(args[0], ...args.slice(1)); | ||
}, | ||
rejects() { | ||
var _arguments = arguments; | ||
return _asyncToGenerator(function* () { | ||
for (var _len3 = _arguments.length, args = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { | ||
args[_key3] = _arguments[_key3]; | ||
} | ||
args[1] = Object.assign({}, options, args[1]); | ||
return rejects(args[0], ...args.slice(1)); | ||
})(); | ||
}, | ||
normalize() { | ||
for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { | ||
args[_key4] = arguments[_key4]; | ||
} | ||
args[1] = Object.assign({}, options, args[1]); | ||
return normalize(args[0], ...args.slice(1)); | ||
} | ||
}; | ||
capture() { | ||
/* istanbul ignore next */ | ||
if (Error.captureStackTrace) { | ||
Error.captureStackTrace(this, this.constructor); | ||
} | ||
return scopes[name]; | ||
}, | ||
/** | ||
* Sets default options for a scope, taking the name of the scope as the first argument, and the `ICoreOptions` options as the second. If no name is passed and a single `ICoreOptions` argument is in its place, it will set the defaults for the root scope. It will also return the scope. | ||
*/ | ||
set() { | ||
for (var _len5 = arguments.length, args = new Array(_len5), _key5 = 0; _key5 < _len5; _key5++) { | ||
args[_key5] = arguments[_key5]; | ||
} | ||
const name = args.find(x => typeof x === 'string'); | ||
const options = args.find(x => typeof x === 'object'); | ||
if (!name) Object.assign(defaults, options);else { | ||
if (!values.hasOwnProperty(name)) values[name] = {}; | ||
Object.assign(values[name], options); | ||
} | ||
return scope.get(name); | ||
return this; | ||
} | ||
}; | ||
} | ||
export { Errorish, ensure, normalize, rejects, scope, throws }; | ||
export { Errorish, ensure, normalize, rejects, throws }; | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "errorish", | ||
"description": "For those times you have an error-ish but what you really want is an Error", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"license": "MIT", | ||
"files": [ | ||
"dist-*/", | ||
"bin/" | ||
"bin/", | ||
"static/", | ||
"dist/" | ||
], | ||
"esnext": "dist-src/index.js", | ||
"main": "dist-node/index.js", | ||
"module": "dist-web/index.js", | ||
"pika": true, | ||
@@ -38,55 +37,25 @@ "sideEffects": false, | ||
"dependencies": { | ||
"promist": "^0.7.0" | ||
"promist": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.4.4", | ||
"@babel/core": "^7.4.4", | ||
"@babel/plugin-proposal-class-properties": "^7.4.4", | ||
"@babel/plugin-proposal-decorators": "^7.4.4", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.4.4", | ||
"@babel/preset-env": "^7.4.4", | ||
"@babel/preset-typescript": "^7.3.3", | ||
"@pika/pack": "^0.3.7", | ||
"@pika/plugin-build-node": "^0.3.15", | ||
"@pika/plugin-build-web": "^0.3.15", | ||
"@pika/plugin-standard-pkg": "^0.3.15", | ||
"@types/jest": "^24.0.11", | ||
"@typescript-eslint/eslint-plugin": "^1.7.0", | ||
"@typescript-eslint/parser": "^1.7.0", | ||
"@zerollup/ts-transform-paths": "^1.7.1", | ||
"babel-eslint": "^10.0.1", | ||
"babel-jest": "^24.7.1", | ||
"babel-plugin-module-resolver": "^3.2.0", | ||
"commitizen": "^3.1.1", | ||
"conventional-changelog-cli": "^2.0.17", | ||
"conventional-recommended-bump": "^5.0.0", | ||
"coveralls": "^3.0.3", | ||
"cz-conventional-changelog": "^2.1.0", | ||
"eslint": "^5.16.0", | ||
"eslint-config-prettier": "^4.2.0", | ||
"eslint-config-standard": "^12.0.0", | ||
"eslint-import-resolver-alias": "^1.1.2", | ||
"eslint-plugin-babel": "^5.3.0", | ||
"eslint-plugin-import": "^2.17.2", | ||
"eslint-plugin-jest": "^22.5.1", | ||
"eslint-plugin-node": "^9.0.0", | ||
"eslint-plugin-prettier": "^3.0.1", | ||
"eslint-plugin-promise": "^4.1.1", | ||
"eslint-plugin-standard": "^4.0.0", | ||
"eslint-restricted-globals": "^0.2.0", | ||
"husky": "^2.2.0", | ||
"jest-cli": "^24.7.1", | ||
"kpo": "^0.5.2", | ||
"markdownlint-cli": "^0.16.0", | ||
"onchange": "^5.2.0", | ||
"prettier": "^1.17.0", | ||
"slimconf": "^0.9.0", | ||
"ttypescript": "^1.5.6", | ||
"typedoc": "^0.14.2", | ||
"typescript": "3.4.5" | ||
"@pika/pack": "^0.4.0", | ||
"@pika/plugin-build-web": "^0.8.1", | ||
"@pika/plugin-standard-pkg": "^0.8.1", | ||
"@riseup/library": "^0.5.0", | ||
"@riseup/tooling": "^0.5.0", | ||
"@types/jest": "^24.0.21", | ||
"@zerollup/ts-transform-paths": "^1.7.3", | ||
"coveralls": "^3.0.7", | ||
"husky": "^3.0.9", | ||
"kpo": "^0.11.1", | ||
"onchange": "^6.0.0", | ||
"typescript": "^3.6.4" | ||
}, | ||
"engines": { | ||
"node": ">=8" | ||
"node": ">=12" | ||
}, | ||
"types": "dist-types/index.d.ts" | ||
"esnext": "dist-src/index.js", | ||
"module": "dist-web/index.js", | ||
"main": "dist/index.js", | ||
"types": "dist/index.d.ts" | ||
} |
185
README.md
@@ -1,2 +0,2 @@ | ||
# errorish | ||
# Errorish | ||
@@ -11,6 +11,2 @@ [![Version](https://img.shields.io/npm/v/errorish.svg)](https://www.npmjs.com/package/errorish) | ||
> For those times you have an error-*ish* but what you really want is an *Error.* | ||
If you find it useful, consider [starring the project](https://github.com/rafamel/errorish) 💪 and/or following [its author](https://github.com/rafamel) ❤️ -there's more on the way! | ||
## Install | ||
@@ -22,28 +18,35 @@ | ||
There are essentially three use cases for `errorish`: | ||
There are three main use cases for *Errorish*: | ||
* [You need to make sure an `Error` has a `message`, `name`, and `stack` properties.](#normalizing-errors) | ||
* [You need to make sure *any* object is actually an error, as expected.](#ensuring-any-is-an-error--otherwise-create-it) | ||
* [You need to make sure an *Error* has a `message`, `name`, and `stack` properties.](#normalizing-errors) | ||
* [You want to catch errors and throw a different *Error*:](#catching-and-throwing-errors-to-be-made-public) | ||
* with a different message and specific data that might be made public, | ||
* while preserving information about the original exception that caused your program to fail, | ||
* on different levels of the call stack, but keeping only the first one of its kind throwed. | ||
* [You want to extend the `Error` class to store an identifying `label`, some `data` fields, and/or the `source` exception that caused your program to fail](#errorish-class) | ||
## Documentation | ||
These are all of `errorish`'s functions -[see docs:](https://rafamel.github.io/errorish/globals.html) | ||
These are all of *Errorish*'s functions and classes -[see docs:](https://rafamel.github.io/errorish/globals.html) | ||
* [`ensure`](https://rafamel.github.io/errorish/globals.html#ensure) ensures `any` is an `Error`, otherwise creating one -optionally, it can also have a normalization step, which is [enabled by default.](https://rafamel.github.io/errorish/globals.html#defaults) | ||
* [`normalize`](https://rafamel.github.io/errorish/globals.html#normalize) ensures an `Error` has a `message`, `name`, and `stack` properties -filling them if they're not defined. | ||
* [`ensure`](https://rafamel.github.io/errorish/globals.html#ensure) ensures `any` is an `Error`, otherwise creating one -it can also have a normalization step, which is enabled by default. | ||
* [`rejects`](https://rafamel.github.io/errorish/globals.html#rejects) returns a promise rejection with an error, having called `ensure` on it. | ||
* [`throws`](https://rafamel.github.io/errorish/globals.html#throws) takes a function and returns its value if it doesn't throw; otherwise, it will call `ensure` on the thrown error and throw it. | ||
* [`Errorish`](https://rafamel.github.io/errorish/classes/errorish.html) is a *class* with some conveniency methods relating to its `label`, `data`, and `source` fields. | ||
[Options](https://rafamel.github.io/errorish/interfaces/icoreoptions.html) can be passed directly to these functions, though they will be merged in all cases with the [defaults](https://rafamel.github.io/errorish/globals.html#defaults) -you can use [`scope.set`](https://rafamel.github.io/errorish/globals.html#scope) to set these. | ||
## Usage | ||
Additionally, you might want to create particular [`scopes` with a different set of default options](https://rafamel.github.io/errorish/globals.html#scope) depending on your use case. | ||
### Normalizing errors | ||
## Usage | ||
Normalization is performed by default by [`ensure`,](https://rafamel.github.io/errorish/globals.html#throws) but it can also be run independently: | ||
### Ensuring `any` is an error -otherwise create it | ||
```javascript | ||
import { normalize } from 'errorish'; | ||
normalize(Error()); // Error: An error occurred | ||
normalize(Error(), { message: 'Foo bar' }); // Error: Foo bar | ||
``` | ||
### Ensuring *any* is an error -otherwise create it | ||
See [`ensure`.](https://rafamel.github.io/errorish/globals.html#ensure) | ||
#### Return an error from any error-*ish* | ||
@@ -56,18 +59,16 @@ | ||
ensure('Foo bar'); // Errorish: Foo bar | ||
ensure({ message: 'Foo bar' }); // Errorish: Foo bar | ||
ensure('Foo bar'); // Error: Foo bar | ||
ensure({ message: 'Foo bar' }); // Error: Foo bar | ||
// As this is a number, it will use the default message | ||
ensure(10); // Errorish: An error occurred | ||
ensure(10); // Error: An error occurred | ||
// We can also allow numbers -or any other type- to be stringified | ||
ensure(10, { allow: ['string', 'number'] }); // Errorish: 10 | ||
ensure(10, { allow: ['string', 'number'] }); // Error: 10 | ||
// Errors will always preserve the original source | ||
ensure(10).source; // 10 | ||
// Additionally, we can pass some data to errors | ||
ensure(10, null, { foo: 'bar' }).data; // { foo: 'bar' } | ||
// Or otherwise, provide a creation function | ||
ensure(10, (err) => Error('10 is not an error')) // Error: 10 is not an error | ||
``` | ||
#### Throw or reject with an error-*ish* | ||
#### Throw or reject from an error-*ish* | ||
@@ -79,12 +80,6 @@ [`throws`](https://rafamel.github.io/errorish/globals.html#throws) and [`rejects`](https://rafamel.github.io/errorish/globals.html#rejects) run [`ensure`](https://rafamel.github.io/errorish/globals.html#ensure) over your error-*ish* and throw or reject with it -these are just convenience functions over `ensure`: | ||
/* rejects */ | ||
Promise.reject(10).catch(rejects) // Reject<Errorish: An error occurred> | ||
Promise.reject(10).catch(rejects) // Reject<Error: An error occurred> | ||
// Options for `rejects` and `throws` also take a `case` field which, | ||
// if false, will make them to have a void response | ||
Promise.reject(10).catch(err => rejects(err, { case: false })); // Resolve<undefined> | ||
throws(() => { throw 10; }); // Throw<Error: An error occurred> | ||
/* throws */ | ||
throws(() => { throw 10; }); // Throw<Errorish: An error occurred> | ||
// The above is equivalent to: | ||
@@ -98,66 +93,88 @@ try { | ||
// it can also be passed an async function | ||
throws(async () => { throw 10; }); // Reject<Errorish: An error occurred> | ||
throws(async () => { throw 10; }); // Reject<Error: An error occurred> | ||
``` | ||
throws(() => 10); // Return<10> | ||
### `Errorish` class | ||
A *class* with some conveniency methods relating to its `label`, `data`, and `source` fields -see [`Errorish`.](https://rafamel.github.io/errorish/classes/errorish.html). | ||
#### Constructor | ||
The `Errorish` constructor takes in the optional arguments `message`, `label`, `data`, and `source`. | ||
```javascript | ||
import { Errorish } from 'errorish'; | ||
const fn = () => { throw Error('Source'); }; | ||
try { | ||
fn(); | ||
} catch(source) { | ||
throw new Errorish('Message', 'label', { code: 401 }, source); | ||
} | ||
``` | ||
### Normalizing errors | ||
#### Static methods | ||
Normalization is performed by default by [`ensure`,](https://rafamel.github.io/errorish/globals.html#throws) but it can also be run independently: | ||
##### `Errorish.is(error: Error, label?: string | null | Array<string | null>): boolean` | ||
Returns `true` if `error` is an instance of the class with label `label`, if passed. | ||
```javascript | ||
import { normalize } from 'errorish'; | ||
import { Errorish } from 'errorish'; | ||
normalize(Error()); // Error: An error occurred | ||
normalize(Error(), { message: 'Foo bar' }); // Error: Foo bar | ||
const error = new Errorish(); | ||
Errorish.is(error); // true | ||
Errorish.is(error, 'Label'); // false | ||
``` | ||
### Catching and throwing errors to be made public | ||
##### `Errorish.recast(error: Error, create: (error: Errorish) => Error, label?: string | null | Array<string | null>)` | ||
Runs and returns the result of `fn` only when `error` is an instance of the class and, optionally, has a specific `label`. | ||
##### `Errorish.raise(fn: () => any, create: (error: Errorish) => Error, label?: string | null | Array<string | null>)` | ||
Calls `recast` and throws its response if `fn` throws or rejects, otherwise returns or throws the same result or error as `fn`. | ||
##### `Errorish.ensure(error: any, create: (error: any) => Error, options: object): Error` | ||
Same as [`ensure`,](#ensuring-any-is-an-error--otherwise-create-it) though it will ensure against the `error` being an instance of `Errorish`. | ||
##### `Errorish.rejects(error: any, create: (error: any) => Error, options: object): Error` | ||
Same as [`rejects`,](#ensuring-any-is-an-error--otherwise-create-it) though it will ensure against the `error` being an instance of `Errorish`. | ||
##### `Errorish.throws(error: () => any, create: (error: any) => Error, options: object): Error` | ||
Same as [`throws`,](#ensuring-any-is-an-error--otherwise-create-it) though it will ensure against the `error` being an instance of `Errorish`. | ||
#### Instance methods | ||
##### `errorish.root(): Errorish` | ||
References the first `Errorish` in the `Errorish.source` chain. | ||
```javascript | ||
import { Errorish, scope } from 'errorish'; | ||
import { Errorish } from 'errorish'; | ||
// As we might want to preserve the defaults for the root scope, | ||
// we'll create a new scope we'll name `ish`. | ||
// For that scope, we'll set Errorish as the class errors | ||
// will be ensured against, so even when an actual `Error` is passed, | ||
// if not an `Errorish`, a new one will be created. | ||
const ish = scope.set('ish', { Error: Errorish, allow: [] }); | ||
const source = Error(); | ||
const a = new Errorish(null, null, null, source); | ||
const b = new Errorish(null, null, null, a); | ||
const c = new Errorish(null, null, null, b); | ||
function authorize() { | ||
throw Error(`Error with details I'd rather not expose`); | ||
} | ||
// Will return `a` | ||
c.root(); | ||
``` | ||
function example() { | ||
try { | ||
authorize(); | ||
} catch (err) { | ||
// As an `Error` is not an instance of `Errorish`, one will be | ||
// created with message `Server failed running your example` | ||
// and data `{ code: 500 }` | ||
throw ish.ensure( | ||
err, | ||
{ message: `Authorization for example failed` }, | ||
{ code: 401 } | ||
); | ||
} | ||
} | ||
##### `errorish.error(): Error` | ||
function server() { | ||
try { | ||
example(); | ||
} catch (err) { | ||
// As example already throwed an `Errorish`, the same one will be | ||
// preserved, ignoring the more general-purpose message and code | ||
throw ish.ensure(err, { message: 'Server failed' }, { code: 500 }); | ||
} | ||
} | ||
Returns `Errorish.source` if it is an `Error`, otherwise it returns itself. | ||
try { | ||
server(); | ||
} catch (e) { | ||
console.log(e.message); // Authorization for example failed | ||
console.log(e.data); // { code: 401 } | ||
console.log(e.source); // Error: Error with details I'd rather not expose | ||
} | ||
``` | ||
##### `errorish.reproduce(data?: object): Errorish` | ||
Clones the instance and assigns it a new `data` field. | ||
##### `errorish.capture(): Errorish` | ||
Runs `Error.captureStackTrace` if running in `V8` to clean up the error stack trace. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
84055
12
42
868
176
1
+ Addedpromist@2.0.2(transitive)
- Removedpromist@0.7.0(transitive)
Updatedpromist@^2.0.0