apify-client 3.0.0-beta.4 → 3.0.0-beta.41
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 +13 -3
- package/dist/apify_api_error.d.ts +62 -21
- package/dist/apify_api_error.js +96 -23
- package/dist/apify_client.d.ts +125 -10
- package/dist/apify_client.js +133 -48
- package/dist/base/api_client.d.ts +7 -7
- package/dist/base/api_client.js +24 -16
- package/dist/base/resource_client.d.ts +23 -9
- package/dist/base/resource_client.js +57 -29
- package/dist/base/resource_collection_client.d.ts +8 -4
- package/dist/base/resource_collection_client.js +26 -15
- package/dist/body_parser.d.ts +3 -4
- package/dist/body_parser.js +19 -26
- package/dist/bundle.js +29 -22
- package/dist/bundle.js.map +1 -1
- package/dist/generated/api.d.ts +887 -322
- package/dist/generated/schemas.d.ts +6717 -0
- package/dist/generated/schemas.js +1527 -0
- package/dist/http_clients/axios.d.ts +60 -0
- package/dist/http_clients/axios.js +117 -0
- package/dist/http_clients/base.d.ts +333 -0
- package/dist/http_clients/base.js +563 -0
- package/dist/http_clients/index.d.ts +4 -0
- package/dist/http_clients/index.js +2 -0
- package/dist/http_compressors/base.d.ts +40 -0
- package/dist/http_compressors/base.js +9 -0
- package/dist/http_compressors/brotli.d.ts +33 -0
- package/dist/http_compressors/brotli.js +39 -0
- package/dist/http_compressors/gzip.d.ts +33 -0
- package/dist/http_compressors/gzip.js +39 -0
- package/dist/http_compressors/index.d.ts +6 -0
- package/dist/http_compressors/index.js +2 -0
- package/dist/http_compressors/resolve.d.ts +23 -0
- package/dist/http_compressors/resolve.js +27 -0
- package/dist/index.d.ts +5 -1
- package/dist/index.js +4 -1
- package/dist/invalid_response_body_error.d.ts +13 -0
- package/dist/invalid_response_body_error.js +17 -0
- package/dist/lazy_schema.d.ts +8 -0
- package/dist/lazy_schema.js +11 -0
- package/dist/models.d.ts +33 -61
- package/dist/resource_clients/actor.d.ts +52 -31
- package/dist/resource_clients/actor.js +81 -58
- 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 +37 -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 +49 -31
- package/dist/resource_clients/dataset.js +102 -76
- package/dist/resource_clients/dataset_collection.d.ts +6 -2
- package/dist/resource_clients/dataset_collection.js +14 -2
- package/dist/resource_clients/key_value_store.d.ts +58 -16
- package/dist/resource_clients/key_value_store.js +80 -41
- package/dist/resource_clients/key_value_store_collection.d.ts +6 -2
- package/dist/resource_clients/key_value_store_collection.js +14 -2
- package/dist/resource_clients/log.d.ts +11 -19
- package/dist/resource_clients/log.js +64 -46
- package/dist/resource_clients/request_queue.d.ts +56 -26
- package/dist/resource_clients/request_queue.js +197 -116
- 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 +53 -18
- package/dist/resource_clients/run.js +94 -47
- 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 +32 -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 +71 -46
- 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 +43 -39
- package/dist/resource_clients/webhook.d.ts +14 -5
- package/dist/resource_clients/webhook.js +31 -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 +49 -0
- package/dist/runtime/types.d.ts +52 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/web.d.ts +5 -0
- package/dist/runtime/web.js +18 -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 +84 -0
- package/dist/timeouts.js +37 -0
- package/dist/timezones.d.ts +1 -1
- package/dist/utils.d.ts +86 -46
- package/dist/utils.js +218 -164
- package/package.json +32 -29
- package/dist/http_client.d.ts +0 -88
- package/dist/http_client.js +0 -255
- package/dist/interceptors.d.ts +0 -19
- package/dist/interceptors.js +0 -105
|
@@ -1,7 +1,23 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { createStorageContentSignatureAsync } from '@apify/utilities';
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { ResourceClient } from '../base/resource_client.js';
|
|
4
|
+
import * as schemas from '../schemas.js';
|
|
5
|
+
import { timeoutOptionsSchema, timeoutOptionsShape } from '../timeouts.js';
|
|
6
|
+
import { anyObjectSchema, applyQueryParamsToUrl, cast, isNonArrayObject, paginationOptionsShape, parseArgument, parseResponse, SCANNED_COUNT, } from '../utils.js';
|
|
7
|
+
/**
|
|
8
|
+
* Supported formats for downloading dataset items.
|
|
9
|
+
*/
|
|
10
|
+
export var DownloadItemsFormat;
|
|
11
|
+
(function (DownloadItemsFormat) {
|
|
12
|
+
DownloadItemsFormat["JSON"] = "json";
|
|
13
|
+
DownloadItemsFormat["JSONL"] = "jsonl";
|
|
14
|
+
DownloadItemsFormat["XML"] = "xml";
|
|
15
|
+
DownloadItemsFormat["HTML"] = "html";
|
|
16
|
+
DownloadItemsFormat["CSV"] = "csv";
|
|
17
|
+
DownloadItemsFormat["XLSX"] = "xlsx";
|
|
18
|
+
DownloadItemsFormat["RSS"] = "rss";
|
|
19
|
+
})(DownloadItemsFormat || (DownloadItemsFormat = {}));
|
|
20
|
+
const itemFormatSchema = z.enum(DownloadItemsFormat);
|
|
5
21
|
// A predicate, not a `z.object()` arm, which would walk and copy every key of every pushed item.
|
|
6
22
|
const itemSchema = z.custom(isNonArrayObject, 'Expected an object');
|
|
7
23
|
const listItemsOptionsSchema = z.strictObject({
|
|
@@ -16,6 +32,7 @@ const listItemsOptionsSchema = z.strictObject({
|
|
|
16
32
|
unwind: z.union([z.string(), z.array(z.string())]).optional(),
|
|
17
33
|
view: z.string().optional(),
|
|
18
34
|
signature: z.string().optional(),
|
|
35
|
+
...timeoutOptionsShape,
|
|
19
36
|
});
|
|
20
37
|
// Spells out `limit` / `offset` instead of spreading `paginationOptionsShape`: a download is one
|
|
21
38
|
// request, so `chunkSize` has nothing to size. The options type omits it to match.
|
|
@@ -38,15 +55,18 @@ const downloadItemsOptionsSchema = z.strictObject({
|
|
|
38
55
|
xmlRoot: z.string().optional(),
|
|
39
56
|
xmlRow: z.string().optional(),
|
|
40
57
|
signature: z.string().optional(),
|
|
58
|
+
...timeoutOptionsShape,
|
|
41
59
|
});
|
|
42
|
-
const pushItemsSchema = z.union([itemSchema, z.string(), z.array(
|
|
43
|
-
//
|
|
44
|
-
// `signature` (which this method produces) are left out. The options type
|
|
60
|
+
const pushItemsSchema = z.union([itemSchema, z.string(), z.array(itemSchema)]);
|
|
61
|
+
// Apart from `timeoutSecs`, `signal` and `expiresInSecs`, every option becomes a query parameter of the generated
|
|
62
|
+
// URL, so `chunkSize` (client-side only) and `signature` (which this method produces) are left out. The options type
|
|
63
|
+
// omits both to match.
|
|
45
64
|
const createItemsPublicUrlOptionsSchema = z.strictObject({
|
|
46
65
|
clean: z.boolean().optional(),
|
|
47
66
|
desc: z.boolean().optional(),
|
|
48
67
|
flatten: z.array(z.string()).optional(),
|
|
49
68
|
fields: z.array(z.string()).optional(),
|
|
69
|
+
format: itemFormatSchema.optional(),
|
|
50
70
|
omit: z.array(z.string()).optional(),
|
|
51
71
|
limit: z.number().min(0).optional(),
|
|
52
72
|
offset: z.number().min(0).optional(),
|
|
@@ -55,6 +75,7 @@ const createItemsPublicUrlOptionsSchema = z.strictObject({
|
|
|
55
75
|
unwind: z.union([z.string(), z.array(z.string())]).optional(),
|
|
56
76
|
view: z.string().optional(),
|
|
57
77
|
expiresInSecs: z.number().optional(),
|
|
78
|
+
...timeoutOptionsShape,
|
|
58
79
|
});
|
|
59
80
|
/**
|
|
60
81
|
* Client for managing a specific Dataset.
|
|
@@ -98,30 +119,39 @@ export class DatasetClient extends ResourceClient {
|
|
|
98
119
|
/**
|
|
99
120
|
* Gets the dataset object from the Apify API.
|
|
100
121
|
*
|
|
122
|
+
* @param options - Request options
|
|
123
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
101
124
|
* @returns The Dataset object, or `undefined` if it does not exist
|
|
102
125
|
* @see https://docs.apify.com/api/v2/dataset-get
|
|
103
126
|
*/
|
|
104
|
-
async get() {
|
|
105
|
-
|
|
127
|
+
async get(options = {}) {
|
|
128
|
+
const { timeoutSecs = 'short', signal } = parseArgument(options, timeoutOptionsSchema, 'TimeoutOptions');
|
|
129
|
+
return this.getResource(schemas.Dataset(), {}, timeoutSecs, signal);
|
|
106
130
|
}
|
|
107
131
|
/**
|
|
108
132
|
* Updates the dataset with specified fields.
|
|
109
133
|
*
|
|
110
134
|
* @param newFields - Fields to update in the dataset
|
|
135
|
+
* @param options - Request options
|
|
136
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
111
137
|
* @returns The updated Dataset object
|
|
112
138
|
* @see https://docs.apify.com/api/v2/dataset-put
|
|
113
139
|
*/
|
|
114
|
-
async update(newFields) {
|
|
140
|
+
async update(newFields, options = {}) {
|
|
115
141
|
parseArgument(newFields, anyObjectSchema);
|
|
116
|
-
|
|
142
|
+
const { timeoutSecs = 'short', signal } = parseArgument(options, timeoutOptionsSchema, 'TimeoutOptions');
|
|
143
|
+
return this.updateResource(schemas.Dataset(), newFields, timeoutSecs, signal);
|
|
117
144
|
}
|
|
118
145
|
/**
|
|
119
146
|
* Deletes the dataset.
|
|
120
147
|
*
|
|
148
|
+
* @param options - Request options
|
|
149
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
121
150
|
* @see https://docs.apify.com/api/v2/dataset-delete
|
|
122
151
|
*/
|
|
123
|
-
async delete() {
|
|
124
|
-
|
|
152
|
+
async delete(options = {}) {
|
|
153
|
+
const { timeoutSecs = 'short', signal } = parseArgument(options, timeoutOptionsSchema, 'TimeoutOptions');
|
|
154
|
+
return this.deleteResource(timeoutSecs, signal);
|
|
125
155
|
}
|
|
126
156
|
/**
|
|
127
157
|
* Lists items in the dataset.
|
|
@@ -143,6 +173,7 @@ export class DatasetClient extends ResourceClient {
|
|
|
143
173
|
* @param options.flatten - Array of field names to flatten. Nested objects are converted to dot notation (e.g., `obj.field`).
|
|
144
174
|
* @param options.unwind - Field name or array of field names to unwind. Each array value creates a separate item.
|
|
145
175
|
* @param options.view - Name of a predefined view to use for field selection.
|
|
176
|
+
* @param options.timeoutSecs - Timeout for each API request. Default is `'long'`.
|
|
146
177
|
* @returns A paginated list with `items`, `total` count, `offset`, `count`, and `limit`
|
|
147
178
|
* @see https://docs.apify.com/api/v2/dataset-items-get
|
|
148
179
|
*
|
|
@@ -168,17 +199,18 @@ export class DatasetClient extends ResourceClient {
|
|
|
168
199
|
* ```
|
|
169
200
|
*/
|
|
170
201
|
listItems(options = {}) {
|
|
171
|
-
const
|
|
202
|
+
const { timeoutSecs = 'long', signal, ...listOptions } = parseArgument(options, listItemsOptionsSchema, 'DatasetClientListItemOptions');
|
|
172
203
|
const fetchItems = async (datasetListOptions = {}) => {
|
|
173
204
|
const response = await this.httpClient.call({
|
|
174
|
-
url: this.
|
|
205
|
+
url: this.buildUrl('items'),
|
|
175
206
|
method: 'GET',
|
|
176
|
-
params: this.
|
|
177
|
-
|
|
207
|
+
params: this.buildParams(datasetListOptions),
|
|
208
|
+
timeoutSecs,
|
|
209
|
+
signal,
|
|
178
210
|
});
|
|
179
|
-
return this
|
|
211
|
+
return this.#createPaginationList(response, datasetListOptions.desc ?? false);
|
|
180
212
|
};
|
|
181
|
-
return this.
|
|
213
|
+
return this.listPaginatedFromCallback(fetchItems, listOptions);
|
|
182
214
|
}
|
|
183
215
|
/**
|
|
184
216
|
* Downloads dataset items in a specific format.
|
|
@@ -197,6 +229,7 @@ export class DatasetClient extends ResourceClient {
|
|
|
197
229
|
* @param options.xmlRow - Name of the XML element for each item. Default is `'item'`.
|
|
198
230
|
* @param options.fields - Array of field names to include in the export.
|
|
199
231
|
* @param options.omit - Array of field names to exclude from the export.
|
|
232
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'long'`.
|
|
200
233
|
* @returns Buffer containing the serialized data in the specified format
|
|
201
234
|
* @see https://docs.apify.com/api/v2/dataset-items-get
|
|
202
235
|
*
|
|
@@ -222,29 +255,33 @@ export class DatasetClient extends ResourceClient {
|
|
|
222
255
|
*/
|
|
223
256
|
async downloadItems(format, options = {}) {
|
|
224
257
|
parseArgument(format, itemFormatSchema);
|
|
225
|
-
const
|
|
258
|
+
const { timeoutSecs = 'long', signal, ...query } = parseArgument(options, downloadItemsOptionsSchema, 'DatasetClientDownloadItemsOptions');
|
|
226
259
|
const { data } = await this.httpClient.call({
|
|
227
|
-
url: this.
|
|
260
|
+
url: this.buildUrl('items'),
|
|
228
261
|
method: 'GET',
|
|
229
|
-
params: this.
|
|
262
|
+
params: this.buildParams({
|
|
230
263
|
format,
|
|
231
|
-
...
|
|
264
|
+
...query,
|
|
232
265
|
}),
|
|
233
|
-
|
|
234
|
-
|
|
266
|
+
responseType: 'buffer',
|
|
267
|
+
timeoutSecs,
|
|
268
|
+
signal,
|
|
235
269
|
});
|
|
236
270
|
return cast(data);
|
|
237
271
|
}
|
|
238
272
|
/**
|
|
239
273
|
* Stores one or more items into the dataset.
|
|
240
274
|
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
*
|
|
244
|
-
*
|
|
275
|
+
* Each item will be stored as a separate record in the dataset. Objects are automatically
|
|
276
|
+
* serialized to JSON. If you provide an array, all items will be stored in order. This method
|
|
277
|
+
* is idempotent - calling it multiple times with the same data will not create duplicates, but
|
|
278
|
+
* will append items each time.
|
|
245
279
|
*
|
|
246
|
-
* @param items - A single item
|
|
247
|
-
*
|
|
280
|
+
* @param items - A single item, an array of items, or a string that is the JSON serialization of
|
|
281
|
+
* either - the API only accepts an object or an array of objects, so a plain string
|
|
282
|
+
* is not a valid item on its own.
|
|
283
|
+
* @param options - Request options
|
|
284
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'medium'`.
|
|
248
285
|
* @see https://docs.apify.com/api/v2/dataset-items-post
|
|
249
286
|
*
|
|
250
287
|
* @example
|
|
@@ -262,23 +299,22 @@ export class DatasetClient extends ResourceClient {
|
|
|
262
299
|
* { url: 'https://test.com', title: 'Test' },
|
|
263
300
|
* { url: 'https://demo.com', title: 'Demo' }
|
|
264
301
|
* ]);
|
|
265
|
-
*
|
|
266
|
-
* // Store string items
|
|
267
|
-
* await client.dataset('my-dataset').pushItems(['item1', 'item2', 'item3']);
|
|
268
302
|
* ```
|
|
269
303
|
*/
|
|
270
|
-
async pushItems(items) {
|
|
304
|
+
async pushItems(items, options = {}) {
|
|
271
305
|
parseArgument(items, pushItemsSchema);
|
|
306
|
+
const { timeoutSecs = 'medium', signal } = parseArgument(options, timeoutOptionsSchema, 'TimeoutOptions');
|
|
272
307
|
await this.httpClient.call({
|
|
273
|
-
url: this.
|
|
308
|
+
url: this.buildUrl('items'),
|
|
274
309
|
method: 'POST',
|
|
275
310
|
headers: {
|
|
276
311
|
'content-type': 'application/json; charset=utf-8',
|
|
277
312
|
},
|
|
278
313
|
data: items,
|
|
279
|
-
params: this.
|
|
280
|
-
doNotRetryTimeouts: true,
|
|
281
|
-
|
|
314
|
+
params: this.buildParams(),
|
|
315
|
+
doNotRetryTimeouts: true,
|
|
316
|
+
timeoutSecs,
|
|
317
|
+
signal,
|
|
282
318
|
});
|
|
283
319
|
}
|
|
284
320
|
/**
|
|
@@ -287,25 +323,22 @@ export class DatasetClient extends ResourceClient {
|
|
|
287
323
|
* Returns statistics for each field in the dataset, including information about
|
|
288
324
|
* data types, null counts, and value ranges.
|
|
289
325
|
*
|
|
290
|
-
* @
|
|
326
|
+
* @param options - Request options
|
|
327
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
328
|
+
* @returns Dataset statistics
|
|
291
329
|
* @see https://docs.apify.com/api/v2/dataset-statistics-get
|
|
292
330
|
* @since Added in 2.11.2
|
|
293
331
|
*/
|
|
294
|
-
async getStatistics() {
|
|
295
|
-
const
|
|
296
|
-
|
|
332
|
+
async getStatistics(options = {}) {
|
|
333
|
+
const { timeoutSecs = 'short', signal } = parseArgument(options, timeoutOptionsSchema, 'TimeoutOptions');
|
|
334
|
+
const response = await this.httpClient.call({
|
|
335
|
+
url: this.buildUrl('statistics'),
|
|
297
336
|
method: 'GET',
|
|
298
|
-
params: this.
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return cast(pluckData(response.data));
|
|
304
|
-
}
|
|
305
|
-
catch (err) {
|
|
306
|
-
catchNotFoundOrThrow(err);
|
|
307
|
-
}
|
|
308
|
-
return undefined;
|
|
337
|
+
params: this.buildParams(),
|
|
338
|
+
timeoutSecs,
|
|
339
|
+
signal,
|
|
340
|
+
});
|
|
341
|
+
return parseResponse(response, schemas.DatasetStatistics());
|
|
309
342
|
}
|
|
310
343
|
/**
|
|
311
344
|
* Generates a public URL for accessing dataset items.
|
|
@@ -317,8 +350,10 @@ export class DatasetClient extends ResourceClient {
|
|
|
317
350
|
* @param options - URL generation options (extends all options from {@link listItems})
|
|
318
351
|
* @param options.expiresInSecs - Number of seconds until the signed URL expires. If omitted, the URL never expires.
|
|
319
352
|
* @param options.fields - Array of field names to include in the response.
|
|
353
|
+
* @param options.format - Format of the items served by the URL. Defaults to `json`.
|
|
320
354
|
* @param options.limit - Maximum number of items to return.
|
|
321
355
|
* @param options.offset - Number of items to skip.
|
|
356
|
+
* @param options.timeoutSecs - Timeout for the API request that fetches the dataset. Default is `'long'`.
|
|
322
357
|
* @returns A public URL string for accessing the dataset items
|
|
323
358
|
*
|
|
324
359
|
* @example
|
|
@@ -340,10 +375,9 @@ export class DatasetClient extends ResourceClient {
|
|
|
340
375
|
* @since Added in 2.13.0
|
|
341
376
|
*/
|
|
342
377
|
async createItemsPublicUrl(options = {}) {
|
|
343
|
-
const
|
|
344
|
-
const dataset = await this.get();
|
|
345
|
-
|
|
346
|
-
let createdItemsPublicUrl = new URL(this._publicUrl('items'));
|
|
378
|
+
const { timeoutSecs = 'long', signal, expiresInSecs, ...queryOptions } = parseArgument(options, createItemsPublicUrlOptionsSchema, 'DatasetClientCreateItemsUrlOptions');
|
|
379
|
+
const dataset = await this.get({ timeoutSecs, signal });
|
|
380
|
+
let createdItemsPublicUrl = new URL(this.buildPublicUrl('items'));
|
|
347
381
|
if (dataset?.urlSigningSecretKey) {
|
|
348
382
|
const signature = await createStorageContentSignatureAsync({
|
|
349
383
|
resourceId: dataset.id,
|
|
@@ -355,31 +389,23 @@ export class DatasetClient extends ResourceClient {
|
|
|
355
389
|
createdItemsPublicUrl = applyQueryParamsToUrl(createdItemsPublicUrl, queryOptions);
|
|
356
390
|
return createdItemsPublicUrl.toString();
|
|
357
391
|
}
|
|
358
|
-
|
|
359
|
-
|
|
392
|
+
#createPaginationList(response, userProvidedDesc) {
|
|
393
|
+
const descHeader = response.headers['x-apify-pagination-desc'];
|
|
394
|
+
const page = {
|
|
360
395
|
items: response.data,
|
|
361
396
|
total: Number(response.headers['x-apify-pagination-total']),
|
|
362
397
|
offset: Number(response.headers['x-apify-pagination-offset']),
|
|
363
|
-
|
|
398
|
+
// `x-apify-pagination-count` reports the rows scanned, which filters and `unwind` can leave above or below
|
|
399
|
+
// the items returned.
|
|
400
|
+
count: response.data.length,
|
|
364
401
|
limit: Number(response.headers['x-apify-pagination-limit']), // API returns 999999999999 when no limit is used
|
|
365
402
|
// TODO: Replace this once https://github.com/apify/apify-core/issues/3503 is solved
|
|
366
|
-
desc: JSON.parse(
|
|
403
|
+
desc: typeof descHeader === 'string' ? JSON.parse(descHeader) : userProvidedDesc,
|
|
367
404
|
};
|
|
405
|
+
const scannedCount = response.headers['x-apify-pagination-count'];
|
|
406
|
+
if (scannedCount === undefined)
|
|
407
|
+
return page;
|
|
408
|
+
// The offset iterator paginates by the scanned number, so it travels with the page outside its public shape.
|
|
409
|
+
return Object.defineProperty(page, SCANNED_COUNT, { value: Number(scannedCount) });
|
|
368
410
|
}
|
|
369
411
|
}
|
|
370
|
-
/**
|
|
371
|
-
* Supported formats for downloading dataset items.
|
|
372
|
-
*/
|
|
373
|
-
export var DownloadItemsFormat;
|
|
374
|
-
(function (DownloadItemsFormat) {
|
|
375
|
-
DownloadItemsFormat["JSON"] = "json";
|
|
376
|
-
DownloadItemsFormat["JSONL"] = "jsonl";
|
|
377
|
-
DownloadItemsFormat["XML"] = "xml";
|
|
378
|
-
DownloadItemsFormat["HTML"] = "html";
|
|
379
|
-
DownloadItemsFormat["CSV"] = "csv";
|
|
380
|
-
DownloadItemsFormat["XLSX"] = "xlsx";
|
|
381
|
-
DownloadItemsFormat["RSS"] = "rss";
|
|
382
|
-
})(DownloadItemsFormat || (DownloadItemsFormat = {}));
|
|
383
|
-
const validItemFormats = [...new Set(Object.values(DownloadItemsFormat).map((item) => item.toLowerCase()))];
|
|
384
|
-
// Declared below `validItemFormats` because it references it at module load time.
|
|
385
|
-
const itemFormatSchema = z.enum(validItemFormats);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { STORAGE_OWNERSHIP_FILTER } from '@apify/consts';
|
|
2
2
|
import type { ApiClientSubResourceOptions } from '../base/api_client.js';
|
|
3
3
|
import { ResourceCollectionClient } from '../base/resource_collection_client.js';
|
|
4
|
+
import type { TimeoutOptions } from '../timeouts.js';
|
|
4
5
|
import type { PaginatedList, PaginationOptions } from '../utils.js';
|
|
5
6
|
import type { Dataset } from './dataset.js';
|
|
6
7
|
/**
|
|
@@ -45,6 +46,7 @@ export declare class DatasetCollectionClient extends ResourceCollectionClient {
|
|
|
45
46
|
* ```
|
|
46
47
|
*
|
|
47
48
|
* @param options - Pagination options.
|
|
49
|
+
* @param options.timeoutSecs - Timeout for each API request. Default is `'medium'`.
|
|
48
50
|
* @returns A paginated iterator of Datasets.
|
|
49
51
|
* @see https://docs.apify.com/api/v2/datasets-get
|
|
50
52
|
*/
|
|
@@ -54,12 +56,14 @@ export declare class DatasetCollectionClient extends ResourceCollectionClient {
|
|
|
54
56
|
*
|
|
55
57
|
* @param name - Name of the dataset. If not provided, a default dataset is used.
|
|
56
58
|
* @param options - Additional options like schema.
|
|
59
|
+
* @param options.schema - Schema of the dataset.
|
|
60
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
57
61
|
* @returns The dataset object.
|
|
58
62
|
* @see https://docs.apify.com/api/v2/datasets-post
|
|
59
63
|
*/
|
|
60
64
|
getOrCreate(name?: string, options?: DatasetCollectionClientGetOrCreateOptions): Promise<Dataset>;
|
|
61
65
|
}
|
|
62
|
-
export interface DatasetCollectionClientListOptions extends PaginationOptions {
|
|
66
|
+
export interface DatasetCollectionClientListOptions extends PaginationOptions, TimeoutOptions {
|
|
63
67
|
unnamed?: boolean;
|
|
64
68
|
desc?: boolean;
|
|
65
69
|
/**
|
|
@@ -71,7 +75,7 @@ export interface DatasetCollectionClientListOptions extends PaginationOptions {
|
|
|
71
75
|
/**
|
|
72
76
|
* @since Added in 2.3.0
|
|
73
77
|
*/
|
|
74
|
-
export interface DatasetCollectionClientGetOrCreateOptions {
|
|
78
|
+
export interface DatasetCollectionClientGetOrCreateOptions extends TimeoutOptions {
|
|
75
79
|
schema?: Record<string, unknown>;
|
|
76
80
|
}
|
|
77
81
|
export type DatasetCollectionClientListResult = PaginatedList<Dataset> & {
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { STORAGE_OWNERSHIP_FILTER } from '@apify/consts';
|
|
3
3
|
import { ResourceCollectionClient } from '../base/resource_collection_client.js';
|
|
4
|
+
import * as schemas from '../schemas.js';
|
|
5
|
+
import { optionalSignalSchema, optionalTimeoutSchema, timeoutOptionsShape } from '../timeouts.js';
|
|
4
6
|
import { anyObjectSchema, paginationOptionsShape, parseArgument } from '../utils.js';
|
|
5
7
|
const listOptionsSchema = z.strictObject({
|
|
6
8
|
unnamed: z.boolean().optional(),
|
|
7
9
|
...paginationOptionsShape,
|
|
8
10
|
desc: z.boolean().optional(),
|
|
9
11
|
ownership: z.enum(STORAGE_OWNERSHIP_FILTER).optional(),
|
|
12
|
+
...timeoutOptionsShape,
|
|
10
13
|
});
|
|
11
14
|
const nameSchema = z.string().optional();
|
|
12
15
|
const schemaSchema = anyObjectSchema.optional();
|
|
@@ -57,24 +60,33 @@ export class DatasetCollectionClient extends ResourceCollectionClient {
|
|
|
57
60
|
* ```
|
|
58
61
|
*
|
|
59
62
|
* @param options - Pagination options.
|
|
63
|
+
* @param options.timeoutSecs - Timeout for each API request. Default is `'medium'`.
|
|
60
64
|
* @returns A paginated iterator of Datasets.
|
|
61
65
|
* @see https://docs.apify.com/api/v2/datasets-get
|
|
62
66
|
*/
|
|
63
67
|
list(options = {}) {
|
|
64
68
|
const parsed = parseArgument(options, listOptionsSchema, 'DatasetCollectionClientListOptions');
|
|
65
|
-
return this.
|
|
69
|
+
return this.listResourcesPaginated(schemas.ListOfDatasets(), parsed, 'medium');
|
|
66
70
|
}
|
|
67
71
|
/**
|
|
68
72
|
* Gets or creates a dataset with the specified name.
|
|
69
73
|
*
|
|
70
74
|
* @param name - Name of the dataset. If not provided, a default dataset is used.
|
|
71
75
|
* @param options - Additional options like schema.
|
|
76
|
+
* @param options.schema - Schema of the dataset.
|
|
77
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
72
78
|
* @returns The dataset object.
|
|
73
79
|
* @see https://docs.apify.com/api/v2/datasets-post
|
|
74
80
|
*/
|
|
75
81
|
async getOrCreate(name, options) {
|
|
76
82
|
parseArgument(name, nameSchema);
|
|
77
83
|
parseArgument(options?.schema, schemaSchema); // TODO: Add schema validation
|
|
78
|
-
|
|
84
|
+
parseArgument(options?.timeoutSecs, optionalTimeoutSchema);
|
|
85
|
+
parseArgument(options?.signal, optionalSignalSchema);
|
|
86
|
+
// `timeoutSecs` and `signal` are not part of the resource, so the body carries only the rest, and stays
|
|
87
|
+
// absent when there is nothing else to send.
|
|
88
|
+
const { timeoutSecs = 'short', signal, ...resource } = options ?? {};
|
|
89
|
+
const hasResource = Object.keys(resource).length > 0;
|
|
90
|
+
return this.getOrCreateResource(schemas.Dataset(), name, hasResource ? resource : undefined, timeoutSecs, signal);
|
|
79
91
|
}
|
|
80
92
|
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { Readable } from 'node:stream';
|
|
2
|
-
import type { JsonValue } from 'type-fest';
|
|
2
|
+
import type { JsonValue, TypedArray } from 'type-fest';
|
|
3
3
|
import type { STORAGE_GENERAL_ACCESS } from '@apify/consts';
|
|
4
4
|
import type { ApiClientSubResourceOptions } from '../base/api_client.js';
|
|
5
5
|
import { ResourceClient } from '../base/resource_client.js';
|
|
6
6
|
import type { KeyValueClientListKeysResult, KeyValueListItem, KeyValueStore } from '../models.js';
|
|
7
|
+
import type { TimeoutOptions } from '../timeouts.js';
|
|
7
8
|
export type { KeyValueClientListKeysResult, KeyValueListItem, KeyValueStore, KeyValueStoreStats } from '../models.js';
|
|
8
9
|
/**
|
|
9
10
|
* Client for managing a specific key-value store.
|
|
@@ -41,10 +42,12 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
41
42
|
/**
|
|
42
43
|
* Gets the key-value store object from the Apify API.
|
|
43
44
|
*
|
|
45
|
+
* @param options - Request options
|
|
46
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
44
47
|
* @returns The KeyValueStore object, or `undefined` if it does not exist
|
|
45
48
|
* @see https://docs.apify.com/api/v2/key-value-store-get
|
|
46
49
|
*/
|
|
47
|
-
get(): Promise<KeyValueStore | undefined>;
|
|
50
|
+
get(options?: TimeoutOptions): Promise<KeyValueStore | undefined>;
|
|
48
51
|
/**
|
|
49
52
|
* Updates the key-value store with specified fields.
|
|
50
53
|
*
|
|
@@ -52,16 +55,20 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
52
55
|
* @param newFields.name - New name for the store
|
|
53
56
|
* @param newFields.title - New title for the store
|
|
54
57
|
* @param newFields.generalAccess - General resource access level ('FOLLOW_USER_SETTING', 'ANYONE_WITH_ID_CAN_READ' or 'RESTRICTED')
|
|
58
|
+
* @param options - Request options
|
|
59
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'long'`.
|
|
55
60
|
* @returns The updated KeyValueStore object
|
|
56
61
|
* @see https://docs.apify.com/api/v2/key-value-store-put
|
|
57
62
|
*/
|
|
58
|
-
update(newFields: KeyValueClientUpdateOptions): Promise<KeyValueStore>;
|
|
63
|
+
update(newFields: KeyValueClientUpdateOptions, options?: TimeoutOptions): Promise<KeyValueStore>;
|
|
59
64
|
/**
|
|
60
65
|
* Deletes the key-value store.
|
|
61
66
|
*
|
|
67
|
+
* @param options - Request options
|
|
68
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
62
69
|
* @see https://docs.apify.com/api/v2/key-value-store-delete
|
|
63
70
|
*/
|
|
64
|
-
delete(): Promise<void>;
|
|
71
|
+
delete(options?: TimeoutOptions): Promise<void>;
|
|
65
72
|
/**
|
|
66
73
|
* Lists all keys in the key-value store.
|
|
67
74
|
*
|
|
@@ -73,6 +80,7 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
73
80
|
* @param options.exclusiveStartKey - Key to start listing from (for pagination). The listing starts with the next key after this one.
|
|
74
81
|
* @param options.collection - Filter keys by collection name.
|
|
75
82
|
* @param options.prefix - Filter keys that start with this prefix.
|
|
83
|
+
* @param options.timeoutSecs - Timeout for each API request. Default is `'medium'`.
|
|
76
84
|
* @returns Object containing `items` array of key metadata, pagination info (`count`, `limit`, `isTruncated`, `nextExclusiveStartKey`)
|
|
77
85
|
* @see https://docs.apify.com/api/v2/key-value-store-keys-get
|
|
78
86
|
*
|
|
@@ -106,6 +114,8 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
106
114
|
* requiring an API token.
|
|
107
115
|
*
|
|
108
116
|
* @param key - The record key
|
|
117
|
+
* @param options - Request options
|
|
118
|
+
* @param options.timeoutSecs - Timeout for the API request that fetches the store. Default is `'long'`.
|
|
109
119
|
* @returns A public URL string for accessing the record
|
|
110
120
|
*
|
|
111
121
|
* @example
|
|
@@ -116,7 +126,7 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
116
126
|
* ```
|
|
117
127
|
* @since Added in 2.14.0
|
|
118
128
|
*/
|
|
119
|
-
getRecordPublicUrl(key: string): Promise<string>;
|
|
129
|
+
getRecordPublicUrl(key: string, options?: TimeoutOptions): Promise<string>;
|
|
120
130
|
/**
|
|
121
131
|
* Generates a public URL for accessing the list of keys in the key-value store.
|
|
122
132
|
*
|
|
@@ -127,6 +137,7 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
127
137
|
* @param options.expiresInSecs - Number of seconds until the signed URL expires. If omitted, the URL never expires.
|
|
128
138
|
* @param options.limit - Maximum number of keys to return.
|
|
129
139
|
* @param options.prefix - Filter keys by prefix.
|
|
140
|
+
* @param options.timeoutSecs - Timeout for the API request that fetches the store. Default is `'long'`.
|
|
130
141
|
* @returns A public URL string for accessing the keys list
|
|
131
142
|
*
|
|
132
143
|
* @example
|
|
@@ -147,6 +158,8 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
147
158
|
* This is more efficient than {@link getRecord} when you only need to check for existence.
|
|
148
159
|
*
|
|
149
160
|
* @param key - The record key to check
|
|
161
|
+
* @param options - Request options
|
|
162
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'long'`.
|
|
150
163
|
* @returns `true` if the record exists, `false` if it does not
|
|
151
164
|
* @see https://docs.apify.com/api/v2/key-value-store-record-get
|
|
152
165
|
*
|
|
@@ -159,15 +172,27 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
159
172
|
* ```
|
|
160
173
|
* @since Added in 2.9.0
|
|
161
174
|
*/
|
|
162
|
-
recordExists(key: string): Promise<boolean>;
|
|
175
|
+
recordExists(key: string, options?: TimeoutOptions): Promise<boolean>;
|
|
163
176
|
/**
|
|
177
|
+
* By default, the value is parsed by the record's content type: `application/json` is parsed into a value,
|
|
178
|
+
* `text/*` and `application/*xml` are decoded to a string, and anything else is returned as a Buffer (Node.js)
|
|
179
|
+
* or ArrayBuffer (browser). A record whose body does not parse as its content type claims, such as a non-JSON
|
|
180
|
+
* string stored under `application/json`, makes the call throw an {@link InvalidResponseBodyError}, which
|
|
181
|
+
* carries the raw body in `error.response`.
|
|
182
|
+
*
|
|
164
183
|
* You can use the `buffer` option to get the value in a Buffer (Node.js)
|
|
165
|
-
* or ArrayBuffer (browser) format. In Node.js (not in browser) you can also
|
|
184
|
+
* or ArrayBuffer (browser) format, which skips the parsing. In Node.js (not in browser) you can also
|
|
166
185
|
* use the `stream` option to get a Readable stream.
|
|
167
186
|
*
|
|
168
187
|
* When the record does not exist, the function resolves to `undefined`. It does
|
|
169
188
|
* NOT resolve to a `KeyValueStore` record with an `undefined` value.
|
|
170
189
|
*
|
|
190
|
+
* @param key - The record key
|
|
191
|
+
* @param options - Retrieval options
|
|
192
|
+
* @param options.buffer - If `true`, the value is returned as a Buffer (Node.js) or ArrayBuffer (browser).
|
|
193
|
+
* @param options.stream - If `true`, the value is returned as a Readable stream. Node.js only.
|
|
194
|
+
* @param options.signature - Signature of a public URL, for reading a record without a token.
|
|
195
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'long'`.
|
|
171
196
|
* @see https://docs.apify.com/api/v2/key-value-store-record-get
|
|
172
197
|
*/
|
|
173
198
|
getRecord(key: string): Promise<KeyValueStoreRecord<JsonValue> | undefined>;
|
|
@@ -179,19 +204,27 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
179
204
|
* The content type is automatically determined based on the value type, but can be
|
|
180
205
|
* overridden using the `contentType` property.
|
|
181
206
|
*
|
|
207
|
+
* A string is sent as it is, even under `application/json`, so a string stored under a JSON content type has
|
|
208
|
+
* to be valid JSON already, or {@link getRecord} fails to parse it back.
|
|
209
|
+
*
|
|
182
210
|
* **Note about streams:** If the value is a stream object (has `.pipe` and `.on` methods),
|
|
183
211
|
* the upload cannot be retried on failure or follow redirects. For reliable uploads,
|
|
184
212
|
* buffer the entire stream into memory first.
|
|
185
213
|
*
|
|
186
214
|
* @param record - The record to store
|
|
187
215
|
* @param record.key - Record key (unique identifier)
|
|
188
|
-
* @param record.value - Record value (
|
|
216
|
+
* @param record.value - Record value (a JSON-serializable value, Buffer, ArrayBuffer, typed array, or Readable)
|
|
189
217
|
* @param record.contentType - Optional MIME type. Auto-detected if not provided:
|
|
190
218
|
* - Objects: `'application/json; charset=utf-8'`
|
|
191
219
|
* - Strings: `'text/plain; charset=utf-8'`
|
|
192
|
-
* -
|
|
220
|
+
* - Binary values and streams: `'application/octet-stream'`
|
|
221
|
+
*
|
|
222
|
+
* Worth setting for media and archives: the client skips compressing a body
|
|
223
|
+
* whose content type already carries its own compression. The
|
|
224
|
+
* `'application/octet-stream'` fallback is treated as compressible, because
|
|
225
|
+
* it could hold any binary data.
|
|
193
226
|
* @param options - Storage options
|
|
194
|
-
* @param options.timeoutSecs - Timeout for the
|
|
227
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'long'`.
|
|
195
228
|
* @param options.doNotRetryTimeouts - If `true`, don't retry on timeout errors. Default is `false`.
|
|
196
229
|
* @see https://docs.apify.com/api/v2/key-value-store-record-put
|
|
197
230
|
*
|
|
@@ -219,11 +252,13 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
219
252
|
* });
|
|
220
253
|
* ```
|
|
221
254
|
*/
|
|
222
|
-
setRecord(record: KeyValueStoreRecord<
|
|
255
|
+
setRecord(record: KeyValueStoreRecord<KeyValueStoreRecordValue>, options?: KeyValueStoreRecordOptions): Promise<void>;
|
|
223
256
|
/**
|
|
224
257
|
* Deletes a record from the key-value store.
|
|
225
258
|
*
|
|
226
259
|
* @param key - The record key to delete
|
|
260
|
+
* @param options - Request options
|
|
261
|
+
* @param options.timeoutSecs - Timeout for the API request. Default is `'short'`.
|
|
227
262
|
* @see https://docs.apify.com/api/v2/key-value-store-record-delete
|
|
228
263
|
*
|
|
229
264
|
* @example
|
|
@@ -231,7 +266,7 @@ export declare class KeyValueStoreClient extends ResourceClient {
|
|
|
231
266
|
* await client.keyValueStore('my-store').deleteRecord('temp-data');
|
|
232
267
|
* ```
|
|
233
268
|
*/
|
|
234
|
-
deleteRecord(key: string): Promise<void>;
|
|
269
|
+
deleteRecord(key: string, options?: TimeoutOptions): Promise<void>;
|
|
235
270
|
}
|
|
236
271
|
/**
|
|
237
272
|
* Options for updating a Key-Value Store.
|
|
@@ -250,7 +285,7 @@ export interface KeyValueClientUpdateOptions {
|
|
|
250
285
|
/**
|
|
251
286
|
* Options for listing keys in a Key-Value Store.
|
|
252
287
|
*/
|
|
253
|
-
export interface KeyValueClientListKeysOptions {
|
|
288
|
+
export interface KeyValueClientListKeysOptions extends TimeoutOptions {
|
|
254
289
|
limit?: number;
|
|
255
290
|
exclusiveStartKey?: string;
|
|
256
291
|
collection?: string;
|
|
@@ -276,7 +311,7 @@ export interface KeyValueClientCreateKeysUrlOptions extends Omit<KeyValueClientL
|
|
|
276
311
|
/**
|
|
277
312
|
* Options for retrieving a record from a Key-Value Store.
|
|
278
313
|
*/
|
|
279
|
-
export interface KeyValueClientGetRecordOptions {
|
|
314
|
+
export interface KeyValueClientGetRecordOptions extends TimeoutOptions {
|
|
280
315
|
buffer?: boolean;
|
|
281
316
|
stream?: boolean;
|
|
282
317
|
/**
|
|
@@ -284,6 +319,14 @@ export interface KeyValueClientGetRecordOptions {
|
|
|
284
319
|
*/
|
|
285
320
|
signature?: string;
|
|
286
321
|
}
|
|
322
|
+
/**
|
|
323
|
+
* A value that `setRecord` accepts.
|
|
324
|
+
*
|
|
325
|
+
* Anything JSON-serializable, or binary content the client uploads as bytes instead of JSON-encoding
|
|
326
|
+
* it: a `Buffer`, an `ArrayBuffer`, a typed array, or a readable stream. `Buffer` is a `Uint8Array`, so
|
|
327
|
+
* `TypedArray` covers it.
|
|
328
|
+
*/
|
|
329
|
+
export type KeyValueStoreRecordValue = JsonValue | ArrayBuffer | TypedArray | Readable;
|
|
287
330
|
/**
|
|
288
331
|
* Represents a record (key-value pair) in a Key-Value Store.
|
|
289
332
|
*
|
|
@@ -298,8 +341,7 @@ export interface KeyValueStoreRecord<T> {
|
|
|
298
341
|
* Options for storing a record in a Key-Value Store.
|
|
299
342
|
* @since Added in 2.12.4
|
|
300
343
|
*/
|
|
301
|
-
export interface KeyValueStoreRecordOptions {
|
|
302
|
-
timeoutSecs?: number;
|
|
344
|
+
export interface KeyValueStoreRecordOptions extends TimeoutOptions {
|
|
303
345
|
doNotRetryTimeouts?: boolean;
|
|
304
346
|
}
|
|
305
347
|
/**
|