@workos-inc/node 7.62.0 → 7.63.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/lib/common/exceptions/parse-error.d.ts +7 -1
- package/lib/common/exceptions/parse-error.js +2 -1
- package/lib/common/net/fetch-client.js +20 -2
- package/lib/common/net/fetch-client.spec.js +67 -0
- package/lib/organization-domains/organization-domains.d.ts +1 -0
- package/lib/organization-domains/organization-domains.js +5 -0
- package/lib/organization-domains/organization-domains.spec.js +7 -0
- package/lib/workos.js +8 -2
- package/package.json +1 -1
|
@@ -3,6 +3,12 @@ export declare class ParseError extends Error implements RequestException {
|
|
|
3
3
|
readonly name = "ParseError";
|
|
4
4
|
readonly status = 500;
|
|
5
5
|
readonly rawBody: string;
|
|
6
|
+
readonly rawStatus: number;
|
|
6
7
|
readonly requestID: string;
|
|
7
|
-
constructor(message
|
|
8
|
+
constructor({ message, rawBody, rawStatus, requestID, }: {
|
|
9
|
+
message: string;
|
|
10
|
+
rawBody: string;
|
|
11
|
+
requestID: string;
|
|
12
|
+
rawStatus: number;
|
|
13
|
+
});
|
|
8
14
|
}
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ParseError = void 0;
|
|
4
4
|
class ParseError extends Error {
|
|
5
|
-
constructor(message, rawBody, requestID) {
|
|
5
|
+
constructor({ message, rawBody, rawStatus, requestID, }) {
|
|
6
6
|
super(message);
|
|
7
7
|
this.name = 'ParseError';
|
|
8
8
|
this.status = 500;
|
|
9
9
|
this.rawBody = rawBody;
|
|
10
|
+
this.rawStatus = rawStatus;
|
|
10
11
|
this.requestID = requestID;
|
|
11
12
|
}
|
|
12
13
|
}
|
|
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.FetchHttpClientResponse = exports.FetchHttpClient = void 0;
|
|
13
13
|
const http_client_1 = require("./http-client");
|
|
14
|
+
const parse_error_1 = require("../exceptions/parse-error");
|
|
14
15
|
class FetchHttpClient extends http_client_1.HttpClient {
|
|
15
16
|
constructor(baseURL, options, fetchFn) {
|
|
16
17
|
super(baseURL, options);
|
|
@@ -74,7 +75,7 @@ class FetchHttpClient extends http_client_1.HttpClient {
|
|
|
74
75
|
});
|
|
75
76
|
}
|
|
76
77
|
fetchRequest(url, method, body, headers) {
|
|
77
|
-
var _a, _b;
|
|
78
|
+
var _a, _b, _c;
|
|
78
79
|
return __awaiter(this, void 0, void 0, function* () {
|
|
79
80
|
// For methods which expect payloads, we should always pass a body value
|
|
80
81
|
// even when it is empty. Without this, some JS runtimes (eg. Deno) will
|
|
@@ -88,12 +89,29 @@ class FetchHttpClient extends http_client_1.HttpClient {
|
|
|
88
89
|
body: requestBody,
|
|
89
90
|
});
|
|
90
91
|
if (!res.ok) {
|
|
92
|
+
const requestID = (_c = res.headers.get('X-Request-ID')) !== null && _c !== void 0 ? _c : '';
|
|
93
|
+
const rawBody = yield res.text();
|
|
94
|
+
let responseJson;
|
|
95
|
+
try {
|
|
96
|
+
responseJson = JSON.parse(rawBody);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (error instanceof SyntaxError) {
|
|
100
|
+
throw new parse_error_1.ParseError({
|
|
101
|
+
message: error.message,
|
|
102
|
+
rawBody,
|
|
103
|
+
requestID,
|
|
104
|
+
rawStatus: res.status,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
91
109
|
throw new http_client_1.HttpClientError({
|
|
92
110
|
message: res.statusText,
|
|
93
111
|
response: {
|
|
94
112
|
status: res.status,
|
|
95
113
|
headers: res.headers,
|
|
96
|
-
data:
|
|
114
|
+
data: responseJson,
|
|
97
115
|
},
|
|
98
116
|
});
|
|
99
117
|
}
|
|
@@ -15,6 +15,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
15
15
|
const jest_fetch_mock_1 = __importDefault(require("jest-fetch-mock"));
|
|
16
16
|
const test_utils_1 = require("../../common/utils/test-utils");
|
|
17
17
|
const fetch_client_1 = require("./fetch-client");
|
|
18
|
+
const parse_error_1 = require("../exceptions/parse-error");
|
|
18
19
|
const fetchClient = new fetch_client_1.FetchHttpClient('https://test.workos.com', {
|
|
19
20
|
headers: {
|
|
20
21
|
Authorization: `Bearer sk_test`,
|
|
@@ -137,4 +138,70 @@ describe('Fetch client', () => {
|
|
|
137
138
|
expect(yield response.toJSON()).toEqual({ data: 'response' });
|
|
138
139
|
}));
|
|
139
140
|
});
|
|
141
|
+
describe('error handling', () => {
|
|
142
|
+
it('should throw ParseError when response body is not valid JSON on non-200 status', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
143
|
+
// Mock a 500 response with invalid JSON (like an HTML error page)
|
|
144
|
+
jest_fetch_mock_1.default.mockResponseOnce('<html><body>Internal Server Error</body></html>', {
|
|
145
|
+
status: 500,
|
|
146
|
+
statusText: 'Internal Server Error',
|
|
147
|
+
headers: {
|
|
148
|
+
'X-Request-ID': 'test-request-123',
|
|
149
|
+
'Content-Type': 'text/html',
|
|
150
|
+
},
|
|
151
|
+
});
|
|
152
|
+
yield expect(fetchClient.get('/users', {})).rejects.toThrow(parse_error_1.ParseError);
|
|
153
|
+
try {
|
|
154
|
+
yield fetchClient.get('/users', {});
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
expect(error).toBeInstanceOf(parse_error_1.ParseError);
|
|
158
|
+
const parseError = error;
|
|
159
|
+
expect(parseError.message).toContain('Unexpected token');
|
|
160
|
+
expect(parseError.rawBody).toBe('<html><body>Internal Server Error</body></html>');
|
|
161
|
+
expect(parseError.requestID).toBe('test-request-123');
|
|
162
|
+
expect(parseError.rawStatus).toBe(500);
|
|
163
|
+
}
|
|
164
|
+
}));
|
|
165
|
+
it('should throw ParseError for non-FGA endpoints with invalid JSON response', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
166
|
+
// Test with a non-FGA endpoint to ensure the error handling works for regular requests too
|
|
167
|
+
jest_fetch_mock_1.default.mockResponseOnce('Not JSON content', {
|
|
168
|
+
status: 400,
|
|
169
|
+
statusText: 'Bad Request',
|
|
170
|
+
headers: {
|
|
171
|
+
'X-Request-ID': 'bad-request-456',
|
|
172
|
+
'Content-Type': 'text/plain',
|
|
173
|
+
},
|
|
174
|
+
});
|
|
175
|
+
yield expect(fetchClient.post('/organizations', { name: 'Test' }, {})).rejects.toThrow(parse_error_1.ParseError);
|
|
176
|
+
try {
|
|
177
|
+
yield fetchClient.post('/organizations', { name: 'Test' }, {});
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
expect(error).toBeInstanceOf(parse_error_1.ParseError);
|
|
181
|
+
const parseError = error;
|
|
182
|
+
expect(parseError.rawBody).toBe('Not JSON content');
|
|
183
|
+
expect(parseError.requestID).toBe('bad-request-456');
|
|
184
|
+
expect(parseError.rawStatus).toBe(400);
|
|
185
|
+
}
|
|
186
|
+
}));
|
|
187
|
+
it('should throw ParseError when X-Request-ID header is missing', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
188
|
+
jest_fetch_mock_1.default.mockResponseOnce('Invalid JSON Response', {
|
|
189
|
+
status: 422,
|
|
190
|
+
statusText: 'Unprocessable Entity',
|
|
191
|
+
headers: {
|
|
192
|
+
'Content-Type': 'application/json',
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
try {
|
|
196
|
+
yield fetchClient.put('/users/123', { name: 'Updated' }, {});
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
expect(error).toBeInstanceOf(parse_error_1.ParseError);
|
|
200
|
+
const parseError = error;
|
|
201
|
+
expect(parseError.rawBody).toBe('Invalid JSON Response');
|
|
202
|
+
expect(parseError.requestID).toBe(''); // Should default to empty string when header is missing
|
|
203
|
+
expect(parseError.rawStatus).toBe(422);
|
|
204
|
+
}
|
|
205
|
+
}));
|
|
206
|
+
});
|
|
140
207
|
});
|
|
@@ -34,5 +34,10 @@ class OrganizationDomains {
|
|
|
34
34
|
return (0, organization_domain_serializer_1.deserializeOrganizationDomain)(data);
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
|
+
delete(id) {
|
|
38
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
39
|
+
yield this.workos.delete(`/organization_domains/${id}`);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
37
42
|
}
|
|
38
43
|
exports.OrganizationDomains = OrganizationDomains;
|
|
@@ -78,4 +78,11 @@ describe('OrganizationDomains', () => {
|
|
|
78
78
|
expect(subject.verificationStrategy).toEqual('dns');
|
|
79
79
|
}));
|
|
80
80
|
});
|
|
81
|
+
describe('delete', () => {
|
|
82
|
+
it('deletes an Organization Domain', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
83
|
+
(0, test_utils_1.fetchOnce)();
|
|
84
|
+
yield workos.organizationDomains.delete('org_domain_01HCZRAP3TPQ0X0DKJHR32TATG');
|
|
85
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/organization_domains/org_domain_01HCZRAP3TPQ0X0DKJHR32TATG');
|
|
86
|
+
}));
|
|
87
|
+
});
|
|
81
88
|
});
|
package/lib/workos.js
CHANGED
|
@@ -32,7 +32,7 @@ const actions_1 = require("./actions/actions");
|
|
|
32
32
|
const vault_1 = require("./vault/vault");
|
|
33
33
|
const conflict_exception_1 = require("./common/exceptions/conflict.exception");
|
|
34
34
|
const parse_error_1 = require("./common/exceptions/parse-error");
|
|
35
|
-
const VERSION = '7.
|
|
35
|
+
const VERSION = '7.63.0';
|
|
36
36
|
const DEFAULT_HOSTNAME = 'api.workos.com';
|
|
37
37
|
const HEADER_AUTHORIZATION = 'Authorization';
|
|
38
38
|
const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
|
|
@@ -214,8 +214,14 @@ class WorkOS {
|
|
|
214
214
|
if (error instanceof SyntaxError) {
|
|
215
215
|
const rawResponse = res.getRawResponse();
|
|
216
216
|
const requestID = (_a = rawResponse.headers.get('X-Request-ID')) !== null && _a !== void 0 ? _a : '';
|
|
217
|
+
const rawStatus = rawResponse.status;
|
|
217
218
|
const rawBody = yield rawResponse.text();
|
|
218
|
-
throw new parse_error_1.ParseError(
|
|
219
|
+
throw new parse_error_1.ParseError({
|
|
220
|
+
message: error.message,
|
|
221
|
+
rawBody,
|
|
222
|
+
rawStatus,
|
|
223
|
+
requestID,
|
|
224
|
+
});
|
|
219
225
|
}
|
|
220
226
|
});
|
|
221
227
|
}
|
package/package.json
CHANGED