@workos-inc/node 2.6.0 → 2.6.1

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/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # WorkOS Node.js Library
2
2
 
3
3
  ![npm](https://img.shields.io/npm/v/@workos-inc/node)
4
- [![Build Status](https://workos.semaphoreci.com/badges/workos-node/branches/master.svg?style=shields)](https://workos.semaphoreci.com/projects/workos-node)
4
+ [![Build Status](https://workos.semaphoreci.com/badges/workos-node/branches/main.svg?style=shields)](https://workos.semaphoreci.com/projects/workos-node)
5
5
 
6
6
  The WorkOS library for Node.js provides convenient access to the WorkOS API from applications written in server-side JavaScript.
7
7
 
@@ -1,8 +1,14 @@
1
1
  import { UnprocessableEntityError } from '../interfaces';
2
2
  export declare class UnprocessableEntityException extends Error {
3
- readonly requestID: string;
4
3
  readonly status: number;
5
4
  readonly name: string;
6
5
  readonly message: string;
7
- constructor(errors: UnprocessableEntityError[], requestID: string);
6
+ readonly code?: string;
7
+ readonly requestID: string;
8
+ constructor({ code, errors, message, requestID, }: {
9
+ code?: string;
10
+ errors?: UnprocessableEntityError[];
11
+ message?: string;
12
+ requestID: string;
13
+ });
8
14
  }
@@ -6,15 +6,24 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.UnprocessableEntityException = void 0;
7
7
  const pluralize_1 = __importDefault(require("pluralize"));
8
8
  class UnprocessableEntityException extends Error {
9
- constructor(errors, requestID) {
9
+ constructor({ code, errors, message, requestID, }) {
10
10
  super();
11
- this.requestID = requestID;
12
11
  this.status = 422;
13
12
  this.name = 'UnprocessableEntityException';
14
- const requirement = (0, pluralize_1.default)('requirement', errors.length);
15
- this.message = `The following ${requirement} must be met:\n`;
16
- for (const { code } of errors) {
17
- this.message = this.message.concat(`\t${code}\n`);
13
+ this.message = 'Unprocessable entity';
14
+ this.requestID = requestID;
15
+ if (message) {
16
+ this.message = message;
17
+ }
18
+ if (code) {
19
+ this.code = code;
20
+ }
21
+ if (errors) {
22
+ const requirement = (0, pluralize_1.default)('requirement', errors.length);
23
+ this.message = `The following ${requirement} must be met:\n`;
24
+ for (const { code } of errors) {
25
+ this.message = this.message.concat(`\t${code}\n`);
26
+ }
18
27
  }
19
28
  }
20
29
  }
@@ -1,10 +1,5 @@
1
1
  import { Challenge } from './challenge.interface';
2
- export interface VerifyResponseSuccess {
2
+ export interface VerifyResponse {
3
3
  challenge: Challenge;
4
4
  valid: boolean;
5
5
  }
6
- export interface VerifyResponseError {
7
- code: string;
8
- message: string;
9
- }
10
- export declare type VerifyResponse = VerifyResponseSuccess | VerifyResponseError;
@@ -14,6 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  const axios_1 = __importDefault(require("axios"));
16
16
  const axios_mock_adapter_1 = __importDefault(require("axios-mock-adapter"));
17
+ const exceptions_1 = require("../common/exceptions");
17
18
  const workos_1 = require("../workos");
18
19
  describe('MFA', () => {
19
20
  describe('getFactor', () => {
@@ -132,6 +133,24 @@ describe('MFA', () => {
132
133
  }
133
134
  `);
134
135
  }));
136
+ describe('when phone number is invalid', () => {
137
+ it('throws an exception', () => __awaiter(void 0, void 0, void 0, function* () {
138
+ const mock = new axios_mock_adapter_1.default(axios_1.default);
139
+ mock.onPost('/auth/factors/enroll').reply(422, {
140
+ message: `Phone number is invalid: 'foo'`,
141
+ code: 'invalid_phone_number',
142
+ }, {
143
+ 'X-Request-ID': 'req_123',
144
+ });
145
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', {
146
+ apiHostname: 'api.workos.dev',
147
+ });
148
+ yield expect(workos.mfa.enrollFactor({
149
+ type: 'sms',
150
+ phoneNumber: 'foo',
151
+ })).rejects.toThrow(exceptions_1.UnprocessableEntityException);
152
+ }));
153
+ });
135
154
  });
136
155
  });
137
156
  describe('challengeFactor', () => {
@@ -252,5 +271,79 @@ describe('MFA', () => {
252
271
  `);
253
272
  }));
254
273
  });
274
+ describe('when the challenge has been previously verified', () => {
275
+ it('throws an exception', () => __awaiter(void 0, void 0, void 0, function* () {
276
+ const mock = new axios_mock_adapter_1.default(axios_1.default);
277
+ mock
278
+ .onPost('/auth/factors/verify', {
279
+ authentication_challenge_id: 'auth_challenge_1234',
280
+ code: '12345',
281
+ })
282
+ .reply(422, {
283
+ message: `The authentication challenge '12345' has already been verified.`,
284
+ code: 'authentication_challenge_previously_verified',
285
+ }, {
286
+ 'X-Request-ID': 'req_123',
287
+ });
288
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', {
289
+ apiHostname: 'api.workos.dev',
290
+ });
291
+ yield expect(workos.mfa.verifyFactor({
292
+ authenticationChallengeId: 'auth_challenge_1234',
293
+ code: '12345',
294
+ })).rejects.toThrow(exceptions_1.UnprocessableEntityException);
295
+ }));
296
+ });
297
+ describe('when the challenge has expired', () => {
298
+ it('throws an exception', () => __awaiter(void 0, void 0, void 0, function* () {
299
+ const mock = new axios_mock_adapter_1.default(axios_1.default);
300
+ mock
301
+ .onPost('/auth/factors/verify', {
302
+ authentication_challenge_id: 'auth_challenge_1234',
303
+ code: '12345',
304
+ })
305
+ .reply(422, {
306
+ message: `The authentication challenge '12345' has expired.`,
307
+ code: 'authentication_challenge_expired',
308
+ }, {
309
+ 'X-Request-ID': 'req_123',
310
+ });
311
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', {
312
+ apiHostname: 'api.workos.dev',
313
+ });
314
+ yield expect(workos.mfa.verifyFactor({
315
+ authenticationChallengeId: 'auth_challenge_1234',
316
+ code: '12345',
317
+ })).rejects.toThrow(exceptions_1.UnprocessableEntityException);
318
+ }));
319
+ it('exception has code', () => __awaiter(void 0, void 0, void 0, function* () {
320
+ const mock = new axios_mock_adapter_1.default(axios_1.default);
321
+ mock
322
+ .onPost('/auth/factors/verify', {
323
+ authentication_challenge_id: 'auth_challenge_1234',
324
+ code: '12345',
325
+ })
326
+ .reply(422, {
327
+ message: `The authentication challenge '12345' has expired.`,
328
+ code: 'authentication_challenge_expired',
329
+ }, {
330
+ 'X-Request-ID': 'req_123',
331
+ });
332
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU', {
333
+ apiHostname: 'api.workos.dev',
334
+ });
335
+ try {
336
+ yield workos.mfa.verifyFactor({
337
+ authenticationChallengeId: 'auth_challenge_1234',
338
+ code: '12345',
339
+ });
340
+ }
341
+ catch (error) {
342
+ expect(error).toMatchObject({
343
+ code: 'authentication_challenge_expired',
344
+ });
345
+ }
346
+ }));
347
+ });
255
348
  });
256
349
  });
package/lib/workos.js CHANGED
@@ -23,7 +23,7 @@ const portal_1 = require("./portal/portal");
23
23
  const sso_1 = require("./sso/sso");
24
24
  const webhooks_1 = require("./webhooks/webhooks");
25
25
  const mfa_1 = require("./mfa/mfa");
26
- const VERSION = '2.6.0';
26
+ const VERSION = '2.6.1';
27
27
  const DEFAULT_HOSTNAME = 'api.workos.com';
28
28
  class WorkOS {
29
29
  constructor(key, options = {}) {
@@ -78,14 +78,19 @@ class WorkOS {
78
78
  if (response) {
79
79
  const { status, data, headers } = response;
80
80
  const requestID = headers['X-Request-ID'];
81
- const { error, error_description: errorDescription } = data;
81
+ const { code, error_description: errorDescription, error, message, } = data;
82
82
  switch (status) {
83
83
  case 401: {
84
84
  throw new exceptions_1.UnauthorizedException(requestID);
85
85
  }
86
86
  case 422: {
87
87
  const { errors } = data;
88
- throw new exceptions_1.UnprocessableEntityException(errors, requestID);
88
+ throw new exceptions_1.UnprocessableEntityException({
89
+ code,
90
+ errors,
91
+ message,
92
+ requestID,
93
+ });
89
94
  }
90
95
  case 404: {
91
96
  throw new exceptions_1.NotFoundException(path, requestID);
@@ -122,14 +127,19 @@ class WorkOS {
122
127
  if (response) {
123
128
  const { status, data, headers } = response;
124
129
  const requestID = headers['X-Request-ID'];
125
- const { error, error_description: errorDescription } = data;
130
+ const { code, error_description: errorDescription, error, message, } = data;
126
131
  switch (status) {
127
132
  case 401: {
128
133
  throw new exceptions_1.UnauthorizedException(requestID);
129
134
  }
130
135
  case 422: {
131
136
  const { errors } = data;
132
- throw new exceptions_1.UnprocessableEntityException(errors, requestID);
137
+ throw new exceptions_1.UnprocessableEntityException({
138
+ code,
139
+ errors,
140
+ message,
141
+ requestID,
142
+ });
133
143
  }
134
144
  case 404: {
135
145
  throw new exceptions_1.NotFoundException(path, requestID);
@@ -165,14 +175,19 @@ class WorkOS {
165
175
  if (response) {
166
176
  const { status, data, headers } = response;
167
177
  const requestID = headers['X-Request-ID'];
168
- const { error, error_description: errorDescription } = data;
178
+ const { code, error_description: errorDescription, error, message, } = data;
169
179
  switch (status) {
170
180
  case 401: {
171
181
  throw new exceptions_1.UnauthorizedException(requestID);
172
182
  }
173
183
  case 422: {
174
184
  const { errors } = data;
175
- throw new exceptions_1.UnprocessableEntityException(errors, requestID);
185
+ throw new exceptions_1.UnprocessableEntityException({
186
+ code,
187
+ errors,
188
+ message,
189
+ requestID,
190
+ });
176
191
  }
177
192
  case 404: {
178
193
  throw new exceptions_1.NotFoundException(path, requestID);
@@ -203,14 +218,19 @@ class WorkOS {
203
218
  if (response) {
204
219
  const { status, data, headers } = response;
205
220
  const requestID = headers['X-Request-ID'];
206
- const { error, error_description: errorDescription } = data;
221
+ const { code, error_description: errorDescription, error, message, } = data;
207
222
  switch (status) {
208
223
  case 401: {
209
224
  throw new exceptions_1.UnauthorizedException(requestID);
210
225
  }
211
226
  case 422: {
212
227
  const { errors } = data;
213
- throw new exceptions_1.UnprocessableEntityException(errors, requestID);
228
+ throw new exceptions_1.UnprocessableEntityException({
229
+ code,
230
+ errors,
231
+ message,
232
+ requestID,
233
+ });
214
234
  }
215
235
  case 404: {
216
236
  throw new exceptions_1.NotFoundException(path, requestID);
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.6.0",
2
+ "version": "2.6.1",
3
3
  "name": "@workos-inc/node",
4
4
  "author": "WorkOS",
5
5
  "description": "A Node wrapper for the WorkOS API",