@naturalcycles/js-lib 14.142.0 → 14.143.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.
- package/dist/error/app.error.d.ts +4 -4
- package/dist/error/app.error.js +3 -3
- package/dist/error/assert.d.ts +5 -3
- package/dist/error/assert.js +18 -6
- package/dist/error/error.model.d.ts +44 -21
- package/dist/error/error.util.d.ts +4 -4
- package/dist/error/error.util.js +8 -11
- package/dist/error/httpRequestError.d.ts +22 -0
- package/dist/error/httpRequestError.js +27 -0
- package/dist/error/jsonParseError.d.ts +11 -0
- package/dist/error/jsonParseError.js +11 -0
- package/dist/error/try.js +1 -1
- package/dist/http/fetcher.js +34 -31
- package/dist/http/http.model.d.ts +4 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/promise/pTimeout.d.ts +2 -2
- package/dist/promise/pTimeout.js +2 -2
- package/dist/string/json.util.d.ts +9 -1
- package/dist/string/json.util.js +19 -1
- package/dist/string/stringifyAny.js +6 -6
- package/dist-esm/error/app.error.js +3 -3
- package/dist-esm/error/assert.js +17 -6
- package/dist-esm/error/error.util.js +5 -8
- package/dist-esm/error/httpRequestError.js +23 -0
- package/dist-esm/error/jsonParseError.js +7 -0
- package/dist-esm/error/try.js +1 -1
- package/dist-esm/http/fetcher.js +36 -28
- package/dist-esm/index.js +2 -1
- package/dist-esm/promise/pTimeout.js +2 -2
- package/dist-esm/string/json.util.js +17 -0
- package/dist-esm/string/stringifyAny.js +7 -7
- package/package.json +1 -1
- package/src/error/app.error.ts +6 -6
- package/src/error/assert.ts +22 -9
- package/src/error/error.model.ts +48 -23
- package/src/error/error.util.ts +15 -12
- package/src/error/httpRequestError.ts +25 -0
- package/src/error/jsonParseError.ts +21 -0
- package/src/error/try.ts +1 -1
- package/src/http/fetcher.ts +42 -32
- package/src/http/http.model.ts +5 -0
- package/src/index.ts +2 -1
- package/src/promise/pTimeout.ts +3 -3
- package/src/string/json.util.ts +20 -4
- package/src/string/stringifyAny.ts +7 -7
- package/dist/error/http.error.d.ts +0 -8
- package/dist/error/http.error.js +0 -13
- package/dist-esm/error/http.error.js +0 -9
- package/src/error/http.error.ts +0 -13
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ErrorData } from './error.model';
|
|
1
|
+
import type { ErrorData, ErrorObject } from './error.model';
|
|
2
2
|
/**
|
|
3
3
|
* Base class for all our (not system) errors.
|
|
4
4
|
*
|
|
@@ -11,8 +11,8 @@ import type { ErrorData } from './error.model';
|
|
|
11
11
|
export declare class AppError<DATA_TYPE extends ErrorData = ErrorData> extends Error {
|
|
12
12
|
data: DATA_TYPE;
|
|
13
13
|
/**
|
|
14
|
-
* cause here is normalized to be
|
|
14
|
+
* cause here is normalized to be an ErrorObject
|
|
15
15
|
*/
|
|
16
|
-
cause?:
|
|
17
|
-
constructor(message: string, data?: DATA_TYPE,
|
|
16
|
+
cause?: ErrorObject;
|
|
17
|
+
constructor(message: string, data?: DATA_TYPE, cause?: ErrorObject, name?: string);
|
|
18
18
|
}
|
package/dist/error/app.error.js
CHANGED
|
@@ -11,7 +11,7 @@ exports.AppError = void 0;
|
|
|
11
11
|
* Based on: https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801
|
|
12
12
|
*/
|
|
13
13
|
class AppError extends Error {
|
|
14
|
-
constructor(message, data = {},
|
|
14
|
+
constructor(message, data = {}, cause, name) {
|
|
15
15
|
super(message);
|
|
16
16
|
Object.defineProperty(this, 'name', {
|
|
17
17
|
value: name || this.constructor.name,
|
|
@@ -30,10 +30,10 @@ class AppError extends Error {
|
|
|
30
30
|
configurable: true,
|
|
31
31
|
enumerable: false,
|
|
32
32
|
});
|
|
33
|
-
if (
|
|
33
|
+
if (cause) {
|
|
34
34
|
Object.defineProperty(this, 'cause', {
|
|
35
35
|
// I'd love to do _anyToError(opt.cause) here, but it causes circular dep ;(
|
|
36
|
-
value:
|
|
36
|
+
value: cause,
|
|
37
37
|
writable: true,
|
|
38
38
|
configurable: true,
|
|
39
39
|
enumerable: false,
|
package/dist/error/assert.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { ErrorData } from '..';
|
|
1
|
+
import type { ErrorData, ErrorObject } from '..';
|
|
2
|
+
import { Class } from '..';
|
|
2
3
|
import { AppError } from './app.error';
|
|
3
4
|
/**
|
|
4
5
|
* Evaluates the `condition` (casts it to Boolean).
|
|
@@ -31,10 +32,11 @@ export declare function _assertEquals<T>(actual: any, expected: T, message?: str
|
|
|
31
32
|
* Does DEEP equality via _deepEquals()
|
|
32
33
|
*/
|
|
33
34
|
export declare function _assertDeepEquals<T>(actual: any, expected: T, message?: string, errorData?: ErrorData): asserts actual is T;
|
|
34
|
-
export declare function _assertIsError<ERR extends Error = Error>(err: any,
|
|
35
|
+
export declare function _assertIsError<ERR extends Error = Error>(err: any, errorClass?: Class<ERR>): asserts err is ERR;
|
|
36
|
+
export declare function _assertIsErrorObject<DATA_TYPE extends ErrorData = ErrorData>(obj: any): asserts obj is ErrorObject<DATA_TYPE>;
|
|
35
37
|
export declare function _assertIsString(v: any, message?: string): asserts v is string;
|
|
36
38
|
export declare function _assertIsNumber(v: any, message?: string): asserts v is number;
|
|
37
39
|
export declare function _assertTypeOf<T>(v: any, expectedType: string, message?: string): asserts v is T;
|
|
38
40
|
export declare class AssertionError extends AppError {
|
|
39
|
-
constructor(message: string, data?: {},
|
|
41
|
+
constructor(message: string, data?: {}, cause?: ErrorObject);
|
|
40
42
|
}
|
package/dist/error/assert.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.AssertionError = exports._assertTypeOf = exports._assertIsNumber = exports._assertIsString = exports._assertIsError = exports._assertDeepEquals = exports._assertEquals = exports._assert = void 0;
|
|
3
|
+
exports.AssertionError = exports._assertTypeOf = exports._assertIsNumber = exports._assertIsString = exports._assertIsErrorObject = exports._assertIsError = exports._assertDeepEquals = exports._assertEquals = exports._assert = void 0;
|
|
4
4
|
const __1 = require("..");
|
|
5
5
|
const app_error_1 = require("./app.error");
|
|
6
6
|
/**
|
|
@@ -72,15 +72,27 @@ function _assertDeepEquals(actual, expected, message, errorData) {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
exports._assertDeepEquals = _assertDeepEquals;
|
|
75
|
-
function _assertIsError(err,
|
|
76
|
-
if (!(err instanceof
|
|
77
|
-
const msg = [
|
|
75
|
+
function _assertIsError(err, errorClass = Error) {
|
|
76
|
+
if (!(err instanceof errorClass)) {
|
|
77
|
+
const msg = [
|
|
78
|
+
`expected to be instanceof ${errorClass.name}`,
|
|
79
|
+
`actual typeof: ${typeof err}`,
|
|
80
|
+
].join('\n');
|
|
78
81
|
throw new AssertionError(msg, {
|
|
79
82
|
userFriendly: true,
|
|
80
83
|
});
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
exports._assertIsError = _assertIsError;
|
|
87
|
+
function _assertIsErrorObject(obj) {
|
|
88
|
+
if (!(0, __1._isErrorObject)(obj)) {
|
|
89
|
+
const msg = [`expected to be ErrorObject`, `actual typeof: ${typeof obj}`].join('\n');
|
|
90
|
+
throw new AssertionError(msg, {
|
|
91
|
+
userFriendly: true,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports._assertIsErrorObject = _assertIsErrorObject;
|
|
84
96
|
function _assertIsString(v, message) {
|
|
85
97
|
_assertTypeOf(v, 'string', message);
|
|
86
98
|
}
|
|
@@ -103,8 +115,8 @@ function _assertTypeOf(v, expectedType, message) {
|
|
|
103
115
|
}
|
|
104
116
|
exports._assertTypeOf = _assertTypeOf;
|
|
105
117
|
class AssertionError extends app_error_1.AppError {
|
|
106
|
-
constructor(message, data = {},
|
|
107
|
-
super(message, data,
|
|
118
|
+
constructor(message, data = {}, cause) {
|
|
119
|
+
super(message, data, cause, 'AssertionError');
|
|
108
120
|
}
|
|
109
121
|
}
|
|
110
122
|
exports.AssertionError = AssertionError;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { HttpMethod, HttpStatusCode } from '../http/http.model';
|
|
2
|
+
import { NumberOfMilliseconds } from '../types';
|
|
1
3
|
/**
|
|
2
4
|
* Extendable payload object to transfer custom additional data with AppError.
|
|
3
5
|
*/
|
|
@@ -18,8 +20,15 @@ export interface ErrorData {
|
|
|
18
20
|
/**
|
|
19
21
|
* Set to true to force reporting this error (e.g to Sentry).
|
|
20
22
|
* Useful to be able to force-report e.g a 4xx error, which by default wouldn't be reported.
|
|
23
|
+
* Set to false to force not-reporting it.
|
|
21
24
|
*/
|
|
22
25
|
report?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Set to true or false to control error reporting on the Client-side.
|
|
28
|
+
* It works as in indication/hint, not a guarantee,
|
|
29
|
+
* because Client-side still need to manually check and respect this property.
|
|
30
|
+
*/
|
|
31
|
+
reportClientSide?: boolean;
|
|
23
32
|
/**
|
|
24
33
|
* If defined - used by SentrySharedService in backend-lib.
|
|
25
34
|
* Allows to report only X% of errors of this type.
|
|
@@ -31,42 +40,52 @@ export interface ErrorData {
|
|
|
31
40
|
* (e.g frontend-lib adds a method, url, etc for all the errors)
|
|
32
41
|
* `originalMessage` is used to preserve the original `error.message` as it came from the backend.
|
|
33
42
|
*/
|
|
34
|
-
originalMessage?: string;
|
|
35
43
|
/**
|
|
36
44
|
* Can be used by error-reporting tools (e.g Sentry).
|
|
37
45
|
* If fingerprint is defined - it'll be used INSTEAD of default fingerprint of a tool.
|
|
38
46
|
* Can be used to force-group errors that are NOT needed to be split by endpoint or calling function.
|
|
39
47
|
*/
|
|
40
48
|
fingerprint?: string[];
|
|
41
|
-
httpStatusCode?: number;
|
|
42
49
|
/**
|
|
43
|
-
*
|
|
50
|
+
* Set when throwing an error from your backend code, to indicate desired http status code.
|
|
51
|
+
* e.g throw new AppError('oj', { backendResponseStatusCode: 401 })
|
|
44
52
|
*/
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
export interface HttpErrorData extends ErrorData {
|
|
53
|
+
backendResponseStatusCode?: HttpStatusCode;
|
|
48
54
|
/**
|
|
49
|
-
*
|
|
55
|
+
* Set to true when the error was thrown after response headers were sent.
|
|
50
56
|
*/
|
|
51
|
-
|
|
57
|
+
headersSent?: boolean;
|
|
52
58
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* GET /api/some-endpoint
|
|
59
|
+
* Used in e.g http 401 error.
|
|
56
60
|
*/
|
|
61
|
+
adminAuthRequired?: boolean;
|
|
57
62
|
/**
|
|
58
|
-
*
|
|
63
|
+
* Used in e.g http 403 error.
|
|
59
64
|
*/
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
65
|
+
adminPermissionsRequired?: string[];
|
|
66
|
+
/**
|
|
67
|
+
* Open-ended.
|
|
68
|
+
*/
|
|
69
|
+
[k: string]: any;
|
|
64
70
|
}
|
|
65
|
-
export interface
|
|
71
|
+
export interface HttpRequestErrorData extends ErrorData {
|
|
72
|
+
requestUrl: string;
|
|
73
|
+
requestBaseUrl?: string;
|
|
74
|
+
requestMethod: HttpMethod;
|
|
66
75
|
/**
|
|
67
|
-
*
|
|
76
|
+
* Conveniently combines Method and Url, respects `logWithSearchParams` (and similar) configuration.
|
|
77
|
+
* E.g:
|
|
78
|
+
* GET /some/url
|
|
68
79
|
*/
|
|
69
|
-
|
|
80
|
+
requestSignature: string;
|
|
81
|
+
/**
|
|
82
|
+
* Can be set to 0 if request "failed to start" or "failed to reach the server".
|
|
83
|
+
*/
|
|
84
|
+
requestDuration: NumberOfMilliseconds;
|
|
85
|
+
/**
|
|
86
|
+
* 0 is used for edge cases when e.g it failed to reach the server.
|
|
87
|
+
*/
|
|
88
|
+
responseStatusCode: HttpStatusCode;
|
|
70
89
|
}
|
|
71
90
|
/**
|
|
72
91
|
* Portable object that represents Error.
|
|
@@ -78,6 +97,8 @@ export interface Admin403ErrorData extends HttpErrorData {
|
|
|
78
97
|
* Cannot contain any properties that stock Error doesn't have, otherwise
|
|
79
98
|
* it will be hard to transform it to ErrorObject.
|
|
80
99
|
* Everything "extra" should go under `data`.
|
|
100
|
+
*
|
|
101
|
+
* Instance of AppError class should satisfy ErrorObject interface.
|
|
81
102
|
*/
|
|
82
103
|
export interface ErrorObject<DATA_TYPE extends ErrorData = ErrorData> {
|
|
83
104
|
/**
|
|
@@ -102,8 +123,10 @@ export interface ErrorObject<DATA_TYPE extends ErrorData = ErrorData> {
|
|
|
102
123
|
cause?: ErrorObject;
|
|
103
124
|
}
|
|
104
125
|
/**
|
|
105
|
-
* JSON HTTP response from the Backend that represents "Error".
|
|
126
|
+
* JSON HTTP response object from the Backend that represents "Error".
|
|
127
|
+
* Assumption is that if JSON response "looks like this" - it's safe to print it in a custom way.
|
|
128
|
+
* Otherwise - it'll be printed in a generic way.
|
|
106
129
|
*/
|
|
107
|
-
export interface
|
|
130
|
+
export interface BackendErrorResponseObject<DATA_TYPE extends ErrorData = ErrorData> {
|
|
108
131
|
error: ErrorObject<DATA_TYPE>;
|
|
109
132
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ErrorData, ErrorObject,
|
|
1
|
+
import type { ErrorData, ErrorObject, BackendErrorResponseObject, Class, HttpRequestErrorData } from '..';
|
|
2
2
|
import { AppError } from '..';
|
|
3
3
|
/**
|
|
4
4
|
* Useful to ensure that error in `catch (err) { ... }`
|
|
@@ -18,12 +18,12 @@ 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 _errorToErrorObject<DATA_TYPE extends ErrorData = ErrorData>(e: AppError<DATA_TYPE> | Error): 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 declare function
|
|
22
|
-
export declare function
|
|
21
|
+
export declare function _isBackendErrorResponseObject(o: any): o is BackendErrorResponseObject;
|
|
22
|
+
export declare function _isHttpRequestErrorObject(o: any): o is ErrorObject<HttpRequestErrorData>;
|
|
23
23
|
/**
|
|
24
24
|
* Note: any instance of AppError is also automatically an ErrorObject
|
|
25
25
|
*/
|
|
26
|
-
export declare function _isErrorObject(o: any): o is ErrorObject
|
|
26
|
+
export declare function _isErrorObject<DATA_TYPE extends ErrorData = ErrorData>(o: any): o is ErrorObject<DATA_TYPE>;
|
|
27
27
|
/**
|
|
28
28
|
* Convenience function to safely add properties to Error's `data` object
|
|
29
29
|
* (even if it wasn't previously existing)
|
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._isErrorObject = exports.
|
|
3
|
+
exports._errorDataAppend = exports._isErrorObject = exports._isHttpRequestErrorObject = exports._isBackendErrorResponseObject = exports._errorObjectToError = exports._errorToErrorObject = exports._anyToErrorObject = exports._anyToError = void 0;
|
|
4
4
|
const __1 = require("..");
|
|
5
5
|
/**
|
|
6
6
|
* Useful to ensure that error in `catch (err) { ... }`
|
|
@@ -43,7 +43,7 @@ function _anyToErrorObject(o, errorData) {
|
|
|
43
43
|
}
|
|
44
44
|
else {
|
|
45
45
|
o = (0, __1._jsonParseIfPossible)(o);
|
|
46
|
-
if (
|
|
46
|
+
if (_isBackendErrorResponseObject(o)) {
|
|
47
47
|
eo = o.error;
|
|
48
48
|
}
|
|
49
49
|
else if (_isErrorObject(o)) {
|
|
@@ -117,17 +117,14 @@ function _errorObjectToError(o, errorClass = Error) {
|
|
|
117
117
|
return err;
|
|
118
118
|
}
|
|
119
119
|
exports._errorObjectToError = _errorObjectToError;
|
|
120
|
-
function
|
|
121
|
-
return
|
|
120
|
+
function _isBackendErrorResponseObject(o) {
|
|
121
|
+
return _isErrorObject(o?.error);
|
|
122
122
|
}
|
|
123
|
-
exports.
|
|
124
|
-
function
|
|
125
|
-
return
|
|
126
|
-
typeof o.name === 'string' &&
|
|
127
|
-
typeof o.message === 'string' &&
|
|
128
|
-
typeof o.data?.httpStatusCode === 'number');
|
|
123
|
+
exports._isBackendErrorResponseObject = _isBackendErrorResponseObject;
|
|
124
|
+
function _isHttpRequestErrorObject(o) {
|
|
125
|
+
return !!o && o.name === 'HttpRequestError' && typeof o.data?.requestUrl === 'string';
|
|
129
126
|
}
|
|
130
|
-
exports.
|
|
127
|
+
exports._isHttpRequestErrorObject = _isHttpRequestErrorObject;
|
|
131
128
|
/**
|
|
132
129
|
* Note: any instance of AppError is also automatically an ErrorObject
|
|
133
130
|
*/
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { AppError } from './app.error';
|
|
2
|
+
import type { ErrorObject, HttpRequestErrorData } from './error.model';
|
|
3
|
+
/**
|
|
4
|
+
* Error that is thrown when Http Request was made and returned an error.
|
|
5
|
+
* Thrown by, for example, Fetcher.
|
|
6
|
+
*
|
|
7
|
+
* On the Frontend this Error class represents the error when calling the API,
|
|
8
|
+
* contains all the necessary request and response information.
|
|
9
|
+
*
|
|
10
|
+
* On the Backend, similarly, it represents the error when calling some 3rd-party API
|
|
11
|
+
* (backend-to-backend call).
|
|
12
|
+
* On the Backend it often propagates all the way to the Backend error handler,
|
|
13
|
+
* where it would be wrapped in BackendErrorResponseObject.
|
|
14
|
+
*
|
|
15
|
+
* Please note that `ErrorData.backendResponseStatusCode` is NOT exactly the same as
|
|
16
|
+
* `HttpRequestErrorData.responseStatusCode`.
|
|
17
|
+
* E.g 3rd-party call may return 401, but our Backend will still wrap it into an 500 error
|
|
18
|
+
* (by default).
|
|
19
|
+
*/
|
|
20
|
+
export declare class HttpRequestError extends AppError<HttpRequestErrorData> {
|
|
21
|
+
constructor(message: string, data: HttpRequestErrorData, cause?: ErrorObject);
|
|
22
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HttpRequestError = void 0;
|
|
4
|
+
const app_error_1 = require("./app.error");
|
|
5
|
+
/**
|
|
6
|
+
* Error that is thrown when Http Request was made and returned an error.
|
|
7
|
+
* Thrown by, for example, Fetcher.
|
|
8
|
+
*
|
|
9
|
+
* On the Frontend this Error class represents the error when calling the API,
|
|
10
|
+
* contains all the necessary request and response information.
|
|
11
|
+
*
|
|
12
|
+
* On the Backend, similarly, it represents the error when calling some 3rd-party API
|
|
13
|
+
* (backend-to-backend call).
|
|
14
|
+
* On the Backend it often propagates all the way to the Backend error handler,
|
|
15
|
+
* where it would be wrapped in BackendErrorResponseObject.
|
|
16
|
+
*
|
|
17
|
+
* Please note that `ErrorData.backendResponseStatusCode` is NOT exactly the same as
|
|
18
|
+
* `HttpRequestErrorData.responseStatusCode`.
|
|
19
|
+
* E.g 3rd-party call may return 401, but our Backend will still wrap it into an 500 error
|
|
20
|
+
* (by default).
|
|
21
|
+
*/
|
|
22
|
+
class HttpRequestError extends app_error_1.AppError {
|
|
23
|
+
constructor(message, data, cause) {
|
|
24
|
+
super(message, data, cause, 'HttpRequestError');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
exports.HttpRequestError = HttpRequestError;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AppError } from './app.error';
|
|
2
|
+
import { ErrorData, ErrorObject } from './error.model';
|
|
3
|
+
export interface JsonParseErrorData extends ErrorData {
|
|
4
|
+
/**
|
|
5
|
+
* Original text that failed to get parsed.
|
|
6
|
+
*/
|
|
7
|
+
text?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare class JsonParseError extends AppError<JsonParseErrorData> {
|
|
10
|
+
constructor(data: JsonParseErrorData, cause?: ErrorObject);
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.JsonParseError = void 0;
|
|
4
|
+
const string_util_1 = require("../string/string.util");
|
|
5
|
+
const app_error_1 = require("./app.error");
|
|
6
|
+
class JsonParseError extends app_error_1.AppError {
|
|
7
|
+
constructor(data, cause) {
|
|
8
|
+
super(['Failed to parse', data?.text && (0, string_util_1._truncateMiddle)(data.text, 200)].filter(Boolean).join(': '), data, cause, 'JsonParseError');
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.JsonParseError = JsonParseError;
|
package/dist/error/try.js
CHANGED
|
@@ -55,7 +55,7 @@ exports.pTry = pTry;
|
|
|
55
55
|
*/
|
|
56
56
|
class UnexpectedPassError extends app_error_1.AppError {
|
|
57
57
|
constructor() {
|
|
58
|
-
super('expected error was not thrown');
|
|
58
|
+
super('expected error was not thrown', {}, undefined, 'UnexpectedPassError');
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
exports.UnexpectedPassError = UnexpectedPassError;
|
package/dist/http/fetcher.js
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.getFetcher = exports.Fetcher = void 0;
|
|
5
5
|
const env_1 = require("../env");
|
|
6
6
|
const error_util_1 = require("../error/error.util");
|
|
7
|
-
const
|
|
7
|
+
const httpRequestError_1 = require("../error/httpRequestError");
|
|
8
8
|
const number_util_1 = require("../number/number.util");
|
|
9
9
|
const object_util_1 = require("../object/object.util");
|
|
10
10
|
const pDelay_1 = require("../promise/pDelay");
|
|
@@ -148,7 +148,7 @@ class Fetcher {
|
|
|
148
148
|
}
|
|
149
149
|
else {
|
|
150
150
|
// !res.ok
|
|
151
|
-
await this.onNotOkResponse(res, timeout);
|
|
151
|
+
await this.onNotOkResponse(res, started, timeout);
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
154
|
for await (const hook of this.cfg.hooks.afterResponse || []) {
|
|
@@ -165,15 +165,21 @@ class Fetcher {
|
|
|
165
165
|
if (text) {
|
|
166
166
|
try {
|
|
167
167
|
res.body = text;
|
|
168
|
-
res.body =
|
|
168
|
+
res.body = (0, json_util_1._jsonParse)(text, req.jsonReviver);
|
|
169
169
|
}
|
|
170
170
|
catch (err) {
|
|
171
|
-
|
|
172
|
-
res.err =
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
171
|
+
// Error while parsing json
|
|
172
|
+
// res.err = _anyToError(err, HttpRequestError, {
|
|
173
|
+
// requestUrl: res.req.url,
|
|
174
|
+
// requestBaseUrl: this.cfg.baseUrl,
|
|
175
|
+
// requestMethod: res.req.init.method,
|
|
176
|
+
// requestSignature: res.signature,
|
|
177
|
+
// requestDuration: Date.now() - started,
|
|
178
|
+
// responseStatusCode: res.fetchResponse.status,
|
|
179
|
+
// } satisfies HttpRequestErrorData)
|
|
180
|
+
res.err = (0, error_util_1._anyToError)(err);
|
|
176
181
|
res.ok = false;
|
|
182
|
+
return await this.onNotOkResponse(res, started, timeout);
|
|
177
183
|
}
|
|
178
184
|
}
|
|
179
185
|
else {
|
|
@@ -222,37 +228,34 @@ class Fetcher {
|
|
|
222
228
|
async callNativeFetch(url, init) {
|
|
223
229
|
return await globalThis.fetch(url, init);
|
|
224
230
|
}
|
|
225
|
-
async onNotOkResponse(res, timeout) {
|
|
231
|
+
async onNotOkResponse(res, started, timeout) {
|
|
226
232
|
clearTimeout(timeout);
|
|
227
|
-
let
|
|
228
|
-
if (res.
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
else if (res.err) {
|
|
233
|
-
errObj = (0, error_util_1._errorToErrorObject)(res.err);
|
|
233
|
+
let cause;
|
|
234
|
+
if (res.err) {
|
|
235
|
+
// This is only possible on JSON.parse error (or CORS error!)
|
|
236
|
+
// This check should go first, to avoid calling .text() twice (which will fail)
|
|
237
|
+
cause = (0, error_util_1._errorToErrorObject)(res.err);
|
|
234
238
|
}
|
|
235
|
-
else {
|
|
236
|
-
|
|
239
|
+
else if (res.fetchResponse) {
|
|
240
|
+
const body = (0, json_util_1._jsonParseIfPossible)(await res.fetchResponse.text());
|
|
241
|
+
if (body) {
|
|
242
|
+
cause = (0, error_util_1._anyToErrorObject)(body);
|
|
243
|
+
}
|
|
237
244
|
}
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
originalMessage,
|
|
242
|
-
]
|
|
243
|
-
.filter(Boolean)
|
|
244
|
-
.join('\n');
|
|
245
|
-
res.err = new http_error_1.HttpError(errObj.message, (0, object_util_1._filterNullishValues)({
|
|
246
|
-
...errObj.data,
|
|
247
|
-
originalMessage,
|
|
248
|
-
httpStatusCode: res.fetchResponse?.status || 0,
|
|
245
|
+
const message = [res.fetchResponse?.status, res.signature].filter(Boolean).join(' ');
|
|
246
|
+
res.err = new httpRequestError_1.HttpRequestError(message, (0, object_util_1._filterNullishValues)({
|
|
247
|
+
responseStatusCode: res.fetchResponse?.status || 0,
|
|
249
248
|
// These properties are provided to be used in e.g custom Sentry error grouping
|
|
250
249
|
// Actually, disabled now, to avoid unnecessary error printing when both msg and data are printed
|
|
251
250
|
// Enabled, cause `data` is not printed by default when error is HttpError
|
|
252
251
|
// method: req.method,
|
|
253
|
-
url: res.req.url,
|
|
254
252
|
// tryCount: req.tryCount,
|
|
255
|
-
|
|
253
|
+
requestUrl: res.req.url,
|
|
254
|
+
requestBaseUrl: this.cfg.baseUrl || null,
|
|
255
|
+
requestMethod: res.req.init.method,
|
|
256
|
+
requestSignature: res.signature,
|
|
257
|
+
requestDuration: Date.now() - started,
|
|
258
|
+
}), cause);
|
|
256
259
|
await this.processRetry(res);
|
|
257
260
|
}
|
|
258
261
|
async processRetry(res) {
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD';
|
|
2
2
|
export type HttpStatusFamily = 5 | 4 | 3 | 2 | 1;
|
|
3
|
+
/**
|
|
4
|
+
* Number, representing a valid Http status code (e.g 401, 500, etc)
|
|
5
|
+
*/
|
|
6
|
+
export type HttpStatusCode = number;
|
|
3
7
|
export declare const HTTP_METHODS: HttpMethod[];
|
package/dist/index.d.ts
CHANGED
|
@@ -20,9 +20,10 @@ export * from './enum.util';
|
|
|
20
20
|
export * from './error/error.model';
|
|
21
21
|
export * from './error/error.util';
|
|
22
22
|
export * from './error/errorMode';
|
|
23
|
-
export * from './error/
|
|
23
|
+
export * from './error/httpRequestError';
|
|
24
24
|
export * from './error/try';
|
|
25
25
|
export * from './error/tryCatch';
|
|
26
|
+
export * from './error/jsonParseError';
|
|
26
27
|
export * from './json-schema/from-data/generateJsonSchemaFromData';
|
|
27
28
|
export * from './json-schema/jsonSchema.cnst';
|
|
28
29
|
export * from './json-schema/jsonSchema.model';
|
package/dist/index.js
CHANGED
|
@@ -24,9 +24,10 @@ tslib_1.__exportStar(require("./enum.util"), exports);
|
|
|
24
24
|
tslib_1.__exportStar(require("./error/error.model"), exports);
|
|
25
25
|
tslib_1.__exportStar(require("./error/error.util"), exports);
|
|
26
26
|
tslib_1.__exportStar(require("./error/errorMode"), exports);
|
|
27
|
-
tslib_1.__exportStar(require("./error/
|
|
27
|
+
tslib_1.__exportStar(require("./error/httpRequestError"), exports);
|
|
28
28
|
tslib_1.__exportStar(require("./error/try"), exports);
|
|
29
29
|
tslib_1.__exportStar(require("./error/tryCatch"), exports);
|
|
30
|
+
tslib_1.__exportStar(require("./error/jsonParseError"), exports);
|
|
30
31
|
tslib_1.__exportStar(require("./json-schema/from-data/generateJsonSchemaFromData"), exports);
|
|
31
32
|
tslib_1.__exportStar(require("./json-schema/jsonSchema.cnst"), exports);
|
|
32
33
|
tslib_1.__exportStar(require("./json-schema/jsonSchema.model"), exports);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { AppError } from '../error/app.error';
|
|
2
|
-
import type { ErrorData } from '../error/error.model';
|
|
2
|
+
import type { ErrorData, ErrorObject } from '../error/error.model';
|
|
3
3
|
import type { AnyAsyncFunction } from '../types';
|
|
4
4
|
export declare class TimeoutError extends AppError {
|
|
5
|
-
constructor(message: string, data?: {},
|
|
5
|
+
constructor(message: string, data?: {}, cause?: ErrorObject);
|
|
6
6
|
}
|
|
7
7
|
export interface PTimeoutOptions {
|
|
8
8
|
/**
|
package/dist/promise/pTimeout.js
CHANGED
|
@@ -4,8 +4,8 @@ exports.pTimeout = exports.pTimeoutFn = exports.TimeoutError = void 0;
|
|
|
4
4
|
const app_error_1 = require("../error/app.error");
|
|
5
5
|
const error_util_1 = require("../error/error.util");
|
|
6
6
|
class TimeoutError extends app_error_1.AppError {
|
|
7
|
-
constructor(message, data = {},
|
|
8
|
-
super(message, data,
|
|
7
|
+
constructor(message, data = {}, cause) {
|
|
8
|
+
super(message, data, cause, 'TimeoutError');
|
|
9
9
|
}
|
|
10
10
|
}
|
|
11
11
|
exports.TimeoutError = TimeoutError;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
import { Reviver } from '../types';
|
|
1
2
|
/**
|
|
2
3
|
* Attempts to parse object as JSON.
|
|
3
4
|
* Returns original object if JSON parse failed (silently).
|
|
4
5
|
*/
|
|
5
|
-
export declare function _jsonParseIfPossible(obj: any, reviver?:
|
|
6
|
+
export declare function _jsonParseIfPossible(obj: any, reviver?: Reviver): any;
|
|
7
|
+
/**
|
|
8
|
+
* Same as JSON.parse, but throws JsonParseError:
|
|
9
|
+
*
|
|
10
|
+
* 1. It's message includes a piece of source text (truncated)
|
|
11
|
+
* 2. It's data.text contains full source text
|
|
12
|
+
*/
|
|
13
|
+
export declare function _jsonParse(s: string, reviver?: Reviver): unknown;
|
package/dist/string/json.util.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports._jsonParseIfPossible = void 0;
|
|
3
|
+
exports._jsonParse = exports._jsonParseIfPossible = void 0;
|
|
4
|
+
const jsonParseError_1 = require("../error/jsonParseError");
|
|
4
5
|
// const possibleJsonStartTokens = ['{', '[', '"']
|
|
5
6
|
const DETECT_JSON = /^\s*[{["\-\d]/;
|
|
6
7
|
/**
|
|
@@ -18,3 +19,20 @@ function _jsonParseIfPossible(obj, reviver) {
|
|
|
18
19
|
return obj;
|
|
19
20
|
}
|
|
20
21
|
exports._jsonParseIfPossible = _jsonParseIfPossible;
|
|
22
|
+
/**
|
|
23
|
+
* Same as JSON.parse, but throws JsonParseError:
|
|
24
|
+
*
|
|
25
|
+
* 1. It's message includes a piece of source text (truncated)
|
|
26
|
+
* 2. It's data.text contains full source text
|
|
27
|
+
*/
|
|
28
|
+
function _jsonParse(s, reviver) {
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(s, reviver);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
throw new jsonParseError_1.JsonParseError({
|
|
34
|
+
text: s,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports._jsonParse = _jsonParse;
|
|
@@ -56,7 +56,7 @@ function _stringifyAny(obj, opt = {}) {
|
|
|
56
56
|
//
|
|
57
57
|
// HttpErrorResponse
|
|
58
58
|
//
|
|
59
|
-
if ((0, error_util_1.
|
|
59
|
+
if ((0, error_util_1._isBackendErrorResponseObject)(obj)) {
|
|
60
60
|
return _stringifyAny(obj.error, opt);
|
|
61
61
|
}
|
|
62
62
|
if (obj instanceof Error || (0, error_util_1._isErrorObject)(obj)) {
|
|
@@ -69,11 +69,11 @@ function _stringifyAny(obj, opt = {}) {
|
|
|
69
69
|
// if (obj?.name === 'Error') {
|
|
70
70
|
// s = obj.message
|
|
71
71
|
// }
|
|
72
|
-
if (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
s
|
|
72
|
+
// if (_isErrorObject(obj) && _isHttpErrorObject(obj)) {
|
|
73
|
+
// // Printing (0) to avoid ambiguity
|
|
74
|
+
// s = `${obj.name}(${obj.data.httpStatusCode}): ${obj.message}`
|
|
75
|
+
// }
|
|
76
|
+
s = [obj.name, obj.message].filter(Boolean).join(': ');
|
|
77
77
|
if (typeof obj.code === 'string') {
|
|
78
78
|
// Error that has no `data`, but has `code` property
|
|
79
79
|
s += `\ncode: ${obj.code}`;
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Based on: https://medium.com/@xpl/javascript-deriving-from-error-properly-8d2f8f315801
|
|
9
9
|
*/
|
|
10
10
|
export class AppError extends Error {
|
|
11
|
-
constructor(message, data = {},
|
|
11
|
+
constructor(message, data = {}, cause, name) {
|
|
12
12
|
super(message);
|
|
13
13
|
Object.defineProperty(this, 'name', {
|
|
14
14
|
value: name || this.constructor.name,
|
|
@@ -27,10 +27,10 @@ export class AppError extends Error {
|
|
|
27
27
|
configurable: true,
|
|
28
28
|
enumerable: false,
|
|
29
29
|
});
|
|
30
|
-
if (
|
|
30
|
+
if (cause) {
|
|
31
31
|
Object.defineProperty(this, 'cause', {
|
|
32
32
|
// I'd love to do _anyToError(opt.cause) here, but it causes circular dep ;(
|
|
33
|
-
value:
|
|
33
|
+
value: cause,
|
|
34
34
|
writable: true,
|
|
35
35
|
configurable: true,
|
|
36
36
|
enumerable: false,
|