@merchi/sdk 1.42.21 → 1.42.22
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/constants/errors.d.ts +1 -1
- package/dist/constants/errors.js +3 -1
- package/dist/constants/errors.test.d.ts +1 -0
- package/dist/constants/errors.test.js +16 -0
- package/dist/request.d.ts +2 -2
- package/dist/request.js +0 -1
- package/dist/request.test.js +35 -0
- package/package.json +1 -1
- package/src/constants/errors.test.ts +23 -0
- package/src/constants/errors.ts +4 -2
- package/src/request.test.ts +32 -0
- package/src/request.ts +3 -3
package/dist/constants/errors.js
CHANGED
|
@@ -25,7 +25,9 @@ export var ErrorType;
|
|
|
25
25
|
ErrorType[ErrorType["DOMAIN_NOT_FOUND"] = 22] = "DOMAIN_NOT_FOUND";
|
|
26
26
|
})(ErrorType || (ErrorType = {}));
|
|
27
27
|
export function getErrorFromCode(code) {
|
|
28
|
-
|
|
28
|
+
// The API can add error codes before this SDK's named constants are updated.
|
|
29
|
+
// Preserve those numeric diagnostics instead of turning them into UNKNOWN.
|
|
30
|
+
if (typeof code === 'number' && Number.isSafeInteger(code) && code >= 0) {
|
|
29
31
|
return code;
|
|
30
32
|
}
|
|
31
33
|
return ErrorType.UNKNOWN_ERROR;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ErrorType, getErrorFromCode } from './errors.js';
|
|
2
|
+
test.each([ErrorType.UNKNOWN_ERROR, ErrorType.INVALID_PHONE_NUMBER, ErrorType.DOMAIN_NOT_FOUND])('preserves known API error code %s', function (code) {
|
|
3
|
+
expect(getErrorFromCode(code)).toBe(code);
|
|
4
|
+
});
|
|
5
|
+
// INVALID_HCAPTCHA and SPAM_DETECTED exist in the API's Python SDK but not
|
|
6
|
+
// this SDK's legacy enum. Future codes must remain diagnosable too.
|
|
7
|
+
test.each([226, 227, 1000, Number.MAX_SAFE_INTEGER])('preserves forward-compatible numeric API error code %s', function (code) {
|
|
8
|
+
expect(getErrorFromCode(code)).toBe(code);
|
|
9
|
+
});
|
|
10
|
+
test.each([
|
|
11
|
+
undefined, null, -1, 1.5, NaN, Infinity, -Infinity,
|
|
12
|
+
Number.MAX_SAFE_INTEGER + 1, '227', 'INVALID_PHONE_NUMBER',
|
|
13
|
+
'toString', '__proto__', true, {}, [],
|
|
14
|
+
])('uses UNKNOWN_ERROR for malformed API code %p', function (code) {
|
|
15
|
+
expect(getErrorFromCode(code)).toBe(ErrorType.UNKNOWN_ERROR);
|
|
16
|
+
});
|
package/dist/request.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ErrorType } from './constants/errors.js';
|
|
2
1
|
export interface RequestOptions extends RequestInit {
|
|
3
2
|
query?: string[][];
|
|
4
3
|
}
|
|
@@ -37,7 +36,8 @@ export interface ApiErrorDetails {
|
|
|
37
36
|
}
|
|
38
37
|
export declare class ApiError extends Error {
|
|
39
38
|
statusCode?: number;
|
|
40
|
-
|
|
39
|
+
/** Numeric API code, including values added after this SDK was published. */
|
|
40
|
+
errorCode?: number;
|
|
41
41
|
errorMessage: string;
|
|
42
42
|
/**
|
|
43
43
|
* Structured context the API may include alongside the error
|
package/dist/request.js
CHANGED
|
@@ -71,7 +71,6 @@ var __values = (this && this.__values) || function(o) {
|
|
|
71
71
|
};
|
|
72
72
|
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
|
|
73
73
|
};
|
|
74
|
-
// eslint-disable-next-line no-unused-vars
|
|
75
74
|
import { getErrorFromCode } from './constants/errors.js';
|
|
76
75
|
function resolveApiErrorMessage(err) {
|
|
77
76
|
if (err && typeof err === 'object' && typeof err.message === 'string' && err.message) {
|
package/dist/request.test.js
CHANGED
|
@@ -83,6 +83,41 @@ test('will get default errorCode', function () {
|
|
|
83
83
|
expect(e.message).toBe('just a test');
|
|
84
84
|
});
|
|
85
85
|
});
|
|
86
|
+
test('lead spam rejection keeps its API code through apiFetch', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
87
|
+
return __generator(this, function (_a) {
|
|
88
|
+
switch (_a.label) {
|
|
89
|
+
case 0:
|
|
90
|
+
mockFetch(false, {
|
|
91
|
+
statusCode: 400,
|
|
92
|
+
errorCode: 227,
|
|
93
|
+
message: 'Invalid submission',
|
|
94
|
+
}, 400);
|
|
95
|
+
return [4 /*yield*/, expect(apiFetch('https://api.merchi.co/', '/create_new_lead/', {
|
|
96
|
+
method: 'POST',
|
|
97
|
+
})).rejects.toMatchObject({
|
|
98
|
+
name: 'ApiError',
|
|
99
|
+
statusCode: 400,
|
|
100
|
+
errorCode: 227,
|
|
101
|
+
message: 'Invalid submission',
|
|
102
|
+
errorMessage: 'Invalid submission',
|
|
103
|
+
})];
|
|
104
|
+
case 1:
|
|
105
|
+
_a.sent();
|
|
106
|
+
return [2 /*return*/];
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}); });
|
|
110
|
+
test.each([226, 1000])('ApiError preserves new numeric API code %s', function (errorCode) {
|
|
111
|
+
var error = new ApiError({ statusCode: 400, errorCode: errorCode, message: 'Rejected' });
|
|
112
|
+
expect(error.errorCode).toBe(errorCode);
|
|
113
|
+
expect(error.original.errorCode).toBe(errorCode);
|
|
114
|
+
});
|
|
115
|
+
test.each(['227', 'INVALID_PHONE_NUMBER', NaN, -1])('ApiError rejects malformed API code %p', function (errorCode) {
|
|
116
|
+
var error = new ApiError({ statusCode: 400, errorCode: errorCode, message: 'Rejected' });
|
|
117
|
+
expect(error.errorCode).toBe(ErrorType.UNKNOWN_ERROR);
|
|
118
|
+
expect(error.statusCode).toBe(400);
|
|
119
|
+
expect(error.message).toBe('Rejected');
|
|
120
|
+
});
|
|
86
121
|
test('ApiError keeps plain string messages', function () {
|
|
87
122
|
var e = new ApiError('empty response');
|
|
88
123
|
expect(e.message).toBe('empty response');
|
package/package.json
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ErrorType, getErrorFromCode } from './errors.js';
|
|
2
|
+
|
|
3
|
+
test.each([ErrorType.UNKNOWN_ERROR, ErrorType.INVALID_PHONE_NUMBER, ErrorType.DOMAIN_NOT_FOUND])(
|
|
4
|
+
'preserves known API error code %s', code => {
|
|
5
|
+
expect(getErrorFromCode(code)).toBe(code);
|
|
6
|
+
},
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
// INVALID_HCAPTCHA and SPAM_DETECTED exist in the API's Python SDK but not
|
|
10
|
+
// this SDK's legacy enum. Future codes must remain diagnosable too.
|
|
11
|
+
test.each([226, 227, 1000, Number.MAX_SAFE_INTEGER])(
|
|
12
|
+
'preserves forward-compatible numeric API error code %s', code => {
|
|
13
|
+
expect(getErrorFromCode(code)).toBe(code);
|
|
14
|
+
},
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
test.each([
|
|
18
|
+
undefined, null, -1, 1.5, NaN, Infinity, -Infinity,
|
|
19
|
+
Number.MAX_SAFE_INTEGER + 1, '227', 'INVALID_PHONE_NUMBER',
|
|
20
|
+
'toString', '__proto__', true, {}, [],
|
|
21
|
+
])('uses UNKNOWN_ERROR for malformed API code %p', code => {
|
|
22
|
+
expect(getErrorFromCode(code)).toBe(ErrorType.UNKNOWN_ERROR);
|
|
23
|
+
});
|
package/src/constants/errors.ts
CHANGED
|
@@ -24,8 +24,10 @@ export enum ErrorType {
|
|
|
24
24
|
DOMAIN_NOT_FOUND = 22,
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
export function getErrorFromCode(code:
|
|
28
|
-
|
|
27
|
+
export function getErrorFromCode(code: unknown): number {
|
|
28
|
+
// The API can add error codes before this SDK's named constants are updated.
|
|
29
|
+
// Preserve those numeric diagnostics instead of turning them into UNKNOWN.
|
|
30
|
+
if (typeof code === 'number' && Number.isSafeInteger(code) && code >= 0) {
|
|
29
31
|
return code;
|
|
30
32
|
}
|
|
31
33
|
return ErrorType.UNKNOWN_ERROR;
|
package/src/request.test.ts
CHANGED
|
@@ -43,6 +43,38 @@ test('will get default errorCode', () => {
|
|
|
43
43
|
});
|
|
44
44
|
});
|
|
45
45
|
|
|
46
|
+
test('lead spam rejection keeps its API code through apiFetch', async () => {
|
|
47
|
+
mockFetch(false, {
|
|
48
|
+
statusCode: 400,
|
|
49
|
+
errorCode: 227,
|
|
50
|
+
message: 'Invalid submission',
|
|
51
|
+
}, 400);
|
|
52
|
+
await expect(apiFetch('https://api.merchi.co/', '/create_new_lead/', {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
})).rejects.toMatchObject({
|
|
55
|
+
name: 'ApiError',
|
|
56
|
+
statusCode: 400,
|
|
57
|
+
errorCode: 227,
|
|
58
|
+
message: 'Invalid submission',
|
|
59
|
+
errorMessage: 'Invalid submission',
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test.each([226, 1000])('ApiError preserves new numeric API code %s', errorCode => {
|
|
64
|
+
const error = new ApiError({ statusCode: 400, errorCode, message: 'Rejected' });
|
|
65
|
+
expect(error.errorCode).toBe(errorCode);
|
|
66
|
+
expect(error.original.errorCode).toBe(errorCode);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test.each(['227', 'INVALID_PHONE_NUMBER', NaN, -1])(
|
|
70
|
+
'ApiError rejects malformed API code %p', errorCode => {
|
|
71
|
+
const error = new ApiError({ statusCode: 400, errorCode, message: 'Rejected' });
|
|
72
|
+
expect(error.errorCode).toBe(ErrorType.UNKNOWN_ERROR);
|
|
73
|
+
expect(error.statusCode).toBe(400);
|
|
74
|
+
expect(error.message).toBe('Rejected');
|
|
75
|
+
},
|
|
76
|
+
);
|
|
77
|
+
|
|
46
78
|
test('ApiError keeps plain string messages', () => {
|
|
47
79
|
const e = new ApiError('empty response');
|
|
48
80
|
expect(e.message).toBe('empty response');
|
package/src/request.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { ErrorType, getErrorFromCode } from './constants/errors.js';
|
|
1
|
+
import { getErrorFromCode } from './constants/errors.js';
|
|
3
2
|
|
|
4
3
|
export interface RequestOptions extends RequestInit {
|
|
5
4
|
query?: string[][];
|
|
@@ -50,7 +49,8 @@ function resolveApiErrorMessage(err: any): string {
|
|
|
50
49
|
|
|
51
50
|
export class ApiError extends Error {
|
|
52
51
|
public statusCode?: number;
|
|
53
|
-
|
|
52
|
+
/** Numeric API code, including values added after this SDK was published. */
|
|
53
|
+
public errorCode?: number;
|
|
54
54
|
public errorMessage: string;
|
|
55
55
|
/**
|
|
56
56
|
* Structured context the API may include alongside the error
|