apify-client 3.0.0-beta.2 → 3.0.0-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/apify_api_error.d.ts +60 -19
- package/dist/apify_api_error.js +88 -22
- package/dist/apify_client.d.ts +22 -3
- package/dist/apify_client.js +37 -31
- package/dist/base/api_client.d.ts +6 -6
- package/dist/base/api_client.js +24 -16
- package/dist/base/resource_client.d.ts +23 -9
- package/dist/base/resource_client.js +49 -25
- package/dist/base/resource_collection_client.d.ts +7 -4
- package/dist/base/resource_collection_client.js +21 -15
- package/dist/body_parser.d.ts +3 -4
- package/dist/body_parser.js +17 -24
- package/dist/bundle.js +38 -48
- package/dist/bundle.js.map +1 -1
- package/dist/generated/api.d.ts +287 -214
- package/dist/generated/schemas.d.ts +6699 -0
- package/dist/generated/schemas.js +1521 -0
- package/dist/http_client.d.ts +18 -51
- package/dist/http_client.js +90 -85
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -1
- package/dist/interceptors.js +24 -6
- package/dist/lazy_schema.d.ts +8 -0
- package/dist/lazy_schema.js +11 -0
- package/dist/models.d.ts +32 -52
- package/dist/resource_clients/actor.d.ts +46 -31
- package/dist/resource_clients/actor.js +71 -53
- package/dist/resource_clients/actor_collection.d.ts +9 -5
- package/dist/resource_clients/actor_collection.js +12 -3
- package/dist/resource_clients/actor_env_var.d.ts +10 -3
- package/dist/resource_clients/actor_env_var.js +17 -6
- package/dist/resource_clients/actor_env_var_collection.d.ts +14 -18
- package/dist/resource_clients/actor_env_var_collection.js +18 -11
- package/dist/resource_clients/actor_version.d.ts +18 -3
- package/dist/resource_clients/actor_version.js +20 -9
- package/dist/resource_clients/actor_version_collection.d.ts +16 -17
- package/dist/resource_clients/actor_version_collection.js +20 -11
- package/dist/resource_clients/build.d.ts +18 -6
- package/dist/resource_clients/build.js +35 -17
- package/dist/resource_clients/build_collection.d.ts +3 -1
- package/dist/resource_clients/build_collection.js +5 -1
- package/dist/resource_clients/dataset.d.ts +23 -9
- package/dist/resource_clients/dataset.js +70 -48
- package/dist/resource_clients/dataset_collection.d.ts +6 -2
- package/dist/resource_clients/dataset_collection.js +13 -2
- package/dist/resource_clients/key_value_store.d.ts +48 -15
- package/dist/resource_clients/key_value_store.js +71 -40
- package/dist/resource_clients/key_value_store_collection.d.ts +6 -2
- package/dist/resource_clients/key_value_store_collection.js +13 -2
- package/dist/resource_clients/log.d.ts +9 -19
- package/dist/resource_clients/log.js +57 -45
- package/dist/resource_clients/request_queue.d.ts +56 -26
- package/dist/resource_clients/request_queue.js +178 -113
- package/dist/resource_clients/request_queue_collection.d.ts +6 -2
- package/dist/resource_clients/request_queue_collection.js +10 -3
- package/dist/resource_clients/run.d.ts +51 -17
- package/dist/resource_clients/run.js +85 -44
- package/dist/resource_clients/run_collection.d.ts +3 -1
- package/dist/resource_clients/run_collection.js +5 -1
- package/dist/resource_clients/schedule.d.ts +16 -7
- package/dist/resource_clients/schedule.js +31 -21
- package/dist/resource_clients/schedule_collection.d.ts +6 -2
- package/dist/resource_clients/schedule_collection.js +10 -3
- package/dist/resource_clients/store_collection.d.ts +3 -1
- package/dist/resource_clients/store_collection.js +5 -1
- package/dist/resource_clients/task.d.ts +28 -10
- package/dist/resource_clients/task.js +67 -44
- package/dist/resource_clients/task_collection.d.ts +6 -2
- package/dist/resource_clients/task_collection.js +10 -3
- package/dist/resource_clients/user.d.ts +17 -8
- package/dist/resource_clients/user.js +40 -39
- package/dist/resource_clients/webhook.d.ts +14 -5
- package/dist/resource_clients/webhook.js +30 -22
- package/dist/resource_clients/webhook_collection.d.ts +6 -2
- package/dist/resource_clients/webhook_collection.js +10 -3
- package/dist/resource_clients/webhook_dispatch.d.ts +4 -1
- package/dist/resource_clients/webhook_dispatch.js +8 -2
- package/dist/resource_clients/webhook_dispatch_collection.d.ts +3 -1
- package/dist/resource_clients/webhook_dispatch_collection.js +5 -1
- package/dist/response_validation_error.d.ts +26 -0
- package/dist/response_validation_error.js +37 -0
- package/dist/runtime/node.d.ts +6 -0
- package/dist/runtime/node.js +58 -0
- package/dist/runtime/types.d.ts +50 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/web.d.ts +5 -0
- package/dist/runtime/web.js +17 -0
- package/dist/schemas.d.ts +15 -0
- package/dist/schemas.js +15 -0
- package/dist/statistics.d.ts +1 -6
- package/dist/statistics.js +2 -2
- package/dist/timeouts.d.ts +72 -0
- package/dist/timeouts.js +31 -0
- package/dist/utils.d.ts +75 -55
- package/dist/utils.js +201 -180
- package/package.json +42 -35
- package/dist/argument_validation_error.d.ts +0 -17
- package/dist/argument_validation_error.js +0 -153
package/dist/base/api_client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { toPath, toPathSegment } from '../utils.js';
|
|
1
|
+
import { SCANNED_COUNT, toPath, toPathSegment } from '../utils.js';
|
|
2
2
|
/** @private */
|
|
3
3
|
export class ApiClient {
|
|
4
4
|
id;
|
|
@@ -16,7 +16,7 @@ export class ApiClient {
|
|
|
16
16
|
constructor(options) {
|
|
17
17
|
const { baseUrl, publicBaseUrl, apifyClient, httpClient, resourcePath, id, params = {} } = options;
|
|
18
18
|
this.id = id;
|
|
19
|
-
this.safeId = id && this.
|
|
19
|
+
this.safeId = id && this.toSafeId(id);
|
|
20
20
|
this.baseUrl = baseUrl;
|
|
21
21
|
this.publicBaseUrl = publicBaseUrl;
|
|
22
22
|
this.resourcePath = resourcePath;
|
|
@@ -25,35 +25,35 @@ export class ApiClient {
|
|
|
25
25
|
this.httpClient = httpClient;
|
|
26
26
|
this.params = params;
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
subResourceOptions(moreOptions) {
|
|
29
29
|
const baseOptions = {
|
|
30
|
-
baseUrl: this.
|
|
30
|
+
baseUrl: this.buildUrl(),
|
|
31
31
|
publicBaseUrl: this.publicBaseUrl,
|
|
32
32
|
apifyClient: this.apifyClient,
|
|
33
33
|
httpClient: this.httpClient,
|
|
34
|
-
params: this.
|
|
34
|
+
params: this.buildParams(),
|
|
35
35
|
};
|
|
36
36
|
return { ...baseOptions, ...moreOptions };
|
|
37
37
|
}
|
|
38
|
-
|
|
38
|
+
buildUrl(path) {
|
|
39
39
|
return path ? `${this.url}/${toPath(path)}` : this.url;
|
|
40
40
|
}
|
|
41
|
-
|
|
41
|
+
buildPublicUrl(path) {
|
|
42
42
|
const url = this.id
|
|
43
43
|
? `${this.publicBaseUrl}/${this.resourcePath}/${toPathSegment(this.safeId)}`
|
|
44
44
|
: `${this.publicBaseUrl}/${this.resourcePath}`;
|
|
45
45
|
return path ? `${url}/${toPath(path)}` : url;
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
buildParams(endpointParams) {
|
|
48
48
|
return { ...this.params, ...endpointParams };
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
toSafeId(id) {
|
|
51
51
|
return id.replaceAll('/', '~');
|
|
52
52
|
}
|
|
53
53
|
/**
|
|
54
54
|
* Returns async iterator to iterate through all items and Promise that can be awaited to get first page of results.
|
|
55
55
|
*/
|
|
56
|
-
|
|
56
|
+
listPaginatedFromCallback(getPaginatedList, options = {}) {
|
|
57
57
|
const minForLimitParam = (a, b) => {
|
|
58
58
|
// API treats 0 as undefined for limit parameter
|
|
59
59
|
if (a === 0)
|
|
@@ -67,20 +67,27 @@ export class ApiClient {
|
|
|
67
67
|
return Math.min(a, b);
|
|
68
68
|
};
|
|
69
69
|
// `chunkSize` only sizes this loop's requests; it is not an API parameter, so it must not reach
|
|
70
|
-
// `
|
|
70
|
+
// `buildParams()` and the query string. The same goes for `timeoutSecs`, which callers take out before
|
|
71
|
+
// calling this, since it also picks the timeout of every page request.
|
|
71
72
|
const { chunkSize, ...listOptions } = options;
|
|
72
73
|
const paginatedListPromise = getPaginatedList({
|
|
73
74
|
...listOptions,
|
|
74
75
|
limit: minForLimitParam(options.limit, chunkSize),
|
|
75
76
|
});
|
|
77
|
+
// A page can return more or fewer items than the rows it scanned (see `SCANNED_COUNT`). The next offset and
|
|
78
|
+
// the stop condition follow the scanned number alone: advancing by `items.length` would re-scan rows after a
|
|
79
|
+
// filter dropped some and skip rows after `unwind` multiplied them, and stopping at an empty page would end
|
|
80
|
+
// the iteration in front of rows a filter hid.
|
|
81
|
+
const scannedRows = (page) => page[SCANNED_COUNT] ?? page.items.length;
|
|
76
82
|
async function* asyncGenerator() {
|
|
77
83
|
let currentPage = await paginatedListPromise;
|
|
78
84
|
yield* currentPage.items;
|
|
79
85
|
const offset = options.offset ?? 0;
|
|
80
86
|
const limit = Math.min(options.limit || currentPage.total, currentPage.total);
|
|
81
|
-
let
|
|
82
|
-
let
|
|
83
|
-
|
|
87
|
+
let pageScanned = scannedRows(currentPage);
|
|
88
|
+
let currentOffset = offset + pageScanned;
|
|
89
|
+
let remainingItems = Math.min(currentPage.total - offset, limit) - pageScanned;
|
|
90
|
+
while (pageScanned > 0 && // Continue only if the last page scanned some rows.
|
|
84
91
|
remainingItems > 0) {
|
|
85
92
|
const newOptions = {
|
|
86
93
|
...listOptions,
|
|
@@ -89,8 +96,9 @@ export class ApiClient {
|
|
|
89
96
|
};
|
|
90
97
|
currentPage = await getPaginatedList(newOptions);
|
|
91
98
|
yield* currentPage.items;
|
|
92
|
-
|
|
93
|
-
|
|
99
|
+
pageScanned = scannedRows(currentPage);
|
|
100
|
+
currentOffset += pageScanned;
|
|
101
|
+
remainingItems -= pageScanned;
|
|
94
102
|
}
|
|
95
103
|
}
|
|
96
104
|
return Object.defineProperty(paginatedListPromise, Symbol.asyncIterator, {
|
|
@@ -1,24 +1,38 @@
|
|
|
1
1
|
import type { ACT_JOB_STATUSES } from '@apify/consts';
|
|
2
|
+
import type { z } from 'zod';
|
|
3
|
+
import type { Timeout, TimeoutOptions, TimeoutTier } from '../timeouts.js';
|
|
2
4
|
import { ApiClient } from './api_client.js';
|
|
3
|
-
export declare const SMALL_TIMEOUT_MILLIS: number;
|
|
4
|
-
export declare const MEDIUM_TIMEOUT_MILLIS: number;
|
|
5
|
-
export declare const DEFAULT_TIMEOUT_MILLIS: number;
|
|
6
5
|
/**
|
|
7
6
|
* Resource client.
|
|
8
7
|
* @private
|
|
9
8
|
*/
|
|
10
9
|
export declare class ResourceClient extends ApiClient {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Picks the timeout of a request that asks the API to hold its response with `waitForFinish`. The request
|
|
12
|
+
* gets the hold the caller asked for plus the round trip its tier allows, so the client does not abort a
|
|
13
|
+
* request while the API is still holding it - which for `start()` and `build()` would retry a call that
|
|
14
|
+
* creates a resource. An explicit per-call `timeoutSecs` is used as given.
|
|
15
|
+
*/
|
|
16
|
+
protected timeoutForWaitForFinish(timeoutSecs: Timeout | undefined, tier: TimeoutTier, waitForFinishSecs: number | undefined): Timeout;
|
|
17
|
+
/**
|
|
18
|
+
* A 404 resolves to `undefined` only when the client names its resource by ID. A chained client without one, such
|
|
19
|
+
* as `run.dataset()`, throws it instead (see `catchNotFoundForResourceOrThrow()`).
|
|
20
|
+
*/
|
|
21
|
+
protected getResource<T, R>(schema: z.ZodType, options: T, timeoutSecs: Timeout): Promise<R | undefined>;
|
|
22
|
+
protected updateResource<T, R>(schema: z.ZodType, newFields: T, timeoutSecs: Timeout): Promise<R>;
|
|
23
|
+
/**
|
|
24
|
+
* A 404 is swallowed, keeping the DELETE idempotent, only when the client names its resource by ID. A chained client
|
|
25
|
+
* without one throws it instead (see `catchNotFoundForResourceOrThrow()`).
|
|
26
|
+
*/
|
|
27
|
+
protected deleteResource(timeoutSecs: Timeout): Promise<void>;
|
|
14
28
|
/**
|
|
15
29
|
* This function is used in Build and Run endpoints so it's kept
|
|
16
30
|
* here to stay DRY.
|
|
17
31
|
*/
|
|
18
|
-
protected
|
|
32
|
+
protected waitForJobFinish<R extends {
|
|
19
33
|
status: (typeof ACT_JOB_STATUSES)[keyof typeof ACT_JOB_STATUSES];
|
|
20
|
-
}>(options?: WaitForFinishOptions): Promise<R>;
|
|
34
|
+
}>(schema: z.ZodType, options?: WaitForFinishOptions): Promise<R>;
|
|
21
35
|
}
|
|
22
|
-
export interface WaitForFinishOptions {
|
|
36
|
+
export interface WaitForFinishOptions extends TimeoutOptions {
|
|
23
37
|
waitSecs?: number;
|
|
24
38
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ACT_JOB_TERMINAL_STATUSES } from '@apify/consts';
|
|
2
|
-
import {
|
|
2
|
+
import { catchNotFoundForResourceOrThrow, catchNotFoundOrThrow, parseResponse } from '../utils.js';
|
|
3
3
|
import { ApiClient } from './api_client.js';
|
|
4
4
|
/**
|
|
5
5
|
* We need to supply some number for the API,
|
|
@@ -7,59 +7,82 @@ import { ApiClient } from './api_client.js';
|
|
|
7
7
|
* 999999 seconds is more than 10 days.
|
|
8
8
|
*/
|
|
9
9
|
const MAX_WAIT_FOR_FINISH = 999999;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export const DEFAULT_TIMEOUT_MILLIS = 360 * 1000; // 6 minutes
|
|
10
|
+
/** The API holds a `waitForFinish` response for at most a minute, however long the parameter asks for. */
|
|
11
|
+
const MAX_WAIT_FOR_FINISH_HOLD_SECS = 60;
|
|
13
12
|
/**
|
|
14
13
|
* Resource client.
|
|
15
14
|
* @private
|
|
16
15
|
*/
|
|
17
16
|
export class ResourceClient extends ApiClient {
|
|
18
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Picks the timeout of a request that asks the API to hold its response with `waitForFinish`. The request
|
|
19
|
+
* gets the hold the caller asked for plus the round trip its tier allows, so the client does not abort a
|
|
20
|
+
* request while the API is still holding it - which for `start()` and `build()` would retry a call that
|
|
21
|
+
* creates a resource. An explicit per-call `timeoutSecs` is used as given.
|
|
22
|
+
*/
|
|
23
|
+
timeoutForWaitForFinish(timeoutSecs, tier, waitForFinishSecs) {
|
|
24
|
+
if (timeoutSecs !== undefined)
|
|
25
|
+
return timeoutSecs;
|
|
26
|
+
if (waitForFinishSecs === undefined)
|
|
27
|
+
return tier;
|
|
28
|
+
const holdSecs = Math.min(waitForFinishSecs, MAX_WAIT_FOR_FINISH_HOLD_SECS);
|
|
29
|
+
if (holdSecs <= 0)
|
|
30
|
+
return tier;
|
|
31
|
+
return holdSecs + this.httpClient.timeoutMillis[tier] / 1000;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A 404 resolves to `undefined` only when the client names its resource by ID. A chained client without one, such
|
|
35
|
+
* as `run.dataset()`, throws it instead (see `catchNotFoundForResourceOrThrow()`).
|
|
36
|
+
*/
|
|
37
|
+
async getResource(schema, options, timeoutSecs) {
|
|
19
38
|
const requestOpts = {
|
|
20
|
-
url: this.
|
|
39
|
+
url: this.buildUrl(),
|
|
21
40
|
method: 'GET',
|
|
22
|
-
params: this.
|
|
23
|
-
|
|
41
|
+
params: this.buildParams(options),
|
|
42
|
+
timeoutSecs,
|
|
24
43
|
};
|
|
25
44
|
try {
|
|
26
45
|
const response = await this.httpClient.call(requestOpts);
|
|
27
|
-
return
|
|
46
|
+
return parseResponse(response, schema);
|
|
28
47
|
}
|
|
29
48
|
catch (err) {
|
|
30
|
-
|
|
49
|
+
catchNotFoundForResourceOrThrow(err, this.id);
|
|
31
50
|
}
|
|
32
51
|
return undefined;
|
|
33
52
|
}
|
|
34
|
-
async
|
|
53
|
+
async updateResource(schema, newFields, timeoutSecs) {
|
|
35
54
|
const response = await this.httpClient.call({
|
|
36
|
-
url: this.
|
|
55
|
+
url: this.buildUrl(),
|
|
37
56
|
method: 'PUT',
|
|
38
|
-
params: this.
|
|
57
|
+
params: this.buildParams(),
|
|
39
58
|
data: newFields,
|
|
40
|
-
|
|
59
|
+
timeoutSecs,
|
|
41
60
|
});
|
|
42
|
-
return
|
|
61
|
+
return parseResponse(response, schema);
|
|
43
62
|
}
|
|
44
|
-
|
|
63
|
+
/**
|
|
64
|
+
* A 404 is swallowed, keeping the DELETE idempotent, only when the client names its resource by ID. A chained client
|
|
65
|
+
* without one throws it instead (see `catchNotFoundForResourceOrThrow()`).
|
|
66
|
+
*/
|
|
67
|
+
async deleteResource(timeoutSecs) {
|
|
45
68
|
try {
|
|
46
69
|
await this.httpClient.call({
|
|
47
|
-
url: this.
|
|
70
|
+
url: this.buildUrl(),
|
|
48
71
|
method: 'DELETE',
|
|
49
|
-
params: this.
|
|
50
|
-
|
|
72
|
+
params: this.buildParams(),
|
|
73
|
+
timeoutSecs,
|
|
51
74
|
});
|
|
52
75
|
}
|
|
53
76
|
catch (err) {
|
|
54
|
-
|
|
77
|
+
catchNotFoundForResourceOrThrow(err, this.id);
|
|
55
78
|
}
|
|
56
79
|
}
|
|
57
80
|
/**
|
|
58
81
|
* This function is used in Build and Run endpoints so it's kept
|
|
59
82
|
* here to stay DRY.
|
|
60
83
|
*/
|
|
61
|
-
async
|
|
62
|
-
const { waitSecs = MAX_WAIT_FOR_FINISH } = options;
|
|
84
|
+
async waitForJobFinish(schema, options = {}) {
|
|
85
|
+
const { waitSecs = MAX_WAIT_FOR_FINISH, timeoutSecs = 'noTimeout' } = options;
|
|
63
86
|
const waitMillis = waitSecs * 1000;
|
|
64
87
|
let job;
|
|
65
88
|
const startedAt = Date.now();
|
|
@@ -75,13 +98,14 @@ export class ResourceClient extends ApiClient {
|
|
|
75
98
|
const remainingWaitSeconds = Math.round((waitMillis - millisSinceStart) / 1000);
|
|
76
99
|
const waitForFinish = Math.max(0, remainingWaitSeconds);
|
|
77
100
|
const requestOpts = {
|
|
78
|
-
url: this.
|
|
101
|
+
url: this.buildUrl(),
|
|
79
102
|
method: 'GET',
|
|
80
|
-
params: this.
|
|
103
|
+
params: this.buildParams({ waitForFinish }),
|
|
104
|
+
timeoutSecs,
|
|
81
105
|
};
|
|
82
106
|
try {
|
|
83
107
|
const response = await this.httpClient.call(requestOpts);
|
|
84
|
-
job =
|
|
108
|
+
job = parseResponse(response, schema);
|
|
85
109
|
}
|
|
86
110
|
catch (err) {
|
|
87
111
|
catchNotFoundOrThrow(err);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import type { Timeout, TimeoutOptions } from '../timeouts.js';
|
|
1
3
|
import type { PaginatedResponse, PaginationOptions } from '../utils.js';
|
|
2
4
|
import { ApiClient } from './api_client.js';
|
|
3
5
|
/**
|
|
@@ -8,11 +10,12 @@ export declare class ResourceCollectionClient extends ApiClient {
|
|
|
8
10
|
/**
|
|
9
11
|
* @private
|
|
10
12
|
*/
|
|
11
|
-
protected
|
|
13
|
+
protected listResources<T, R>(schema: z.ZodType, options: T | undefined, timeoutSecs: Timeout): Promise<R>;
|
|
12
14
|
/**
|
|
13
15
|
* Returns async iterator to iterate through all items and Promise that can be awaited to get first page of results.
|
|
16
|
+
* `defaultTimeoutSecs` applies to every page request unless `options.timeoutSecs` overrides it.
|
|
14
17
|
*/
|
|
15
|
-
protected
|
|
16
|
-
protected
|
|
17
|
-
protected
|
|
18
|
+
protected listResourcesPaginated<T extends PaginationOptions & TimeoutOptions, Data, R extends PaginatedResponse<Data>>(schema: z.ZodType, options: T, defaultTimeoutSecs: Timeout): AsyncIterable<Data> & Promise<R>;
|
|
19
|
+
protected createResource<D, R>(schema: z.ZodType, resource: D, timeoutSecs: Timeout): Promise<R>;
|
|
20
|
+
protected getOrCreateResource<D, R>(schema: z.ZodType, name: string | undefined, resource: D | undefined, timeoutSecs: Timeout): Promise<R>;
|
|
18
21
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseResponse } from '../utils.js';
|
|
2
2
|
import { ApiClient } from './api_client.js';
|
|
3
3
|
/**
|
|
4
4
|
* Resource collection client.
|
|
@@ -8,36 +8,42 @@ export class ResourceCollectionClient extends ApiClient {
|
|
|
8
8
|
/**
|
|
9
9
|
* @private
|
|
10
10
|
*/
|
|
11
|
-
async
|
|
11
|
+
async listResources(schema, options, timeoutSecs) {
|
|
12
12
|
const response = await this.httpClient.call({
|
|
13
|
-
url: this.
|
|
13
|
+
url: this.buildUrl(),
|
|
14
14
|
method: 'GET',
|
|
15
|
-
params: this.
|
|
15
|
+
params: this.buildParams(options),
|
|
16
|
+
timeoutSecs,
|
|
16
17
|
});
|
|
17
|
-
return
|
|
18
|
+
return parseResponse(response, schema);
|
|
18
19
|
}
|
|
19
20
|
/**
|
|
20
21
|
* Returns async iterator to iterate through all items and Promise that can be awaited to get first page of results.
|
|
22
|
+
* `defaultTimeoutSecs` applies to every page request unless `options.timeoutSecs` overrides it.
|
|
21
23
|
*/
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
listResourcesPaginated(schema, options, defaultTimeoutSecs) {
|
|
25
|
+
// `timeoutSecs` only times the page requests; it is not an API parameter, so it must not reach the query string.
|
|
26
|
+
const { timeoutSecs = defaultTimeoutSecs, ...listOptions } = options;
|
|
27
|
+
return this.listPaginatedFromCallback(async (pageOptions) => this.listResources(schema, pageOptions, timeoutSecs), listOptions);
|
|
24
28
|
}
|
|
25
|
-
async
|
|
29
|
+
async createResource(schema, resource, timeoutSecs) {
|
|
26
30
|
const response = await this.httpClient.call({
|
|
27
|
-
url: this.
|
|
31
|
+
url: this.buildUrl(),
|
|
28
32
|
method: 'POST',
|
|
29
|
-
params: this.
|
|
33
|
+
params: this.buildParams(),
|
|
30
34
|
data: resource,
|
|
35
|
+
timeoutSecs,
|
|
31
36
|
});
|
|
32
|
-
return
|
|
37
|
+
return parseResponse(response, schema);
|
|
33
38
|
}
|
|
34
|
-
async
|
|
39
|
+
async getOrCreateResource(schema, name, resource, timeoutSecs) {
|
|
35
40
|
const response = await this.httpClient.call({
|
|
36
|
-
url: this.
|
|
41
|
+
url: this.buildUrl(),
|
|
37
42
|
method: 'POST',
|
|
38
|
-
params: this.
|
|
43
|
+
params: this.buildParams({ name }),
|
|
39
44
|
data: resource,
|
|
45
|
+
timeoutSecs,
|
|
40
46
|
});
|
|
41
|
-
return
|
|
47
|
+
return parseResponse(response, schema);
|
|
42
48
|
}
|
|
43
49
|
}
|
package/dist/body_parser.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import type { JsonArray, JsonObject } from 'type-fest';
|
|
2
2
|
/**
|
|
3
|
-
* Parses a
|
|
3
|
+
* Parses a binary response body using the provided content type header.
|
|
4
4
|
*
|
|
5
5
|
* - application/json is returned as a parsed object.
|
|
6
6
|
* - application/*xml and text/* are returned as strings.
|
|
7
7
|
* - everything else is returned as original body.
|
|
8
8
|
*
|
|
9
9
|
* If the header includes a charset, the body will be stringified only
|
|
10
|
-
* if the charset
|
|
10
|
+
* if the charset is an encoding `TextDecoder` knows.
|
|
11
11
|
*/
|
|
12
|
-
export declare function maybeParseBody(body:
|
|
13
|
-
export declare function isomorphicBufferToString(buffer: Buffer | ArrayBuffer, encoding: BufferEncoding): string;
|
|
12
|
+
export declare function maybeParseBody(body: ArrayBuffer | ArrayBufferView, contentTypeHeader: string): string | ArrayBuffer | ArrayBufferView | JsonObject | JsonArray;
|
package/dist/body_parser.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
import contentTypeParser from 'content-type';
|
|
2
|
-
import { isNode } from './utils.js';
|
|
3
2
|
const CONTENT_TYPE_JSON = 'application/json';
|
|
4
3
|
const STRINGIFIABLE_CONTENT_TYPE_RXS = [new RegExp(`^${CONTENT_TYPE_JSON}`, 'i'), /^application\/.*xml$/i, /^text\//i];
|
|
5
4
|
/**
|
|
6
|
-
* Parses a
|
|
5
|
+
* Parses a binary response body using the provided content type header.
|
|
7
6
|
*
|
|
8
7
|
* - application/json is returned as a parsed object.
|
|
9
8
|
* - application/*xml and text/* are returned as strings.
|
|
10
9
|
* - everything else is returned as original body.
|
|
11
10
|
*
|
|
12
11
|
* If the header includes a charset, the body will be stringified only
|
|
13
|
-
* if the charset
|
|
12
|
+
* if the charset is an encoding `TextDecoder` knows.
|
|
14
13
|
*/
|
|
15
14
|
export function maybeParseBody(body, contentTypeHeader) {
|
|
16
15
|
let contentType;
|
|
@@ -24,35 +23,29 @@ export function maybeParseBody(body, contentTypeHeader) {
|
|
|
24
23
|
// can't parse, keep original body
|
|
25
24
|
return body;
|
|
26
25
|
}
|
|
27
|
-
|
|
26
|
+
if (!isContentTypeStringifiable(contentType))
|
|
27
|
+
return body;
|
|
28
|
+
// If we can't successfully decode it, we return
|
|
28
29
|
// the original buffer rather than a mangled string.
|
|
29
|
-
|
|
30
|
+
const decoder = createDecoder(charset);
|
|
31
|
+
if (!decoder)
|
|
30
32
|
return body;
|
|
31
|
-
const dataString =
|
|
33
|
+
const dataString = decoder.decode(body);
|
|
32
34
|
return contentType === CONTENT_TYPE_JSON ? JSON.parse(dataString) : dataString;
|
|
33
35
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
function createDecoder(charset) {
|
|
37
|
+
try {
|
|
38
|
+
// No charset defaults to utf-8. A leading BOM is kept, so a BOM-prefixed CSV stored in a key-value store
|
|
39
|
+
// round-trips through `getRecord()` unchanged.
|
|
40
|
+
return new TextDecoder(charset, { ignoreBOM: true });
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// `TextDecoder` throws a `RangeError` for a label it does not know.
|
|
44
|
+
return undefined;
|
|
37
45
|
}
|
|
38
|
-
// Browser decoding only works with UTF-8.
|
|
39
|
-
const utf8decoder = new TextDecoder();
|
|
40
|
-
return utf8decoder.decode(new Uint8Array(buffer));
|
|
41
|
-
}
|
|
42
|
-
function isCharsetStringifiable(charset) {
|
|
43
|
-
if (!charset)
|
|
44
|
-
return true; // hope that it's utf-8
|
|
45
|
-
if (isNode())
|
|
46
|
-
return Buffer.isEncoding(charset);
|
|
47
|
-
const normalizedCharset = charset.toLowerCase().replace('-', '');
|
|
48
|
-
// Browsers only support decoding utf-8 buffers.
|
|
49
|
-
return normalizedCharset === 'utf8';
|
|
50
46
|
}
|
|
51
47
|
function isContentTypeStringifiable(contentType) {
|
|
52
48
|
if (!contentType)
|
|
53
49
|
return false; // keep buffer
|
|
54
50
|
return STRINGIFIABLE_CONTENT_TYPE_RXS.some((rx) => rx.test(contentType));
|
|
55
51
|
}
|
|
56
|
-
function areDataStringifiable(contentType, charset) {
|
|
57
|
-
return isContentTypeStringifiable(contentType) && isCharsetStringifiable(charset);
|
|
58
|
-
}
|