@unito/integration-sdk 2.0.2 → 2.1.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/dist/src/index.cjs +37 -4
- package/dist/src/resources/context.d.ts +1 -1
- package/dist/src/resources/provider.d.ts +18 -0
- package/dist/src/resources/provider.js +37 -4
- package/dist/test/resources/provider.test.js +32 -0
- package/package.json +2 -2
- package/src/resources/context.ts +1 -1
- package/src/resources/provider.ts +37 -5
- package/test/resources/provider.test.ts +37 -0
- package/tsconfig.json +0 -1
package/dist/src/index.cjs
CHANGED
|
@@ -1301,6 +1301,33 @@ class Provider {
|
|
|
1301
1301
|
},
|
|
1302
1302
|
});
|
|
1303
1303
|
}
|
|
1304
|
+
/**
|
|
1305
|
+
* Performs a PUT request to the provider with a Buffer body, typically used for sending binary data.
|
|
1306
|
+
*
|
|
1307
|
+
* IMPORTANT: This method should ONLY be used as a last resort when FormData cannot be used.
|
|
1308
|
+
* It bypasses normal form handling and is used to **manually send chunked** binary data, which may not be appropriate
|
|
1309
|
+
* for all providers. Always be mindful not to load entire binary files in memory!
|
|
1310
|
+
*
|
|
1311
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
1312
|
+
* adds the following headers:
|
|
1313
|
+
* - Content-Type: application/octet-stream
|
|
1314
|
+
* - Accept: application/json
|
|
1315
|
+
*
|
|
1316
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
1317
|
+
* @param body The Buffer containing the binary data to be sent.
|
|
1318
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
1319
|
+
* @returns The {@link Response} extracted from the provider.
|
|
1320
|
+
*/
|
|
1321
|
+
async putBuffer(endpoint, body, options) {
|
|
1322
|
+
return this.fetchWrapper(endpoint, body, {
|
|
1323
|
+
...options,
|
|
1324
|
+
method: 'PUT',
|
|
1325
|
+
defaultHeaders: {
|
|
1326
|
+
'Content-Type': 'application/octet-stream',
|
|
1327
|
+
Accept: 'application/json',
|
|
1328
|
+
},
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1304
1331
|
/**
|
|
1305
1332
|
* Performs a PATCH request to the provider.
|
|
1306
1333
|
*
|
|
@@ -1360,14 +1387,20 @@ class Provider {
|
|
|
1360
1387
|
const { url: providerUrl, headers: providerHeaders } = await this.prepareRequest(options);
|
|
1361
1388
|
const absoluteUrl = this.generateAbsoluteUrl(providerUrl, endpoint, options.queryParams);
|
|
1362
1389
|
const headers = { ...options.defaultHeaders, ...providerHeaders, ...options.additionnalheaders };
|
|
1363
|
-
let
|
|
1390
|
+
let fetchBody = null;
|
|
1364
1391
|
if (body) {
|
|
1365
1392
|
if (headers['Content-Type'] === 'application/x-www-form-urlencoded') {
|
|
1366
|
-
|
|
1393
|
+
fetchBody = new URLSearchParams(body).toString();
|
|
1367
1394
|
}
|
|
1368
1395
|
else if (headers['Content-Type'] === 'application/json' ||
|
|
1369
1396
|
headers['Content-Type'] === 'application/json-patch+json') {
|
|
1370
|
-
|
|
1397
|
+
fetchBody = JSON.stringify(body);
|
|
1398
|
+
}
|
|
1399
|
+
else if (headers['Content-Type'] === 'application/octet-stream' && body instanceof Buffer) {
|
|
1400
|
+
fetchBody = body;
|
|
1401
|
+
}
|
|
1402
|
+
else {
|
|
1403
|
+
throw this.handleError(400, `Content type not supported: ${headers['Content-Type']}`, options);
|
|
1371
1404
|
}
|
|
1372
1405
|
}
|
|
1373
1406
|
const callToProvider = async () => {
|
|
@@ -1376,7 +1409,7 @@ class Provider {
|
|
|
1376
1409
|
response = await fetch(absoluteUrl, {
|
|
1377
1410
|
method: options.method,
|
|
1378
1411
|
headers,
|
|
1379
|
-
body:
|
|
1412
|
+
body: fetchBody,
|
|
1380
1413
|
...(options.signal ? { signal: options.signal } : {}),
|
|
1381
1414
|
});
|
|
1382
1415
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as API from '@unito/integration-api';
|
|
2
2
|
import Logger from './logger.js';
|
|
3
3
|
import { Credentials } from '../middlewares/credentials.js';
|
|
4
|
-
import { Secrets } from '
|
|
4
|
+
import { Secrets } from '../middlewares/secrets.js';
|
|
5
5
|
import { Filter } from '../middlewares/filters.js';
|
|
6
6
|
type Maybe<T> = T | null;
|
|
7
7
|
type Empty = Record<string, never>;
|
|
@@ -165,6 +165,24 @@ export declare class Provider {
|
|
|
165
165
|
* @returns The {@link Response} extracted from the provider.
|
|
166
166
|
*/
|
|
167
167
|
put<T>(endpoint: string, body: RequestBody, options: RequestOptions): Promise<Response<T>>;
|
|
168
|
+
/**
|
|
169
|
+
* Performs a PUT request to the provider with a Buffer body, typically used for sending binary data.
|
|
170
|
+
*
|
|
171
|
+
* IMPORTANT: This method should ONLY be used as a last resort when FormData cannot be used.
|
|
172
|
+
* It bypasses normal form handling and is used to **manually send chunked** binary data, which may not be appropriate
|
|
173
|
+
* for all providers. Always be mindful not to load entire binary files in memory!
|
|
174
|
+
*
|
|
175
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
176
|
+
* adds the following headers:
|
|
177
|
+
* - Content-Type: application/octet-stream
|
|
178
|
+
* - Accept: application/json
|
|
179
|
+
*
|
|
180
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
181
|
+
* @param body The Buffer containing the binary data to be sent.
|
|
182
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
183
|
+
* @returns The {@link Response} extracted from the provider.
|
|
184
|
+
*/
|
|
185
|
+
putBuffer<T>(endpoint: string, body: Buffer, options: RequestOptions): Promise<Response<T>>;
|
|
168
186
|
/**
|
|
169
187
|
* Performs a PATCH request to the provider.
|
|
170
188
|
*
|
|
@@ -181,6 +181,33 @@ export class Provider {
|
|
|
181
181
|
},
|
|
182
182
|
});
|
|
183
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Performs a PUT request to the provider with a Buffer body, typically used for sending binary data.
|
|
186
|
+
*
|
|
187
|
+
* IMPORTANT: This method should ONLY be used as a last resort when FormData cannot be used.
|
|
188
|
+
* It bypasses normal form handling and is used to **manually send chunked** binary data, which may not be appropriate
|
|
189
|
+
* for all providers. Always be mindful not to load entire binary files in memory!
|
|
190
|
+
*
|
|
191
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
192
|
+
* adds the following headers:
|
|
193
|
+
* - Content-Type: application/octet-stream
|
|
194
|
+
* - Accept: application/json
|
|
195
|
+
*
|
|
196
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
197
|
+
* @param body The Buffer containing the binary data to be sent.
|
|
198
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
199
|
+
* @returns The {@link Response} extracted from the provider.
|
|
200
|
+
*/
|
|
201
|
+
async putBuffer(endpoint, body, options) {
|
|
202
|
+
return this.fetchWrapper(endpoint, body, {
|
|
203
|
+
...options,
|
|
204
|
+
method: 'PUT',
|
|
205
|
+
defaultHeaders: {
|
|
206
|
+
'Content-Type': 'application/octet-stream',
|
|
207
|
+
Accept: 'application/json',
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
}
|
|
184
211
|
/**
|
|
185
212
|
* Performs a PATCH request to the provider.
|
|
186
213
|
*
|
|
@@ -240,14 +267,20 @@ export class Provider {
|
|
|
240
267
|
const { url: providerUrl, headers: providerHeaders } = await this.prepareRequest(options);
|
|
241
268
|
const absoluteUrl = this.generateAbsoluteUrl(providerUrl, endpoint, options.queryParams);
|
|
242
269
|
const headers = { ...options.defaultHeaders, ...providerHeaders, ...options.additionnalheaders };
|
|
243
|
-
let
|
|
270
|
+
let fetchBody = null;
|
|
244
271
|
if (body) {
|
|
245
272
|
if (headers['Content-Type'] === 'application/x-www-form-urlencoded') {
|
|
246
|
-
|
|
273
|
+
fetchBody = new URLSearchParams(body).toString();
|
|
247
274
|
}
|
|
248
275
|
else if (headers['Content-Type'] === 'application/json' ||
|
|
249
276
|
headers['Content-Type'] === 'application/json-patch+json') {
|
|
250
|
-
|
|
277
|
+
fetchBody = JSON.stringify(body);
|
|
278
|
+
}
|
|
279
|
+
else if (headers['Content-Type'] === 'application/octet-stream' && body instanceof Buffer) {
|
|
280
|
+
fetchBody = body;
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
throw this.handleError(400, `Content type not supported: ${headers['Content-Type']}`, options);
|
|
251
284
|
}
|
|
252
285
|
}
|
|
253
286
|
const callToProvider = async () => {
|
|
@@ -256,7 +289,7 @@ export class Provider {
|
|
|
256
289
|
response = await fetch(absoluteUrl, {
|
|
257
290
|
method: options.method,
|
|
258
291
|
headers,
|
|
259
|
-
body:
|
|
292
|
+
body: fetchBody,
|
|
260
293
|
...(options.signal ? { signal: options.signal } : {}),
|
|
261
294
|
});
|
|
262
295
|
}
|
|
@@ -310,6 +310,38 @@ describe('Provider', () => {
|
|
|
310
310
|
]);
|
|
311
311
|
assert.deepEqual(actualResponse, { status: 201, headers: response.headers, body: { data: 'value' } });
|
|
312
312
|
});
|
|
313
|
+
it('putBuffer with Buffer body', async (context) => {
|
|
314
|
+
const response = new Response('{"data": "value"}', {
|
|
315
|
+
status: 201,
|
|
316
|
+
headers: { 'Content-Type': 'application/json' },
|
|
317
|
+
});
|
|
318
|
+
const fetchMock = context.mock.method(global, 'fetch', () => Promise.resolve(response));
|
|
319
|
+
const buffer = Buffer.from('binary data content');
|
|
320
|
+
// What matters is that the body of put is a buffer
|
|
321
|
+
const actualResponse = await provider.putBuffer('endpoint/123', buffer, {
|
|
322
|
+
credentials: { apiKey: 'apikey#1111' },
|
|
323
|
+
logger: logger,
|
|
324
|
+
signal: new AbortController().signal,
|
|
325
|
+
additionnalheaders: { 'X-Additional-Header': 'value1', 'Content-Type': 'application/octet-stream' },
|
|
326
|
+
});
|
|
327
|
+
assert.equal(fetchMock.mock.calls.length, 1);
|
|
328
|
+
assert.deepEqual(fetchMock.mock.calls[0]?.arguments, [
|
|
329
|
+
'www.myApi.com/endpoint/123',
|
|
330
|
+
{
|
|
331
|
+
method: 'PUT',
|
|
332
|
+
body: buffer,
|
|
333
|
+
signal: new AbortController().signal,
|
|
334
|
+
headers: {
|
|
335
|
+
'Content-Type': 'application/octet-stream',
|
|
336
|
+
Accept: 'application/json',
|
|
337
|
+
'X-Custom-Provider-Header': 'value',
|
|
338
|
+
'X-Provider-Credential-Header': 'apikey#1111',
|
|
339
|
+
'X-Additional-Header': 'value1',
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
]);
|
|
343
|
+
assert.deepEqual(actualResponse, { status: 201, headers: response.headers, body: { data: 'value' } });
|
|
344
|
+
});
|
|
313
345
|
it('patch with query params', async (context) => {
|
|
314
346
|
const response = new Response('{"data": "value"}', {
|
|
315
347
|
status: 201,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unito/integration-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Integration SDK",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@unito/integration-api": "4.x",
|
|
56
56
|
"busboy": "^1.6.0",
|
|
57
|
-
"cachette": "
|
|
57
|
+
"cachette": "4.x",
|
|
58
58
|
"express": "^5.x",
|
|
59
59
|
"form-data": "^4.0.0"
|
|
60
60
|
},
|
package/src/resources/context.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as API from '@unito/integration-api';
|
|
3
3
|
import Logger from './logger.js';
|
|
4
4
|
import { Credentials } from '../middlewares/credentials.js';
|
|
5
|
-
import { Secrets } from '
|
|
5
|
+
import { Secrets } from '../middlewares/secrets.js';
|
|
6
6
|
import { Filter } from '../middlewares/filters.js';
|
|
7
7
|
|
|
8
8
|
type Maybe<T> = T | null;
|
|
@@ -274,6 +274,34 @@ export class Provider {
|
|
|
274
274
|
});
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Performs a PUT request to the provider with a Buffer body, typically used for sending binary data.
|
|
279
|
+
*
|
|
280
|
+
* IMPORTANT: This method should ONLY be used as a last resort when FormData cannot be used.
|
|
281
|
+
* It bypasses normal form handling and is used to **manually send chunked** binary data, which may not be appropriate
|
|
282
|
+
* for all providers. Always be mindful not to load entire binary files in memory!
|
|
283
|
+
*
|
|
284
|
+
* Uses the prepareRequest function to get the base URL and any specific headers to add to the request and by default
|
|
285
|
+
* adds the following headers:
|
|
286
|
+
* - Content-Type: application/octet-stream
|
|
287
|
+
* - Accept: application/json
|
|
288
|
+
*
|
|
289
|
+
* @param endpoint Path to the provider's resource. Will be added to the URL returned by the prepareRequest function.
|
|
290
|
+
* @param body The Buffer containing the binary data to be sent.
|
|
291
|
+
* @param options RequestOptions used to adjust the call made to the provider (use to override default headers).
|
|
292
|
+
* @returns The {@link Response} extracted from the provider.
|
|
293
|
+
*/
|
|
294
|
+
public async putBuffer<T>(endpoint: string, body: Buffer, options: RequestOptions): Promise<Response<T>> {
|
|
295
|
+
return this.fetchWrapper<T>(endpoint, body, {
|
|
296
|
+
...options,
|
|
297
|
+
method: 'PUT',
|
|
298
|
+
defaultHeaders: {
|
|
299
|
+
'Content-Type': 'application/octet-stream',
|
|
300
|
+
Accept: 'application/json',
|
|
301
|
+
},
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
|
|
277
305
|
/**
|
|
278
306
|
* Performs a PATCH request to the provider.
|
|
279
307
|
*
|
|
@@ -335,23 +363,27 @@ export class Provider {
|
|
|
335
363
|
|
|
336
364
|
private async fetchWrapper<T>(
|
|
337
365
|
endpoint: string,
|
|
338
|
-
body: RequestBody | null,
|
|
366
|
+
body: RequestBody | Buffer | null,
|
|
339
367
|
options: RequestOptions & { defaultHeaders: { 'Content-Type'?: string; Accept?: string }; method: string },
|
|
340
368
|
): Promise<Response<T>> {
|
|
341
369
|
const { url: providerUrl, headers: providerHeaders } = await this.prepareRequest(options);
|
|
342
370
|
const absoluteUrl = this.generateAbsoluteUrl(providerUrl, endpoint, options.queryParams);
|
|
343
371
|
const headers = { ...options.defaultHeaders, ...providerHeaders, ...options.additionnalheaders };
|
|
344
372
|
|
|
345
|
-
let
|
|
373
|
+
let fetchBody: string | Buffer | null = null;
|
|
346
374
|
|
|
347
375
|
if (body) {
|
|
348
376
|
if (headers['Content-Type'] === 'application/x-www-form-urlencoded') {
|
|
349
|
-
|
|
377
|
+
fetchBody = new URLSearchParams(body as Record<string, string>).toString();
|
|
350
378
|
} else if (
|
|
351
379
|
headers['Content-Type'] === 'application/json' ||
|
|
352
380
|
headers['Content-Type'] === 'application/json-patch+json'
|
|
353
381
|
) {
|
|
354
|
-
|
|
382
|
+
fetchBody = JSON.stringify(body);
|
|
383
|
+
} else if (headers['Content-Type'] === 'application/octet-stream' && body instanceof Buffer) {
|
|
384
|
+
fetchBody = body;
|
|
385
|
+
} else {
|
|
386
|
+
throw this.handleError(400, `Content type not supported: ${headers['Content-Type']}`, options);
|
|
355
387
|
}
|
|
356
388
|
}
|
|
357
389
|
|
|
@@ -362,7 +394,7 @@ export class Provider {
|
|
|
362
394
|
response = await fetch(absoluteUrl, {
|
|
363
395
|
method: options.method,
|
|
364
396
|
headers,
|
|
365
|
-
body:
|
|
397
|
+
body: fetchBody,
|
|
366
398
|
...(options.signal ? { signal: options.signal } : {}),
|
|
367
399
|
});
|
|
368
400
|
} catch (error) {
|
|
@@ -375,6 +375,43 @@ describe('Provider', () => {
|
|
|
375
375
|
assert.deepEqual(actualResponse, { status: 201, headers: response.headers, body: { data: 'value' } });
|
|
376
376
|
});
|
|
377
377
|
|
|
378
|
+
it('putBuffer with Buffer body', async context => {
|
|
379
|
+
const response = new Response('{"data": "value"}', {
|
|
380
|
+
status: 201,
|
|
381
|
+
headers: { 'Content-Type': 'application/json' },
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
const fetchMock = context.mock.method(global, 'fetch', () => Promise.resolve(response));
|
|
385
|
+
|
|
386
|
+
const buffer = Buffer.from('binary data content');
|
|
387
|
+
|
|
388
|
+
// What matters is that the body of put is a buffer
|
|
389
|
+
const actualResponse = await provider.putBuffer('endpoint/123', buffer, {
|
|
390
|
+
credentials: { apiKey: 'apikey#1111' },
|
|
391
|
+
logger: logger,
|
|
392
|
+
signal: new AbortController().signal,
|
|
393
|
+
additionnalheaders: { 'X-Additional-Header': 'value1', 'Content-Type': 'application/octet-stream' },
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
assert.equal(fetchMock.mock.calls.length, 1);
|
|
397
|
+
assert.deepEqual(fetchMock.mock.calls[0]?.arguments, [
|
|
398
|
+
'www.myApi.com/endpoint/123',
|
|
399
|
+
{
|
|
400
|
+
method: 'PUT',
|
|
401
|
+
body: buffer,
|
|
402
|
+
signal: new AbortController().signal,
|
|
403
|
+
headers: {
|
|
404
|
+
'Content-Type': 'application/octet-stream',
|
|
405
|
+
Accept: 'application/json',
|
|
406
|
+
'X-Custom-Provider-Header': 'value',
|
|
407
|
+
'X-Provider-Credential-Header': 'apikey#1111',
|
|
408
|
+
'X-Additional-Header': 'value1',
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
]);
|
|
412
|
+
assert.deepEqual(actualResponse, { status: 201, headers: response.headers, body: { data: 'value' } });
|
|
413
|
+
});
|
|
414
|
+
|
|
378
415
|
it('patch with query params', async context => {
|
|
379
416
|
const response = new Response('{"data": "value"}', {
|
|
380
417
|
status: 201,
|