@naturalcycles/js-lib 14.171.0 → 14.172.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -17,6 +17,14 @@ export interface ErrorData {
|
|
|
17
17
|
* Error id in some error tracking system (e.g Sentry).
|
|
18
18
|
*/
|
|
19
19
|
errorId?: string;
|
|
20
|
+
/**
|
|
21
|
+
* If set - provides a short semi-user-friendly error message snippet,
|
|
22
|
+
* that would allow to give a hint to the user what went wrong,
|
|
23
|
+
* also to developers and CS to distinguish between different errors.
|
|
24
|
+
*
|
|
25
|
+
* It's not supposed to have full information about the error, just a small extract from it.
|
|
26
|
+
*/
|
|
27
|
+
snippet?: string;
|
|
20
28
|
/**
|
|
21
29
|
* Set to true to force reporting this error (e.g to Sentry).
|
|
22
30
|
* Useful to be able to force-report e.g a 4xx error, which by default wouldn't be reported.
|
|
@@ -35,11 +43,6 @@ export interface ErrorData {
|
|
|
35
43
|
* E.g 0.1 will report 10% of errors (and ignore the 90%)
|
|
36
44
|
*/
|
|
37
45
|
reportRate?: number;
|
|
38
|
-
/**
|
|
39
|
-
* Sometimes error.message gets "decorated" with extra information
|
|
40
|
-
* (e.g frontend-lib adds a method, url, etc for all the errors)
|
|
41
|
-
* `originalMessage` is used to preserve the original `error.message` as it came from the backend.
|
|
42
|
-
*/
|
|
43
46
|
/**
|
|
44
47
|
* Can be used by error-reporting tools (e.g Sentry).
|
|
45
48
|
* If fingerprint is defined - it'll be used INSTEAD of default fingerprint of a tool.
|
|
@@ -18,6 +18,22 @@ export declare function _anyToError<ERROR_TYPE extends Error = Error>(o: any, er
|
|
|
18
18
|
export declare function _anyToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(o: any, errorData?: Partial<DATA_TYPE>): ErrorObject<DATA_TYPE>;
|
|
19
19
|
export declare function _errorLikeToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(e: AppError<DATA_TYPE> | Error | ErrorLike): ErrorObject<DATA_TYPE>;
|
|
20
20
|
export declare function _errorObjectToError<DATA_TYPE extends ErrorData, ERROR_TYPE extends Error>(o: ErrorObject<DATA_TYPE>, errorClass?: Class<ERROR_TYPE>): ERROR_TYPE;
|
|
21
|
+
export interface ErrorSnippetOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Max length of the error line.
|
|
24
|
+
* Snippet may have multiple lines, one original and one per `cause`.
|
|
25
|
+
*/
|
|
26
|
+
maxLineLength?: number;
|
|
27
|
+
maxLines?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Provides a short semi-user-friendly error message snippet,
|
|
31
|
+
* that would allow to give a hint to the user what went wrong,
|
|
32
|
+
* also to developers and CS to distinguish between different errors.
|
|
33
|
+
*
|
|
34
|
+
* It's not supposed to have full information about the error, just a small extract from it.
|
|
35
|
+
*/
|
|
36
|
+
export declare function _errorSnippet(err: any, opt?: ErrorSnippetOptions): string;
|
|
21
37
|
export declare function _isBackendErrorResponseObject(o: any): o is BackendErrorResponseObject;
|
|
22
38
|
export declare function _isHttpRequestErrorObject(o: any): o is ErrorObject<HttpRequestErrorData>;
|
|
23
39
|
/**
|
package/dist/error/error.util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports._errorDataAppend = exports._isErrorLike = exports._isErrorObject = exports._isHttpRequestErrorObject = exports._isBackendErrorResponseObject = exports._errorObjectToError = exports._errorLikeToErrorObject = exports._anyToErrorObject = exports._anyToError = void 0;
|
|
3
|
+
exports._errorDataAppend = exports._isErrorLike = exports._isErrorObject = exports._isHttpRequestErrorObject = exports._isBackendErrorResponseObject = exports._errorSnippet = exports._errorObjectToError = exports._errorLikeToErrorObject = exports._anyToErrorObject = exports._anyToError = void 0;
|
|
4
4
|
const __1 = require("..");
|
|
5
5
|
/**
|
|
6
6
|
* Useful to ensure that error in `catch (err) { ... }`
|
|
@@ -38,7 +38,6 @@ exports._anyToError = _anyToError;
|
|
|
38
38
|
*/
|
|
39
39
|
function _anyToErrorObject(o, errorData) {
|
|
40
40
|
let eo;
|
|
41
|
-
// if (o instanceof Error) {
|
|
42
41
|
if (_isErrorLike(o)) {
|
|
43
42
|
eo = _errorLikeToErrorObject(o);
|
|
44
43
|
}
|
|
@@ -71,6 +70,14 @@ function _anyToErrorObject(o, errorData) {
|
|
|
71
70
|
}
|
|
72
71
|
exports._anyToErrorObject = _anyToErrorObject;
|
|
73
72
|
function _errorLikeToErrorObject(e) {
|
|
73
|
+
// If it's already an ErrorObject - just return it
|
|
74
|
+
// AppError satisfies ErrorObject interface
|
|
75
|
+
// Error does not satisfy (lacks `data`)
|
|
76
|
+
// UPD: no, we expect a "plain object" here as an output,
|
|
77
|
+
// because Error classes sometimes have non-enumerable properties (e.g data)
|
|
78
|
+
if (!(e instanceof Error) && _isErrorObject(e)) {
|
|
79
|
+
return e;
|
|
80
|
+
}
|
|
74
81
|
const obj = {
|
|
75
82
|
name: e.name,
|
|
76
83
|
message: e.message,
|
|
@@ -129,6 +136,48 @@ function _errorObjectToError(o, errorClass = Error) {
|
|
|
129
136
|
return err;
|
|
130
137
|
}
|
|
131
138
|
exports._errorObjectToError = _errorObjectToError;
|
|
139
|
+
// These "common" error classes will not be printed as part of the Error snippet
|
|
140
|
+
const commonErrorClasses = new Set([
|
|
141
|
+
'Error',
|
|
142
|
+
'AppError',
|
|
143
|
+
'AssertionError',
|
|
144
|
+
'HttpRequestError',
|
|
145
|
+
'JoiValidationError',
|
|
146
|
+
]);
|
|
147
|
+
/**
|
|
148
|
+
* Provides a short semi-user-friendly error message snippet,
|
|
149
|
+
* that would allow to give a hint to the user what went wrong,
|
|
150
|
+
* also to developers and CS to distinguish between different errors.
|
|
151
|
+
*
|
|
152
|
+
* It's not supposed to have full information about the error, just a small extract from it.
|
|
153
|
+
*/
|
|
154
|
+
function _errorSnippet(err, opt = {}) {
|
|
155
|
+
const { maxLineLength = 60, maxLines = 3 } = opt;
|
|
156
|
+
const e = _anyToErrorObject(err);
|
|
157
|
+
const lines = [errorObjectToSnippet(e)];
|
|
158
|
+
let { cause } = e;
|
|
159
|
+
while (cause && lines.length < maxLines) {
|
|
160
|
+
lines.push('Caused by ' + errorObjectToSnippet(cause));
|
|
161
|
+
cause = cause.cause; // insert DiCaprio Inception meme
|
|
162
|
+
}
|
|
163
|
+
return lines.map(line => (0, __1._truncate)(line, maxLineLength)).join('\n');
|
|
164
|
+
function errorObjectToSnippet(e) {
|
|
165
|
+
// Return snippet if it was already prepared
|
|
166
|
+
if (e.data.snippet)
|
|
167
|
+
return e.data.snippet;
|
|
168
|
+
// Code already serves the purpose of the snippet, so we can just return it
|
|
169
|
+
if (e.data.code)
|
|
170
|
+
return e.data.code;
|
|
171
|
+
return [
|
|
172
|
+
!commonErrorClasses.has(e.name) && e.name,
|
|
173
|
+
// replace "1+ white space characters" with a single space
|
|
174
|
+
e.message.replaceAll(/\s+/gm, ' ').trim(),
|
|
175
|
+
]
|
|
176
|
+
.filter(Boolean)
|
|
177
|
+
.join(': ');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
exports._errorSnippet = _errorSnippet;
|
|
132
181
|
function _isBackendErrorResponseObject(o) {
|
|
133
182
|
return _isErrorObject(o?.error);
|
|
134
183
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppError, _jsonParseIfPossible, _stringifyAny } from '..';
|
|
1
|
+
import { AppError, _jsonParseIfPossible, _stringifyAny, _truncate } from '..';
|
|
2
2
|
/**
|
|
3
3
|
* Useful to ensure that error in `catch (err) { ... }`
|
|
4
4
|
* is indeed an Error (and not e.g `string` or `undefined`).
|
|
@@ -31,7 +31,6 @@ export function _anyToError(o, errorClass = Error, errorData) {
|
|
|
31
31
|
*/
|
|
32
32
|
export function _anyToErrorObject(o, errorData) {
|
|
33
33
|
let eo;
|
|
34
|
-
// if (o instanceof Error) {
|
|
35
34
|
if (_isErrorLike(o)) {
|
|
36
35
|
eo = _errorLikeToErrorObject(o);
|
|
37
36
|
}
|
|
@@ -63,6 +62,14 @@ export function _anyToErrorObject(o, errorData) {
|
|
|
63
62
|
return eo;
|
|
64
63
|
}
|
|
65
64
|
export function _errorLikeToErrorObject(e) {
|
|
65
|
+
// If it's already an ErrorObject - just return it
|
|
66
|
+
// AppError satisfies ErrorObject interface
|
|
67
|
+
// Error does not satisfy (lacks `data`)
|
|
68
|
+
// UPD: no, we expect a "plain object" here as an output,
|
|
69
|
+
// because Error classes sometimes have non-enumerable properties (e.g data)
|
|
70
|
+
if (!(e instanceof Error) && _isErrorObject(e)) {
|
|
71
|
+
return e;
|
|
72
|
+
}
|
|
66
73
|
const obj = {
|
|
67
74
|
name: e.name,
|
|
68
75
|
message: e.message,
|
|
@@ -119,6 +126,47 @@ export function _errorObjectToError(o, errorClass = Error) {
|
|
|
119
126
|
}
|
|
120
127
|
return err;
|
|
121
128
|
}
|
|
129
|
+
// These "common" error classes will not be printed as part of the Error snippet
|
|
130
|
+
const commonErrorClasses = new Set([
|
|
131
|
+
'Error',
|
|
132
|
+
'AppError',
|
|
133
|
+
'AssertionError',
|
|
134
|
+
'HttpRequestError',
|
|
135
|
+
'JoiValidationError',
|
|
136
|
+
]);
|
|
137
|
+
/**
|
|
138
|
+
* Provides a short semi-user-friendly error message snippet,
|
|
139
|
+
* that would allow to give a hint to the user what went wrong,
|
|
140
|
+
* also to developers and CS to distinguish between different errors.
|
|
141
|
+
*
|
|
142
|
+
* It's not supposed to have full information about the error, just a small extract from it.
|
|
143
|
+
*/
|
|
144
|
+
export function _errorSnippet(err, opt = {}) {
|
|
145
|
+
const { maxLineLength = 60, maxLines = 3 } = opt;
|
|
146
|
+
const e = _anyToErrorObject(err);
|
|
147
|
+
const lines = [errorObjectToSnippet(e)];
|
|
148
|
+
let { cause } = e;
|
|
149
|
+
while (cause && lines.length < maxLines) {
|
|
150
|
+
lines.push('Caused by ' + errorObjectToSnippet(cause));
|
|
151
|
+
cause = cause.cause; // insert DiCaprio Inception meme
|
|
152
|
+
}
|
|
153
|
+
return lines.map(line => _truncate(line, maxLineLength)).join('\n');
|
|
154
|
+
function errorObjectToSnippet(e) {
|
|
155
|
+
// Return snippet if it was already prepared
|
|
156
|
+
if (e.data.snippet)
|
|
157
|
+
return e.data.snippet;
|
|
158
|
+
// Code already serves the purpose of the snippet, so we can just return it
|
|
159
|
+
if (e.data.code)
|
|
160
|
+
return e.data.code;
|
|
161
|
+
return [
|
|
162
|
+
!commonErrorClasses.has(e.name) && e.name,
|
|
163
|
+
// replace "1+ white space characters" with a single space
|
|
164
|
+
e.message.replaceAll(/\s+/gm, ' ').trim(),
|
|
165
|
+
]
|
|
166
|
+
.filter(Boolean)
|
|
167
|
+
.join(': ');
|
|
168
|
+
}
|
|
169
|
+
}
|
|
122
170
|
export function _isBackendErrorResponseObject(o) {
|
|
123
171
|
return _isErrorObject(o === null || o === void 0 ? void 0 : o.error);
|
|
124
172
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naturalcycles/js-lib",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.172.0",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"prepare": "husky install",
|
|
6
6
|
"build-prod": "build-prod-esm-cjs",
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"devDependencies": {
|
|
15
15
|
"@naturalcycles/bench-lib": "^1.5.0",
|
|
16
16
|
"@naturalcycles/dev-lib": "^13.0.1",
|
|
17
|
-
"@naturalcycles/nodejs-lib": "^
|
|
17
|
+
"@naturalcycles/nodejs-lib": "^13.0.1",
|
|
18
18
|
"@naturalcycles/time-lib": "^3.5.1",
|
|
19
19
|
"@types/crypto-js": "^4.1.1",
|
|
20
20
|
"@types/node": "^20.1.0",
|
package/src/error/error.model.ts
CHANGED
|
@@ -21,6 +21,15 @@ export interface ErrorData {
|
|
|
21
21
|
*/
|
|
22
22
|
errorId?: string
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* If set - provides a short semi-user-friendly error message snippet,
|
|
26
|
+
* that would allow to give a hint to the user what went wrong,
|
|
27
|
+
* also to developers and CS to distinguish between different errors.
|
|
28
|
+
*
|
|
29
|
+
* It's not supposed to have full information about the error, just a small extract from it.
|
|
30
|
+
*/
|
|
31
|
+
snippet?: string
|
|
32
|
+
|
|
24
33
|
/**
|
|
25
34
|
* Set to true to force reporting this error (e.g to Sentry).
|
|
26
35
|
* Useful to be able to force-report e.g a 4xx error, which by default wouldn't be reported.
|
|
@@ -42,14 +51,6 @@ export interface ErrorData {
|
|
|
42
51
|
*/
|
|
43
52
|
reportRate?: number
|
|
44
53
|
|
|
45
|
-
/**
|
|
46
|
-
* Sometimes error.message gets "decorated" with extra information
|
|
47
|
-
* (e.g frontend-lib adds a method, url, etc for all the errors)
|
|
48
|
-
* `originalMessage` is used to preserve the original `error.message` as it came from the backend.
|
|
49
|
-
*/
|
|
50
|
-
// originalMessage?: string
|
|
51
|
-
// use .cause.message instead
|
|
52
|
-
|
|
53
54
|
/**
|
|
54
55
|
* Can be used by error-reporting tools (e.g Sentry).
|
|
55
56
|
* If fingerprint is defined - it'll be used INSTEAD of default fingerprint of a tool.
|
package/src/error/error.util.ts
CHANGED
|
@@ -6,7 +6,7 @@ import type {
|
|
|
6
6
|
HttpRequestErrorData,
|
|
7
7
|
ErrorLike,
|
|
8
8
|
} from '..'
|
|
9
|
-
import { AppError, _jsonParseIfPossible, _stringifyAny } from '..'
|
|
9
|
+
import { AppError, _jsonParseIfPossible, _stringifyAny, _truncate } from '..'
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Useful to ensure that error in `catch (err) { ... }`
|
|
@@ -54,7 +54,6 @@ export function _anyToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
|
|
|
54
54
|
): ErrorObject<DATA_TYPE> {
|
|
55
55
|
let eo: ErrorObject<DATA_TYPE>
|
|
56
56
|
|
|
57
|
-
// if (o instanceof Error) {
|
|
58
57
|
if (_isErrorLike(o)) {
|
|
59
58
|
eo = _errorLikeToErrorObject(o)
|
|
60
59
|
} else {
|
|
@@ -88,6 +87,15 @@ export function _anyToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
|
|
|
88
87
|
export function _errorLikeToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(
|
|
89
88
|
e: AppError<DATA_TYPE> | Error | ErrorLike,
|
|
90
89
|
): ErrorObject<DATA_TYPE> {
|
|
90
|
+
// If it's already an ErrorObject - just return it
|
|
91
|
+
// AppError satisfies ErrorObject interface
|
|
92
|
+
// Error does not satisfy (lacks `data`)
|
|
93
|
+
// UPD: no, we expect a "plain object" here as an output,
|
|
94
|
+
// because Error classes sometimes have non-enumerable properties (e.g data)
|
|
95
|
+
if (!(e instanceof Error) && _isErrorObject(e)) {
|
|
96
|
+
return e as ErrorObject<DATA_TYPE>
|
|
97
|
+
}
|
|
98
|
+
|
|
91
99
|
const obj: ErrorObject<DATA_TYPE> = {
|
|
92
100
|
name: e.name,
|
|
93
101
|
message: e.message,
|
|
@@ -156,6 +164,64 @@ export function _errorObjectToError<DATA_TYPE extends ErrorData, ERROR_TYPE exte
|
|
|
156
164
|
return err
|
|
157
165
|
}
|
|
158
166
|
|
|
167
|
+
export interface ErrorSnippetOptions {
|
|
168
|
+
/**
|
|
169
|
+
* Max length of the error line.
|
|
170
|
+
* Snippet may have multiple lines, one original and one per `cause`.
|
|
171
|
+
*/
|
|
172
|
+
maxLineLength?: number
|
|
173
|
+
|
|
174
|
+
maxLines?: number
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// These "common" error classes will not be printed as part of the Error snippet
|
|
178
|
+
const commonErrorClasses = new Set([
|
|
179
|
+
'Error',
|
|
180
|
+
'AppError',
|
|
181
|
+
'AssertionError',
|
|
182
|
+
'HttpRequestError',
|
|
183
|
+
'JoiValidationError',
|
|
184
|
+
])
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Provides a short semi-user-friendly error message snippet,
|
|
188
|
+
* that would allow to give a hint to the user what went wrong,
|
|
189
|
+
* also to developers and CS to distinguish between different errors.
|
|
190
|
+
*
|
|
191
|
+
* It's not supposed to have full information about the error, just a small extract from it.
|
|
192
|
+
*/
|
|
193
|
+
export function _errorSnippet(err: any, opt: ErrorSnippetOptions = {}): string {
|
|
194
|
+
const { maxLineLength = 60, maxLines = 3 } = opt
|
|
195
|
+
const e = _anyToErrorObject(err)
|
|
196
|
+
|
|
197
|
+
const lines = [errorObjectToSnippet(e)]
|
|
198
|
+
|
|
199
|
+
let { cause } = e
|
|
200
|
+
|
|
201
|
+
while (cause && lines.length < maxLines) {
|
|
202
|
+
lines.push('Caused by ' + errorObjectToSnippet(cause))
|
|
203
|
+
cause = cause.cause // insert DiCaprio Inception meme
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return lines.map(line => _truncate(line, maxLineLength)).join('\n')
|
|
207
|
+
|
|
208
|
+
function errorObjectToSnippet(e: ErrorObject): string {
|
|
209
|
+
// Return snippet if it was already prepared
|
|
210
|
+
if (e.data.snippet) return e.data.snippet
|
|
211
|
+
|
|
212
|
+
// Code already serves the purpose of the snippet, so we can just return it
|
|
213
|
+
if (e.data.code) return e.data.code
|
|
214
|
+
|
|
215
|
+
return [
|
|
216
|
+
!commonErrorClasses.has(e.name) && e.name,
|
|
217
|
+
// replace "1+ white space characters" with a single space
|
|
218
|
+
e.message.replaceAll(/\s+/gm, ' ').trim(),
|
|
219
|
+
]
|
|
220
|
+
.filter(Boolean)
|
|
221
|
+
.join(': ')
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
159
225
|
export function _isBackendErrorResponseObject(o: any): o is BackendErrorResponseObject {
|
|
160
226
|
return _isErrorObject(o?.error)
|
|
161
227
|
}
|