@workos-inc/node 7.29.1 → 7.30.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.
Files changed (36) hide show
  1. package/lib/common/net/fetch-client.d.ts +2 -0
  2. package/lib/common/net/fetch-client.js +64 -4
  3. package/lib/common/net/http-client.d.ts +6 -0
  4. package/lib/common/net/http-client.js +11 -0
  5. package/lib/common/net/node-client.d.ts +2 -0
  6. package/lib/common/net/node-client.js +87 -4
  7. package/lib/fga/fga.spec.js +609 -0
  8. package/lib/organizations/fixtures/clear-stripe-customer-id.json +13 -0
  9. package/lib/organizations/fixtures/get-stripe-customer-id.json +17 -0
  10. package/lib/organizations/fixtures/set-stripe-customer-id-disabled.json +4 -0
  11. package/lib/organizations/fixtures/set-stripe-customer-id.json +14 -0
  12. package/lib/organizations/interfaces/organization.interface.d.ts +2 -0
  13. package/lib/organizations/interfaces/set-stripe-customer-id-options.interface.d.ts +4 -0
  14. package/lib/organizations/interfaces/set-stripe-customer-id-options.interface.js +2 -0
  15. package/lib/organizations/interfaces/update-organization-options.interface.d.ts +2 -0
  16. package/lib/organizations/organizations.d.ts +3 -0
  17. package/lib/organizations/organizations.js +12 -0
  18. package/lib/organizations/organizations.spec.js +77 -0
  19. package/lib/organizations/serializers/organization.serializer.js +3 -9
  20. package/lib/organizations/serializers/update-organization-options.serializer.js +1 -0
  21. package/lib/user-management/interfaces/authenticate-with-session-cookie.interface.d.ts +2 -0
  22. package/lib/user-management/session.js +2 -1
  23. package/lib/user-management/session.spec.js +2 -1
  24. package/lib/user-management/user-management.js +2 -1
  25. package/lib/user-management/user-management.spec.js +2 -1
  26. package/lib/widgets/fixtures/get-token-error.json +5 -0
  27. package/lib/widgets/fixtures/token.json +3 -0
  28. package/lib/widgets/interfaces/get-token.d.ts +19 -0
  29. package/lib/widgets/interfaces/get-token.js +13 -0
  30. package/lib/widgets/widgets.d.ts +7 -0
  31. package/lib/widgets/widgets.js +25 -0
  32. package/lib/widgets/widgets.spec.d.ts +1 -0
  33. package/lib/widgets/widgets.spec.js +49 -0
  34. package/lib/workos.d.ts +2 -0
  35. package/lib/workos.js +4 -2
  36. package/package.json +1 -1
@@ -12,6 +12,8 @@ export declare class FetchHttpClient extends HttpClient implements HttpClientInt
12
12
  put<Entity = any>(path: string, entity: Entity, options: RequestOptions): Promise<HttpClientResponseInterface>;
13
13
  delete(path: string, options: RequestOptions): Promise<HttpClientResponseInterface>;
14
14
  private fetchRequest;
15
+ private fetchRequestWithRetry;
16
+ private shouldRetryRequest;
15
17
  }
16
18
  export declare class FetchHttpClientResponse extends HttpClientResponse implements HttpClientResponseInterface {
17
19
  _res: Response;
@@ -32,25 +32,45 @@ class FetchHttpClient extends http_client_1.HttpClient {
32
32
  get(path, options) {
33
33
  return __awaiter(this, void 0, void 0, function* () {
34
34
  const resourceURL = http_client_1.HttpClient.getResourceURL(this.baseURL, path, options.params);
35
- return yield this.fetchRequest(resourceURL, 'GET', null, options.headers);
35
+ if (path.startsWith('/fga/')) {
36
+ return yield this.fetchRequestWithRetry(resourceURL, 'GET', null, options.headers);
37
+ }
38
+ else {
39
+ return yield this.fetchRequest(resourceURL, 'GET', null, options.headers);
40
+ }
36
41
  });
37
42
  }
38
43
  post(path, entity, options) {
39
44
  return __awaiter(this, void 0, void 0, function* () {
40
45
  const resourceURL = http_client_1.HttpClient.getResourceURL(this.baseURL, path, options.params);
41
- return yield this.fetchRequest(resourceURL, 'POST', http_client_1.HttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
46
+ if (path.startsWith('/fga/')) {
47
+ return yield this.fetchRequestWithRetry(resourceURL, 'POST', http_client_1.HttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
48
+ }
49
+ else {
50
+ return yield this.fetchRequest(resourceURL, 'POST', http_client_1.HttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
51
+ }
42
52
  });
43
53
  }
44
54
  put(path, entity, options) {
45
55
  return __awaiter(this, void 0, void 0, function* () {
46
56
  const resourceURL = http_client_1.HttpClient.getResourceURL(this.baseURL, path, options.params);
47
- return yield this.fetchRequest(resourceURL, 'PUT', http_client_1.HttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
57
+ if (path.startsWith('/fga/')) {
58
+ return yield this.fetchRequestWithRetry(resourceURL, 'PUT', http_client_1.HttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
59
+ }
60
+ else {
61
+ return yield this.fetchRequest(resourceURL, 'PUT', http_client_1.HttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
62
+ }
48
63
  });
49
64
  }
50
65
  delete(path, options) {
51
66
  return __awaiter(this, void 0, void 0, function* () {
52
67
  const resourceURL = http_client_1.HttpClient.getResourceURL(this.baseURL, path, options.params);
53
- return yield this.fetchRequest(resourceURL, 'DELETE', null, options.headers);
68
+ if (path.startsWith('/fga/')) {
69
+ return yield this.fetchRequestWithRetry(resourceURL, 'DELETE', null, options.headers);
70
+ }
71
+ else {
72
+ return yield this.fetchRequest(resourceURL, 'DELETE', null, options.headers);
73
+ }
54
74
  });
55
75
  }
56
76
  fetchRequest(url, method, body, headers) {
@@ -80,6 +100,46 @@ class FetchHttpClient extends http_client_1.HttpClient {
80
100
  return new FetchHttpClientResponse(res);
81
101
  });
82
102
  }
103
+ fetchRequestWithRetry(url, method, body, headers) {
104
+ return __awaiter(this, void 0, void 0, function* () {
105
+ let response;
106
+ let retryAttempts = 1;
107
+ const makeRequest = () => __awaiter(this, void 0, void 0, function* () {
108
+ let requestError = null;
109
+ try {
110
+ response = yield this.fetchRequest(url, method, body, headers);
111
+ }
112
+ catch (e) {
113
+ requestError = e;
114
+ }
115
+ if (this.shouldRetryRequest(requestError, retryAttempts)) {
116
+ retryAttempts++;
117
+ yield this.sleep(retryAttempts);
118
+ return makeRequest();
119
+ }
120
+ if (requestError != null) {
121
+ throw requestError;
122
+ }
123
+ return response;
124
+ });
125
+ return makeRequest();
126
+ });
127
+ }
128
+ shouldRetryRequest(requestError, retryAttempt) {
129
+ if (retryAttempt > this.MAX_RETRY_ATTEMPTS) {
130
+ return false;
131
+ }
132
+ if (requestError != null) {
133
+ if (requestError instanceof TypeError) {
134
+ return true;
135
+ }
136
+ if (requestError instanceof http_client_1.HttpClientError &&
137
+ this.RETRY_STATUS_CODES.includes(requestError.response.status)) {
138
+ return true;
139
+ }
140
+ }
141
+ return false;
142
+ }
83
143
  }
84
144
  exports.FetchHttpClient = FetchHttpClient;
85
145
  // tslint:disable-next-line
@@ -2,6 +2,10 @@ import { HttpClientInterface, HttpClientResponseInterface, RequestHeaders, Reque
2
2
  export declare abstract class HttpClient implements HttpClientInterface {
3
3
  readonly baseURL: string;
4
4
  readonly options?: RequestInit | undefined;
5
+ readonly MAX_RETRY_ATTEMPTS = 3;
6
+ readonly BACKOFF_MULTIPLIER = 1.5;
7
+ readonly MINIMUM_SLEEP_TIME_IN_MILLISECONDS = 500;
8
+ readonly RETRY_STATUS_CODES: number[];
5
9
  constructor(baseURL: string, options?: RequestInit | undefined);
6
10
  /** The HTTP client name used for diagnostics */
7
11
  getClientName(): string;
@@ -14,6 +18,8 @@ export declare abstract class HttpClient implements HttpClientInterface {
14
18
  static getQueryString(queryObj?: Record<string, any>): string | undefined;
15
19
  static getContentTypeHeader(entity: any): RequestHeaders | undefined;
16
20
  static getBody(entity: any): BodyInit | null | undefined;
21
+ private getSleepTimeInMilliseconds;
22
+ sleep: (retryAttempt: number) => Promise<unknown>;
17
23
  }
18
24
  export declare abstract class HttpClientResponse implements HttpClientResponseInterface {
19
25
  _statusCode: number;
@@ -5,6 +5,11 @@ class HttpClient {
5
5
  constructor(baseURL, options) {
6
6
  this.baseURL = baseURL;
7
7
  this.options = options;
8
+ this.MAX_RETRY_ATTEMPTS = 3;
9
+ this.BACKOFF_MULTIPLIER = 1.5;
10
+ this.MINIMUM_SLEEP_TIME_IN_MILLISECONDS = 500;
11
+ this.RETRY_STATUS_CODES = [500, 502, 504];
12
+ this.sleep = (retryAttempt) => new Promise((resolve) => setTimeout(resolve, this.getSleepTimeInMilliseconds(retryAttempt)));
8
13
  }
9
14
  /** The HTTP client name used for diagnostics */
10
15
  getClientName() {
@@ -47,6 +52,12 @@ class HttpClient {
47
52
  }
48
53
  return JSON.stringify(entity);
49
54
  }
55
+ getSleepTimeInMilliseconds(retryAttempt) {
56
+ const sleepTime = this.MINIMUM_SLEEP_TIME_IN_MILLISECONDS *
57
+ Math.pow(this.BACKOFF_MULTIPLIER, retryAttempt);
58
+ const jitter = Math.random() + 0.5;
59
+ return sleepTime * jitter;
60
+ }
50
61
  }
51
62
  exports.HttpClient = HttpClient;
52
63
  // tslint:disable-next-line
@@ -14,6 +14,8 @@ export declare class NodeHttpClient extends HttpClient implements HttpClientInte
14
14
  put<Entity = any>(path: string, entity: Entity, options: RequestOptions): Promise<HttpClientResponseInterface>;
15
15
  delete(path: string, options: RequestOptions): Promise<HttpClientResponseInterface>;
16
16
  private nodeRequest;
17
+ private nodeRequestWithRetry;
18
+ private shouldRetryRequest;
17
19
  }
18
20
  export declare class NodeHttpClientResponse extends HttpClientResponse implements HttpClientResponseInterface {
19
21
  _res: http_.IncomingMessage;
@@ -67,25 +67,45 @@ class NodeHttpClient extends http_client_1.HttpClient {
67
67
  get(path, options) {
68
68
  return __awaiter(this, void 0, void 0, function* () {
69
69
  const resourceURL = http_client_1.HttpClient.getResourceURL(this.baseURL, path, options.params);
70
- return yield this.nodeRequest(resourceURL, 'GET', null, options.headers);
70
+ if (path.startsWith('/fga/')) {
71
+ return yield this.nodeRequestWithRetry(resourceURL, 'GET', null, options.headers);
72
+ }
73
+ else {
74
+ return yield this.nodeRequest(resourceURL, 'GET', null, options.headers);
75
+ }
71
76
  });
72
77
  }
73
78
  post(path, entity, options) {
74
79
  return __awaiter(this, void 0, void 0, function* () {
75
80
  const resourceURL = http_client_1.HttpClient.getResourceURL(this.baseURL, path, options.params);
76
- return yield this.nodeRequest(resourceURL, 'POST', NodeHttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
81
+ if (path.startsWith('/fga/')) {
82
+ return yield this.nodeRequestWithRetry(resourceURL, 'POST', NodeHttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
83
+ }
84
+ else {
85
+ return yield this.nodeRequest(resourceURL, 'POST', NodeHttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
86
+ }
77
87
  });
78
88
  }
79
89
  put(path, entity, options) {
80
90
  return __awaiter(this, void 0, void 0, function* () {
81
91
  const resourceURL = http_client_1.HttpClient.getResourceURL(this.baseURL, path, options.params);
82
- return yield this.nodeRequest(resourceURL, 'PUT', NodeHttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
92
+ if (path.startsWith('/fga/')) {
93
+ return yield this.nodeRequestWithRetry(resourceURL, 'PUT', NodeHttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
94
+ }
95
+ else {
96
+ return yield this.nodeRequest(resourceURL, 'PUT', NodeHttpClient.getBody(entity), Object.assign(Object.assign({}, http_client_1.HttpClient.getContentTypeHeader(entity)), options.headers));
97
+ }
83
98
  });
84
99
  }
85
100
  delete(path, options) {
86
101
  return __awaiter(this, void 0, void 0, function* () {
87
102
  const resourceURL = http_client_1.HttpClient.getResourceURL(this.baseURL, path, options.params);
88
- return yield this.nodeRequest(resourceURL, 'DELETE', null, options.headers);
103
+ if (path.startsWith('/fga/')) {
104
+ return yield this.nodeRequestWithRetry(resourceURL, 'DELETE', null, options.headers);
105
+ }
106
+ else {
107
+ return yield this.nodeRequest(resourceURL, 'DELETE', null, options.headers);
108
+ }
89
109
  });
90
110
  }
91
111
  nodeRequest(url, method, body, headers) {
@@ -126,6 +146,69 @@ class NodeHttpClient extends http_client_1.HttpClient {
126
146
  });
127
147
  });
128
148
  }
149
+ nodeRequestWithRetry(url, method, body, headers) {
150
+ var _a, _b;
151
+ return __awaiter(this, void 0, void 0, function* () {
152
+ const isSecureConnection = url.startsWith('https');
153
+ const agent = isSecureConnection ? this.httpsAgent : this.httpAgent;
154
+ const lib = isSecureConnection ? https : http;
155
+ const { 'User-Agent': userAgent } = (_a = this.options) === null || _a === void 0 ? void 0 : _a.headers;
156
+ const options = {
157
+ method,
158
+ headers: Object.assign(Object.assign(Object.assign({ Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, (_b = this.options) === null || _b === void 0 ? void 0 : _b.headers), headers), { 'User-Agent': this.addClientToUserAgent(userAgent.toString()) }),
159
+ agent,
160
+ };
161
+ let retryAttempts = 1;
162
+ const makeRequest = () => __awaiter(this, void 0, void 0, function* () {
163
+ return new Promise((resolve, reject) => {
164
+ const req = lib.request(url, options, (res) => __awaiter(this, void 0, void 0, function* () {
165
+ const clientResponse = new NodeHttpClientResponse(res);
166
+ if (this.shouldRetryRequest(res, retryAttempts)) {
167
+ retryAttempts++;
168
+ yield this.sleep(retryAttempts);
169
+ return makeRequest().then(resolve).catch(reject);
170
+ }
171
+ if (res.statusCode &&
172
+ (res.statusCode < 200 || res.statusCode > 299)) {
173
+ reject(new http_client_1.HttpClientError({
174
+ message: res.statusMessage,
175
+ response: {
176
+ status: res.statusCode,
177
+ headers: res.headers,
178
+ data: yield clientResponse.toJSON(),
179
+ },
180
+ }));
181
+ }
182
+ resolve(new NodeHttpClientResponse(res));
183
+ }));
184
+ req.on('error', (err) => __awaiter(this, void 0, void 0, function* () {
185
+ if (err != null && err instanceof TypeError) {
186
+ retryAttempts++;
187
+ yield this.sleep(retryAttempts);
188
+ return makeRequest().then(resolve).catch(reject);
189
+ }
190
+ reject(new Error(err.message));
191
+ }));
192
+ if (body) {
193
+ req.setHeader('Content-Length', Buffer.byteLength(body));
194
+ req.write(body);
195
+ }
196
+ req.end();
197
+ });
198
+ });
199
+ return makeRequest();
200
+ });
201
+ }
202
+ shouldRetryRequest(response, retryAttempt) {
203
+ if (retryAttempt > this.MAX_RETRY_ATTEMPTS) {
204
+ return false;
205
+ }
206
+ if (response != null &&
207
+ this.RETRY_STATUS_CODES.includes(response.statusCode)) {
208
+ return true;
209
+ }
210
+ return false;
211
+ }
129
212
  }
130
213
  exports.NodeHttpClient = NodeHttpClient;
131
214
  // tslint:disable-next-line