@unito/integration-sdk 0.1.10 → 1.0.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/dist/src/handler.d.ts +39 -0
- package/dist/src/handler.js +9 -0
- package/dist/src/httpErrors.d.ts +29 -0
- package/dist/src/httpErrors.js +30 -0
- package/dist/src/index.cjs +289 -39
- package/dist/src/index.d.ts +2 -0
- package/dist/src/integration.d.ts +49 -0
- package/dist/src/integration.js +53 -17
- package/dist/src/middlewares/filters.d.ts +11 -2
- package/dist/src/middlewares/secrets.d.ts +5 -0
- package/dist/src/middlewares/signal.d.ts +15 -0
- package/dist/src/middlewares/signal.js +22 -0
- package/dist/src/resources/cache.d.ts +51 -2
- package/dist/src/resources/cache.js +49 -8
- package/dist/src/resources/context.d.ts +42 -13
- package/dist/src/resources/logger.d.ts +17 -0
- package/dist/src/resources/logger.js +17 -0
- package/dist/src/resources/provider.d.ts +93 -8
- package/dist/src/resources/provider.js +92 -11
- package/dist/test/middlewares/signal.test.d.ts +1 -0
- package/dist/test/middlewares/signal.test.js +20 -0
- package/dist/test/resources/cache.test.js +2 -2
- package/dist/test/resources/provider.test.js +116 -21
- package/package.json +4 -4
- package/src/handler.ts +48 -0
- package/src/httpErrors.ts +30 -0
- package/src/index.ts +2 -0
- package/src/integration.ts +53 -20
- package/src/middlewares/filters.ts +11 -2
- package/src/middlewares/secrets.ts +5 -0
- package/src/middlewares/signal.ts +41 -0
- package/src/resources/cache.ts +49 -11
- package/src/resources/context.ts +50 -33
- package/src/resources/logger.ts +17 -0
- package/src/resources/provider.ts +118 -19
- package/test/middlewares/signal.test.ts +28 -0
- package/test/resources/cache.test.ts +2 -2
- package/test/resources/provider.test.ts +122 -21
|
@@ -11,7 +11,7 @@ import Logger from '../resources/logger.js';
|
|
|
11
11
|
* NOTE: make sure to return one of the supported HttpErrors from the SDK, otherwise the error will be translated to a
|
|
12
12
|
* generic server (500) error.
|
|
13
13
|
*
|
|
14
|
-
* @param
|
|
14
|
+
* @param options - The credentials and the logger from the RequestOptions passed with the provider call.
|
|
15
15
|
* @param targetFunction - The function to call the provider.
|
|
16
16
|
* @returns The response from the provider.
|
|
17
17
|
* @throws RateLimitExceededError when the rate limit is exceeded.
|
|
@@ -19,32 +19,59 @@ import Logger from '../resources/logger.js';
|
|
|
19
19
|
* @throws HttpError when the provider returns an error.
|
|
20
20
|
*/
|
|
21
21
|
export type RateLimiter = <T>(
|
|
22
|
-
|
|
22
|
+
options: { credentials: Credentials; logger: Logger },
|
|
23
23
|
targetFunction: () => Promise<Response<T>>,
|
|
24
24
|
) => Promise<Response<T>>;
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* RequestOptions are the options passed to the Provider's call.
|
|
28
|
+
*
|
|
29
|
+
* @property credentials - The credentials to use for the call.
|
|
30
|
+
* @property logger - The logger to use during the call.
|
|
31
|
+
* @property queryParams - The query parameters to add when calling the provider.
|
|
32
|
+
* @property additionnalheaders - The headers to add when calling the provider.
|
|
33
|
+
*/
|
|
34
|
+
export type RequestOptions = {
|
|
27
35
|
credentials: Credentials;
|
|
28
36
|
logger: Logger;
|
|
37
|
+
signal: AbortSignal;
|
|
29
38
|
queryParams?: { [key: string]: string };
|
|
30
39
|
additionnalheaders?: { [key: string]: string };
|
|
31
|
-
}
|
|
40
|
+
};
|
|
32
41
|
|
|
33
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Response object returned by the Provider's method.
|
|
44
|
+
*
|
|
45
|
+
* Contains;
|
|
46
|
+
* - the body typed as specified when calling the method
|
|
47
|
+
* - the status code of the response
|
|
48
|
+
* - the headers of the response.
|
|
49
|
+
*/
|
|
50
|
+
export type Response<T> = {
|
|
34
51
|
body: T;
|
|
35
52
|
status: number;
|
|
36
53
|
headers: Headers;
|
|
37
|
-
}
|
|
54
|
+
};
|
|
38
55
|
|
|
56
|
+
/**
|
|
57
|
+
* The Provider class is a wrapper around the fetch function to call a provider's HTTP API.
|
|
58
|
+
*
|
|
59
|
+
* Defines methods for the following HTTP methods: GET, POST, PUT, PATCH, DELETE.
|
|
60
|
+
*
|
|
61
|
+
* Needs to be initialized with a prepareRequest function to define the Provider's base URL and any specific headers to
|
|
62
|
+
* add to the requests, and can also be configured to use a provided rate limiting function.
|
|
63
|
+
* @see {@link RateLimiter}
|
|
64
|
+
* @see {@link prepareRequest}
|
|
65
|
+
*/
|
|
39
66
|
export class Provider {
|
|
40
67
|
protected rateLimiter: RateLimiter | undefined = undefined;
|
|
41
|
-
protected prepareRequest: (
|
|
68
|
+
protected prepareRequest: (options: { credentials: Credentials; logger: Logger }) => {
|
|
42
69
|
url: string;
|
|
43
70
|
headers: Record<string, string>;
|
|
44
71
|
};
|
|
45
72
|
|
|
46
73
|
/**
|
|
47
|
-
*
|
|
74
|
+
* Initializes a Provider with the given options.
|
|
48
75
|
*
|
|
49
76
|
* @property prepareRequest - function to define the Provider's base URL and specific headers to add to the request.
|
|
50
77
|
* @property rateLimiter - function to limit the rate of calls to the provider based on the caller's credentials.
|
|
@@ -54,39 +81,85 @@ export class Provider {
|
|
|
54
81
|
this.rateLimiter = options.rateLimiter;
|
|
55
82
|
}
|
|
56
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Performs a GET request to the provider.
|
|
86
|
+
*
|
|
87
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
88
|
+
* adds the following headers:
|
|
89
|
+
* - Accept: application/json
|
|
90
|
+
*
|
|
91
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
92
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
93
|
+
* @returns The {@link Response} extracted from the provider.
|
|
94
|
+
*/
|
|
57
95
|
public async get<T>(endpoint: string, options: RequestOptions): Promise<Response<T>> {
|
|
58
96
|
return this.fetchWrapper<T>(endpoint, null, {
|
|
59
97
|
...options,
|
|
60
98
|
method: 'GET',
|
|
61
99
|
defaultHeaders: {
|
|
62
|
-
'Content-Type': 'application/json',
|
|
63
100
|
Accept: 'application/json',
|
|
64
101
|
},
|
|
65
102
|
});
|
|
66
103
|
}
|
|
67
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Performs a POST request to the provider.
|
|
107
|
+
*
|
|
108
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
109
|
+
* adds the following headers:
|
|
110
|
+
* - Content-Type: application/json',
|
|
111
|
+
* - Accept: application/json
|
|
112
|
+
*
|
|
113
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
114
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
115
|
+
* @returns The {@link Response} extracted from the provider.
|
|
116
|
+
*/
|
|
68
117
|
public async post<T>(endpoint: string, body: Record<string, unknown>, options: RequestOptions): Promise<Response<T>> {
|
|
69
118
|
return this.fetchWrapper<T>(endpoint, body, {
|
|
70
119
|
...options,
|
|
71
120
|
method: 'POST',
|
|
72
121
|
defaultHeaders: {
|
|
73
|
-
'Content-Type': 'application/
|
|
122
|
+
'Content-Type': 'application/json',
|
|
74
123
|
Accept: 'application/json',
|
|
75
124
|
},
|
|
76
125
|
});
|
|
77
126
|
}
|
|
78
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Performs a PUT request to the provider.
|
|
130
|
+
*
|
|
131
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
132
|
+
* adds the following headers:
|
|
133
|
+
* - Content-Type: application/json',
|
|
134
|
+
* - Accept: application/json
|
|
135
|
+
*
|
|
136
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
137
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
138
|
+
* @returns The {@link Response} extracted from the provider.
|
|
139
|
+
*/
|
|
79
140
|
public async put<T>(endpoint: string, body: Record<string, unknown>, options: RequestOptions): Promise<Response<T>> {
|
|
80
141
|
return this.fetchWrapper<T>(endpoint, body, {
|
|
81
142
|
...options,
|
|
82
143
|
method: 'PUT',
|
|
83
144
|
defaultHeaders: {
|
|
84
|
-
'Content-Type': 'application/
|
|
145
|
+
'Content-Type': 'application/json',
|
|
85
146
|
Accept: 'application/json',
|
|
86
147
|
},
|
|
87
148
|
});
|
|
88
149
|
}
|
|
89
150
|
|
|
151
|
+
/**
|
|
152
|
+
* Performs a PATCH request to the provider.
|
|
153
|
+
*
|
|
154
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
155
|
+
* adds the following headers:
|
|
156
|
+
* - Content-Type: application/json',
|
|
157
|
+
* - Accept: application/json
|
|
158
|
+
*
|
|
159
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
160
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
161
|
+
* @returns The {@link Response} extracted from the provider.
|
|
162
|
+
*/
|
|
90
163
|
public async patch<T>(
|
|
91
164
|
endpoint: string,
|
|
92
165
|
body: Record<string, unknown>,
|
|
@@ -96,18 +169,28 @@ export class Provider {
|
|
|
96
169
|
...options,
|
|
97
170
|
method: 'PATCH',
|
|
98
171
|
defaultHeaders: {
|
|
99
|
-
'Content-Type': 'application/
|
|
172
|
+
'Content-Type': 'application/json',
|
|
100
173
|
Accept: 'application/json',
|
|
101
174
|
},
|
|
102
175
|
});
|
|
103
176
|
}
|
|
104
177
|
|
|
178
|
+
/**
|
|
179
|
+
* Performs a DELETE request to the provider.
|
|
180
|
+
*
|
|
181
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
182
|
+
* adds the following headers:
|
|
183
|
+
* - Accept: application/json
|
|
184
|
+
*
|
|
185
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
186
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
187
|
+
* @returns The {@link Response} extracted from the provider.
|
|
188
|
+
*/
|
|
105
189
|
public async delete<T = undefined>(endpoint: string, options: RequestOptions): Promise<Response<T>> {
|
|
106
190
|
return this.fetchWrapper<T>(endpoint, null, {
|
|
107
191
|
...options,
|
|
108
192
|
method: 'DELETE',
|
|
109
193
|
defaultHeaders: {
|
|
110
|
-
'Content-Type': 'application/x-www-form-urlencoded',
|
|
111
194
|
Accept: 'application/json',
|
|
112
195
|
},
|
|
113
196
|
});
|
|
@@ -116,7 +199,7 @@ export class Provider {
|
|
|
116
199
|
private async fetchWrapper<T>(
|
|
117
200
|
endpoint: string,
|
|
118
201
|
body: Record<string, unknown> | null,
|
|
119
|
-
options: RequestOptions & { defaultHeaders: { 'Content-Type'
|
|
202
|
+
options: RequestOptions & { defaultHeaders: { 'Content-Type'?: string; Accept?: string }; method: string },
|
|
120
203
|
): Promise<Response<T>> {
|
|
121
204
|
const { url: providerUrl, headers: providerHeaders } = this.prepareRequest(options);
|
|
122
205
|
|
|
@@ -139,11 +222,27 @@ export class Provider {
|
|
|
139
222
|
}
|
|
140
223
|
|
|
141
224
|
const callToProvider = async (): Promise<Response<T>> => {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
225
|
+
let response: globalThis.Response;
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
response = await fetch(absoluteUrl, {
|
|
229
|
+
method: options.method,
|
|
230
|
+
signal: options.signal,
|
|
231
|
+
headers,
|
|
232
|
+
body: stringifiedBody,
|
|
233
|
+
});
|
|
234
|
+
} catch (error) {
|
|
235
|
+
if (error instanceof Error) {
|
|
236
|
+
switch (error.name) {
|
|
237
|
+
case 'AbortError':
|
|
238
|
+
throw buildHttpError(408, 'Request aborted');
|
|
239
|
+
case 'TimeoutError':
|
|
240
|
+
throw buildHttpError(408, 'Request timeout');
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
throw buildHttpError(500, `Unexpected error while calling the provider: "${error}"`);
|
|
245
|
+
}
|
|
147
246
|
|
|
148
247
|
if (response.status >= 400) {
|
|
149
248
|
const textResult = await response.text();
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { describe, it } from 'node:test';
|
|
4
|
+
import middleware from '../../src/middlewares/signal.js';
|
|
5
|
+
|
|
6
|
+
describe('signal middleware', () => {
|
|
7
|
+
it('uses header', () => {
|
|
8
|
+
const deadline = Math.floor((Date.now() + 5000) / 1000);
|
|
9
|
+
|
|
10
|
+
const request = { header: (_key: string) => deadline } as unknown as express.Request;
|
|
11
|
+
const response = { locals: {} } as express.Response;
|
|
12
|
+
|
|
13
|
+
middleware(request, response, () => {});
|
|
14
|
+
|
|
15
|
+
assert.ok(response.locals.signal instanceof AbortSignal);
|
|
16
|
+
assert.equal(response.locals.signal.aborted, false);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it('defaults', () => {
|
|
20
|
+
const request = { header: (_key: string) => undefined } as unknown as express.Request;
|
|
21
|
+
const response = { locals: {} } as express.Response;
|
|
22
|
+
|
|
23
|
+
middleware(request, response, () => {});
|
|
24
|
+
|
|
25
|
+
assert.ok(response.locals.signal instanceof AbortSignal);
|
|
26
|
+
assert.equal(response.locals.signal.aborted, false);
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
2
|
import { describe, it } from 'node:test';
|
|
3
3
|
import { LocalCache } from 'cachette';
|
|
4
|
-
import { Cache
|
|
4
|
+
import { Cache } from '../../src/resources/cache.js';
|
|
5
5
|
|
|
6
6
|
describe('Cache', () => {
|
|
7
7
|
describe('initializeCache', () => {
|
|
@@ -11,7 +11,7 @@ describe('Cache', () => {
|
|
|
11
11
|
assert.ok(cache instanceof Cache);
|
|
12
12
|
assert.ok(cache['cacheInstance'] instanceof LocalCache);
|
|
13
13
|
|
|
14
|
-
await
|
|
14
|
+
await cache['cacheInstance'].quit();
|
|
15
15
|
});
|
|
16
16
|
|
|
17
17
|
it('redis url returns (tries) WriteThroughCache', () => {
|
|
@@ -2,6 +2,7 @@ import assert from 'node:assert/strict';
|
|
|
2
2
|
import { describe, it } from 'node:test';
|
|
3
3
|
|
|
4
4
|
import { Provider } from '../../src/resources/provider.js';
|
|
5
|
+
import * as HttpErrors from '../../src/httpErrors.js';
|
|
5
6
|
import Logger from '../../src/resources/logger.js';
|
|
6
7
|
|
|
7
8
|
describe('Provider', () => {
|
|
@@ -30,6 +31,7 @@ describe('Provider', () => {
|
|
|
30
31
|
const actualResponse = await provider.get('/endpoint', {
|
|
31
32
|
credentials: { apiKey: 'apikey#1111' },
|
|
32
33
|
logger: logger,
|
|
34
|
+
signal: new AbortController().signal,
|
|
33
35
|
additionnalheaders: { 'X-Additional-Header': 'value1' },
|
|
34
36
|
});
|
|
35
37
|
|
|
@@ -39,8 +41,8 @@ describe('Provider', () => {
|
|
|
39
41
|
{
|
|
40
42
|
method: 'GET',
|
|
41
43
|
body: null,
|
|
44
|
+
signal: new AbortController().signal,
|
|
42
45
|
headers: {
|
|
43
|
-
'Content-Type': 'application/json',
|
|
44
46
|
Accept: 'application/json',
|
|
45
47
|
'X-Custom-Provider-Header': 'value',
|
|
46
48
|
'X-Provider-Credential-Header': 'apikey#1111',
|
|
@@ -67,7 +69,8 @@ describe('Provider', () => {
|
|
|
67
69
|
{
|
|
68
70
|
credentials: { apiKey: 'apikey#1111' },
|
|
69
71
|
logger: logger,
|
|
70
|
-
|
|
72
|
+
signal: new AbortController().signal,
|
|
73
|
+
additionnalheaders: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Additional-Header': 'value1' },
|
|
71
74
|
},
|
|
72
75
|
);
|
|
73
76
|
|
|
@@ -77,6 +80,7 @@ describe('Provider', () => {
|
|
|
77
80
|
{
|
|
78
81
|
method: 'POST',
|
|
79
82
|
body: 'data=createdItemInfo',
|
|
83
|
+
signal: new AbortController().signal,
|
|
80
84
|
headers: {
|
|
81
85
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
82
86
|
Accept: 'application/json',
|
|
@@ -106,6 +110,7 @@ describe('Provider', () => {
|
|
|
106
110
|
{
|
|
107
111
|
credentials: { apiKey: 'apikey#1111' },
|
|
108
112
|
logger: logger,
|
|
113
|
+
signal: new AbortController().signal,
|
|
109
114
|
additionnalheaders: { 'X-Additional-Header': 'value1', 'Content-Type': 'application/json' },
|
|
110
115
|
},
|
|
111
116
|
);
|
|
@@ -116,6 +121,7 @@ describe('Provider', () => {
|
|
|
116
121
|
{
|
|
117
122
|
method: 'PUT',
|
|
118
123
|
body: JSON.stringify({ data: 'updatedItemInfo' }),
|
|
124
|
+
signal: new AbortController().signal,
|
|
119
125
|
headers: {
|
|
120
126
|
'Content-Type': 'application/json',
|
|
121
127
|
Accept: 'application/json',
|
|
@@ -144,8 +150,9 @@ describe('Provider', () => {
|
|
|
144
150
|
{
|
|
145
151
|
credentials: { apiKey: 'apikey#1111' },
|
|
146
152
|
logger: logger,
|
|
153
|
+
signal: new AbortController().signal,
|
|
147
154
|
queryParams: { param1: 'value1', param2: 'value2' },
|
|
148
|
-
additionnalheaders: { 'X-Additional-Header': 'value1'
|
|
155
|
+
additionnalheaders: { 'X-Additional-Header': 'value1' },
|
|
149
156
|
},
|
|
150
157
|
);
|
|
151
158
|
|
|
@@ -155,6 +162,7 @@ describe('Provider', () => {
|
|
|
155
162
|
{
|
|
156
163
|
method: 'PATCH',
|
|
157
164
|
body: JSON.stringify({ data: 'updatedItemInfo' }),
|
|
165
|
+
signal: new AbortController().signal,
|
|
158
166
|
headers: {
|
|
159
167
|
'Content-Type': 'application/json',
|
|
160
168
|
Accept: 'application/json',
|
|
@@ -178,7 +186,8 @@ describe('Provider', () => {
|
|
|
178
186
|
const actualResponse = await provider.delete('/endpoint/123', {
|
|
179
187
|
credentials: { apiKey: 'apikey#1111' },
|
|
180
188
|
logger: logger,
|
|
181
|
-
|
|
189
|
+
signal: new AbortController().signal,
|
|
190
|
+
additionnalheaders: { 'X-Additional-Header': 'value1' },
|
|
182
191
|
});
|
|
183
192
|
|
|
184
193
|
assert.equal(fetchMock.mock.calls.length, 1);
|
|
@@ -187,8 +196,8 @@ describe('Provider', () => {
|
|
|
187
196
|
{
|
|
188
197
|
method: 'DELETE',
|
|
189
198
|
body: null,
|
|
199
|
+
signal: new AbortController().signal,
|
|
190
200
|
headers: {
|
|
191
|
-
'Content-Type': 'application/json',
|
|
192
201
|
Accept: 'application/json',
|
|
193
202
|
'X-Custom-Provider-Header': 'value',
|
|
194
203
|
'X-Provider-Credential-Header': 'apikey#1111',
|
|
@@ -225,7 +234,8 @@ describe('Provider', () => {
|
|
|
225
234
|
const options = {
|
|
226
235
|
credentials: { apiKey: 'apikey#1111' },
|
|
227
236
|
logger: logger,
|
|
228
|
-
|
|
237
|
+
signal: new AbortController().signal,
|
|
238
|
+
additionnalheaders: { 'X-Additional-Header': 'value1' },
|
|
229
239
|
};
|
|
230
240
|
|
|
231
241
|
const actualResponse = await rateLimitedProvider.delete('/endpoint/123', options);
|
|
@@ -238,8 +248,8 @@ describe('Provider', () => {
|
|
|
238
248
|
{
|
|
239
249
|
method: 'DELETE',
|
|
240
250
|
body: null,
|
|
251
|
+
signal: new AbortController().signal,
|
|
241
252
|
headers: {
|
|
242
|
-
'Content-Type': 'application/json',
|
|
243
253
|
Accept: 'application/json',
|
|
244
254
|
'X-Custom-Provider-Header': 'value',
|
|
245
255
|
'X-Provider-Credential-Header': 'apikey#1111',
|
|
@@ -257,41 +267,132 @@ describe('Provider', () => {
|
|
|
257
267
|
|
|
258
268
|
context.mock.method(global, 'fetch', () => Promise.resolve(response));
|
|
259
269
|
|
|
260
|
-
|
|
261
|
-
|
|
270
|
+
let error;
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
await provider.get('/endpoint/123', {
|
|
262
274
|
credentials: { apiKey: 'apikey#1111' },
|
|
263
275
|
logger: logger,
|
|
264
|
-
|
|
265
|
-
|
|
276
|
+
signal: new AbortController().signal,
|
|
277
|
+
});
|
|
278
|
+
} catch (e) {
|
|
279
|
+
error = e;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
assert.ok(error instanceof HttpErrors.BadRequestError);
|
|
283
|
+
assert.equal(error.message, 'Invalid JSON response');
|
|
266
284
|
});
|
|
267
285
|
|
|
268
286
|
it('throws on status 400', async context => {
|
|
269
|
-
const response = new Response(
|
|
287
|
+
const response = new Response('response body', {
|
|
270
288
|
status: 400,
|
|
271
289
|
});
|
|
272
290
|
|
|
273
291
|
context.mock.method(global, 'fetch', () => Promise.resolve(response));
|
|
274
292
|
|
|
275
|
-
|
|
276
|
-
|
|
293
|
+
let error;
|
|
294
|
+
|
|
295
|
+
try {
|
|
296
|
+
await provider.get('/endpoint/123', {
|
|
277
297
|
credentials: { apiKey: 'apikey#1111' },
|
|
298
|
+
signal: new AbortController().signal,
|
|
278
299
|
logger: logger,
|
|
279
|
-
})
|
|
280
|
-
)
|
|
300
|
+
});
|
|
301
|
+
} catch (e) {
|
|
302
|
+
error = e;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
assert.ok(error instanceof HttpErrors.BadRequestError);
|
|
306
|
+
assert.equal(error.message, 'response body');
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
it('throws on timeout', async context => {
|
|
310
|
+
context.mock.method(global, 'fetch', () => {
|
|
311
|
+
const error = new Error();
|
|
312
|
+
error.name = 'TimeoutError';
|
|
313
|
+
throw error;
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
let error;
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
await provider.get('/endpoint/123', {
|
|
320
|
+
credentials: { apiKey: 'apikey#1111' },
|
|
321
|
+
signal: new AbortController().signal,
|
|
322
|
+
logger: logger,
|
|
323
|
+
});
|
|
324
|
+
} catch (e) {
|
|
325
|
+
error = e;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
assert.ok(error instanceof HttpErrors.TimeoutError);
|
|
329
|
+
assert.equal(error.message, 'Request timeout');
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it('throws on abort', async context => {
|
|
333
|
+
context.mock.method(global, 'fetch', () => {
|
|
334
|
+
const error = new Error();
|
|
335
|
+
error.name = 'AbortError';
|
|
336
|
+
throw error;
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
let error;
|
|
340
|
+
|
|
341
|
+
try {
|
|
342
|
+
await provider.get('/endpoint/123', {
|
|
343
|
+
credentials: { apiKey: 'apikey#1111' },
|
|
344
|
+
signal: new AbortController().signal,
|
|
345
|
+
logger: logger,
|
|
346
|
+
});
|
|
347
|
+
} catch (e) {
|
|
348
|
+
error = e;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
assert.ok(error instanceof HttpErrors.TimeoutError);
|
|
352
|
+
assert.equal(error.message, 'Request aborted');
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
it('throws on unknown errors', async context => {
|
|
356
|
+
context.mock.method(global, 'fetch', () => {
|
|
357
|
+
throw new Error('foo');
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
let error;
|
|
361
|
+
|
|
362
|
+
try {
|
|
363
|
+
await provider.get('/endpoint/123', {
|
|
364
|
+
credentials: { apiKey: 'apikey#1111' },
|
|
365
|
+
signal: new AbortController().signal,
|
|
366
|
+
logger: logger,
|
|
367
|
+
});
|
|
368
|
+
} catch (e) {
|
|
369
|
+
error = e;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
assert.ok(error instanceof HttpErrors.HttpError);
|
|
373
|
+
assert.equal(error.message, 'Unexpected error while calling the provider: "Error: foo"');
|
|
281
374
|
});
|
|
282
375
|
|
|
283
376
|
it('throws on status 429', async context => {
|
|
284
|
-
const response = new Response(
|
|
377
|
+
const response = new Response('response body', {
|
|
285
378
|
status: 429,
|
|
286
379
|
});
|
|
287
380
|
|
|
288
381
|
context.mock.method(global, 'fetch', () => Promise.resolve(response));
|
|
289
382
|
|
|
290
|
-
|
|
291
|
-
|
|
383
|
+
let error;
|
|
384
|
+
|
|
385
|
+
try {
|
|
386
|
+
await provider.get('/endpoint/123', {
|
|
292
387
|
credentials: { apiKey: 'apikey#1111' },
|
|
388
|
+
signal: new AbortController().signal,
|
|
293
389
|
logger: logger,
|
|
294
|
-
})
|
|
295
|
-
)
|
|
390
|
+
});
|
|
391
|
+
} catch (e) {
|
|
392
|
+
error = e;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
assert.ok(error instanceof HttpErrors.RateLimitExceededError);
|
|
396
|
+
assert.equal(error.message, 'response body');
|
|
296
397
|
});
|
|
297
398
|
});
|