@workos-inc/node 7.29.1 → 7.30.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/net/fetch-client.d.ts +2 -0
- package/lib/common/net/fetch-client.js +64 -4
- package/lib/common/net/http-client.d.ts +6 -0
- package/lib/common/net/http-client.js +11 -0
- package/lib/common/net/node-client.d.ts +2 -0
- package/lib/common/net/node-client.js +86 -4
- package/lib/fga/fga.spec.js +609 -0
- package/lib/workos.js +1 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,68 @@ 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
|
+
}));
|
|
191
|
+
if (body) {
|
|
192
|
+
req.setHeader('Content-Length', Buffer.byteLength(body));
|
|
193
|
+
req.write(body);
|
|
194
|
+
}
|
|
195
|
+
req.end();
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
return makeRequest();
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
shouldRetryRequest(response, retryAttempt) {
|
|
202
|
+
if (retryAttempt > this.MAX_RETRY_ATTEMPTS) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
if (response != null &&
|
|
206
|
+
this.RETRY_STATUS_CODES.includes(response.statusCode)) {
|
|
207
|
+
return true;
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
129
211
|
}
|
|
130
212
|
exports.NodeHttpClient = NodeHttpClient;
|
|
131
213
|
// tslint:disable-next-line
|
package/lib/fga/fga.spec.js
CHANGED
|
@@ -16,6 +16,7 @@ const jest_fetch_mock_1 = __importDefault(require("jest-fetch-mock"));
|
|
|
16
16
|
const test_utils_1 = require("../common/utils/test-utils");
|
|
17
17
|
const workos_1 = require("../workos");
|
|
18
18
|
const interfaces_1 = require("./interfaces");
|
|
19
|
+
const exceptions_1 = require("../common/exceptions");
|
|
19
20
|
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
|
|
20
21
|
describe('FGA', () => {
|
|
21
22
|
beforeEach(() => jest_fetch_mock_1.default.resetMocks());
|
|
@@ -46,6 +47,60 @@ describe('FGA', () => {
|
|
|
46
47
|
isImplicit: false,
|
|
47
48
|
});
|
|
48
49
|
}));
|
|
50
|
+
it('makes check request after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
51
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
52
|
+
status: 500,
|
|
53
|
+
});
|
|
54
|
+
(0, test_utils_1.fetchOnce)({
|
|
55
|
+
result: 'authorized',
|
|
56
|
+
is_implicit: false,
|
|
57
|
+
});
|
|
58
|
+
const checkResult = yield workos.fga.check({
|
|
59
|
+
checks: [
|
|
60
|
+
{
|
|
61
|
+
resource: {
|
|
62
|
+
resourceType: 'role',
|
|
63
|
+
resourceId: 'admin',
|
|
64
|
+
},
|
|
65
|
+
relation: 'member',
|
|
66
|
+
subject: {
|
|
67
|
+
resourceType: 'user',
|
|
68
|
+
resourceId: 'user_123',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
});
|
|
73
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/check');
|
|
74
|
+
expect(checkResult).toMatchObject({
|
|
75
|
+
result: 'authorized',
|
|
76
|
+
isImplicit: false,
|
|
77
|
+
});
|
|
78
|
+
}));
|
|
79
|
+
it('fails check request after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
80
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
81
|
+
message: 'Internal Server Error',
|
|
82
|
+
}), { status: 500 });
|
|
83
|
+
try {
|
|
84
|
+
yield workos.fga.check({
|
|
85
|
+
checks: [
|
|
86
|
+
{
|
|
87
|
+
resource: {
|
|
88
|
+
resourceType: 'role',
|
|
89
|
+
resourceId: 'admin',
|
|
90
|
+
},
|
|
91
|
+
relation: 'member',
|
|
92
|
+
subject: {
|
|
93
|
+
resourceType: 'user',
|
|
94
|
+
resourceId: 'user_123',
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
catch (e) {
|
|
101
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
102
|
+
}
|
|
103
|
+
}), 8000);
|
|
49
104
|
});
|
|
50
105
|
describe('createResource', () => {
|
|
51
106
|
it('creates resource', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -65,6 +120,42 @@ describe('FGA', () => {
|
|
|
65
120
|
resourceId: 'admin',
|
|
66
121
|
});
|
|
67
122
|
}));
|
|
123
|
+
it('creates resource after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
124
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
125
|
+
status: 502,
|
|
126
|
+
});
|
|
127
|
+
(0, test_utils_1.fetchOnce)({
|
|
128
|
+
resource_type: 'role',
|
|
129
|
+
resource_id: 'admin',
|
|
130
|
+
});
|
|
131
|
+
const resource = yield workos.fga.createResource({
|
|
132
|
+
resource: {
|
|
133
|
+
resourceType: 'role',
|
|
134
|
+
resourceId: 'admin',
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/resources');
|
|
138
|
+
expect(resource).toMatchObject({
|
|
139
|
+
resourceType: 'role',
|
|
140
|
+
resourceId: 'admin',
|
|
141
|
+
});
|
|
142
|
+
}));
|
|
143
|
+
it('fails to creates resource after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
144
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
145
|
+
message: 'Internal Server Error',
|
|
146
|
+
}), { status: 500 });
|
|
147
|
+
try {
|
|
148
|
+
yield workos.fga.createResource({
|
|
149
|
+
resource: {
|
|
150
|
+
resourceType: 'role',
|
|
151
|
+
resourceId: 'admin',
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
catch (e) {
|
|
156
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
157
|
+
}
|
|
158
|
+
}), 8000);
|
|
68
159
|
it('creates resource with metadata', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
69
160
|
(0, test_utils_1.fetchOnce)({
|
|
70
161
|
resource_type: 'role',
|
|
@@ -108,6 +199,38 @@ describe('FGA', () => {
|
|
|
108
199
|
resourceId: 'admin',
|
|
109
200
|
});
|
|
110
201
|
}));
|
|
202
|
+
it('gets resource after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
203
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
204
|
+
status: 504,
|
|
205
|
+
});
|
|
206
|
+
(0, test_utils_1.fetchOnce)({
|
|
207
|
+
resource_type: 'role',
|
|
208
|
+
resource_id: 'admin',
|
|
209
|
+
});
|
|
210
|
+
const resource = yield workos.fga.getResource({
|
|
211
|
+
resourceType: 'role',
|
|
212
|
+
resourceId: 'admin',
|
|
213
|
+
});
|
|
214
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/resources/role/admin');
|
|
215
|
+
expect(resource).toMatchObject({
|
|
216
|
+
resourceType: 'role',
|
|
217
|
+
resourceId: 'admin',
|
|
218
|
+
});
|
|
219
|
+
}));
|
|
220
|
+
it('fails to get resource after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
221
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
222
|
+
message: 'Internal Server Error',
|
|
223
|
+
}), { status: 500 });
|
|
224
|
+
try {
|
|
225
|
+
yield workos.fga.getResource({
|
|
226
|
+
resourceType: 'role',
|
|
227
|
+
resourceId: 'admin',
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch (e) {
|
|
231
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
232
|
+
}
|
|
233
|
+
}), 8000);
|
|
111
234
|
});
|
|
112
235
|
describe('listResources', () => {
|
|
113
236
|
it('lists resources', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -140,6 +263,53 @@ describe('FGA', () => {
|
|
|
140
263
|
},
|
|
141
264
|
]);
|
|
142
265
|
}));
|
|
266
|
+
it('lists resources after two retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
267
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
268
|
+
status: 502,
|
|
269
|
+
});
|
|
270
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
271
|
+
status: 500,
|
|
272
|
+
});
|
|
273
|
+
(0, test_utils_1.fetchOnce)({
|
|
274
|
+
data: [
|
|
275
|
+
{
|
|
276
|
+
resource_type: 'role',
|
|
277
|
+
resource_id: 'admin',
|
|
278
|
+
},
|
|
279
|
+
{
|
|
280
|
+
resource_type: 'role',
|
|
281
|
+
resource_id: 'manager',
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
list_metadata: {
|
|
285
|
+
before: null,
|
|
286
|
+
after: null,
|
|
287
|
+
},
|
|
288
|
+
});
|
|
289
|
+
const { data: resources } = yield workos.fga.listResources();
|
|
290
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/resources');
|
|
291
|
+
expect(resources).toMatchObject([
|
|
292
|
+
{
|
|
293
|
+
resourceType: 'role',
|
|
294
|
+
resourceId: 'admin',
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
resourceType: 'role',
|
|
298
|
+
resourceId: 'manager',
|
|
299
|
+
},
|
|
300
|
+
]);
|
|
301
|
+
}));
|
|
302
|
+
it('fails to list resources after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
303
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
304
|
+
message: 'Internal Server Error',
|
|
305
|
+
}), { status: 500 });
|
|
306
|
+
try {
|
|
307
|
+
yield workos.fga.listResources();
|
|
308
|
+
}
|
|
309
|
+
catch (e) {
|
|
310
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
311
|
+
}
|
|
312
|
+
}), 8000);
|
|
143
313
|
it('sends correct params when filtering', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
144
314
|
(0, test_utils_1.fetchOnce)({
|
|
145
315
|
data: [
|
|
@@ -177,6 +347,32 @@ describe('FGA', () => {
|
|
|
177
347
|
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/resources/role/admin');
|
|
178
348
|
expect(response).toBeUndefined();
|
|
179
349
|
}));
|
|
350
|
+
it('should delete resource after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
351
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
352
|
+
status: 500,
|
|
353
|
+
});
|
|
354
|
+
(0, test_utils_1.fetchOnce)();
|
|
355
|
+
const response = yield workos.fga.deleteResource({
|
|
356
|
+
resourceType: 'role',
|
|
357
|
+
resourceId: 'admin',
|
|
358
|
+
});
|
|
359
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/resources/role/admin');
|
|
360
|
+
expect(response).toBeUndefined();
|
|
361
|
+
}));
|
|
362
|
+
it('fails to delete resource after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
363
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
364
|
+
message: 'Internal Server Error',
|
|
365
|
+
}), { status: 500 });
|
|
366
|
+
try {
|
|
367
|
+
yield workos.fga.deleteResource({
|
|
368
|
+
resourceType: 'role',
|
|
369
|
+
resourceId: 'admin',
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
catch (e) {
|
|
373
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
374
|
+
}
|
|
375
|
+
}), 8000);
|
|
180
376
|
});
|
|
181
377
|
describe('batchWriteResources', () => {
|
|
182
378
|
it('batch create resources', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -244,6 +440,110 @@ describe('FGA', () => {
|
|
|
244
440
|
},
|
|
245
441
|
]);
|
|
246
442
|
}));
|
|
443
|
+
it('batch create resources after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
444
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
445
|
+
status: 500,
|
|
446
|
+
});
|
|
447
|
+
(0, test_utils_1.fetchOnce)({
|
|
448
|
+
data: [
|
|
449
|
+
{
|
|
450
|
+
resource_type: 'role',
|
|
451
|
+
resource_id: 'admin',
|
|
452
|
+
meta: {
|
|
453
|
+
description: 'The admin role',
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
{
|
|
457
|
+
resource_type: 'role',
|
|
458
|
+
resource_id: 'manager',
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
resource_type: 'role',
|
|
462
|
+
resource_id: 'employee',
|
|
463
|
+
},
|
|
464
|
+
],
|
|
465
|
+
});
|
|
466
|
+
const createdResources = yield workos.fga.batchWriteResources({
|
|
467
|
+
op: interfaces_1.ResourceOp.Create,
|
|
468
|
+
resources: [
|
|
469
|
+
{
|
|
470
|
+
resource: {
|
|
471
|
+
resourceType: 'role',
|
|
472
|
+
resourceId: 'admin',
|
|
473
|
+
},
|
|
474
|
+
meta: {
|
|
475
|
+
description: 'The admin role',
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
resource: {
|
|
480
|
+
resourceType: 'role',
|
|
481
|
+
resourceId: 'manager',
|
|
482
|
+
},
|
|
483
|
+
},
|
|
484
|
+
{
|
|
485
|
+
resource: {
|
|
486
|
+
resourceType: 'role',
|
|
487
|
+
resourceId: 'employee',
|
|
488
|
+
},
|
|
489
|
+
},
|
|
490
|
+
],
|
|
491
|
+
});
|
|
492
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/resources/batch');
|
|
493
|
+
expect(createdResources).toMatchObject([
|
|
494
|
+
{
|
|
495
|
+
resourceType: 'role',
|
|
496
|
+
resourceId: 'admin',
|
|
497
|
+
meta: {
|
|
498
|
+
description: 'The admin role',
|
|
499
|
+
},
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
resourceType: 'role',
|
|
503
|
+
resourceId: 'manager',
|
|
504
|
+
},
|
|
505
|
+
{
|
|
506
|
+
resourceType: 'role',
|
|
507
|
+
resourceId: 'employee',
|
|
508
|
+
},
|
|
509
|
+
]);
|
|
510
|
+
}));
|
|
511
|
+
it('fails to batch create resources after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
512
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
513
|
+
message: 'Internal Server Error',
|
|
514
|
+
}), { status: 500 });
|
|
515
|
+
try {
|
|
516
|
+
yield workos.fga.batchWriteResources({
|
|
517
|
+
op: interfaces_1.ResourceOp.Create,
|
|
518
|
+
resources: [
|
|
519
|
+
{
|
|
520
|
+
resource: {
|
|
521
|
+
resourceType: 'role',
|
|
522
|
+
resourceId: 'admin',
|
|
523
|
+
},
|
|
524
|
+
meta: {
|
|
525
|
+
description: 'The admin role',
|
|
526
|
+
},
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
resource: {
|
|
530
|
+
resourceType: 'role',
|
|
531
|
+
resourceId: 'manager',
|
|
532
|
+
},
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
resource: {
|
|
536
|
+
resourceType: 'role',
|
|
537
|
+
resourceId: 'employee',
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
],
|
|
541
|
+
});
|
|
542
|
+
}
|
|
543
|
+
catch (e) {
|
|
544
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
545
|
+
}
|
|
546
|
+
}), 8000);
|
|
247
547
|
it('batch delete resources', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
248
548
|
(0, test_utils_1.fetchOnce)({
|
|
249
549
|
data: [
|
|
@@ -365,6 +665,62 @@ describe('FGA', () => {
|
|
|
365
665
|
warrantToken: 'some_token',
|
|
366
666
|
});
|
|
367
667
|
}));
|
|
668
|
+
it('should create warrant after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
669
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
670
|
+
status: 500,
|
|
671
|
+
});
|
|
672
|
+
(0, test_utils_1.fetchOnce)({
|
|
673
|
+
warrant_token: 'some_token',
|
|
674
|
+
});
|
|
675
|
+
const warrantToken = yield workos.fga.writeWarrant({
|
|
676
|
+
op: interfaces_1.WarrantOp.Create,
|
|
677
|
+
resource: {
|
|
678
|
+
resourceType: 'role',
|
|
679
|
+
resourceId: 'admin',
|
|
680
|
+
},
|
|
681
|
+
relation: 'member',
|
|
682
|
+
subject: {
|
|
683
|
+
resourceType: 'user',
|
|
684
|
+
resourceId: 'user_123',
|
|
685
|
+
},
|
|
686
|
+
});
|
|
687
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/warrants');
|
|
688
|
+
expect((0, test_utils_1.fetchBody)()).toEqual({
|
|
689
|
+
op: 'create',
|
|
690
|
+
resource_type: 'role',
|
|
691
|
+
resource_id: 'admin',
|
|
692
|
+
relation: 'member',
|
|
693
|
+
subject: {
|
|
694
|
+
resource_type: 'user',
|
|
695
|
+
resource_id: 'user_123',
|
|
696
|
+
},
|
|
697
|
+
});
|
|
698
|
+
expect(warrantToken).toMatchObject({
|
|
699
|
+
warrantToken: 'some_token',
|
|
700
|
+
});
|
|
701
|
+
}));
|
|
702
|
+
it('fails to create warrant after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
703
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
704
|
+
message: 'Internal Server Error',
|
|
705
|
+
}), { status: 500 });
|
|
706
|
+
try {
|
|
707
|
+
yield workos.fga.writeWarrant({
|
|
708
|
+
op: interfaces_1.WarrantOp.Create,
|
|
709
|
+
resource: {
|
|
710
|
+
resourceType: 'role',
|
|
711
|
+
resourceId: 'admin',
|
|
712
|
+
},
|
|
713
|
+
relation: 'member',
|
|
714
|
+
subject: {
|
|
715
|
+
resourceType: 'user',
|
|
716
|
+
resourceId: 'user_123',
|
|
717
|
+
},
|
|
718
|
+
});
|
|
719
|
+
}
|
|
720
|
+
catch (e) {
|
|
721
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
722
|
+
}
|
|
723
|
+
}), 8000);
|
|
368
724
|
it('should delete warrant with delete op', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
369
725
|
(0, test_utils_1.fetchOnce)({
|
|
370
726
|
warrant_token: 'some_token',
|
|
@@ -475,6 +831,133 @@ describe('FGA', () => {
|
|
|
475
831
|
warrantToken: 'some_token',
|
|
476
832
|
});
|
|
477
833
|
}));
|
|
834
|
+
it('should batch write warrants after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
835
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
836
|
+
status: 500,
|
|
837
|
+
});
|
|
838
|
+
(0, test_utils_1.fetchOnce)({
|
|
839
|
+
warrant_token: 'some_token',
|
|
840
|
+
});
|
|
841
|
+
const warrantToken = yield workos.fga.batchWriteWarrants([
|
|
842
|
+
{
|
|
843
|
+
resource: {
|
|
844
|
+
resourceType: 'role',
|
|
845
|
+
resourceId: 'admin',
|
|
846
|
+
},
|
|
847
|
+
relation: 'member',
|
|
848
|
+
subject: {
|
|
849
|
+
resourceType: 'user',
|
|
850
|
+
resourceId: 'user_123',
|
|
851
|
+
},
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
op: interfaces_1.WarrantOp.Create,
|
|
855
|
+
resource: {
|
|
856
|
+
resourceType: 'role',
|
|
857
|
+
resourceId: 'admin',
|
|
858
|
+
},
|
|
859
|
+
relation: 'member',
|
|
860
|
+
subject: {
|
|
861
|
+
resourceType: 'user',
|
|
862
|
+
resourceId: 'user_124',
|
|
863
|
+
},
|
|
864
|
+
},
|
|
865
|
+
{
|
|
866
|
+
op: interfaces_1.WarrantOp.Delete,
|
|
867
|
+
resource: {
|
|
868
|
+
resourceType: 'role',
|
|
869
|
+
resourceId: 'admin',
|
|
870
|
+
},
|
|
871
|
+
relation: 'member',
|
|
872
|
+
subject: {
|
|
873
|
+
resourceType: 'user',
|
|
874
|
+
resourceId: 'user_125',
|
|
875
|
+
},
|
|
876
|
+
},
|
|
877
|
+
]);
|
|
878
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/warrants');
|
|
879
|
+
expect((0, test_utils_1.fetchBody)()).toEqual([
|
|
880
|
+
{
|
|
881
|
+
resource_type: 'role',
|
|
882
|
+
resource_id: 'admin',
|
|
883
|
+
relation: 'member',
|
|
884
|
+
subject: {
|
|
885
|
+
resource_type: 'user',
|
|
886
|
+
resource_id: 'user_123',
|
|
887
|
+
},
|
|
888
|
+
},
|
|
889
|
+
{
|
|
890
|
+
op: 'create',
|
|
891
|
+
resource_type: 'role',
|
|
892
|
+
resource_id: 'admin',
|
|
893
|
+
relation: 'member',
|
|
894
|
+
subject: {
|
|
895
|
+
resource_type: 'user',
|
|
896
|
+
resource_id: 'user_124',
|
|
897
|
+
},
|
|
898
|
+
},
|
|
899
|
+
{
|
|
900
|
+
op: 'delete',
|
|
901
|
+
resource_type: 'role',
|
|
902
|
+
resource_id: 'admin',
|
|
903
|
+
relation: 'member',
|
|
904
|
+
subject: {
|
|
905
|
+
resource_type: 'user',
|
|
906
|
+
resource_id: 'user_125',
|
|
907
|
+
},
|
|
908
|
+
},
|
|
909
|
+
]);
|
|
910
|
+
expect(warrantToken).toMatchObject({
|
|
911
|
+
warrantToken: 'some_token',
|
|
912
|
+
});
|
|
913
|
+
}));
|
|
914
|
+
it('fails to batch write warrants after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
915
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
916
|
+
message: 'Internal Server Error',
|
|
917
|
+
}), { status: 500 });
|
|
918
|
+
try {
|
|
919
|
+
yield workos.fga.batchWriteWarrants([
|
|
920
|
+
{
|
|
921
|
+
resource: {
|
|
922
|
+
resourceType: 'role',
|
|
923
|
+
resourceId: 'admin',
|
|
924
|
+
},
|
|
925
|
+
relation: 'member',
|
|
926
|
+
subject: {
|
|
927
|
+
resourceType: 'user',
|
|
928
|
+
resourceId: 'user_123',
|
|
929
|
+
},
|
|
930
|
+
},
|
|
931
|
+
{
|
|
932
|
+
op: interfaces_1.WarrantOp.Create,
|
|
933
|
+
resource: {
|
|
934
|
+
resourceType: 'role',
|
|
935
|
+
resourceId: 'admin',
|
|
936
|
+
},
|
|
937
|
+
relation: 'member',
|
|
938
|
+
subject: {
|
|
939
|
+
resourceType: 'user',
|
|
940
|
+
resourceId: 'user_124',
|
|
941
|
+
},
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
op: interfaces_1.WarrantOp.Delete,
|
|
945
|
+
resource: {
|
|
946
|
+
resourceType: 'role',
|
|
947
|
+
resourceId: 'admin',
|
|
948
|
+
},
|
|
949
|
+
relation: 'member',
|
|
950
|
+
subject: {
|
|
951
|
+
resourceType: 'user',
|
|
952
|
+
resourceId: 'user_125',
|
|
953
|
+
},
|
|
954
|
+
},
|
|
955
|
+
]);
|
|
956
|
+
}
|
|
957
|
+
catch (e) {
|
|
958
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
959
|
+
}
|
|
960
|
+
}), 8000);
|
|
478
961
|
});
|
|
479
962
|
describe('listWarrants', () => {
|
|
480
963
|
it('should list warrants', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
@@ -529,6 +1012,72 @@ describe('FGA', () => {
|
|
|
529
1012
|
},
|
|
530
1013
|
]);
|
|
531
1014
|
}));
|
|
1015
|
+
it('should list warrants after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1016
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
1017
|
+
status: 500,
|
|
1018
|
+
});
|
|
1019
|
+
(0, test_utils_1.fetchOnce)({
|
|
1020
|
+
data: [
|
|
1021
|
+
{
|
|
1022
|
+
resource_type: 'role',
|
|
1023
|
+
resource_id: 'admin',
|
|
1024
|
+
relation: 'member',
|
|
1025
|
+
subject: {
|
|
1026
|
+
resource_type: 'user',
|
|
1027
|
+
resource_id: 'user_123',
|
|
1028
|
+
},
|
|
1029
|
+
},
|
|
1030
|
+
{
|
|
1031
|
+
resource_type: 'role',
|
|
1032
|
+
resource_id: 'admin',
|
|
1033
|
+
relation: 'member',
|
|
1034
|
+
subject: {
|
|
1035
|
+
resource_type: 'user',
|
|
1036
|
+
resource_id: 'user_124',
|
|
1037
|
+
},
|
|
1038
|
+
policy: 'region == "us"',
|
|
1039
|
+
},
|
|
1040
|
+
],
|
|
1041
|
+
list_metadata: {
|
|
1042
|
+
before: null,
|
|
1043
|
+
after: null,
|
|
1044
|
+
},
|
|
1045
|
+
});
|
|
1046
|
+
const { data: warrants } = yield workos.fga.listWarrants();
|
|
1047
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/warrants');
|
|
1048
|
+
expect(warrants).toMatchObject([
|
|
1049
|
+
{
|
|
1050
|
+
resourceType: 'role',
|
|
1051
|
+
resourceId: 'admin',
|
|
1052
|
+
relation: 'member',
|
|
1053
|
+
subject: {
|
|
1054
|
+
resourceType: 'user',
|
|
1055
|
+
resourceId: 'user_123',
|
|
1056
|
+
},
|
|
1057
|
+
},
|
|
1058
|
+
{
|
|
1059
|
+
resourceType: 'role',
|
|
1060
|
+
resourceId: 'admin',
|
|
1061
|
+
relation: 'member',
|
|
1062
|
+
subject: {
|
|
1063
|
+
resourceType: 'user',
|
|
1064
|
+
resourceId: 'user_124',
|
|
1065
|
+
},
|
|
1066
|
+
policy: 'region == "us"',
|
|
1067
|
+
},
|
|
1068
|
+
]);
|
|
1069
|
+
}));
|
|
1070
|
+
it('fails to list warrants after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1071
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
1072
|
+
message: 'Internal Server Error',
|
|
1073
|
+
}), { status: 500 });
|
|
1074
|
+
try {
|
|
1075
|
+
yield workos.fga.listWarrants();
|
|
1076
|
+
}
|
|
1077
|
+
catch (e) {
|
|
1078
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
1079
|
+
}
|
|
1080
|
+
}), 8000);
|
|
532
1081
|
it('sends correct params when filtering', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
533
1082
|
(0, test_utils_1.fetchOnce)({
|
|
534
1083
|
data: [
|
|
@@ -604,6 +1153,66 @@ describe('FGA', () => {
|
|
|
604
1153
|
},
|
|
605
1154
|
]);
|
|
606
1155
|
}));
|
|
1156
|
+
it('makes query request after one retry', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1157
|
+
(0, test_utils_1.fetchOnce)({}, {
|
|
1158
|
+
status: 500,
|
|
1159
|
+
});
|
|
1160
|
+
(0, test_utils_1.fetchOnce)({
|
|
1161
|
+
data: [
|
|
1162
|
+
{
|
|
1163
|
+
resource_type: 'role',
|
|
1164
|
+
resource_id: 'admin',
|
|
1165
|
+
warrant: {
|
|
1166
|
+
resource_type: 'role',
|
|
1167
|
+
resource_id: 'admin',
|
|
1168
|
+
relation: 'member',
|
|
1169
|
+
subject: {
|
|
1170
|
+
resource_type: 'user',
|
|
1171
|
+
resource_id: 'user_123',
|
|
1172
|
+
},
|
|
1173
|
+
},
|
|
1174
|
+
is_implicit: false,
|
|
1175
|
+
},
|
|
1176
|
+
],
|
|
1177
|
+
list_metadata: {
|
|
1178
|
+
before: null,
|
|
1179
|
+
after: null,
|
|
1180
|
+
},
|
|
1181
|
+
});
|
|
1182
|
+
const { data: queryResults } = yield workos.fga.query({
|
|
1183
|
+
q: 'select role where user:user_123 is member',
|
|
1184
|
+
});
|
|
1185
|
+
expect((0, test_utils_1.fetchURL)()).toContain('/fga/v1/query');
|
|
1186
|
+
expect(queryResults).toMatchObject([
|
|
1187
|
+
{
|
|
1188
|
+
resourceType: 'role',
|
|
1189
|
+
resourceId: 'admin',
|
|
1190
|
+
warrant: {
|
|
1191
|
+
resourceType: 'role',
|
|
1192
|
+
resourceId: 'admin',
|
|
1193
|
+
relation: 'member',
|
|
1194
|
+
subject: {
|
|
1195
|
+
resourceType: 'user',
|
|
1196
|
+
resourceId: 'user_123',
|
|
1197
|
+
},
|
|
1198
|
+
},
|
|
1199
|
+
isImplicit: false,
|
|
1200
|
+
},
|
|
1201
|
+
]);
|
|
1202
|
+
}));
|
|
1203
|
+
it('fails to make query after max retries', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1204
|
+
jest_fetch_mock_1.default.mockResponse(JSON.stringify({
|
|
1205
|
+
message: 'Internal Server Error',
|
|
1206
|
+
}), { status: 500 });
|
|
1207
|
+
try {
|
|
1208
|
+
yield workos.fga.query({
|
|
1209
|
+
q: 'select role where user:user_123 is member',
|
|
1210
|
+
});
|
|
1211
|
+
}
|
|
1212
|
+
catch (e) {
|
|
1213
|
+
expect(e).toBeInstanceOf(exceptions_1.GenericServerException);
|
|
1214
|
+
}
|
|
1215
|
+
}), 8000);
|
|
607
1216
|
it('sends correct params and options', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
608
1217
|
(0, test_utils_1.fetchOnce)({
|
|
609
1218
|
data: [
|
package/lib/workos.js
CHANGED
|
@@ -27,7 +27,7 @@ const bad_request_exception_1 = require("./common/exceptions/bad-request.excepti
|
|
|
27
27
|
const http_client_1 = require("./common/net/http-client");
|
|
28
28
|
const subtle_crypto_provider_1 = require("./common/crypto/subtle-crypto-provider");
|
|
29
29
|
const fetch_client_1 = require("./common/net/fetch-client");
|
|
30
|
-
const VERSION = '7.
|
|
30
|
+
const VERSION = '7.30.0';
|
|
31
31
|
const DEFAULT_HOSTNAME = 'api.workos.com';
|
|
32
32
|
const HEADER_AUTHORIZATION = 'Authorization';
|
|
33
33
|
const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
|
package/package.json
CHANGED