@workos-inc/node 5.2.0 → 6.0.0-rc.2
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/audit-logs/audit-logs.spec.js +18 -4
- package/lib/common/interfaces/workos-options.interface.d.ts +1 -2
- package/lib/common/utils/fetch-client.d.ts +29 -0
- package/lib/common/utils/fetch-client.js +97 -0
- package/lib/common/utils/fetch-error.d.ts +13 -0
- package/lib/common/utils/fetch-error.js +13 -0
- package/lib/common/utils/test-utils.d.ts +8 -0
- package/lib/common/utils/test-utils.js +45 -0
- package/lib/directory-sync/directory-sync.spec.js +34 -45
- package/lib/events/events.spec.js +5 -6
- package/lib/mfa/mfa.spec.js +39 -42
- package/lib/organization-domains/organization-domains.spec.js +12 -24
- package/lib/organizations/organizations.spec.js +49 -74
- package/lib/passwordless/passwordless.spec.js +9 -16
- package/lib/portal/portal.spec.js +41 -47
- package/lib/sso/sso.spec.js +56 -100
- package/lib/user-management/user-management.spec.js +90 -123
- package/lib/webhooks/webhooks.d.ts +5 -5
- package/lib/webhooks/webhooks.js +64 -42
- package/lib/webhooks/webhooks.spec.js +40 -30
- package/lib/workos.d.ts +11 -6
- package/lib/workos.js +16 -19
- package/lib/workos.spec.js +17 -22
- package/package.json +3 -2
package/lib/webhooks/webhooks.js
CHANGED
|
@@ -1,32 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var
|
|
3
|
-
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
4
10
|
};
|
|
5
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
12
|
exports.Webhooks = void 0;
|
|
7
|
-
const crypto_1 = __importDefault(require("crypto"));
|
|
8
13
|
const exceptions_1 = require("../common/exceptions");
|
|
9
14
|
const serializers_1 = require("../common/serializers");
|
|
10
15
|
class Webhooks {
|
|
11
16
|
constructEvent({ payload, sigHeader, secret, tolerance = 180000, }) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
17
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
18
|
+
const options = { payload, sigHeader, secret, tolerance };
|
|
19
|
+
yield this.verifyHeader(options);
|
|
20
|
+
const webhookPayload = payload;
|
|
21
|
+
return (0, serializers_1.deserializeEvent)(webhookPayload);
|
|
22
|
+
});
|
|
16
23
|
}
|
|
17
24
|
verifyHeader({ payload, sigHeader, secret, tolerance = 180000, }) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
+
const [timestamp, signatureHash] = this.getTimestampAndSignatureHash(sigHeader);
|
|
27
|
+
if (!signatureHash || Object.keys(signatureHash).length === 0) {
|
|
28
|
+
throw new exceptions_1.SignatureVerificationException('No signature hash found with expected scheme v1');
|
|
29
|
+
}
|
|
30
|
+
if (parseInt(timestamp, 10) < Date.now() - tolerance) {
|
|
31
|
+
throw new exceptions_1.SignatureVerificationException('Timestamp outside the tolerance zone');
|
|
32
|
+
}
|
|
33
|
+
const expectedSig = yield this.computeSignature(timestamp, payload, secret);
|
|
34
|
+
if ((yield this.secureCompare(expectedSig, signatureHash)) === false) {
|
|
35
|
+
throw new exceptions_1.SignatureVerificationException('Signature hash does not match the expected signature hash for payload');
|
|
36
|
+
}
|
|
37
|
+
return true;
|
|
38
|
+
});
|
|
30
39
|
}
|
|
31
40
|
getTimestampAndSignatureHash(sigHeader) {
|
|
32
41
|
const signature = sigHeader;
|
|
@@ -39,31 +48,44 @@ class Webhooks {
|
|
|
39
48
|
return [timestamp, signatureHash];
|
|
40
49
|
}
|
|
41
50
|
computeSignature(timestamp, payload, secret) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
.
|
|
46
|
-
.
|
|
47
|
-
.
|
|
48
|
-
.
|
|
49
|
-
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
payload = JSON.stringify(payload);
|
|
53
|
+
const signedPayload = `${timestamp}.${payload}`;
|
|
54
|
+
const key = yield crypto.subtle.importKey('raw', new TextEncoder().encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
|
|
55
|
+
const signatureBuffer = yield crypto.subtle.sign('HMAC', key, new TextEncoder().encode(signedPayload));
|
|
56
|
+
// crypto.subtle returns the signature in base64 format. This must be
|
|
57
|
+
// encoded in hex to match the CryptoProvider contract. We map each byte in
|
|
58
|
+
// the buffer to its corresponding hex octet and then combine into a string.
|
|
59
|
+
const signatureBytes = new Uint8Array(signatureBuffer);
|
|
60
|
+
const signatureHexCodes = new Array(signatureBytes.length);
|
|
61
|
+
for (let i = 0; i < signatureBytes.length; i++) {
|
|
62
|
+
signatureHexCodes[i] = byteHexMapping[signatureBytes[i]];
|
|
63
|
+
}
|
|
64
|
+
return signatureHexCodes.join('');
|
|
65
|
+
});
|
|
50
66
|
}
|
|
51
67
|
secureCompare(stringA, stringB) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
69
|
+
const bufferA = Buffer.from(stringA);
|
|
70
|
+
const bufferB = Buffer.from(stringB);
|
|
71
|
+
if (bufferA.length !== bufferB.length) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
const algorithm = { name: 'HMAC', hash: 'SHA-256' };
|
|
75
|
+
const key = (yield crypto.subtle.generateKey(algorithm, false, [
|
|
76
|
+
'sign',
|
|
77
|
+
'verify',
|
|
78
|
+
]));
|
|
79
|
+
const hmac = yield crypto.subtle.sign(algorithm, key, bufferA);
|
|
80
|
+
const equal = yield crypto.subtle.verify(algorithm, key, hmac, bufferB);
|
|
81
|
+
return equal;
|
|
82
|
+
});
|
|
67
83
|
}
|
|
68
84
|
}
|
|
69
85
|
exports.Webhooks = Webhooks;
|
|
86
|
+
// Cached mapping of byte to hex representation. We do this once to avoid re-
|
|
87
|
+
// computing every time we need to convert the result of a signature to hex.
|
|
88
|
+
const byteHexMapping = new Array(256);
|
|
89
|
+
for (let i = 0; i < byteHexMapping.length; i++) {
|
|
90
|
+
byteHexMapping[i] = i.toString(16).padStart(2, '0');
|
|
91
|
+
}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
2
11
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
13
|
};
|
|
@@ -90,76 +99,77 @@ describe('Webhooks', () => {
|
|
|
90
99
|
});
|
|
91
100
|
describe('constructEvent', () => {
|
|
92
101
|
describe('with the correct payload, sig_header, and secret', () => {
|
|
93
|
-
it('returns a webhook event', () => {
|
|
102
|
+
it('returns a webhook event', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
94
103
|
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
95
104
|
const options = { payload, sigHeader, secret };
|
|
96
|
-
const webhook = workos.webhooks.constructEvent(options);
|
|
105
|
+
const webhook = yield workos.webhooks.constructEvent(options);
|
|
97
106
|
expect(webhook.data).toEqual(expectation);
|
|
98
107
|
expect(webhook.event).toEqual('dsync.user.created');
|
|
99
108
|
expect(webhook.id).toEqual('wh_123');
|
|
100
|
-
});
|
|
109
|
+
}));
|
|
101
110
|
});
|
|
102
111
|
describe('with the correct payload, sig_header, secret, and tolerance', () => {
|
|
103
|
-
it('returns a webhook event', () => {
|
|
112
|
+
it('returns a webhook event', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
104
113
|
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
105
114
|
const options = { payload, sigHeader, secret, tolerance: 200 };
|
|
106
|
-
const webhook = workos.webhooks.constructEvent(options);
|
|
115
|
+
const webhook = yield workos.webhooks.constructEvent(options);
|
|
107
116
|
expect(webhook.data).toEqual(expectation);
|
|
108
117
|
expect(webhook.event).toEqual('dsync.user.created');
|
|
109
118
|
expect(webhook.id).toEqual('wh_123');
|
|
110
|
-
});
|
|
119
|
+
}));
|
|
111
120
|
});
|
|
112
121
|
describe('with an empty header', () => {
|
|
113
|
-
it('raises an error', () => {
|
|
122
|
+
it('raises an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
123
|
const sigHeader = '';
|
|
115
124
|
const options = { payload, sigHeader, secret };
|
|
116
|
-
expect(
|
|
117
|
-
});
|
|
125
|
+
yield expect(workos.webhooks.constructEvent(options)).rejects.toThrowError(exceptions_1.SignatureVerificationException);
|
|
126
|
+
}));
|
|
118
127
|
});
|
|
119
128
|
describe('with an empty signature hash', () => {
|
|
120
|
-
it('raises an error', () => {
|
|
129
|
+
it('raises an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
121
130
|
const sigHeader = `t=${timestamp}, v1=`;
|
|
122
131
|
const options = { payload, sigHeader, secret };
|
|
123
|
-
expect(
|
|
124
|
-
});
|
|
132
|
+
yield expect(workos.webhooks.constructEvent(options)).rejects.toThrowError(exceptions_1.SignatureVerificationException);
|
|
133
|
+
}));
|
|
125
134
|
});
|
|
126
135
|
describe('with an incorrect signature hash', () => {
|
|
127
|
-
it('raises an error', () => {
|
|
136
|
+
it('raises an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
128
137
|
const sigHeader = `t=${timestamp}, v1=99999`;
|
|
129
138
|
const options = { payload, sigHeader, secret };
|
|
130
|
-
expect(
|
|
131
|
-
});
|
|
139
|
+
yield expect(workos.webhooks.constructEvent(options)).rejects.toThrowError(exceptions_1.SignatureVerificationException);
|
|
140
|
+
}));
|
|
132
141
|
});
|
|
133
142
|
describe('with an incorrect payload', () => {
|
|
134
|
-
it('raises an error', () => {
|
|
143
|
+
it('raises an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
135
144
|
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
136
145
|
payload = 'invalid';
|
|
137
146
|
const options = { payload, sigHeader, secret };
|
|
138
|
-
expect(
|
|
139
|
-
});
|
|
147
|
+
yield expect(workos.webhooks.constructEvent(options)).rejects.toThrowError(exceptions_1.SignatureVerificationException);
|
|
148
|
+
}));
|
|
140
149
|
});
|
|
141
150
|
describe('with an incorrect webhook secret', () => {
|
|
142
|
-
it('raises an error', () => {
|
|
151
|
+
it('raises an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
143
152
|
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
144
153
|
secret = 'invalid';
|
|
145
154
|
const options = { payload, sigHeader, secret };
|
|
146
|
-
expect(
|
|
147
|
-
});
|
|
155
|
+
yield expect(workos.webhooks.constructEvent(options)).rejects.toThrowError(exceptions_1.SignatureVerificationException);
|
|
156
|
+
}));
|
|
148
157
|
});
|
|
149
158
|
describe('with a timestamp outside tolerance', () => {
|
|
150
|
-
it('raises an error', () => {
|
|
159
|
+
it('raises an error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
151
160
|
const sigHeader = `t=9999, v1=${signatureHash}`;
|
|
152
161
|
const options = { payload, sigHeader, secret };
|
|
153
|
-
expect(
|
|
154
|
-
});
|
|
162
|
+
yield expect(workos.webhooks.constructEvent(options)).rejects.toThrowError(exceptions_1.SignatureVerificationException);
|
|
163
|
+
}));
|
|
155
164
|
});
|
|
156
165
|
});
|
|
157
166
|
describe('verifyHeader', () => {
|
|
158
|
-
it('returns true when the signature is valid', () => {
|
|
167
|
+
it('returns true when the signature is valid', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
159
168
|
const sigHeader = `t=${timestamp}, v1=${signatureHash}`;
|
|
160
169
|
const options = { payload, sigHeader, secret };
|
|
161
|
-
|
|
162
|
-
|
|
170
|
+
const result = yield workos.webhooks.verifyHeader(options);
|
|
171
|
+
expect(result).toBeTruthy();
|
|
172
|
+
}));
|
|
163
173
|
});
|
|
164
174
|
describe('getTimestampAndSignatureHash', () => {
|
|
165
175
|
it('returns the timestamp and signature when the signature is valid', () => {
|
|
@@ -172,9 +182,9 @@ describe('Webhooks', () => {
|
|
|
172
182
|
});
|
|
173
183
|
});
|
|
174
184
|
describe('computeSignature', () => {
|
|
175
|
-
it('returns the computed signature', () => {
|
|
176
|
-
const signature = workos.webhooks.computeSignature(timestamp, payload, secret);
|
|
185
|
+
it('returns the computed signature', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
186
|
+
const signature = yield workos.webhooks.computeSignature(timestamp, payload, secret);
|
|
177
187
|
expect(signature).toEqual(signatureHash);
|
|
178
|
-
});
|
|
188
|
+
}));
|
|
179
189
|
});
|
|
180
190
|
});
|
package/lib/workos.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { AxiosResponse } from 'axios';
|
|
2
1
|
import { GetOptions, PostOptions, PutOptions, WorkOSOptions } from './common/interfaces';
|
|
3
2
|
import { DirectorySync } from './directory-sync/directory-sync';
|
|
4
3
|
import { Events } from './events/events';
|
|
@@ -29,10 +28,16 @@ export declare class WorkOS {
|
|
|
29
28
|
readonly userManagement: UserManagement;
|
|
30
29
|
constructor(key?: string | undefined, options?: WorkOSOptions);
|
|
31
30
|
get version(): string;
|
|
32
|
-
post<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
post<Result = any, Entity = any>(path: string, entity: Entity, options?: PostOptions): Promise<{
|
|
32
|
+
data: Result;
|
|
33
|
+
}>;
|
|
34
|
+
get<Result = any>(path: string, options?: GetOptions): Promise<{
|
|
35
|
+
data: Result;
|
|
36
|
+
}>;
|
|
37
|
+
put<Result = any, Entity = any>(path: string, entity: Entity, options?: PutOptions): Promise<{
|
|
38
|
+
data: Result;
|
|
39
|
+
}>;
|
|
40
|
+
delete(path: string, query?: any): Promise<void>;
|
|
36
41
|
emitWarning(warning: string): void;
|
|
37
|
-
private
|
|
42
|
+
private handleFetchError;
|
|
38
43
|
}
|
package/lib/workos.js
CHANGED
|
@@ -8,12 +8,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
-
};
|
|
14
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
12
|
exports.WorkOS = void 0;
|
|
16
|
-
const axios_1 = __importDefault(require("axios"));
|
|
17
13
|
const exceptions_1 = require("./common/exceptions");
|
|
18
14
|
const directory_sync_1 = require("./directory-sync/directory-sync");
|
|
19
15
|
const events_1 = require("./events/events");
|
|
@@ -27,7 +23,8 @@ const mfa_1 = require("./mfa/mfa");
|
|
|
27
23
|
const audit_logs_1 = require("./audit-logs/audit-logs");
|
|
28
24
|
const user_management_1 = require("./user-management/user-management");
|
|
29
25
|
const bad_request_exception_1 = require("./common/exceptions/bad-request.exception");
|
|
30
|
-
const
|
|
26
|
+
const fetch_client_1 = require("./common/utils/fetch-client");
|
|
27
|
+
const VERSION = '6.0.0-rc.2';
|
|
31
28
|
const DEFAULT_HOSTNAME = 'api.workos.com';
|
|
32
29
|
class WorkOS {
|
|
33
30
|
constructor(key, options = {}) {
|
|
@@ -46,7 +43,8 @@ class WorkOS {
|
|
|
46
43
|
this.events = new events_1.Events(this);
|
|
47
44
|
this.userManagement = new user_management_1.UserManagement(this);
|
|
48
45
|
if (!key) {
|
|
49
|
-
|
|
46
|
+
// process might be undefined in some environments
|
|
47
|
+
this.key = process === null || process === void 0 ? void 0 : process.env.WORKOS_API_KEY;
|
|
50
48
|
if (!this.key) {
|
|
51
49
|
throw new exceptions_1.NoApiKeyProvidedException();
|
|
52
50
|
}
|
|
@@ -61,7 +59,7 @@ class WorkOS {
|
|
|
61
59
|
if (port) {
|
|
62
60
|
this.baseURL = this.baseURL + `:${port}`;
|
|
63
61
|
}
|
|
64
|
-
this.client =
|
|
62
|
+
this.client = new fetch_client_1.FetchClient(this.baseURL, Object.assign(Object.assign({}, options.config), { headers: Object.assign(Object.assign({}, (_a = options.config) === null || _a === void 0 ? void 0 : _a.headers), { Authorization: `Bearer ${this.key}`, 'User-Agent': `workos-node/${VERSION}` }) }));
|
|
65
63
|
}
|
|
66
64
|
get version() {
|
|
67
65
|
return VERSION;
|
|
@@ -79,7 +77,7 @@ class WorkOS {
|
|
|
79
77
|
});
|
|
80
78
|
}
|
|
81
79
|
catch (error) {
|
|
82
|
-
this.
|
|
80
|
+
this.handleFetchError({ path, error });
|
|
83
81
|
throw error;
|
|
84
82
|
}
|
|
85
83
|
});
|
|
@@ -91,14 +89,12 @@ class WorkOS {
|
|
|
91
89
|
return yield this.client.get(path, {
|
|
92
90
|
params: options.query,
|
|
93
91
|
headers: accessToken
|
|
94
|
-
? {
|
|
95
|
-
Authorization: `Bearer ${accessToken}`,
|
|
96
|
-
}
|
|
92
|
+
? { Authorization: `Bearer ${accessToken}` }
|
|
97
93
|
: undefined,
|
|
98
94
|
});
|
|
99
95
|
}
|
|
100
96
|
catch (error) {
|
|
101
|
-
this.
|
|
97
|
+
this.handleFetchError({ path, error });
|
|
102
98
|
throw error;
|
|
103
99
|
}
|
|
104
100
|
});
|
|
@@ -116,7 +112,7 @@ class WorkOS {
|
|
|
116
112
|
});
|
|
117
113
|
}
|
|
118
114
|
catch (error) {
|
|
119
|
-
this.
|
|
115
|
+
this.handleFetchError({ path, error });
|
|
120
116
|
throw error;
|
|
121
117
|
}
|
|
122
118
|
});
|
|
@@ -124,35 +120,36 @@ class WorkOS {
|
|
|
124
120
|
delete(path, query) {
|
|
125
121
|
return __awaiter(this, void 0, void 0, function* () {
|
|
126
122
|
try {
|
|
127
|
-
|
|
123
|
+
yield this.client.delete(path, {
|
|
128
124
|
params: query,
|
|
129
125
|
});
|
|
130
126
|
}
|
|
131
127
|
catch (error) {
|
|
132
|
-
this.
|
|
128
|
+
this.handleFetchError({ path, error });
|
|
133
129
|
throw error;
|
|
134
130
|
}
|
|
135
131
|
});
|
|
136
132
|
}
|
|
137
133
|
emitWarning(warning) {
|
|
138
|
-
|
|
134
|
+
// process might be undefined in some environments
|
|
135
|
+
if (typeof (process === null || process === void 0 ? void 0 : process.emitWarning) !== 'function') {
|
|
139
136
|
// tslint:disable:no-console
|
|
140
137
|
return console.warn(`WorkOS: ${warning}`);
|
|
141
138
|
}
|
|
142
139
|
return process.emitWarning(warning, 'WorkOS');
|
|
143
140
|
}
|
|
144
|
-
|
|
141
|
+
handleFetchError({ path, error }) {
|
|
142
|
+
var _a;
|
|
145
143
|
const { response } = error;
|
|
146
144
|
if (response) {
|
|
147
145
|
const { status, data, headers } = response;
|
|
148
|
-
const requestID = headers
|
|
146
|
+
const requestID = (_a = headers.get('X-Request-ID')) !== null && _a !== void 0 ? _a : '';
|
|
149
147
|
const { code, error_description: errorDescription, error, errors, message, } = data;
|
|
150
148
|
switch (status) {
|
|
151
149
|
case 401: {
|
|
152
150
|
throw new exceptions_1.UnauthorizedException(requestID);
|
|
153
151
|
}
|
|
154
152
|
case 422: {
|
|
155
|
-
const { errors } = data;
|
|
156
153
|
throw new exceptions_1.UnprocessableEntityException({
|
|
157
154
|
code,
|
|
158
155
|
errors,
|
package/lib/workos.spec.js
CHANGED
|
@@ -12,13 +12,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const jest_fetch_mock_1 = __importDefault(require("jest-fetch-mock"));
|
|
16
|
+
const test_utils_1 = require("./common/utils/test-utils");
|
|
17
17
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
18
18
|
const exceptions_1 = require("./common/exceptions");
|
|
19
19
|
const workos_1 = require("./workos");
|
|
20
|
-
const mock = new axios_mock_adapter_1.default(axios_1.default);
|
|
21
20
|
describe('WorkOS', () => {
|
|
21
|
+
beforeEach(() => jest_fetch_mock_1.default.resetMocks());
|
|
22
22
|
describe('constructor', () => {
|
|
23
23
|
const OLD_ENV = process.env;
|
|
24
24
|
beforeEach(() => {
|
|
@@ -66,18 +66,18 @@ describe('WorkOS', () => {
|
|
|
66
66
|
expect(workos.baseURL).toEqual('https://localhost:4000');
|
|
67
67
|
});
|
|
68
68
|
});
|
|
69
|
-
describe('when the `
|
|
70
|
-
it('applies the configuration to the
|
|
71
|
-
|
|
69
|
+
describe('when the `config` option is provided', () => {
|
|
70
|
+
it('applies the configuration to the fetch client', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
71
|
+
(0, test_utils_1.fetchOnce)('{}', { headers: { 'X-Request-ID': 'a-request-id' } });
|
|
72
72
|
const workos = new workos_1.WorkOS('sk_test', {
|
|
73
|
-
|
|
73
|
+
config: {
|
|
74
74
|
headers: {
|
|
75
75
|
'X-My-Custom-Header': 'Hey there!',
|
|
76
76
|
},
|
|
77
77
|
},
|
|
78
78
|
});
|
|
79
79
|
yield workos.post('/somewhere', {});
|
|
80
|
-
expect(
|
|
80
|
+
expect((0, test_utils_1.fetchHeaders)()).toMatchObject({
|
|
81
81
|
'X-My-Custom-Header': 'Hey there!',
|
|
82
82
|
});
|
|
83
83
|
}));
|
|
@@ -96,9 +96,7 @@ describe('WorkOS', () => {
|
|
|
96
96
|
describe('when the api responds with a 404', () => {
|
|
97
97
|
it('throws a NotFoundException', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
98
98
|
const message = 'Not Found';
|
|
99
|
-
|
|
100
|
-
message,
|
|
101
|
-
}, { 'X-Request-ID': 'a-request-id' });
|
|
99
|
+
(0, test_utils_1.fetchOnce)({ message }, { status: 404, headers: { 'X-Request-ID': 'a-request-id' } });
|
|
102
100
|
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
|
|
103
101
|
yield expect(workos.post('/path', {})).rejects.toStrictEqual(new exceptions_1.NotFoundException({
|
|
104
102
|
message,
|
|
@@ -109,10 +107,7 @@ describe('WorkOS', () => {
|
|
|
109
107
|
it('preserves the error code, status, and message from the underlying response', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
110
108
|
const message = 'The thing you are looking for is not here.';
|
|
111
109
|
const code = 'thing-not-found';
|
|
112
|
-
|
|
113
|
-
code,
|
|
114
|
-
message,
|
|
115
|
-
}, { 'X-Request-ID': 'a-request-id' });
|
|
110
|
+
(0, test_utils_1.fetchOnce)({ code, message }, { status: 404, headers: { 'X-Request-ID': 'a-request-id' } });
|
|
116
111
|
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
|
|
117
112
|
yield expect(workos.post('/path', {})).rejects.toMatchObject({
|
|
118
113
|
code,
|
|
@@ -123,9 +118,7 @@ describe('WorkOS', () => {
|
|
|
123
118
|
it('includes the path in the message if there is no message in the response', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
124
119
|
const code = 'thing-not-found';
|
|
125
120
|
const path = '/path/to/thing/that-aint-there';
|
|
126
|
-
|
|
127
|
-
code,
|
|
128
|
-
}, { 'X-Request-ID': 'a-request-id' });
|
|
121
|
+
(0, test_utils_1.fetchOnce)({ code }, { status: 404, headers: { 'X-Request-ID': 'a-request-id' } });
|
|
129
122
|
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
|
|
130
123
|
yield expect(workos.post(path, {})).rejects.toMatchObject({
|
|
131
124
|
code,
|
|
@@ -136,8 +129,9 @@ describe('WorkOS', () => {
|
|
|
136
129
|
});
|
|
137
130
|
describe('when the api responds with a 500 and no error/error_description', () => {
|
|
138
131
|
it('throws an GenericServerException', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
139
|
-
|
|
140
|
-
|
|
132
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
133
|
+
status: 500,
|
|
134
|
+
headers: { 'X-Request-ID': 'a-request-id' },
|
|
141
135
|
});
|
|
142
136
|
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
|
|
143
137
|
yield expect(workos.post('/path', {})).rejects.toStrictEqual(new exceptions_1.GenericServerException(500, undefined, {}, 'a-request-id'));
|
|
@@ -145,8 +139,9 @@ describe('WorkOS', () => {
|
|
|
145
139
|
});
|
|
146
140
|
describe('when the api responds with a 400 and an error/error_description', () => {
|
|
147
141
|
it('throws an OauthException', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
148
|
-
|
|
149
|
-
|
|
142
|
+
(0, test_utils_1.fetchOnce)({ error: 'error', error_description: 'error description' }, {
|
|
143
|
+
status: 400,
|
|
144
|
+
headers: { 'X-Request-ID': 'a-request-id' },
|
|
150
145
|
});
|
|
151
146
|
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
|
|
152
147
|
yield expect(workos.post('/path', {})).rejects.toStrictEqual(new exceptions_1.OauthException(400, 'a-request-id', 'error', 'error description', { error: 'error', error_description: 'error description' }));
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "6.0.0-rc.2",
|
|
3
3
|
"name": "@workos-inc/node",
|
|
4
4
|
"author": "WorkOS",
|
|
5
5
|
"description": "A Node wrapper for the WorkOS API",
|
|
@@ -34,15 +34,16 @@
|
|
|
34
34
|
"prepublishOnly": "yarn run build"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"axios": "~1.6.5",
|
|
38
37
|
"pluralize": "8.0.0"
|
|
39
38
|
},
|
|
40
39
|
"devDependencies": {
|
|
40
|
+
"@peculiar/webcrypto": "^1.4.5",
|
|
41
41
|
"@types/jest": "29.5.3",
|
|
42
42
|
"@types/node": "14.18.54",
|
|
43
43
|
"@types/pluralize": "0.0.30",
|
|
44
44
|
"axios-mock-adapter": "1.21.5",
|
|
45
45
|
"jest": "29.6.2",
|
|
46
|
+
"jest-fetch-mock": "^3.0.3",
|
|
46
47
|
"prettier": "2.8.8",
|
|
47
48
|
"supertest": "6.3.3",
|
|
48
49
|
"ts-jest": "29.1.1",
|