@crawlee/core 4.0.0-beta.7 → 4.0.0-beta.71
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 +17 -13
- package/autoscaling/autoscaled_pool.d.ts +3 -5
- package/autoscaling/autoscaled_pool.d.ts.map +1 -1
- package/autoscaling/autoscaled_pool.js +3 -9
- package/autoscaling/autoscaled_pool.js.map +1 -1
- package/autoscaling/snapshotter.d.ts +3 -13
- package/autoscaling/snapshotter.d.ts.map +1 -1
- package/autoscaling/snapshotter.js +18 -29
- package/autoscaling/snapshotter.js.map +1 -1
- package/autoscaling/system_status.d.ts +0 -3
- package/autoscaling/system_status.d.ts.map +1 -1
- package/autoscaling/system_status.js +2 -3
- package/autoscaling/system_status.js.map +1 -1
- package/configuration.d.ts +88 -227
- package/configuration.d.ts.map +1 -1
- package/configuration.js +162 -223
- package/configuration.js.map +1 -1
- package/cookie_utils.d.ts +4 -2
- package/cookie_utils.d.ts.map +1 -1
- package/cookie_utils.js +18 -12
- package/cookie_utils.js.map +1 -1
- package/crawlers/context_pipeline.d.ts +71 -0
- package/crawlers/context_pipeline.d.ts.map +1 -0
- package/crawlers/context_pipeline.js +123 -0
- package/crawlers/context_pipeline.js.map +1 -0
- package/crawlers/crawler_commons.d.ts +20 -29
- package/crawlers/crawler_commons.d.ts.map +1 -1
- package/crawlers/crawler_commons.js +12 -20
- package/crawlers/crawler_commons.js.map +1 -1
- package/crawlers/crawler_utils.d.ts +2 -2
- package/crawlers/crawler_utils.d.ts.map +1 -1
- package/crawlers/crawler_utils.js +1 -1
- package/crawlers/crawler_utils.js.map +1 -1
- package/crawlers/error_snapshotter.d.ts +3 -2
- package/crawlers/error_snapshotter.d.ts.map +1 -1
- package/crawlers/error_snapshotter.js +2 -2
- package/crawlers/error_snapshotter.js.map +1 -1
- package/crawlers/error_tracker.d.ts +2 -1
- package/crawlers/error_tracker.d.ts.map +1 -1
- package/crawlers/error_tracker.js.map +1 -1
- package/crawlers/index.d.ts +1 -1
- package/crawlers/index.d.ts.map +1 -1
- package/crawlers/index.js +1 -1
- package/crawlers/index.js.map +1 -1
- package/crawlers/internals/types.d.ts +8 -0
- package/crawlers/internals/types.d.ts.map +1 -0
- package/crawlers/internals/types.js +2 -0
- package/crawlers/internals/types.js.map +1 -0
- package/crawlers/statistics.d.ts +16 -16
- package/crawlers/statistics.d.ts.map +1 -1
- package/crawlers/statistics.js +22 -25
- package/crawlers/statistics.js.map +1 -1
- package/enqueue_links/enqueue_links.d.ts +36 -21
- package/enqueue_links/enqueue_links.d.ts.map +1 -1
- package/enqueue_links/enqueue_links.js +47 -26
- package/enqueue_links/enqueue_links.js.map +1 -1
- package/enqueue_links/shared.d.ts +25 -8
- package/enqueue_links/shared.d.ts.map +1 -1
- package/enqueue_links/shared.js +69 -37
- package/enqueue_links/shared.js.map +1 -1
- package/errors.d.ts +33 -3
- package/errors.d.ts.map +1 -1
- package/errors.js +48 -4
- package/errors.js.map +1 -1
- package/events/event_manager.d.ts +34 -7
- package/events/event_manager.d.ts.map +1 -1
- package/events/event_manager.js +8 -9
- package/events/event_manager.js.map +1 -1
- package/events/local_event_manager.d.ts +14 -4
- package/events/local_event_manager.d.ts.map +1 -1
- package/events/local_event_manager.js +33 -39
- package/events/local_event_manager.js.map +1 -1
- package/index.d.ts +4 -2
- package/index.d.ts.map +1 -1
- package/index.js +3 -1
- package/index.js.map +1 -1
- package/log.d.ts +82 -2
- package/log.d.ts.map +1 -1
- package/log.js +102 -0
- package/log.js.map +1 -1
- package/memory-storage/consts.d.ts +5 -0
- package/memory-storage/consts.d.ts.map +1 -0
- package/memory-storage/consts.js +5 -0
- package/memory-storage/consts.js.map +1 -0
- package/memory-storage/index.d.ts +2 -0
- package/memory-storage/index.d.ts.map +1 -0
- package/memory-storage/index.js +2 -0
- package/memory-storage/index.js.map +1 -0
- package/memory-storage/memory-storage.d.ts +47 -0
- package/memory-storage/memory-storage.d.ts.map +1 -0
- package/memory-storage/memory-storage.js +137 -0
- package/memory-storage/memory-storage.js.map +1 -0
- package/memory-storage/resource-clients/common/base-client.d.ts +5 -0
- package/memory-storage/resource-clients/common/base-client.d.ts.map +1 -0
- package/memory-storage/resource-clients/common/base-client.js +7 -0
- package/memory-storage/resource-clients/common/base-client.js.map +1 -0
- package/memory-storage/resource-clients/dataset.d.ts +41 -0
- package/memory-storage/resource-clients/dataset.d.ts.map +1 -0
- package/memory-storage/resource-clients/dataset.js +114 -0
- package/memory-storage/resource-clients/dataset.js.map +1 -0
- package/memory-storage/resource-clients/key-value-store.d.ts +64 -0
- package/memory-storage/resource-clients/key-value-store.d.ts.map +1 -0
- package/memory-storage/resource-clients/key-value-store.js +204 -0
- package/memory-storage/resource-clients/key-value-store.js.map +1 -0
- package/memory-storage/resource-clients/request-queue.d.ts +97 -0
- package/memory-storage/resource-clients/request-queue.d.ts.map +1 -0
- package/memory-storage/resource-clients/request-queue.js +422 -0
- package/memory-storage/resource-clients/request-queue.js.map +1 -0
- package/memory-storage/utils.d.ts +12 -0
- package/memory-storage/utils.d.ts.map +1 -0
- package/memory-storage/utils.js +28 -0
- package/memory-storage/utils.js.map +1 -0
- package/package.json +12 -10
- package/proxy_configuration.d.ts +14 -148
- package/proxy_configuration.d.ts.map +1 -1
- package/proxy_configuration.js +19 -167
- package/proxy_configuration.js.map +1 -1
- package/recoverable_state.d.ts +121 -0
- package/recoverable_state.d.ts.map +1 -0
- package/recoverable_state.js +142 -0
- package/recoverable_state.js.map +1 -0
- package/request.d.ts +84 -12
- package/request.d.ts.map +1 -1
- package/request.js +107 -27
- package/request.js.map +1 -1
- package/router.d.ts.map +1 -1
- package/router.js.map +1 -1
- package/serialization.js +1 -1
- package/serialization.js.map +1 -1
- package/service_locator.d.ts +157 -0
- package/service_locator.d.ts.map +1 -0
- package/service_locator.js +239 -0
- package/service_locator.js.map +1 -0
- package/session_pool/consts.d.ts +1 -1
- package/session_pool/consts.d.ts.map +1 -1
- package/session_pool/consts.js +1 -1
- package/session_pool/consts.js.map +1 -1
- package/session_pool/fingerprint.d.ts +10 -0
- package/session_pool/fingerprint.d.ts.map +1 -0
- package/session_pool/fingerprint.js +31 -0
- package/session_pool/fingerprint.js.map +1 -0
- package/session_pool/index.d.ts +0 -1
- package/session_pool/index.d.ts.map +1 -1
- package/session_pool/index.js +0 -1
- package/session_pool/index.js.map +1 -1
- package/session_pool/session.d.ts +35 -72
- package/session_pool/session.d.ts.map +1 -1
- package/session_pool/session.js +46 -98
- package/session_pool/session.js.map +1 -1
- package/session_pool/session_pool.d.ts +71 -71
- package/session_pool/session_pool.d.ts.map +1 -1
- package/session_pool/session_pool.js +111 -99
- package/session_pool/session_pool.js.map +1 -1
- package/storages/access_checking.d.ts.map +1 -1
- package/storages/access_checking.js +5 -1
- package/storages/access_checking.js.map +1 -1
- package/storages/dataset.d.ts +98 -47
- package/storages/dataset.d.ts.map +1 -1
- package/storages/dataset.js +166 -123
- package/storages/dataset.js.map +1 -1
- package/storages/index.d.ts +8 -6
- package/storages/index.d.ts.map +1 -1
- package/storages/index.js +6 -6
- package/storages/index.js.map +1 -1
- package/storages/key_value_store.d.ts +163 -33
- package/storages/key_value_store.d.ts.map +1 -1
- package/storages/key_value_store.js +267 -119
- package/storages/key_value_store.js.map +1 -1
- package/storages/key_value_store_codec.d.ts +33 -0
- package/storages/key_value_store_codec.d.ts.map +1 -0
- package/storages/key_value_store_codec.js +114 -0
- package/storages/key_value_store_codec.js.map +1 -0
- package/storages/request_list.d.ts +32 -81
- package/storages/request_list.d.ts.map +1 -1
- package/storages/request_list.js +49 -39
- package/storages/request_list.js.map +1 -1
- package/storages/request_loader.d.ts +97 -0
- package/storages/request_loader.d.ts.map +1 -0
- package/storages/request_loader.js +2 -0
- package/storages/request_loader.js.map +1 -0
- package/storages/request_manager.d.ts +34 -0
- package/storages/request_manager.d.ts.map +1 -0
- package/storages/request_manager.js +2 -0
- package/storages/request_manager.js.map +1 -0
- package/storages/request_manager_tandem.d.ts +107 -0
- package/storages/request_manager_tandem.d.ts.map +1 -0
- package/storages/request_manager_tandem.js +198 -0
- package/storages/request_manager_tandem.js.map +1 -0
- package/storages/request_queue.d.ts +282 -45
- package/storages/request_queue.d.ts.map +1 -1
- package/storages/request_queue.js +592 -213
- package/storages/request_queue.js.map +1 -1
- package/storages/{sitemap_request_list.d.ts → sitemap_request_loader.d.ts} +29 -24
- package/storages/sitemap_request_loader.d.ts.map +1 -0
- package/storages/{sitemap_request_list.js → sitemap_request_loader.js} +50 -46
- package/storages/sitemap_request_loader.js.map +1 -0
- package/storages/storage_instance_manager.d.ts +92 -0
- package/storages/storage_instance_manager.d.ts.map +1 -0
- package/storages/storage_instance_manager.js +261 -0
- package/storages/storage_instance_manager.js.map +1 -0
- package/storages/storage_stats.d.ts +49 -0
- package/storages/storage_stats.d.ts.map +1 -0
- package/storages/storage_stats.js +30 -0
- package/storages/storage_stats.js.map +1 -0
- package/storages/utils.d.ts +51 -5
- package/storages/utils.d.ts.map +1 -1
- package/storages/utils.js +60 -8
- package/storages/utils.js.map +1 -1
- package/typedefs.d.ts +1 -1
- package/typedefs.d.ts.map +1 -1
- package/validators.d.ts +8 -0
- package/validators.d.ts.map +1 -1
- package/validators.js +8 -0
- package/validators.js.map +1 -1
- package/crawlers/crawler_extension.d.ts +0 -12
- package/crawlers/crawler_extension.d.ts.map +0 -1
- package/crawlers/crawler_extension.js +0 -14
- package/crawlers/crawler_extension.js.map +0 -1
- package/http_clients/base-http-client.d.ts +0 -134
- package/http_clients/base-http-client.d.ts.map +0 -1
- package/http_clients/base-http-client.js +0 -33
- package/http_clients/base-http-client.js.map +0 -1
- package/http_clients/form-data-like.d.ts +0 -67
- package/http_clients/form-data-like.d.ts.map +0 -1
- package/http_clients/form-data-like.js +0 -5
- package/http_clients/form-data-like.js.map +0 -1
- package/http_clients/got-scraping-http-client.d.ts +0 -15
- package/http_clients/got-scraping-http-client.d.ts.map +0 -1
- package/http_clients/got-scraping-http-client.js +0 -69
- package/http_clients/got-scraping-http-client.js.map +0 -1
- package/http_clients/index.d.ts +0 -3
- package/http_clients/index.d.ts.map +0 -1
- package/http_clients/index.js +0 -3
- package/http_clients/index.js.map +0 -1
- package/session_pool/events.d.ts +0 -3
- package/session_pool/events.d.ts.map +0 -1
- package/session_pool/events.js +0 -3
- package/session_pool/events.js.map +0 -1
- package/storages/request_provider.d.ts +0 -307
- package/storages/request_provider.d.ts.map +0 -1
- package/storages/request_provider.js +0 -555
- package/storages/request_provider.js.map +0 -1
- package/storages/request_queue_v2.d.ts +0 -87
- package/storages/request_queue_v2.d.ts.map +0 -1
- package/storages/request_queue_v2.js +0 -438
- package/storages/request_queue_v2.js.map +0 -1
- package/storages/sitemap_request_list.d.ts.map +0 -1
- package/storages/sitemap_request_list.js.map +0 -1
- package/storages/storage_manager.d.ts +0 -58
- package/storages/storage_manager.d.ts.map +0 -1
- package/storages/storage_manager.js +0 -105
- package/storages/storage_manager.js.map +0 -1
- package/tsconfig.build.tsbuildinfo +0 -1
package/storages/dataset.d.ts
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DatasetBackend, DatasetInfo, Dictionary } from '@crawlee/types';
|
|
2
2
|
import { Configuration } from '../configuration.js';
|
|
3
|
-
import {
|
|
3
|
+
import type { CrawleeLogger } from '../log.js';
|
|
4
4
|
import type { Awaitable } from '../typedefs.js';
|
|
5
|
-
import type {
|
|
5
|
+
import type { DatasetStats } from './storage_stats.js';
|
|
6
|
+
import type { StorageIdentifier } from './storage_instance_manager.js';
|
|
7
|
+
import type { StorageOpenOptions } from './utils.js';
|
|
6
8
|
/** @internal */
|
|
7
9
|
export declare const DATASET_ITERATORS_DEFAULT_LIMIT = 10000;
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* in an array to provide better error messages. Returns serialized object.
|
|
12
|
-
* @ignore
|
|
13
|
-
*/
|
|
14
|
-
export declare function checkAndSerialize<T>(item: T, limitBytes: number, index?: number): string;
|
|
15
|
-
/**
|
|
16
|
-
* Takes an array of JSONs (payloads) as input and produces an array of JSON strings
|
|
17
|
-
* where each string is a JSON array of payloads with a maximum size of limitBytes per one
|
|
18
|
-
* JSON array. Fits as many payloads as possible into a single JSON array and then moves
|
|
19
|
-
* on to the next, preserving item order.
|
|
11
|
+
* Validates that the given value is a plain JSON-serializable object
|
|
12
|
+
* (not an array, not a primitive, not circular).
|
|
20
13
|
*
|
|
21
|
-
*
|
|
14
|
+
* @param item The value to validate.
|
|
15
|
+
* @param index Optional index for error messages when validating inside an array.
|
|
22
16
|
* @ignore
|
|
23
17
|
*/
|
|
24
|
-
export declare function
|
|
18
|
+
export declare function assertJsonSerializable<T>(item: T, index?: number): void;
|
|
25
19
|
export interface DatasetDataOptions {
|
|
26
20
|
/**
|
|
27
21
|
* Number of array elements that should be skipped at the start.
|
|
@@ -67,6 +61,11 @@ export interface DatasetDataOptions {
|
|
|
67
61
|
skipEmpty?: boolean;
|
|
68
62
|
}
|
|
69
63
|
export interface DatasetExportOptions extends Omit<DatasetDataOptions, 'offset' | 'limit'> {
|
|
64
|
+
/**
|
|
65
|
+
* If true, includes all unique keys from all dataset items in the CSV export header.
|
|
66
|
+
* If omitted or false, only keys from the first item are used.
|
|
67
|
+
*/
|
|
68
|
+
collectAllKeys?: boolean;
|
|
70
69
|
}
|
|
71
70
|
export interface DatasetIteratorOptions extends Omit<DatasetDataOptions, 'offset' | 'limit' | 'clean' | 'skipHidden' | 'skipEmpty'> {
|
|
72
71
|
/** @internal */
|
|
@@ -86,8 +85,8 @@ export interface DatasetIteratorOptions extends Omit<DatasetDataOptions, 'offset
|
|
|
86
85
|
format?: string;
|
|
87
86
|
}
|
|
88
87
|
export interface DatasetExportToOptions extends DatasetExportOptions {
|
|
89
|
-
fromDataset?: string;
|
|
90
|
-
toKVS?: string;
|
|
88
|
+
fromDataset?: string | StorageIdentifier;
|
|
89
|
+
toKVS?: string | StorageIdentifier;
|
|
91
90
|
}
|
|
92
91
|
/**
|
|
93
92
|
* The `Dataset` class represents a store for structured data where each object stored has the same attributes,
|
|
@@ -144,12 +143,18 @@ export declare class Dataset<Data extends Dictionary = Dictionary> {
|
|
|
144
143
|
readonly config: Configuration;
|
|
145
144
|
id: string;
|
|
146
145
|
name?: string;
|
|
147
|
-
|
|
148
|
-
log:
|
|
146
|
+
backend: DatasetBackend<Data>;
|
|
147
|
+
log: CrawleeLogger;
|
|
148
|
+
private readonly statsTracker;
|
|
149
149
|
/**
|
|
150
150
|
* @internal
|
|
151
151
|
*/
|
|
152
152
|
constructor(options: DatasetOptions, config?: Configuration);
|
|
153
|
+
/**
|
|
154
|
+
* Backend-independent usage counters tracked for this dataset (read / write operations issued to
|
|
155
|
+
* the underlying storage backend). Counted per backend call.
|
|
156
|
+
*/
|
|
157
|
+
get stats(): DatasetStats;
|
|
153
158
|
/**
|
|
154
159
|
* Stores an object or an array of objects to the dataset.
|
|
155
160
|
* The function returns a promise that resolves when the operation finishes.
|
|
@@ -158,21 +163,8 @@ export declare class Dataset<Data extends Dictionary = Dictionary> {
|
|
|
158
163
|
* **IMPORTANT**: Make sure to use the `await` keyword when calling `pushData()`,
|
|
159
164
|
* otherwise the crawler process might finish before the data is stored!
|
|
160
165
|
*
|
|
161
|
-
* The size of the data is limited by the receiving API and therefore `pushData()` will only
|
|
162
|
-
* allow objects whose JSON representation is smaller than 9MB. When an array is passed,
|
|
163
|
-
* none of the included objects
|
|
164
|
-
* may be larger than 9MB, but the array itself may be of any size.
|
|
165
|
-
*
|
|
166
|
-
* The function internally
|
|
167
|
-
* chunks the array into separate items and pushes them sequentially.
|
|
168
|
-
* The chunking process is stable (keeps order of data), but it does not provide a transaction
|
|
169
|
-
* safety mechanism. Therefore, in the event of an uploading error (after several automatic retries),
|
|
170
|
-
* the function's Promise will reject and the dataset will be left in a state where some of
|
|
171
|
-
* the items have already been saved to the dataset while other items from the source array were not.
|
|
172
|
-
* To overcome this limitation, the developer may, for example, read the last item saved in the dataset
|
|
173
|
-
* and re-attempt the save of the data from this item onwards to prevent duplicates.
|
|
174
166
|
* @param data Object or array of objects containing data to be stored in the default dataset.
|
|
175
|
-
* The objects must be serializable to JSON
|
|
167
|
+
* The objects must be serializable to JSON.
|
|
176
168
|
*/
|
|
177
169
|
pushData(data: Data | Data[]): Promise<void>;
|
|
178
170
|
/**
|
|
@@ -223,26 +215,21 @@ export declare class Dataset<Data extends Dictionary = Dictionary> {
|
|
|
223
215
|
/**
|
|
224
216
|
* Returns an object containing general information about the dataset.
|
|
225
217
|
*
|
|
226
|
-
* The function returns the same object as the Apify API Client's
|
|
227
|
-
* [getDataset](https://docs.apify.com/api/apify-client-js/latest#ApifyClient-datasets-getDataset)
|
|
228
|
-
* function, which in turn calls the
|
|
229
|
-
* [Get dataset](https://apify.com/docs/api/v2#/reference/datasets/dataset/get-dataset)
|
|
230
|
-
* API endpoint.
|
|
231
|
-
*
|
|
232
218
|
* **Example:**
|
|
233
219
|
* ```
|
|
234
220
|
* {
|
|
235
221
|
* id: "WkzbQMuFYuamGv3YF",
|
|
236
222
|
* name: "my-dataset",
|
|
237
|
-
* userId: "wRsJZtadYvn4mBZmm",
|
|
238
223
|
* createdAt: new Date("2015-12-12T07:34:14.202Z"),
|
|
239
224
|
* modifiedAt: new Date("2015-12-13T08:36:13.202Z"),
|
|
240
225
|
* accessedAt: new Date("2015-12-14T08:36:13.202Z"),
|
|
241
226
|
* itemCount: 14,
|
|
242
227
|
* }
|
|
243
228
|
* ```
|
|
229
|
+
*
|
|
230
|
+
* @throws If the underlying storage no longer exists (e.g. it was deleted externally).
|
|
244
231
|
*/
|
|
245
|
-
getInfo(): Promise<DatasetInfo
|
|
232
|
+
getInfo(): Promise<DatasetInfo>;
|
|
246
233
|
/**
|
|
247
234
|
* Iterates over dataset items, yielding each in turn to an `iteratee` function.
|
|
248
235
|
* Each invocation of `iteratee` is called with two arguments: `(item, index)`.
|
|
@@ -326,6 +313,69 @@ export declare class Dataset<Data extends Dictionary = Dictionary> {
|
|
|
326
313
|
* @param [options] An object containing extra options for `reduce()`
|
|
327
314
|
*/
|
|
328
315
|
reduce<T>(iteratee: DatasetReducer<T, Data>, memo: T, options?: DatasetIteratorOptions): Promise<T>;
|
|
316
|
+
private fetchEntryPages;
|
|
317
|
+
private fetchPages;
|
|
318
|
+
/**
|
|
319
|
+
* Returns dataset items.
|
|
320
|
+
*
|
|
321
|
+
* When awaited (`await dataset.values()`), returns all items as a flat `Data[]` array.
|
|
322
|
+
* When used as an async iterable (`for await...of`), iterates over all items across pages
|
|
323
|
+
* without loading everything into memory at once.
|
|
324
|
+
*
|
|
325
|
+
* **Example usage:**
|
|
326
|
+
* ```javascript
|
|
327
|
+
* const dataset = await Dataset.open('my-results');
|
|
328
|
+
*
|
|
329
|
+
* // Iterate over all items (memory-efficient for large datasets)
|
|
330
|
+
* for await (const item of dataset.values()) {
|
|
331
|
+
* console.log(item);
|
|
332
|
+
* }
|
|
333
|
+
*
|
|
334
|
+
* // Or fetch all items at once
|
|
335
|
+
* const items = await dataset.values();
|
|
336
|
+
* console.log(items);
|
|
337
|
+
* ```
|
|
338
|
+
*
|
|
339
|
+
* @param options Options for the iteration.
|
|
340
|
+
*/
|
|
341
|
+
values(options?: DatasetIteratorOptions): AsyncIterable<Data> & Promise<Data[]>;
|
|
342
|
+
/**
|
|
343
|
+
* Returns dataset entries (index-value pairs).
|
|
344
|
+
*
|
|
345
|
+
* When awaited (`await dataset.entries()`), returns all entries as a flat `[index, item][]` array.
|
|
346
|
+
* When used as an async iterable (`for await...of`), iterates over all entries across pages
|
|
347
|
+
* without loading everything into memory at once.
|
|
348
|
+
*
|
|
349
|
+
* **Example usage:**
|
|
350
|
+
* ```javascript
|
|
351
|
+
* const dataset = await Dataset.open('my-results');
|
|
352
|
+
*
|
|
353
|
+
* // Iterate over all entries
|
|
354
|
+
* for await (const [index, item] of dataset.entries()) {
|
|
355
|
+
* console.log(`Item at ${index}: ${JSON.stringify(item)}`);
|
|
356
|
+
* }
|
|
357
|
+
*
|
|
358
|
+
* // Or fetch all at once
|
|
359
|
+
* const entries = await dataset.entries();
|
|
360
|
+
* console.log(entries);
|
|
361
|
+
* ```
|
|
362
|
+
*
|
|
363
|
+
* @param options Options for the iteration.
|
|
364
|
+
*/
|
|
365
|
+
entries(options?: DatasetIteratorOptions): AsyncIterable<[number, Data]> & Promise<[number, Data][]>;
|
|
366
|
+
/**
|
|
367
|
+
* Default async iterator for the dataset, iterating over items.
|
|
368
|
+
* Allows using the dataset directly in a `for await...of` loop.
|
|
369
|
+
*
|
|
370
|
+
* **Example usage:**
|
|
371
|
+
* ```javascript
|
|
372
|
+
* const dataset = await Dataset.open('my-results');
|
|
373
|
+
* for await (const item of dataset) {
|
|
374
|
+
* console.log(item);
|
|
375
|
+
* }
|
|
376
|
+
* ```
|
|
377
|
+
*/
|
|
378
|
+
[Symbol.asyncIterator](): AsyncGenerator<Data, void, undefined>;
|
|
329
379
|
/**
|
|
330
380
|
* Removes the dataset either from the Apify cloud storage or from the local directory,
|
|
331
381
|
* depending on the mode of operation.
|
|
@@ -340,12 +390,13 @@ export declare class Dataset<Data extends Dictionary = Dictionary> {
|
|
|
340
390
|
*
|
|
341
391
|
* For more details and code examples, see the {@link Dataset} class.
|
|
342
392
|
*
|
|
343
|
-
* @param [
|
|
344
|
-
* ID or name of the dataset to be opened. If
|
|
345
|
-
*
|
|
393
|
+
* @param [identifier]
|
|
394
|
+
* ID or name of the dataset to be opened. If a string is provided, it will first be
|
|
395
|
+
* looked up as an ID; if no such storage exists, it will be treated as a name.
|
|
396
|
+
* If `null` or `undefined`, the function returns the default dataset associated with the crawler run.
|
|
346
397
|
* @param [options] Storage manager options.
|
|
347
398
|
*/
|
|
348
|
-
static open<Data extends Dictionary = Dictionary>(
|
|
399
|
+
static open<Data extends Dictionary = Dictionary>(identifier?: string | StorageIdentifier | null, options?: StorageOpenOptions): Promise<Dataset<Data>>;
|
|
349
400
|
/**
|
|
350
401
|
* Stores an object or an array of objects to the default {@link Dataset} of the current crawler run.
|
|
351
402
|
*
|
|
@@ -411,7 +462,7 @@ export interface DatasetReducer<T, Data> {
|
|
|
411
462
|
export interface DatasetOptions {
|
|
412
463
|
id: string;
|
|
413
464
|
name?: string;
|
|
414
|
-
|
|
465
|
+
backend: DatasetBackend;
|
|
415
466
|
}
|
|
416
467
|
export interface DatasetContent<Data> {
|
|
417
468
|
/** Total count of entries in the dataset. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset.d.ts","sourceRoot":"","sources":["../../src/storages/dataset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"dataset.d.ts","sourceRoot":"","sources":["../../src/storages/dataset.ts"],"names":[],"mappings":"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"}
|
package/storages/dataset.js
CHANGED
|
@@ -1,80 +1,35 @@
|
|
|
1
1
|
import { stringify } from 'csv-stringify/sync';
|
|
2
2
|
import ow from 'ow';
|
|
3
|
-
import { MAX_PAYLOAD_SIZE_BYTES } from '@apify/consts';
|
|
4
3
|
import { Configuration } from '../configuration.js';
|
|
5
|
-
import {
|
|
4
|
+
import { serviceLocator } from '../service_locator.js';
|
|
6
5
|
import { checkStorageAccess } from './access_checking.js';
|
|
7
6
|
import { KeyValueStore } from './key_value_store.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { StorageStatsTracker } from './storage_stats.js';
|
|
8
|
+
import { resolveStorageIdentifier } from './storage_instance_manager.js';
|
|
9
|
+
import { createDualIterable, purgeDefaultStorages } from './utils.js';
|
|
10
10
|
/** @internal */
|
|
11
11
|
export const DATASET_ITERATORS_DEFAULT_LIMIT = 10000;
|
|
12
|
-
const SAFETY_BUFFER_PERCENT = 0.01 / 100; // 0.01%
|
|
13
12
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
13
|
+
* Validates that the given value is a plain JSON-serializable object
|
|
14
|
+
* (not an array, not a primitive, not circular).
|
|
15
|
+
*
|
|
16
|
+
* @param item The value to validate.
|
|
17
|
+
* @param index Optional index for error messages when validating inside an array.
|
|
17
18
|
* @ignore
|
|
18
19
|
*/
|
|
19
|
-
export function
|
|
20
|
+
export function assertJsonSerializable(item, index) {
|
|
20
21
|
const s = typeof index === 'number' ? ` at index ${index} ` : ' ';
|
|
21
22
|
const isItemObject = item && typeof item === 'object' && !Array.isArray(item);
|
|
22
23
|
if (!isItemObject) {
|
|
23
24
|
throw new Error(`Data item${s}is not an object. You can push only objects into a dataset.`);
|
|
24
25
|
}
|
|
25
|
-
let payload;
|
|
26
26
|
try {
|
|
27
|
-
|
|
27
|
+
JSON.stringify(item);
|
|
28
28
|
}
|
|
29
29
|
catch (e) {
|
|
30
30
|
const err = e;
|
|
31
31
|
throw new Error(`Data item${s}is not serializable to JSON.\nCause: ${err.message}`);
|
|
32
32
|
}
|
|
33
|
-
const bytes = Buffer.byteLength(payload);
|
|
34
|
-
if (bytes > limitBytes) {
|
|
35
|
-
throw new Error(`Data item${s}is too large (size: ${bytes} bytes, limit: ${limitBytes} bytes)`);
|
|
36
|
-
}
|
|
37
|
-
return payload;
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Takes an array of JSONs (payloads) as input and produces an array of JSON strings
|
|
41
|
-
* where each string is a JSON array of payloads with a maximum size of limitBytes per one
|
|
42
|
-
* JSON array. Fits as many payloads as possible into a single JSON array and then moves
|
|
43
|
-
* on to the next, preserving item order.
|
|
44
|
-
*
|
|
45
|
-
* The function assumes that none of the items is larger than limitBytes and does not validate.
|
|
46
|
-
* @ignore
|
|
47
|
-
*/
|
|
48
|
-
export function chunkBySize(items, limitBytes) {
|
|
49
|
-
if (!items.length)
|
|
50
|
-
return [];
|
|
51
|
-
if (items.length === 1)
|
|
52
|
-
return items;
|
|
53
|
-
// Split payloads into buckets of valid size.
|
|
54
|
-
let lastChunkBytes = 2; // Add 2 bytes for [] wrapper.
|
|
55
|
-
const chunks = [];
|
|
56
|
-
for (const payload of items) {
|
|
57
|
-
const bytes = Buffer.byteLength(payload);
|
|
58
|
-
if (bytes <= limitBytes && bytes + 2 > limitBytes) {
|
|
59
|
-
// Handle cases where wrapping with [] would fail, but solo object is fine.
|
|
60
|
-
chunks.push(payload);
|
|
61
|
-
lastChunkBytes = bytes;
|
|
62
|
-
}
|
|
63
|
-
else if (lastChunkBytes + bytes <= limitBytes) {
|
|
64
|
-
// ensure array
|
|
65
|
-
if (!Array.isArray(chunks[chunks.length - 1])) {
|
|
66
|
-
chunks.push([]);
|
|
67
|
-
}
|
|
68
|
-
chunks[chunks.length - 1].push(payload);
|
|
69
|
-
lastChunkBytes += bytes + 1; // Add 1 byte for ',' separator.
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
chunks.push([payload]);
|
|
73
|
-
lastChunkBytes = bytes + 2; // Add 2 bytes for [] wrapper.
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
// Stringify array chunks.
|
|
77
|
-
return chunks.map((chunk) => (typeof chunk === 'string' ? chunk : `[${chunk.join(',')}]`));
|
|
78
33
|
}
|
|
79
34
|
/**
|
|
80
35
|
* The `Dataset` class represents a store for structured data where each object stored has the same attributes,
|
|
@@ -131,8 +86,12 @@ export class Dataset {
|
|
|
131
86
|
config;
|
|
132
87
|
id;
|
|
133
88
|
name;
|
|
134
|
-
|
|
135
|
-
log
|
|
89
|
+
backend;
|
|
90
|
+
log;
|
|
91
|
+
statsTracker = new StorageStatsTracker({
|
|
92
|
+
readCount: 0,
|
|
93
|
+
writeCount: 0,
|
|
94
|
+
});
|
|
136
95
|
/**
|
|
137
96
|
* @internal
|
|
138
97
|
*/
|
|
@@ -140,7 +99,15 @@ export class Dataset {
|
|
|
140
99
|
this.config = config;
|
|
141
100
|
this.id = options.id;
|
|
142
101
|
this.name = options.name;
|
|
143
|
-
this.
|
|
102
|
+
this.backend = options.backend;
|
|
103
|
+
this.log = serviceLocator.getLogger().child({ prefix: 'Dataset' });
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Backend-independent usage counters tracked for this dataset (read / write operations issued to
|
|
107
|
+
* the underlying storage backend). Counted per backend call.
|
|
108
|
+
*/
|
|
109
|
+
get stats() {
|
|
110
|
+
return this.statsTracker.current;
|
|
144
111
|
}
|
|
145
112
|
/**
|
|
146
113
|
* Stores an object or an array of objects to the dataset.
|
|
@@ -150,40 +117,19 @@ export class Dataset {
|
|
|
150
117
|
* **IMPORTANT**: Make sure to use the `await` keyword when calling `pushData()`,
|
|
151
118
|
* otherwise the crawler process might finish before the data is stored!
|
|
152
119
|
*
|
|
153
|
-
* The size of the data is limited by the receiving API and therefore `pushData()` will only
|
|
154
|
-
* allow objects whose JSON representation is smaller than 9MB. When an array is passed,
|
|
155
|
-
* none of the included objects
|
|
156
|
-
* may be larger than 9MB, but the array itself may be of any size.
|
|
157
|
-
*
|
|
158
|
-
* The function internally
|
|
159
|
-
* chunks the array into separate items and pushes them sequentially.
|
|
160
|
-
* The chunking process is stable (keeps order of data), but it does not provide a transaction
|
|
161
|
-
* safety mechanism. Therefore, in the event of an uploading error (after several automatic retries),
|
|
162
|
-
* the function's Promise will reject and the dataset will be left in a state where some of
|
|
163
|
-
* the items have already been saved to the dataset while other items from the source array were not.
|
|
164
|
-
* To overcome this limitation, the developer may, for example, read the last item saved in the dataset
|
|
165
|
-
* and re-attempt the save of the data from this item onwards to prevent duplicates.
|
|
166
120
|
* @param data Object or array of objects containing data to be stored in the default dataset.
|
|
167
|
-
* The objects must be serializable to JSON
|
|
121
|
+
* The objects must be serializable to JSON.
|
|
168
122
|
*/
|
|
169
123
|
async pushData(data) {
|
|
170
124
|
checkStorageAccess();
|
|
171
125
|
ow(data, 'data', ow.object);
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
const payload = checkAndSerialize(data, limit);
|
|
177
|
-
await dispatch(payload);
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
// Handle Arrays
|
|
181
|
-
const payloads = data.map((item, index) => checkAndSerialize(item, limit, index));
|
|
182
|
-
const chunks = chunkBySize(payloads, limit);
|
|
183
|
-
// Invoke client in series to preserve order of data
|
|
184
|
-
for (const chunk of chunks) {
|
|
185
|
-
await dispatch(chunk);
|
|
126
|
+
// Normalize to array and validate each item
|
|
127
|
+
const items = Array.isArray(data) ? data : [data];
|
|
128
|
+
for (let i = 0; i < items.length; i++) {
|
|
129
|
+
assertJsonSerializable(items[i], i);
|
|
186
130
|
}
|
|
131
|
+
this.statsTracker.add('writeCount');
|
|
132
|
+
await this.backend.pushData(items);
|
|
187
133
|
}
|
|
188
134
|
/**
|
|
189
135
|
* Returns {@link DatasetContent} object holding the items in the dataset based on the provided parameters.
|
|
@@ -191,7 +137,8 @@ export class Dataset {
|
|
|
191
137
|
async getData(options = {}) {
|
|
192
138
|
checkStorageAccess();
|
|
193
139
|
try {
|
|
194
|
-
|
|
140
|
+
this.statsTracker.add('readCount');
|
|
141
|
+
return await this.backend.getData(options);
|
|
195
142
|
}
|
|
196
143
|
catch (e) {
|
|
197
144
|
const error = e;
|
|
@@ -208,18 +155,9 @@ export class Dataset {
|
|
|
208
155
|
async export(options = {}) {
|
|
209
156
|
checkStorageAccess();
|
|
210
157
|
const items = [];
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (value.count === 0) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
items.push(...value.items);
|
|
218
|
-
if (value.total > offset + value.count) {
|
|
219
|
-
await fetchNextChunk(offset + value.count);
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
await fetchNextChunk();
|
|
158
|
+
for await (const page of this.fetchPages(options)) {
|
|
159
|
+
items.push(...page.items);
|
|
160
|
+
}
|
|
223
161
|
return items;
|
|
224
162
|
}
|
|
225
163
|
/**
|
|
@@ -233,7 +171,14 @@ export class Dataset {
|
|
|
233
171
|
const kvStore = await KeyValueStore.open(options?.toKVS ?? null, { config: this.config });
|
|
234
172
|
const items = await this.export(options);
|
|
235
173
|
if (contentType === 'text/csv') {
|
|
236
|
-
|
|
174
|
+
// To handle empty dataset exports gracefully.
|
|
175
|
+
if (items.length === 0) {
|
|
176
|
+
await kvStore.setValue(key, '', { contentType });
|
|
177
|
+
return items;
|
|
178
|
+
}
|
|
179
|
+
const keys = options?.collectAllKeys
|
|
180
|
+
? Array.from(new Set(items.flatMap(Object.keys)))
|
|
181
|
+
: Object.keys(items[0]);
|
|
237
182
|
const value = stringify([
|
|
238
183
|
keys,
|
|
239
184
|
...items.map((item) => {
|
|
@@ -248,7 +193,6 @@ export class Dataset {
|
|
|
248
193
|
return items;
|
|
249
194
|
}
|
|
250
195
|
throw new Error(`Unsupported content type: ${contentType}`);
|
|
251
|
-
return items;
|
|
252
196
|
}
|
|
253
197
|
/**
|
|
254
198
|
* Save entire default dataset's contents into one JSON file within a key-value store.
|
|
@@ -293,28 +237,23 @@ export class Dataset {
|
|
|
293
237
|
/**
|
|
294
238
|
* Returns an object containing general information about the dataset.
|
|
295
239
|
*
|
|
296
|
-
* The function returns the same object as the Apify API Client's
|
|
297
|
-
* [getDataset](https://docs.apify.com/api/apify-client-js/latest#ApifyClient-datasets-getDataset)
|
|
298
|
-
* function, which in turn calls the
|
|
299
|
-
* [Get dataset](https://apify.com/docs/api/v2#/reference/datasets/dataset/get-dataset)
|
|
300
|
-
* API endpoint.
|
|
301
|
-
*
|
|
302
240
|
* **Example:**
|
|
303
241
|
* ```
|
|
304
242
|
* {
|
|
305
243
|
* id: "WkzbQMuFYuamGv3YF",
|
|
306
244
|
* name: "my-dataset",
|
|
307
|
-
* userId: "wRsJZtadYvn4mBZmm",
|
|
308
245
|
* createdAt: new Date("2015-12-12T07:34:14.202Z"),
|
|
309
246
|
* modifiedAt: new Date("2015-12-13T08:36:13.202Z"),
|
|
310
247
|
* accessedAt: new Date("2015-12-14T08:36:13.202Z"),
|
|
311
248
|
* itemCount: 14,
|
|
312
249
|
* }
|
|
313
250
|
* ```
|
|
251
|
+
*
|
|
252
|
+
* @throws If the underlying storage no longer exists (e.g. it was deleted externally).
|
|
314
253
|
*/
|
|
315
254
|
async getInfo() {
|
|
316
255
|
checkStorageAccess();
|
|
317
|
-
return this.
|
|
256
|
+
return this.backend.getMetadata();
|
|
318
257
|
}
|
|
319
258
|
/**
|
|
320
259
|
* Iterates over dataset items, yielding each in turn to an `iteratee` function.
|
|
@@ -388,15 +327,115 @@ export class Dataset {
|
|
|
388
327
|
await this.forEach(wrappedFunc, options);
|
|
389
328
|
return currentMemo;
|
|
390
329
|
}
|
|
330
|
+
async *fetchEntryPages(options) {
|
|
331
|
+
let index = options.offset ?? 0;
|
|
332
|
+
for await (const page of this.fetchPages(options)) {
|
|
333
|
+
yield {
|
|
334
|
+
...page,
|
|
335
|
+
items: page.items.map((item) => [index++, item]),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
async *fetchPages(options, pageSize = DATASET_ITERATORS_DEFAULT_LIMIT) {
|
|
340
|
+
let offset = options.offset ?? 0;
|
|
341
|
+
const totalLimit = options.limit;
|
|
342
|
+
let yielded = 0;
|
|
343
|
+
while (true) {
|
|
344
|
+
const fetchLimit = totalLimit !== undefined ? Math.min(pageSize, totalLimit - yielded) : pageSize;
|
|
345
|
+
if (fetchLimit <= 0)
|
|
346
|
+
break;
|
|
347
|
+
this.statsTracker.add('readCount');
|
|
348
|
+
const page = await this.backend.getData({ ...options, offset, limit: fetchLimit });
|
|
349
|
+
yield page;
|
|
350
|
+
yielded += page.items.length;
|
|
351
|
+
if (page.items.length < fetchLimit || offset + page.items.length >= page.total)
|
|
352
|
+
break;
|
|
353
|
+
offset += page.items.length;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Returns dataset items.
|
|
358
|
+
*
|
|
359
|
+
* When awaited (`await dataset.values()`), returns all items as a flat `Data[]` array.
|
|
360
|
+
* When used as an async iterable (`for await...of`), iterates over all items across pages
|
|
361
|
+
* without loading everything into memory at once.
|
|
362
|
+
*
|
|
363
|
+
* **Example usage:**
|
|
364
|
+
* ```javascript
|
|
365
|
+
* const dataset = await Dataset.open('my-results');
|
|
366
|
+
*
|
|
367
|
+
* // Iterate over all items (memory-efficient for large datasets)
|
|
368
|
+
* for await (const item of dataset.values()) {
|
|
369
|
+
* console.log(item);
|
|
370
|
+
* }
|
|
371
|
+
*
|
|
372
|
+
* // Or fetch all items at once
|
|
373
|
+
* const items = await dataset.values();
|
|
374
|
+
* console.log(items);
|
|
375
|
+
* ```
|
|
376
|
+
*
|
|
377
|
+
* @param options Options for the iteration.
|
|
378
|
+
*/
|
|
379
|
+
values(options = {}) {
|
|
380
|
+
checkStorageAccess();
|
|
381
|
+
return createDualIterable({
|
|
382
|
+
createPages: () => this.fetchPages(options),
|
|
383
|
+
extractItems: (page) => page.items,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Returns dataset entries (index-value pairs).
|
|
388
|
+
*
|
|
389
|
+
* When awaited (`await dataset.entries()`), returns all entries as a flat `[index, item][]` array.
|
|
390
|
+
* When used as an async iterable (`for await...of`), iterates over all entries across pages
|
|
391
|
+
* without loading everything into memory at once.
|
|
392
|
+
*
|
|
393
|
+
* **Example usage:**
|
|
394
|
+
* ```javascript
|
|
395
|
+
* const dataset = await Dataset.open('my-results');
|
|
396
|
+
*
|
|
397
|
+
* // Iterate over all entries
|
|
398
|
+
* for await (const [index, item] of dataset.entries()) {
|
|
399
|
+
* console.log(`Item at ${index}: ${JSON.stringify(item)}`);
|
|
400
|
+
* }
|
|
401
|
+
*
|
|
402
|
+
* // Or fetch all at once
|
|
403
|
+
* const entries = await dataset.entries();
|
|
404
|
+
* console.log(entries);
|
|
405
|
+
* ```
|
|
406
|
+
*
|
|
407
|
+
* @param options Options for the iteration.
|
|
408
|
+
*/
|
|
409
|
+
entries(options = {}) {
|
|
410
|
+
checkStorageAccess();
|
|
411
|
+
return createDualIterable({
|
|
412
|
+
createPages: () => this.fetchEntryPages(options),
|
|
413
|
+
extractItems: (page) => page.items,
|
|
414
|
+
});
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Default async iterator for the dataset, iterating over items.
|
|
418
|
+
* Allows using the dataset directly in a `for await...of` loop.
|
|
419
|
+
*
|
|
420
|
+
* **Example usage:**
|
|
421
|
+
* ```javascript
|
|
422
|
+
* const dataset = await Dataset.open('my-results');
|
|
423
|
+
* for await (const item of dataset) {
|
|
424
|
+
* console.log(item);
|
|
425
|
+
* }
|
|
426
|
+
* ```
|
|
427
|
+
*/
|
|
428
|
+
async *[Symbol.asyncIterator]() {
|
|
429
|
+
yield* this.values();
|
|
430
|
+
}
|
|
391
431
|
/**
|
|
392
432
|
* Removes the dataset either from the Apify cloud storage or from the local directory,
|
|
393
433
|
* depending on the mode of operation.
|
|
394
434
|
*/
|
|
395
435
|
async drop() {
|
|
396
436
|
checkStorageAccess();
|
|
397
|
-
await this.
|
|
398
|
-
|
|
399
|
-
manager.closeStorage(this);
|
|
437
|
+
await this.backend.drop();
|
|
438
|
+
serviceLocator.getStorageInstanceManager().removeFromCache(this);
|
|
400
439
|
}
|
|
401
440
|
/**
|
|
402
441
|
* Opens a dataset and returns a promise resolving to an instance of the {@link Dataset} class.
|
|
@@ -407,23 +446,27 @@ export class Dataset {
|
|
|
407
446
|
*
|
|
408
447
|
* For more details and code examples, see the {@link Dataset} class.
|
|
409
448
|
*
|
|
410
|
-
* @param [
|
|
411
|
-
* ID or name of the dataset to be opened. If
|
|
412
|
-
*
|
|
449
|
+
* @param [identifier]
|
|
450
|
+
* ID or name of the dataset to be opened. If a string is provided, it will first be
|
|
451
|
+
* looked up as an ID; if no such storage exists, it will be treated as a name.
|
|
452
|
+
* If `null` or `undefined`, the function returns the default dataset associated with the crawler run.
|
|
413
453
|
* @param [options] Storage manager options.
|
|
414
454
|
*/
|
|
415
|
-
static async open(
|
|
455
|
+
static async open(identifier, options = {}) {
|
|
416
456
|
checkStorageAccess();
|
|
417
|
-
ow(datasetIdOrName, ow.optional.string);
|
|
418
457
|
ow(options, ow.object.exactShape({
|
|
419
458
|
config: ow.optional.object.instanceOf(Configuration),
|
|
420
|
-
|
|
459
|
+
storageBackend: ow.optional.object,
|
|
421
460
|
}));
|
|
422
461
|
options.config ??= Configuration.getGlobalConfig();
|
|
423
|
-
options.
|
|
424
|
-
await purgeDefaultStorages({ onlyPurgeOnce: true,
|
|
425
|
-
const
|
|
426
|
-
return
|
|
462
|
+
const storageBackend = options.storageBackend ?? serviceLocator.getStorageBackend();
|
|
463
|
+
await purgeDefaultStorages({ onlyPurgeOnce: true, storageBackend, config: options.config });
|
|
464
|
+
const resolved = await resolveStorageIdentifier(identifier, storageBackend, 'Dataset');
|
|
465
|
+
return serviceLocator.getStorageInstanceManager().openStorage(this, {
|
|
466
|
+
...resolved,
|
|
467
|
+
backendOpener: () => storageBackend.createDatasetBackend(resolved),
|
|
468
|
+
backendCacheKey: storageBackend.getStorageBackendCacheKey?.() ?? storageBackend.constructor.name,
|
|
469
|
+
});
|
|
427
470
|
}
|
|
428
471
|
/**
|
|
429
472
|
* Stores an object or an array of objects to the default {@link Dataset} of the current crawler run.
|