new changes

This commit is contained in:
Niranjan
2026-04-07 05:05:28 +05:30
parent 7c070224bd
commit a18bba15f2
29975 changed files with 3247495 additions and 2761 deletions

View File

@@ -0,0 +1,56 @@
# [8.0.0](https://github.com/nfroidure/yerror/compare/v7.0.0...v8.0.0) (2023-08-12)
# [7.0.0](https://github.com/nfroidure/yerror/compare/v6.2.1...v7.0.0) (2023-08-11)
## [6.2.1](https://github.com/nfroidure/yerror/compare/v6.2.0...v6.2.1) (2022-12-19)
### Bug Fixes
* **lib:** fix stack printing ([edf5fd3](https://github.com/nfroidure/yerror/commit/edf5fd32126a1689863cc995859243251d25c8b4))
# [6.2.0](https://github.com/nfroidure/yerror/compare/v6.1.1...v6.2.0) (2022-12-19)
## [6.1.1](https://github.com/nfroidure/yerror/compare/v6.1.0...v6.1.1) (2022-05-27)
### Bug Fixes
* **types:** fix types declarations ([b068701](https://github.com/nfroidure/yerror/commit/b0687012a769dd6f560fd4342a66907c8834301a))
# [6.1.0](https://github.com/nfroidure/yerror/compare/v6.0.2...v6.1.0) (2022-05-27)
### Features
* **api:** export class as non-default for ESM compatibility ([355a929](https://github.com/nfroidure/yerror/commit/355a92922300e5e4730d30da6be35e84d8552585))
## [6.0.2](https://github.com/nfroidure/yerror/compare/v6.0.1...v6.0.2) (2022-05-25)
## [6.0.1](https://github.com/nfroidure/yerror/compare/v6.0.0...v6.0.1) (2021-04-10)
### Bug Fixes
* **types:** fix types declarations path ([da5344d](https://github.com/nfroidure/yerror/commit/da5344ddc3aa47f0867a1cc720f0bde02943932a))
# [6.0.0](https://github.com/nfroidure/yerror/compare/v5.0.0...v6.0.0) (2021-04-09)

20
YakPanel-server/frontend/node_modules/yerror/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,20 @@
The MIT License (MIT)
Copyright © 2017 Nicolas Froidure (formerly at SimpliField)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the “Software”), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

174
YakPanel-server/frontend/node_modules/yerror/README.md generated vendored Normal file
View File

@@ -0,0 +1,174 @@
[//]: # ( )
[//]: # (This file is automatically generated by a `metapak`)
[//]: # (module. Do not change it except between the)
[//]: # (`content:start/end` flags, your changes would)
[//]: # (be overridden.)
[//]: # ( )
# yerror
> It helps to know why you got an error.
[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/nfroidure/yerror/blob/main/LICENSE)
[![Coverage Status](https://coveralls.io/repos/github/git://github.com/nfroidure/yerror.git/badge.svg?branch=main)](https://coveralls.io/github/git://github.com/nfroidure/yerror.git?branch=main)
[//]: # (::contents:start)
## Usage
First, require me where you could throw errors:
```js
import YError from 'yerror';
```
Then, emit errors with a bonus: parameters!
```js
function doSomething(pay, action) {
if(parseInt(pay, 10) !== pay) {
throw new YError('E_BAD_PAY', pay, action);
}
}
doSomething('nuts', 'code');
// YError: E_BAD_PAY (nuts, code)
// at doSomething (/home/nfroidure/nfroidure/yerror/test.js:5:11)
// at Object.<anonymous> (/home/nfroidure/nfroidure/yerror/test.js:9:1)
// (...)
```
You don't have to use constant like error messages, we use this convention
mainly for i18n reasons.
Also, you could want to wrap errors and keep a valuable stack trace:
```js
function doSomethingAsync(pay, action) {
return new Promise(function(resolve, reject) {
try {
doSomething(pay, action);
resolve();
} catch(err) {
reject(YError.bump(err));
}
});
}
doSomethingAsync('nuts', 'code')
.catch(function(err) {
console.log(err.stack);
});
// YError: E_BAD_PAY (nuts, code)
// at doSomething (/home/nfroidure/nfroidure/yerror/test.js:5:11)
// (...)
// YError: E_BAD_TRANSACTION (pay)
// at Function.YError.wrap (/home/nfroidure/nfroidure/yerror/src/index.js:41:12)
// at /home/nfroidure/nfroidure/yerror/test.js:16:21
// at doSomethingAsync (/home/nfroidure/nfroidure/yerror/test.js:11:11)
// (...)
```
[//]: # (::contents:end)
# API
## Classes
<dl>
<dt><a href="#YError">YError</a> ⇐ <code>Error</code></dt>
<dd><p>A YError class able to contain some params and
print better stack traces</p>
</dd>
</dl>
## Functions
<dl>
<dt><a href="#printStackTrace">printStackTrace(err)</a> ⇒ <code>string</code></dt>
<dd><p>Allow to print a stack from anything (especially catched
errors that may or may not contain errors 🤷).</p>
</dd>
</dl>
<a name="YError"></a>
## YError ⇐ <code>Error</code>
A YError class able to contain some params and
print better stack traces
**Kind**: global class
**Extends**: <code>Error</code>
* [YError](#YError) ⇐ <code>Error</code>
* [.wrap(err, [errorCode], [...params])](#YError.wrap) ⇒ [<code>YError</code>](#YError)
* [.cast(err, [errorCode], [...params])](#YError.cast) ⇒ [<code>YError</code>](#YError)
* [.bump(err, [errorCode], [...params])](#YError.bump) ⇒ [<code>YError</code>](#YError)
<a name="YError.wrap"></a>
### YError.wrap(err, [errorCode], [...params]) ⇒ [<code>YError</code>](#YError)
Wraps any error and output a YError with an error
code and some params as debug values.
**Kind**: static method of [<code>YError</code>](#YError)
**Returns**: [<code>YError</code>](#YError) - The wrapped error
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| err | <code>Error</code> | | The error to wrap |
| [errorCode] | <code>string</code> | <code>&quot;&#x27;E_UNEXPECTED&#x27;&quot;</code> | The error code corresponding to the actual error |
| [...params] | <code>YErrorParams</code> | | Some additional debugging values |
<a name="YError.cast"></a>
### YError.cast(err, [errorCode], [...params]) ⇒ [<code>YError</code>](#YError)
Return a YError as is or wraps any other error and output
a YError with a code and some params as debug values.
**Kind**: static method of [<code>YError</code>](#YError)
**Returns**: [<code>YError</code>](#YError) - The wrapped error
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| err | <code>Error</code> | | The error to cast |
| [errorCode] | <code>string</code> | <code>&quot;&#x27;E_UNEXPECTED&#x27;&quot;</code> | The error code corresponding to the actual error |
| [...params] | <code>YErrorParams</code> | | Some additional debugging values |
<a name="YError.bump"></a>
### YError.bump(err, [errorCode], [...params]) ⇒ [<code>YError</code>](#YError)
Same than `YError.wrap()` but preserves the code
and the debug values of the error if it is
already an instance of the YError constructor.
**Kind**: static method of [<code>YError</code>](#YError)
**Returns**: [<code>YError</code>](#YError) - The wrapped error
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| err | <code>Error</code> | | The error to bump |
| [errorCode] | <code>string</code> | <code>&quot;&#x27;E_UNEXPECTED&#x27;&quot;</code> | The error code corresponding to the actual error |
| [...params] | <code>YErrorParams</code> | | Some additional debugging values |
<a name="printStackTrace"></a>
## printStackTrace(err) ⇒ <code>string</code>
Allow to print a stack from anything (especially catched
errors that may or may not contain errors 🤷).
**Kind**: global function
**Returns**: <code>string</code> - The stack trace if any
| Param | Type | Description |
| --- | --- | --- |
| err | <code>Error</code> | The error to print |
# Authors
- [Nicolas Froidure (formerly at SimpliField)](http://insertafter.com/en/index.html)
# License
[MIT](https://github.com/nfroidure/yerror/blob/main/LICENSE)

View File

@@ -0,0 +1,72 @@
type YErrorParams = any;
/**
* A YError class able to contain some params and
* print better stack traces
* @extends Error
*/
declare class YError extends Error {
code: string;
params: YErrorParams[];
wrappedErrors: (Error | YError)[];
/**
* Creates a new YError with an error code
* and some params as debug values.
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
*/
constructor(errorCode: string, ...params: YErrorParams[]);
constructor(wrappedErrors?: Error[], errorCode?: string, ...params: YErrorParams[]);
/**
* Wraps any error and output a YError with an error
* code and some params as debug values.
* @param {Error} err
* The error to wrap
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static wrap<E extends Error | YError>(err: E, errorCode?: string, ...params: YErrorParams[]): YError;
/**
* Return a YError as is or wraps any other error and output
* a YError with a code and some params as debug values.
* @param {Error} err
* The error to cast
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static cast<E extends Error | YError>(err: E, errorCode?: string, ...params: YErrorParams[]): YError;
/**
* Same than `YError.wrap()` but preserves the code
* and the debug values of the error if it is
* already an instance of the YError constructor.
* @param {Error} err
* The error to bump
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static bump<E extends Error | YError>(err: E, errorCode?: string, ...params: YErrorParams[]): YError;
toString(): string;
}
/**
* Allow to print a stack from anything (especially catched
* errors that may or may not contain errors 🤷).
* @param {Error} err
* The error to print
* @return {string}
* The stack trace if any
*/
export declare function printStackTrace(err: Error | YError): string;
export { YError };

View File

@@ -0,0 +1,140 @@
import os from 'os';
/**
* A YError class able to contain some params and
* print better stack traces
* @extends Error
*/
class YError extends Error {
code;
params;
wrappedErrors;
constructor(wrappedErrors, errorCode, ...params) {
// Detecting if wrappedErrors are passed
if (!(wrappedErrors instanceof Array)) {
params = ('undefined' === typeof errorCode ? [] : [errorCode]).concat(params);
errorCode = wrappedErrors;
wrappedErrors = [];
}
// Call the parent constructor
super(errorCode);
// Filling error
this.code = errorCode || 'E_UNEXPECTED';
this.params = params;
this.wrappedErrors = wrappedErrors;
this.name = this.toString();
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
/**
* Wraps any error and output a YError with an error
* code and some params as debug values.
* @param {Error} err
* The error to wrap
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static wrap(err, errorCode, ...params) {
const wrappedErrorIsACode = _looksLikeAYErrorCode(err.message);
const wrappedErrors = ('wrappedErrors' in err ? err.wrappedErrors : []).concat(err);
if (!errorCode) {
if (wrappedErrorIsACode) {
errorCode = err.message;
}
else {
errorCode = 'E_UNEXPECTED';
}
}
if (err.message && !wrappedErrorIsACode) {
params.push(err.message);
}
return new YError(wrappedErrors, errorCode, ...params);
}
/**
* Return a YError as is or wraps any other error and output
* a YError with a code and some params as debug values.
* @param {Error} err
* The error to cast
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static cast(err, errorCode, ...params) {
if (_looksLikeAYError(err)) {
return err;
}
return YError.wrap(err, errorCode, ...params);
}
/**
* Same than `YError.wrap()` but preserves the code
* and the debug values of the error if it is
* already an instance of the YError constructor.
* @param {Error} err
* The error to bump
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static bump(err, errorCode, ...params) {
if (_looksLikeAYError(err)) {
return YError.wrap(err, err.code, ...err.params);
}
return YError.wrap(err, errorCode, ...params);
}
toString() {
return ((this.wrappedErrors.length
? // eslint-disable-next-line
this.wrappedErrors[this.wrappedErrors.length - 1].stack + os.EOL
: '') +
this.constructor.name +
': ' +
this.code +
' (' +
this.params.join(', ') +
')');
}
}
/**
* Allow to print a stack from anything (especially catched
* errors that may or may not contain errors 🤷).
* @param {Error} err
* The error to print
* @return {string}
* The stack trace if any
*/
export function printStackTrace(err) {
return typeof err === 'object' && typeof err.stack === 'string'
? err.stack
: `[no_stack_trace]: error is ${err != null && typeof err.toString === 'function'
? err.toString()
: typeof err}`;
}
// In order to keep compatibility through major versions
// we have to make kind of an cross major version instanceof
function _looksLikeAYError(err) {
return (!!(err instanceof YError) ||
!!(err.constructor &&
err.constructor.name &&
err.constructor.name.endsWith('Error') &&
'code' in err &&
'string' === typeof err.code &&
_looksLikeAYErrorCode(err.code) &&
'params' in err &&
err.params &&
err.params instanceof Array));
}
function _looksLikeAYErrorCode(str) {
return /^([A-Z0-9_]+)$/.test(str);
}
export { YError };
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1 @@
export {};

View File

@@ -0,0 +1,145 @@
/* eslint max-nested-callbacks:[0], no-magic-numbers:[0] */
import { describe, test } from '@jest/globals';
import assert from 'assert';
import { YError } from './index.js';
describe('YError', () => {
describe('.__constructor', () => {
test('Should work', () => {
const err = new YError('E_ERROR', 'arg1', 'arg2');
assert(err instanceof Error);
assert.equal(err.name, err.toString());
assert.equal(err.code, 'E_ERROR');
assert.deepEqual(err.params, ['arg1', 'arg2']);
assert.equal(err.toString(), 'YError: E_ERROR (arg1, arg2)');
});
test('Should work without code', () => {
const err = new YError();
assert.equal(err.code, 'E_UNEXPECTED');
assert.deepEqual(err.params, []);
assert.equal(err.toString(), 'YError: E_UNEXPECTED ()');
assert.equal(err.name, err.toString());
});
test('Should work without new', () => {
const err = new YError('E_ERROR', 'arg1', 'arg2');
assert.equal(err.code, 'E_ERROR');
assert(err instanceof YError);
assert.deepEqual(err.params, ['arg1', 'arg2']);
assert.equal(err.toString(), 'YError: E_ERROR (arg1, arg2)');
assert.equal(err.name, err.toString());
});
});
describe('.wrap()', () => {
test('Should work with standard errors and a message', () => {
// eslint-disable-line
const err = YError.wrap(new Error('This is an error!'));
assert.equal(err.code, 'E_UNEXPECTED');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['This is an error!']);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('Error: This is an error!'), 'Stack contains original error.');
assert(-1 !==
(err.stack || '').indexOf('YError: E_UNEXPECTED (This is an error!)'), 'Stack contains cast error.');
assert.equal(err.name, err.toString());
}
});
test('Should work with standard errors and an error code', () => {
const err = YError.wrap(new Error('E_ERROR'));
assert.equal(err.code, 'E_ERROR');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, []);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('Error: E_ERROR'), 'Stack contains original error.');
assert(-1 !== (err.stack || '').indexOf('YError: E_ERROR ()'), 'Stack contains cast error.');
}
assert.equal(err.name, err.toString());
});
test('Should work with standard errors, an error code and params', () => {
const err = YError.wrap(new Error('E_ERROR'), 'E_ERROR_2', 'arg1', 'arg2');
assert.equal(err.code, 'E_ERROR_2');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['arg1', 'arg2']);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('Error: E_ERROR'), 'Stack contains first error.');
assert(-1 !== (err.stack || '').indexOf('YError: E_ERROR_2 (arg1, arg2)'), 'Stack contains second error.');
}
assert.equal(err.name, err.toString());
});
test('Should work with several wrapped errors', () => {
const err = YError.wrap(YError.wrap(new Error('E_ERROR_1'), 'E_ERROR_2', 'arg2.1', 'arg2.2'), 'E_ERROR_3', 'arg3.1', 'arg3.2');
assert.equal(err.code, 'E_ERROR_3');
assert.equal(err.wrappedErrors.length, 2);
assert.deepEqual(err.params, ['arg3.1', 'arg3.2']);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('Error: E_ERROR_1'), 'Stack contains first error.');
assert(-1 !==
(err.stack || '').indexOf('YError: E_ERROR_2 (arg2.1, arg2.2)'), 'Stack contains second error.');
assert(-1 !==
(err.stack || '').indexOf('YError: E_ERROR_3 (arg3.1, arg3.2)'), 'Stack contains second error.');
}
assert.equal(err.name, err.toString());
});
});
describe('.cast()', () => {
test('Should work with standard errors and a message', () => {
const err = YError.cast(new Error('This is an error!'));
assert.equal(err.code, 'E_UNEXPECTED');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['This is an error!']);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('Error: This is an error!'), 'Stack contains original error.');
assert(-1 !==
(err.stack || '').indexOf('YError: E_UNEXPECTED (This is an error!)'), 'Stack contains cast error.');
}
assert.equal(err.name, err.toString());
});
test('Should let YError instances pass through', () => {
const err = YError.cast(new YError('E_ERROR', 'arg1', 'arg2'));
assert.equal(err.code, 'E_ERROR');
assert.deepEqual(err.params, ['arg1', 'arg2']);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('YError: E_ERROR (arg1, arg2)'), 'Stack contains cast error.');
}
assert.equal(err.name, err.toString());
});
});
describe('.bump()', () => {
test('Should work with standard errors and a message', () => {
const err = YError.bump(new Error('This is an error!'));
assert.equal(err.code, 'E_UNEXPECTED');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['This is an error!']);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('Error: This is an error!'), 'Stack contains original error.');
assert(-1 !==
(err.stack || '').indexOf('YError: E_UNEXPECTED (This is an error!)'), 'Stack contains bumped error.');
}
assert.equal(err.name, err.toString());
});
test('Should work with YError like errors', () => {
const baseErr = new Error('E_A_NEW_ERROR');
baseErr.code = 'E_A_NEW_ERROR';
baseErr.params = ['baseParam1', 'baseParam2'];
const err = YError.bump(baseErr);
assert.equal(err.code, 'E_A_NEW_ERROR');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['baseParam1', 'baseParam2']);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('Error: E_A_NEW_ERROR'), 'Stack contains original error.');
assert(-1 !==
(err.stack || '').indexOf('YError: E_A_NEW_ERROR (baseParam1, baseParam2)'), 'Stack contains bumped error.');
}
assert.equal(err.name, err.toString());
});
test('Should work with Y errors and a message', () => {
const err = YError.bump(new YError('E_ERROR', 'arg1.1', 'arg1.2'), 'E_ERROR_2', 'arg2.1', 'arg2.2');
assert.equal(err.code, 'E_ERROR');
assert.deepEqual(err.params, ['arg1.1', 'arg1.2']);
if ('captureStackTrace' in Error) {
assert(-1 !== (err.stack || '').indexOf('YError: E_ERROR (arg1.1, arg1.2)'), 'Stack contains original error.');
assert(-1 !== (err.stack || '').indexOf('YError: E_ERROR (arg1.1, arg1.2)'), 'Stack contains bumped error.');
}
assert.equal(err.name, err.toString());
});
});
});
//# sourceMappingURL=index.test.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,257 @@
{
"metapak": {
"configs": [
"main",
"readme",
"eslint",
"tsesm",
"jest",
"codeclimate",
"ghactions",
"jsdocs"
],
"data": {
"files": "'src/**/*.ts'",
"testsFiles": "'src/**/*.test.ts'",
"distFiles": "'dist/**/*.js'",
"ignore": [
"dist"
],
"bundleFiles": [
"dist",
"src"
]
}
},
"name": "yerror",
"version": "8.0.0",
"description": "It helps to know why you got an error.",
"scripts": {
"build": "rimraf 'dist' && tsc --outDir dist",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md",
"cli": "env NODE_ENV=${NODE_ENV:-cli}",
"cover": "npm run jest -- --coverage",
"coveralls": "npm run cover && cat ./coverage/lcov.info | coveralls && rm -rf ./coverage",
"cz": "env NODE_ENV=${NODE_ENV:-cli} git cz",
"doc": "echo \"# API\" > API.md; jsdoc2md 'dist/**/*.js' >> API.md && git add API.md",
"jest": "NODE_OPTIONS=--experimental-vm-modules NODE_ENV=test jest",
"lint": "eslint 'src/**/*.ts'",
"metapak": "metapak",
"precz": "npm t && npm run lint && npm run build && npm run metapak -- -s && npm run doc",
"prettier": "prettier --write 'src/**/*.ts'",
"preversion": "npm t && npm run lint && npm run build && npm run metapak -- -s && npm run doc",
"rebuild": "swc ./src -s -d dist -C jsc.target=es2022",
"test": "echo \"WARNING: No tests specified\" && npm run jest",
"type-check": "tsc --pretty --noEmit",
"version": "npm run changelog"
},
"engines": {
"node": ">=18.16.0"
},
"repository": {
"type": "git",
"url": "git://github.com/nfroidure/yerror.git"
},
"keywords": [
"error",
"why",
"better"
],
"author": {
"name": "Nicolas Froidure (formerly at SimpliField)",
"email": "nicolas.froidure@insertafter.com",
"url": "http://insertafter.com/en/index.html"
},
"license": "MIT",
"bugs": {
"url": "https://github.com/nfroidure/yerror/issues"
},
"devDependencies": {
"@swc/cli": "^0.1.62",
"@swc/core": "^1.3.76",
"@swc/helpers": "^0.5.1",
"@swc/jest": "^0.2.28",
"@typescript-eslint/eslint-plugin": "^6.3.0",
"@typescript-eslint/parser": "^6.3.0",
"commitizen": "^4.3.0",
"conventional-changelog-cli": "^3.0.0",
"coveralls": "^3.1.1",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^8.46.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
"jest": "^29.6.2",
"jsdoc-to-markdown": "^8.0.0",
"metapak": "^5.1.3",
"metapak-nfroidure": "15.0.0",
"prettier": "^3.0.1",
"rimraf": "^5.0.1",
"typescript": "^5.1.6"
},
"dependencies": {},
"contributors": [],
"files": [
"dist",
"src",
"LICENSE",
"README.md",
"CHANGELOG.md"
],
"config": {
"commitizen": {
"path": "./node_modules/cz-conventional-changelog"
}
},
"greenkeeper": {
"ignore": [
"commitizen",
"cz-conventional-changelog",
"conventional-changelog-cli",
"eslint",
"prettier",
"eslint-config-prettier",
"eslint-plugin-prettier",
"@typescript-eslint/eslint-plugin",
"@typescript-eslint/parser",
"typescript",
"rimraf",
"@swc/cli",
"@swc/core",
"@swc/helpers",
"jest",
"coveralls",
"@swc/jest",
"jsdoc-to-markdown"
]
},
"eslintConfig": {
"extends": [
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "script",
"modules": true
},
"env": {
"es6": true,
"node": true,
"jest": true,
"mocha": true
},
"plugins": [
"prettier"
],
"rules": {
"prettier/prettier": "error"
},
"parser": "@typescript-eslint/parser",
"ignorePatterns": [
"*.d.ts"
]
},
"prettier": {
"semi": true,
"printWidth": 80,
"singleQuote": true,
"trailingComma": "all",
"proseWrap": "always"
},
"babel": {
"plugins": [
[
"@babel/plugin-proposal-object-rest-spread"
],
[
"@babel/plugin-transform-classes",
{}
],
[
"babel-plugin-transform-builtin-extend",
{
"globals": [
"Error",
"Array"
]
}
]
],
"presets": [
[
"@babel/env",
{
"targets": {
"node": "12.19.0"
}
}
]
],
"env": {
"cjs": {
"presets": [
[
"@babel/env",
{
"targets": {
"node": "10"
},
"modules": "commonjs"
}
]
],
"comments": true
},
"mjs": {
"presets": [
[
"@babel/env",
{
"targets": {
"node": "12"
},
"modules": false
}
]
],
"comments": false
}
},
"sourceMaps": true
},
"nyc": {
"exclude": [
"src/*.mocha.js"
]
},
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"jest": {
"coverageReporters": [
"lcov"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"roots": [
"<rootDir>/src"
],
"transform": {
"^.+\\.tsx?$": [
"@swc/jest",
{}
]
},
"testEnvironment": "node",
"moduleNameMapper": {
"(.+)\\.js": "$1"
},
"extensionsToTreatAsEsm": [
".ts"
],
"prettierPath": null
}
}

View File

@@ -0,0 +1,254 @@
/* eslint max-nested-callbacks:[0], no-magic-numbers:[0] */
import { describe, test } from '@jest/globals';
import assert from 'assert';
import { YError } from './index.js';
describe('YError', () => {
describe('.__constructor', () => {
test('Should work', () => {
const err = new YError('E_ERROR', 'arg1', 'arg2');
assert(err instanceof Error);
assert.equal(err.name, err.toString());
assert.equal(err.code, 'E_ERROR');
assert.deepEqual(err.params, ['arg1', 'arg2']);
assert.equal(err.toString(), 'YError: E_ERROR (arg1, arg2)');
});
test('Should work without code', () => {
const err = new YError();
assert.equal(err.code, 'E_UNEXPECTED');
assert.deepEqual(err.params, []);
assert.equal(err.toString(), 'YError: E_UNEXPECTED ()');
assert.equal(err.name, err.toString());
});
test('Should work without new', () => {
const err = new YError('E_ERROR', 'arg1', 'arg2');
assert.equal(err.code, 'E_ERROR');
assert(err instanceof YError);
assert.deepEqual(err.params, ['arg1', 'arg2']);
assert.equal(err.toString(), 'YError: E_ERROR (arg1, arg2)');
assert.equal(err.name, err.toString());
});
});
describe('.wrap()', () => {
test('Should work with standard errors and a message', () => {
// eslint-disable-line
const err = YError.wrap(new Error('This is an error!'));
assert.equal(err.code, 'E_UNEXPECTED');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['This is an error!']);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('Error: This is an error!'),
'Stack contains original error.',
);
assert(
-1 !==
(err.stack || '').indexOf(
'YError: E_UNEXPECTED (This is an error!)',
),
'Stack contains cast error.',
);
assert.equal(err.name, err.toString());
}
});
test('Should work with standard errors and an error code', () => {
const err = YError.wrap(new Error('E_ERROR'));
assert.equal(err.code, 'E_ERROR');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, []);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('Error: E_ERROR'),
'Stack contains original error.',
);
assert(
-1 !== (err.stack || '').indexOf('YError: E_ERROR ()'),
'Stack contains cast error.',
);
}
assert.equal(err.name, err.toString());
});
test('Should work with standard errors, an error code and params', () => {
const err = YError.wrap(
new Error('E_ERROR'),
'E_ERROR_2',
'arg1',
'arg2',
);
assert.equal(err.code, 'E_ERROR_2');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['arg1', 'arg2']);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('Error: E_ERROR'),
'Stack contains first error.',
);
assert(
-1 !== (err.stack || '').indexOf('YError: E_ERROR_2 (arg1, arg2)'),
'Stack contains second error.',
);
}
assert.equal(err.name, err.toString());
});
test('Should work with several wrapped errors', () => {
const err = YError.wrap(
YError.wrap(new Error('E_ERROR_1'), 'E_ERROR_2', 'arg2.1', 'arg2.2'),
'E_ERROR_3',
'arg3.1',
'arg3.2',
);
assert.equal(err.code, 'E_ERROR_3');
assert.equal(err.wrappedErrors.length, 2);
assert.deepEqual(err.params, ['arg3.1', 'arg3.2']);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('Error: E_ERROR_1'),
'Stack contains first error.',
);
assert(
-1 !==
(err.stack || '').indexOf('YError: E_ERROR_2 (arg2.1, arg2.2)'),
'Stack contains second error.',
);
assert(
-1 !==
(err.stack || '').indexOf('YError: E_ERROR_3 (arg3.1, arg3.2)'),
'Stack contains second error.',
);
}
assert.equal(err.name, err.toString());
});
});
describe('.cast()', () => {
test('Should work with standard errors and a message', () => {
const err = YError.cast(new Error('This is an error!'));
assert.equal(err.code, 'E_UNEXPECTED');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['This is an error!']);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('Error: This is an error!'),
'Stack contains original error.',
);
assert(
-1 !==
(err.stack || '').indexOf(
'YError: E_UNEXPECTED (This is an error!)',
),
'Stack contains cast error.',
);
}
assert.equal(err.name, err.toString());
});
test('Should let YError instances pass through', () => {
const err = YError.cast(new YError('E_ERROR', 'arg1', 'arg2'));
assert.equal(err.code, 'E_ERROR');
assert.deepEqual(err.params, ['arg1', 'arg2']);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('YError: E_ERROR (arg1, arg2)'),
'Stack contains cast error.',
);
}
assert.equal(err.name, err.toString());
});
});
describe('.bump()', () => {
test('Should work with standard errors and a message', () => {
const err = YError.bump(new Error('This is an error!'));
assert.equal(err.code, 'E_UNEXPECTED');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['This is an error!']);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('Error: This is an error!'),
'Stack contains original error.',
);
assert(
-1 !==
(err.stack || '').indexOf(
'YError: E_UNEXPECTED (This is an error!)',
),
'Stack contains bumped error.',
);
}
assert.equal(err.name, err.toString());
});
test('Should work with YError like errors', () => {
const baseErr = new Error('E_A_NEW_ERROR');
(baseErr as YError).code = 'E_A_NEW_ERROR';
(baseErr as YError).params = ['baseParam1', 'baseParam2'];
const err = YError.bump(baseErr);
assert.equal(err.code, 'E_A_NEW_ERROR');
assert.equal(err.wrappedErrors.length, 1);
assert.deepEqual(err.params, ['baseParam1', 'baseParam2']);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('Error: E_A_NEW_ERROR'),
'Stack contains original error.',
);
assert(
-1 !==
(err.stack || '').indexOf(
'YError: E_A_NEW_ERROR (baseParam1, baseParam2)',
),
'Stack contains bumped error.',
);
}
assert.equal(err.name, err.toString());
});
test('Should work with Y errors and a message', () => {
const err = YError.bump(
new YError('E_ERROR', 'arg1.1', 'arg1.2'),
'E_ERROR_2',
'arg2.1',
'arg2.2',
);
assert.equal(err.code, 'E_ERROR');
assert.deepEqual(err.params, ['arg1.1', 'arg1.2']);
if ('captureStackTrace' in Error) {
assert(
-1 !== (err.stack || '').indexOf('YError: E_ERROR (arg1.1, arg1.2)'),
'Stack contains original error.',
);
assert(
-1 !== (err.stack || '').indexOf('YError: E_ERROR (arg1.1, arg1.2)'),
'Stack contains bumped error.',
);
}
assert.equal(err.name, err.toString());
});
});
});

View File

@@ -0,0 +1,192 @@
import os from 'os';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type YErrorParams = any;
/**
* A YError class able to contain some params and
* print better stack traces
* @extends Error
*/
class YError extends Error {
code: string;
params: YErrorParams[];
wrappedErrors: (Error | YError)[];
/**
* Creates a new YError with an error code
* and some params as debug values.
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
*/
constructor(errorCode: string, ...params: YErrorParams[]);
constructor(
wrappedErrors?: Error[],
errorCode?: string,
...params: YErrorParams[]
);
constructor(wrappedErrors, errorCode, ...params) {
// Detecting if wrappedErrors are passed
if (!(wrappedErrors instanceof Array)) {
params = ('undefined' === typeof errorCode ? [] : [errorCode]).concat(
params,
);
errorCode = wrappedErrors;
wrappedErrors = [];
}
// Call the parent constructor
super(errorCode);
// Filling error
this.code = errorCode || 'E_UNEXPECTED';
this.params = params;
this.wrappedErrors = wrappedErrors;
this.name = this.toString();
if (Error.captureStackTrace) {
Error.captureStackTrace(this, this.constructor);
}
}
/**
* Wraps any error and output a YError with an error
* code and some params as debug values.
* @param {Error} err
* The error to wrap
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static wrap<E extends Error | YError>(
err: E,
errorCode?: string,
...params: YErrorParams[]
): YError {
const wrappedErrorIsACode = _looksLikeAYErrorCode(err.message);
const wrappedErrors = (
'wrappedErrors' in err ? err.wrappedErrors : []
).concat(err);
if (!errorCode) {
if (wrappedErrorIsACode) {
errorCode = err.message;
} else {
errorCode = 'E_UNEXPECTED';
}
}
if (err.message && !wrappedErrorIsACode) {
params.push(err.message);
}
return new YError(wrappedErrors, errorCode, ...params);
}
/**
* Return a YError as is or wraps any other error and output
* a YError with a code and some params as debug values.
* @param {Error} err
* The error to cast
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static cast<E extends Error | YError>(
err: E,
errorCode?: string,
...params: YErrorParams[]
): YError {
if (_looksLikeAYError(err)) {
return err as unknown as YError;
}
return YError.wrap(err, errorCode, ...params);
}
/**
* Same than `YError.wrap()` but preserves the code
* and the debug values of the error if it is
* already an instance of the YError constructor.
* @param {Error} err
* The error to bump
* @param {string} [errorCode = 'E_UNEXPECTED']
* The error code corresponding to the actual error
* @param {...YErrorParams} [params]
* Some additional debugging values
* @return {YError}
* The wrapped error
*/
static bump<E extends Error | YError>(
err: E,
errorCode?: string,
...params: YErrorParams[]
): YError {
if (_looksLikeAYError(err)) {
return YError.wrap(err, (err as YError).code, ...(err as YError).params);
}
return YError.wrap(err, errorCode, ...params);
}
toString(): string {
return (
(this.wrappedErrors.length
? // eslint-disable-next-line
this.wrappedErrors[this.wrappedErrors.length - 1].stack + os.EOL
: '') +
this.constructor.name +
': ' +
this.code +
' (' +
this.params.join(', ') +
')'
);
}
}
/**
* Allow to print a stack from anything (especially catched
* errors that may or may not contain errors 🤷).
* @param {Error} err
* The error to print
* @return {string}
* The stack trace if any
*/
export function printStackTrace(err: Error | YError): string {
return typeof err === 'object' && typeof err.stack === 'string'
? err.stack
: `[no_stack_trace]: error is ${
err != null && typeof err.toString === 'function'
? err.toString()
: typeof err
}`;
}
// In order to keep compatibility through major versions
// we have to make kind of an cross major version instanceof
function _looksLikeAYError(err: Error | YError): boolean {
return (
!!(err instanceof YError) ||
!!(
err.constructor &&
err.constructor.name &&
err.constructor.name.endsWith('Error') &&
'code' in err &&
'string' === typeof err.code &&
_looksLikeAYErrorCode(err.code) &&
'params' in err &&
err.params &&
err.params instanceof Array
)
);
}
function _looksLikeAYErrorCode(str: string): boolean {
return /^([A-Z0-9_]+)$/.test(str);
}
export { YError };