@crawlee/core 4.0.0-beta.14 → 4.0.0-beta.141
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 +14 -14
- package/autoscaling/autoscaled_pool.d.ts +67 -172
- package/autoscaling/autoscaled_pool.js +182 -329
- package/autoscaling/concurrency_system.d.ts +269 -0
- package/autoscaling/concurrency_system.js +365 -0
- package/autoscaling/cpu_load_signal.d.ts +43 -0
- package/autoscaling/cpu_load_signal.js +47 -0
- package/autoscaling/event_loop_load_signal.d.ts +51 -0
- package/autoscaling/event_loop_load_signal.js +60 -0
- package/autoscaling/index.d.ts +6 -1
- package/autoscaling/index.js +6 -1
- package/autoscaling/load_signal.d.ts +100 -0
- package/autoscaling/load_signal.js +105 -0
- package/autoscaling/memory_load_signal.d.ts +47 -0
- package/autoscaling/memory_load_signal.js +106 -0
- package/autoscaling/snapshotter.d.ts +58 -163
- package/autoscaling/snapshotter.js +45 -263
- package/autoscaling/storage_backend_load_signal.d.ts +56 -0
- package/autoscaling/storage_backend_load_signal.js +73 -0
- package/autoscaling/system_status.d.ts +67 -89
- package/autoscaling/system_status.js +92 -122
- package/autoscaling/weighted_avg.d.ts +5 -0
- package/autoscaling/weighted_avg.js +14 -0
- package/byte_utils.d.ts +17 -0
- package/byte_utils.js +42 -0
- package/configuration.d.ts +96 -223
- package/configuration.js +170 -222
- package/cookie_utils.d.ts +3 -2
- package/cookie_utils.js +18 -7
- package/crawlers/context_pipeline.d.ts +10 -1
- package/crawlers/context_pipeline.js +31 -8
- package/crawlers/crawler_commons.d.ts +90 -126
- package/crawlers/crawler_commons.js +1 -108
- package/crawlers/error_snapshotter.d.ts +2 -5
- package/crawlers/error_snapshotter.js +7 -8
- package/crawlers/error_tracker.d.ts +0 -1
- package/crawlers/error_tracker.js +0 -1
- package/crawlers/index.d.ts +1 -3
- package/crawlers/index.js +0 -3
- package/crawlers/internals/types.d.ts +0 -1
- package/crawlers/internals/types.js +0 -1
- package/crawlers/statistics.d.ts +187 -63
- package/crawlers/statistics.js +354 -164
- package/debug.d.ts +36 -0
- package/debug.js +70 -0
- package/enqueue_links/enqueue_links.d.ts +60 -153
- package/enqueue_links/enqueue_links.js +38 -229
- package/enqueue_links/index.d.ts +0 -1
- package/enqueue_links/index.js +0 -1
- package/enqueue_links/shared.d.ts +49 -30
- package/enqueue_links/shared.js +94 -68
- package/errors.d.ts +72 -4
- package/errors.js +89 -5
- package/events/event_manager.d.ts +35 -9
- package/events/event_manager.js +12 -13
- package/events/index.d.ts +0 -1
- package/events/index.js +0 -1
- package/events/local_event_manager.d.ts +15 -3
- package/events/local_event_manager.js +39 -13
- package/http.d.ts +9 -0
- package/http.js +28 -0
- package/index.d.ts +7 -5
- package/index.js +8 -4
- package/iterables.d.ts +79 -0
- package/iterables.js +134 -0
- package/log.d.ts +78 -1
- package/log.js +106 -1
- package/memory-storage/consts.d.ts +4 -0
- package/memory-storage/consts.js +4 -0
- package/memory-storage/index.d.ts +1 -0
- package/memory-storage/index.js +1 -0
- package/memory-storage/memory-storage.d.ts +44 -0
- package/memory-storage/memory-storage.js +160 -0
- package/memory-storage/resource-clients/common/base-client.d.ts +4 -0
- package/memory-storage/resource-clients/common/base-client.js +6 -0
- package/memory-storage/resource-clients/dataset.d.ts +40 -0
- package/memory-storage/resource-clients/dataset.js +106 -0
- package/memory-storage/resource-clients/key-value-store.d.ts +63 -0
- package/memory-storage/resource-clients/key-value-store.js +199 -0
- package/memory-storage/resource-clients/request-queue.d.ts +77 -0
- package/memory-storage/resource-clients/request-queue.js +407 -0
- package/memory-storage/utils.d.ts +16 -0
- package/memory-storage/utils.js +41 -0
- package/owned_or_injected.d.ts +58 -0
- package/owned_or_injected.js +98 -0
- package/package.json +13 -12
- package/proxy_configuration.d.ts +22 -128
- package/proxy_configuration.js +32 -144
- package/recoverable_state.d.ts +83 -51
- package/recoverable_state.js +163 -72
- package/request.d.ts +57 -16
- package/request.js +130 -69
- package/router.d.ts +193 -21
- package/router.js +188 -43
- package/serialization.d.ts +0 -1
- package/serialization.js +15 -15
- package/service_locator.d.ts +165 -0
- package/service_locator.js +253 -0
- package/session_pool/consts.d.ts +1 -2
- package/session_pool/consts.js +1 -2
- package/session_pool/errors.d.ts +0 -1
- package/session_pool/errors.js +0 -1
- package/session_pool/fingerprint.d.ts +9 -0
- package/session_pool/fingerprint.js +30 -0
- package/session_pool/index.d.ts +0 -2
- package/session_pool/index.js +0 -2
- package/session_pool/session.d.ts +35 -88
- package/session_pool/session.js +101 -159
- package/session_pool/session_pool.d.ts +74 -91
- package/session_pool/session_pool.js +175 -165
- package/storages/batched_adds.d.ts +37 -0
- package/storages/batched_adds.js +73 -0
- package/storages/dataset.d.ts +109 -56
- package/storages/dataset.js +283 -149
- package/storages/index.d.ts +9 -9
- package/storages/index.js +7 -9
- package/storages/key_value_store.d.ts +183 -48
- package/storages/key_value_store.js +445 -171
- package/storages/key_value_store_codec.d.ts +32 -0
- package/storages/key_value_store_codec.js +113 -0
- package/storages/request_dedup_cache.d.ts +22 -0
- package/storages/request_dedup_cache.js +48 -0
- package/storages/request_list.d.ts +52 -109
- package/storages/request_list.js +183 -152
- package/storages/request_loader.d.ts +101 -0
- package/storages/request_loader.js +1 -0
- package/storages/request_manager.d.ts +33 -0
- package/storages/request_manager.js +1 -0
- package/storages/request_manager_tandem.d.ts +48 -19
- package/storages/request_manager_tandem.js +118 -45
- package/storages/request_queue.d.ts +290 -47
- package/storages/request_queue.js +762 -216
- package/storages/{sitemap_request_list.d.ts → sitemap_request_loader.d.ts} +45 -89
- package/storages/sitemap_request_loader.js +438 -0
- package/storages/storage_instance_manager.d.ts +87 -0
- package/storages/storage_instance_manager.js +256 -0
- package/storages/storage_stats.d.ts +48 -0
- package/storages/storage_stats.js +29 -0
- package/storages/throttling_request_manager.d.ts +239 -0
- package/storages/throttling_request_manager.js +646 -0
- package/storages/transaction.d.ts +252 -0
- package/storages/transaction.js +251 -0
- package/storages/utils.d.ts +59 -11
- package/storages/utils.js +75 -15
- package/system-info/cpu-info.d.ts +67 -0
- package/system-info/cpu-info.js +216 -0
- package/system-info/memory-info.d.ts +31 -0
- package/system-info/memory-info.js +115 -0
- package/system-info/ps-tree.d.ts +17 -0
- package/system-info/ps-tree.js +144 -0
- package/system-info/runtime.d.ts +14 -0
- package/system-info/runtime.js +80 -0
- package/typedefs.d.ts +0 -6
- package/typedefs.js +0 -1
- package/url.d.ts +9 -0
- package/url.js +11 -0
- package/validators.d.ts +22 -18
- package/validators.js +13 -18
- package/autoscaling/autoscaled_pool.d.ts.map +0 -1
- package/autoscaling/autoscaled_pool.js.map +0 -1
- package/autoscaling/index.d.ts.map +0 -1
- package/autoscaling/index.js.map +0 -1
- package/autoscaling/snapshotter.d.ts.map +0 -1
- package/autoscaling/snapshotter.js.map +0 -1
- package/autoscaling/system_status.d.ts.map +0 -1
- package/autoscaling/system_status.js.map +0 -1
- package/configuration.d.ts.map +0 -1
- package/configuration.js.map +0 -1
- package/cookie_utils.d.ts.map +0 -1
- package/cookie_utils.js.map +0 -1
- package/crawlers/context_pipeline.d.ts.map +0 -1
- package/crawlers/context_pipeline.js.map +0 -1
- package/crawlers/crawler_commons.d.ts.map +0 -1
- package/crawlers/crawler_commons.js.map +0 -1
- package/crawlers/crawler_utils.d.ts +0 -10
- package/crawlers/crawler_utils.d.ts.map +0 -1
- package/crawlers/crawler_utils.js +0 -12
- package/crawlers/crawler_utils.js.map +0 -1
- package/crawlers/error_snapshotter.d.ts.map +0 -1
- package/crawlers/error_snapshotter.js.map +0 -1
- package/crawlers/error_tracker.d.ts.map +0 -1
- package/crawlers/error_tracker.js.map +0 -1
- package/crawlers/index.d.ts.map +0 -1
- package/crawlers/index.js.map +0 -1
- package/crawlers/internals/types.d.ts.map +0 -1
- package/crawlers/internals/types.js.map +0 -1
- package/crawlers/statistics.d.ts.map +0 -1
- package/crawlers/statistics.js.map +0 -1
- package/enqueue_links/enqueue_links.d.ts.map +0 -1
- package/enqueue_links/enqueue_links.js.map +0 -1
- package/enqueue_links/index.d.ts.map +0 -1
- package/enqueue_links/index.js.map +0 -1
- package/enqueue_links/shared.d.ts.map +0 -1
- package/enqueue_links/shared.js.map +0 -1
- package/errors.d.ts.map +0 -1
- package/errors.js.map +0 -1
- package/events/event_manager.d.ts.map +0 -1
- package/events/event_manager.js.map +0 -1
- package/events/index.d.ts.map +0 -1
- package/events/index.js.map +0 -1
- package/events/local_event_manager.d.ts.map +0 -1
- package/events/local_event_manager.js.map +0 -1
- package/http_clients/base-http-client.d.ts +0 -140
- package/http_clients/base-http-client.d.ts.map +0 -1
- package/http_clients/base-http-client.js +0 -40
- 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 -20
- package/http_clients/got-scraping-http-client.d.ts.map +0 -1
- package/http_clients/got-scraping-http-client.js +0 -85
- 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/index.d.ts.map +0 -1
- package/index.js.map +0 -1
- package/log.d.ts.map +0 -1
- package/log.js.map +0 -1
- package/proxy_configuration.d.ts.map +0 -1
- package/proxy_configuration.js.map +0 -1
- package/recoverable_state.d.ts.map +0 -1
- package/recoverable_state.js.map +0 -1
- package/request.d.ts.map +0 -1
- package/request.js.map +0 -1
- package/router.d.ts.map +0 -1
- package/router.js.map +0 -1
- package/serialization.d.ts.map +0 -1
- package/serialization.js.map +0 -1
- package/session_pool/consts.d.ts.map +0 -1
- package/session_pool/consts.js.map +0 -1
- package/session_pool/errors.d.ts.map +0 -1
- package/session_pool/errors.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/session_pool/index.d.ts.map +0 -1
- package/session_pool/index.js.map +0 -1
- package/session_pool/session.d.ts.map +0 -1
- package/session_pool/session.js.map +0 -1
- package/session_pool/session_pool.d.ts.map +0 -1
- package/session_pool/session_pool.js.map +0 -1
- package/storages/access_checking.d.ts +0 -13
- package/storages/access_checking.d.ts.map +0 -1
- package/storages/access_checking.js +0 -14
- package/storages/access_checking.js.map +0 -1
- package/storages/dataset.d.ts.map +0 -1
- package/storages/dataset.js.map +0 -1
- package/storages/index.d.ts.map +0 -1
- package/storages/index.js.map +0 -1
- package/storages/key_value_store.d.ts.map +0 -1
- package/storages/key_value_store.js.map +0 -1
- package/storages/request_list.d.ts.map +0 -1
- package/storages/request_list.js.map +0 -1
- package/storages/request_list_adapter.d.ts +0 -58
- package/storages/request_list_adapter.d.ts.map +0 -1
- package/storages/request_list_adapter.js +0 -81
- package/storages/request_list_adapter.js.map +0 -1
- package/storages/request_manager_tandem.d.ts.map +0 -1
- package/storages/request_manager_tandem.js.map +0 -1
- package/storages/request_provider.d.ts +0 -371
- package/storages/request_provider.d.ts.map +0 -1
- package/storages/request_provider.js +0 -585
- package/storages/request_provider.js.map +0 -1
- package/storages/request_queue.d.ts.map +0 -1
- package/storages/request_queue.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 +0 -430
- 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/storages/utils.d.ts.map +0 -1
- package/storages/utils.js.map +0 -1
- package/typedefs.d.ts.map +0 -1
- package/typedefs.js.map +0 -1
- package/validators.d.ts.map +0 -1
- package/validators.js.map +0 -1
package/request.js
CHANGED
|
@@ -1,32 +1,13 @@
|
|
|
1
1
|
import crypto from 'node:crypto';
|
|
2
2
|
import util from 'node:util';
|
|
3
|
-
import
|
|
4
|
-
import { normalizeUrl } from '@apify/utilities';
|
|
5
|
-
import {
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import { cryptoRandomObjectId, normalizeUrl } from '@apify/utilities';
|
|
5
|
+
import { serviceLocator } from './service_locator.js';
|
|
6
6
|
import { keys } from './typedefs.js';
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
loadedUrl: ow.optional.string.url,
|
|
12
|
-
uniqueKey: ow.optional.string,
|
|
13
|
-
method: ow.optional.string,
|
|
14
|
-
payload: ow.optional.any(ow.string, ow.uint8Array),
|
|
15
|
-
noRetry: ow.optional.boolean,
|
|
16
|
-
retryCount: ow.optional.number,
|
|
17
|
-
sessionRotationCount: ow.optional.number,
|
|
18
|
-
maxRetries: ow.optional.number,
|
|
19
|
-
errorMessages: ow.optional.array.ofType(ow.string),
|
|
20
|
-
headers: ow.optional.object,
|
|
21
|
-
userData: ow.optional.object,
|
|
22
|
-
label: ow.optional.string,
|
|
23
|
-
handledAt: ow.optional.any(ow.string.date, ow.date),
|
|
24
|
-
keepUrlFragment: ow.optional.boolean,
|
|
25
|
-
useExtendedUniqueKey: ow.optional.boolean,
|
|
26
|
-
skipNavigation: ow.optional.boolean,
|
|
27
|
-
crawlDepth: ow.optional.number.greaterThanOrEqual(0),
|
|
28
|
-
state: ow.optional.number.greaterThanOrEqual(0).lessThanOrEqual(6),
|
|
29
|
-
};
|
|
7
|
+
import { parseArgument, schemas } from './validators.js';
|
|
8
|
+
const dateString = z.string().refine((value) => !Number.isNaN(Date.parse(value)), {
|
|
9
|
+
message: 'Invalid input: expected a date string',
|
|
10
|
+
});
|
|
30
11
|
export var RequestState;
|
|
31
12
|
(function (RequestState) {
|
|
32
13
|
RequestState[RequestState["UNPROCESSED"] = 0] = "UNPROCESSED";
|
|
@@ -38,6 +19,34 @@ export var RequestState;
|
|
|
38
19
|
RequestState[RequestState["ERROR"] = 6] = "ERROR";
|
|
39
20
|
RequestState[RequestState["SKIPPED"] = 7] = "SKIPPED";
|
|
40
21
|
})(RequestState || (RequestState = {}));
|
|
22
|
+
const requestUrlSchema = z.object({ url: z.string() });
|
|
23
|
+
// new properties on the Request object breaks serialization
|
|
24
|
+
const requestOptionalSchemaShapes = {
|
|
25
|
+
id: z.string().optional(),
|
|
26
|
+
loadedUrl: z.url().optional(),
|
|
27
|
+
uniqueKey: z.string().optional(),
|
|
28
|
+
method: z.string().optional(),
|
|
29
|
+
payload: z.union([z.string(), z.instanceof(Uint8Array)]).optional(),
|
|
30
|
+
noRetry: z.boolean().optional(),
|
|
31
|
+
retryCount: schemas.anyNumber.optional(),
|
|
32
|
+
sessionId: z.string().optional(),
|
|
33
|
+
maxRetries: schemas.anyNumber.optional(),
|
|
34
|
+
errorMessages: schemas.arrayOf(z.string(), 'strings').optional(),
|
|
35
|
+
headers: z.looseObject({}).optional(),
|
|
36
|
+
userData: z.looseObject({}).optional(),
|
|
37
|
+
label: z.string().optional(),
|
|
38
|
+
handledAt: z.union([dateString, z.date()]).optional(),
|
|
39
|
+
keepUrlFragment: z.boolean().optional(),
|
|
40
|
+
useExtendedUniqueKey: z.boolean().optional(),
|
|
41
|
+
alwaysEnqueue: z.boolean().optional(),
|
|
42
|
+
skipNavigation: z.boolean().optional(),
|
|
43
|
+
crawlDepth: schemas.anyNumber
|
|
44
|
+
.refine((value) => value >= 0, 'Expected a number greater than or equal to 0')
|
|
45
|
+
.optional(),
|
|
46
|
+
state: z.enum(RequestState).optional(),
|
|
47
|
+
};
|
|
48
|
+
// Each schema is wrapped in a single-key object so validation errors carry the property name.
|
|
49
|
+
const requestOptionalSchemas = Object.fromEntries(Object.entries(requestOptionalSchemaShapes).map(([key, schema]) => [key, z.object({ [key]: schema })]));
|
|
41
50
|
/**
|
|
42
51
|
* Represents a URL to be crawled, optionally including HTTP method, headers, payload and other metadata.
|
|
43
52
|
* The `Request` object also stores information about errors that occurred during processing of the request.
|
|
@@ -101,8 +110,13 @@ class CrawleeRequest {
|
|
|
101
110
|
/** Object with HTTP headers. Key is header name, value is the value. */
|
|
102
111
|
headers;
|
|
103
112
|
/** Private store for the custom user data assigned to the request. */
|
|
104
|
-
|
|
105
|
-
/**
|
|
113
|
+
#userData = {};
|
|
114
|
+
/**
|
|
115
|
+
* Custom user data assigned to the request.
|
|
116
|
+
*
|
|
117
|
+
* All data stored in `userData` must be JSON-serializable.
|
|
118
|
+
* Storing non-serializable values (e.g. functions, symbols) may result in unexpected results.
|
|
119
|
+
*/
|
|
106
120
|
userData = {};
|
|
107
121
|
/**
|
|
108
122
|
* ISO datetime string that indicates the time when the request has been processed.
|
|
@@ -113,76 +127,89 @@ class CrawleeRequest {
|
|
|
113
127
|
* `Request` parameters including the URL, HTTP method and headers, and others.
|
|
114
128
|
*/
|
|
115
129
|
constructor(options) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
130
|
+
// A bare URL is a common slip — point at the object form instead of a generic type error.
|
|
131
|
+
if (typeof options === 'string') {
|
|
132
|
+
throw new TypeError(`\`Request\` options must be an object, got the string '${options}'. ` +
|
|
133
|
+
'Did you mean `new Request({ url })`?');
|
|
134
|
+
}
|
|
135
|
+
parseArgument(options, schemas.anyObject, 'RequestOptions');
|
|
136
|
+
parseArgument(options, requestUrlSchema, 'RequestOptions');
|
|
137
|
+
// Full-shape validation is slow, because it checks all predicates
|
|
119
138
|
// even if the validated object has only 1 property.
|
|
120
139
|
// This custom validation loop iterates only over existing
|
|
121
140
|
// properties and speeds up the validation cca 3-fold.
|
|
122
|
-
// See https://github.com/sindresorhus/ow/issues/193
|
|
123
141
|
keys(options).forEach((prop) => {
|
|
124
142
|
// skip url, because it is validated above
|
|
125
143
|
if (prop === 'url') {
|
|
126
144
|
return;
|
|
127
145
|
}
|
|
128
|
-
const
|
|
146
|
+
const schema = requestOptionalSchemas[prop];
|
|
129
147
|
const value = options[prop];
|
|
130
|
-
if (
|
|
131
|
-
|
|
148
|
+
if (schema) {
|
|
149
|
+
parseArgument({ [prop]: value }, schema, 'RequestOptions');
|
|
132
150
|
}
|
|
133
151
|
});
|
|
134
|
-
const { id, url, loadedUrl, uniqueKey, payload, noRetry = false, retryCount = 0,
|
|
152
|
+
const { id, url, loadedUrl, uniqueKey, payload, noRetry = false, retryCount = 0, sessionId, maxRetries, errorMessages = [], headers = {}, userData = {}, label, handledAt, keepUrlFragment = false, useExtendedUniqueKey = false, alwaysEnqueue = false, skipNavigation, enqueueStrategy, crawlDepth, } = options;
|
|
135
153
|
let { method = 'GET' } = options;
|
|
136
154
|
method = method.toUpperCase();
|
|
137
155
|
if (method === 'GET' && payload)
|
|
138
156
|
throw new Error('Request with GET method cannot have a payload.');
|
|
157
|
+
if (uniqueKey && alwaysEnqueue) {
|
|
158
|
+
throw new Error('`alwaysEnqueue` cannot be used together with a custom `uniqueKey`.');
|
|
159
|
+
}
|
|
139
160
|
this.id = id;
|
|
140
161
|
this.url = url;
|
|
141
162
|
this.loadedUrl = loadedUrl;
|
|
142
163
|
this.uniqueKey =
|
|
143
164
|
uniqueKey ||
|
|
144
|
-
CrawleeRequest.computeUniqueKey({
|
|
165
|
+
CrawleeRequest.computeUniqueKey({
|
|
166
|
+
url,
|
|
167
|
+
method,
|
|
168
|
+
payload,
|
|
169
|
+
keepUrlFragment,
|
|
170
|
+
useExtendedUniqueKey,
|
|
171
|
+
alwaysEnqueue,
|
|
172
|
+
});
|
|
145
173
|
this.method = method;
|
|
146
174
|
this.payload = payload;
|
|
147
175
|
this.noRetry = noRetry;
|
|
148
176
|
this.retryCount = retryCount;
|
|
149
|
-
this.sessionRotationCount = sessionRotationCount;
|
|
150
177
|
this.errorMessages = [...errorMessages];
|
|
151
178
|
this.headers = { ...headers };
|
|
152
179
|
this.handledAt = handledAt instanceof Date ? handledAt.toISOString() : handledAt;
|
|
153
180
|
if (label) {
|
|
154
181
|
userData.label = label;
|
|
155
182
|
}
|
|
183
|
+
// Read `__crawlee` explicitly - on a `userData` coming from another Request instance the
|
|
184
|
+
// bag is non-enumerable, so the spread alone would silently drop the internal state
|
|
185
|
+
// (e.g. `skipNavigation`) when a request is re-wrapped after a storage round trip.
|
|
186
|
+
this.#userData = { __crawlee: userData.__crawlee ?? {}, ...userData };
|
|
187
|
+
// `userData` must stay an enumerable own accessor — serialization in the storages relies on it
|
|
156
188
|
Object.defineProperties(this, {
|
|
157
|
-
_userData: {
|
|
158
|
-
value: { __crawlee: {}, ...userData },
|
|
159
|
-
enumerable: false,
|
|
160
|
-
writable: true,
|
|
161
|
-
},
|
|
162
189
|
userData: {
|
|
163
|
-
get: () => this
|
|
190
|
+
get: () => this.#userData,
|
|
164
191
|
set: (value) => {
|
|
165
192
|
Object.defineProperties(value, {
|
|
166
193
|
__crawlee: {
|
|
167
|
-
value: this.
|
|
194
|
+
value: this.#userData.__crawlee,
|
|
168
195
|
enumerable: false,
|
|
169
196
|
writable: true,
|
|
170
197
|
},
|
|
171
198
|
toJSON: {
|
|
172
199
|
value: () => {
|
|
173
|
-
if (Object.keys(this.
|
|
200
|
+
if (Object.keys(this.#userData.__crawlee).length > 0) {
|
|
174
201
|
return {
|
|
175
|
-
...this
|
|
176
|
-
__crawlee: this.
|
|
202
|
+
...this.#userData,
|
|
203
|
+
__crawlee: this.#userData.__crawlee,
|
|
177
204
|
};
|
|
178
205
|
}
|
|
179
|
-
return this
|
|
206
|
+
return this.#userData;
|
|
180
207
|
},
|
|
181
208
|
enumerable: false,
|
|
182
209
|
writable: true,
|
|
183
210
|
},
|
|
184
211
|
});
|
|
185
|
-
this
|
|
212
|
+
this.#userData = value;
|
|
186
213
|
},
|
|
187
214
|
enumerable: true,
|
|
188
215
|
},
|
|
@@ -195,6 +222,8 @@ class CrawleeRequest {
|
|
|
195
222
|
this.maxRetries = maxRetries;
|
|
196
223
|
if (crawlDepth != null)
|
|
197
224
|
this.userData.__crawlee.crawlDepth ??= crawlDepth;
|
|
225
|
+
if (sessionId)
|
|
226
|
+
this.sessionId = sessionId;
|
|
198
227
|
// If it's already set, don't override it (for instance when fetching from storage)
|
|
199
228
|
if (enqueueStrategy) {
|
|
200
229
|
this.enqueueStrategy ??= enqueueStrategy;
|
|
@@ -211,11 +240,23 @@ class CrawleeRequest {
|
|
|
211
240
|
body: this.payload,
|
|
212
241
|
});
|
|
213
242
|
}
|
|
214
|
-
/**
|
|
243
|
+
/**
|
|
244
|
+
* Tells the crawler processing this request to skip the navigation and process the request directly.
|
|
245
|
+
*
|
|
246
|
+
* When this is set to `true`, the crawling context will not contain the results of the navigation
|
|
247
|
+
* (e.g. `response`, `body`, `contentType`, `$` or `request.loadedUrl`).
|
|
248
|
+
* Accessing these properties will throw a {@link NavigationSkippedError} at runtime.
|
|
249
|
+
*/
|
|
215
250
|
get skipNavigation() {
|
|
216
251
|
return this.userData.__crawlee?.skipNavigation ?? false;
|
|
217
252
|
}
|
|
218
|
-
/**
|
|
253
|
+
/**
|
|
254
|
+
* Tells the crawler processing this request to skip the navigation and process the request directly.
|
|
255
|
+
*
|
|
256
|
+
* When this is set to `true`, the crawling context will not contain the results of the navigation
|
|
257
|
+
* (e.g. `response`, `body`, `contentType`, `$` or `request.loadedUrl`).
|
|
258
|
+
* Accessing these properties will throw a {@link NavigationSkippedError} at runtime.
|
|
259
|
+
*/
|
|
219
260
|
set skipNavigation(value) {
|
|
220
261
|
if (!this.userData.__crawlee) {
|
|
221
262
|
this.userData.__crawlee = { skipNavigation: value };
|
|
@@ -239,18 +280,13 @@ class CrawleeRequest {
|
|
|
239
280
|
this.userData.__crawlee ??= {};
|
|
240
281
|
this.userData.__crawlee.crawlDepth = value;
|
|
241
282
|
}
|
|
242
|
-
/**
|
|
243
|
-
get
|
|
244
|
-
return this.userData.__crawlee?.
|
|
283
|
+
/** ID of a session to use for this request. When set, the crawler will fetch this session from the session pool instead of creating a new one. */
|
|
284
|
+
get sessionId() {
|
|
285
|
+
return this.userData.__crawlee?.sessionId;
|
|
245
286
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
this.userData.__crawlee = { sessionRotationCount: value };
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
this.userData.__crawlee.sessionRotationCount = value;
|
|
253
|
-
}
|
|
287
|
+
set sessionId(value) {
|
|
288
|
+
this.userData.__crawlee ??= {};
|
|
289
|
+
this.userData.__crawlee.sessionId = value;
|
|
254
290
|
}
|
|
255
291
|
/** shortcut for getting `request.userData.label` */
|
|
256
292
|
get label() {
|
|
@@ -286,6 +322,23 @@ class CrawleeRequest {
|
|
|
286
322
|
this.userData.__crawlee.state = value;
|
|
287
323
|
}
|
|
288
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* Reason for skipping this request.
|
|
327
|
+
*/
|
|
328
|
+
get skippedReason() {
|
|
329
|
+
return this.userData.__crawlee?.skippedReason;
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* Reason for skipping this request.
|
|
333
|
+
*/
|
|
334
|
+
set skippedReason(value) {
|
|
335
|
+
if (!this.userData.__crawlee) {
|
|
336
|
+
this.userData.__crawlee = { skippedReason: value };
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
this.userData.__crawlee.skippedReason = value;
|
|
340
|
+
}
|
|
341
|
+
}
|
|
289
342
|
get enqueueStrategy() {
|
|
290
343
|
return this.userData.__crawlee?.enqueueStrategy;
|
|
291
344
|
}
|
|
@@ -348,19 +401,28 @@ class CrawleeRequest {
|
|
|
348
401
|
this.errorMessages.push(message);
|
|
349
402
|
}
|
|
350
403
|
/** @internal */
|
|
351
|
-
static computeUniqueKey({ url, method = 'GET', payload, keepUrlFragment = false, useExtendedUniqueKey = false, }) {
|
|
404
|
+
static computeUniqueKey({ url, method = 'GET', payload, keepUrlFragment = false, useExtendedUniqueKey = false, alwaysEnqueue = false, }) {
|
|
352
405
|
const normalizedMethod = method.toUpperCase();
|
|
353
406
|
const normalizedUrl = normalizeUrl(url, keepUrlFragment) || url; // It returns null when url is invalid, causing weird errors.
|
|
407
|
+
let uniqueKey;
|
|
354
408
|
if (!useExtendedUniqueKey) {
|
|
355
409
|
if (normalizedMethod !== 'GET' && payload) {
|
|
356
|
-
|
|
410
|
+
serviceLocator
|
|
411
|
+
.getLogger()
|
|
412
|
+
.warningOnce(`We've encountered a ${normalizedMethod} Request with a payload. ` +
|
|
357
413
|
'This is fine. Just letting you know that if your requests point to the same URL ' +
|
|
358
414
|
'and differ only in method and payload, you should see the "useExtendedUniqueKey" option of Request constructor.');
|
|
359
415
|
}
|
|
360
|
-
|
|
416
|
+
uniqueKey = normalizedUrl;
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
const payloadHash = payload ? CrawleeRequest.hashPayload(payload) : '';
|
|
420
|
+
uniqueKey = `${normalizedMethod}|${payloadHash}|${normalizedUrl}`;
|
|
421
|
+
}
|
|
422
|
+
if (alwaysEnqueue) {
|
|
423
|
+
uniqueKey = `${cryptoRandomObjectId(17)}|${uniqueKey}`;
|
|
361
424
|
}
|
|
362
|
-
|
|
363
|
-
return `${normalizedMethod}(${payloadHash}):${normalizedUrl}`;
|
|
425
|
+
return uniqueKey;
|
|
364
426
|
}
|
|
365
427
|
/** @internal */
|
|
366
428
|
static hashPayload(payload) {
|
|
@@ -368,4 +430,3 @@ class CrawleeRequest {
|
|
|
368
430
|
}
|
|
369
431
|
}
|
|
370
432
|
export { CrawleeRequest as Request };
|
|
371
|
-
//# sourceMappingURL=request.js.map
|
package/router.d.ts
CHANGED
|
@@ -1,14 +1,91 @@
|
|
|
1
|
-
import type { Dictionary } from '@crawlee/types';
|
|
2
|
-
import type {
|
|
1
|
+
import type { Awaitable, Dictionary } from '@crawlee/types';
|
|
2
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
3
|
+
import type { CrawlingContext, LoadedRequest, RestrictedCrawlingContext, TypedContextAddRequests, TypedContextEnqueueLinks } from './crawlers/crawler_commons.js';
|
|
3
4
|
import type { Request } from './request.js';
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The key of the default route — the fallback handler registered via {@link Router.addDefaultHandler}.
|
|
7
|
+
* Use it in a {@link RouteSchemas} map to register a schema that validates the `userData` of every request
|
|
8
|
+
* that falls through to the default handler (i.e. whose label has no route of its own).
|
|
9
|
+
*/
|
|
10
|
+
export declare const defaultRoute: unique symbol;
|
|
11
|
+
/**
|
|
12
|
+
* The crawling context received by a route handler, with `request.userData` narrowed to `UserData`, and
|
|
13
|
+
* `addRequests`/`enqueueLinks` typed according to the router's route map (`Routes`) so that enqueuing a
|
|
14
|
+
* request under a declared label requires the matching `userData` shape.
|
|
15
|
+
*/
|
|
16
|
+
export type RouterHandlerContext<Context, UserData extends Dictionary, Routes extends Record<keyof Routes, Dictionary>> = Omit<Context, 'request' | 'addRequests' | 'enqueueLinks'> & {
|
|
17
|
+
request: LoadedRequest<Request<UserData>>;
|
|
18
|
+
addRequests: TypedContextAddRequests<Routes>;
|
|
19
|
+
} & (Context extends {
|
|
20
|
+
enqueueLinks: infer EnqueueLinks;
|
|
21
|
+
} ? {
|
|
22
|
+
enqueueLinks: TypedContextEnqueueLinks<EnqueueLinks, Routes>;
|
|
23
|
+
} : {});
|
|
24
|
+
/**
|
|
25
|
+
* A map of request labels to a [Standard Schema](https://standardschema.dev) (Zod, Valibot, ArkType, …)
|
|
26
|
+
* validating that label's `request.userData`. Pass it to {@link Router.create} or a `createXRouter`
|
|
27
|
+
* factory to derive the per-label `request.userData` types *and* validate them at runtime. The optional
|
|
28
|
+
* {@link defaultRoute} key registers a schema for requests handled by the default route.
|
|
29
|
+
*/
|
|
30
|
+
export type RouteSchemas = Record<string, StandardSchemaV1> & {
|
|
31
|
+
[defaultRoute]?: StandardSchemaV1;
|
|
32
|
+
};
|
|
33
|
+
/** Infers a label's `userData` type from its schema, falling back to a plain {@link Dictionary}. */
|
|
34
|
+
type SchemaUserData<Schema extends StandardSchemaV1> = StandardSchemaV1.InferOutput<Schema> extends Dictionary ? StandardSchemaV1.InferOutput<Schema> : Dictionary;
|
|
35
|
+
/**
|
|
36
|
+
* Derives a route map (label → `userData` type) from a {@link RouteSchemas} map by inferring each schema's
|
|
37
|
+
* output type. Outputs that are not object-shaped fall back to a plain {@link Dictionary}. The
|
|
38
|
+
* {@link defaultRoute} schema is kept under its symbol key so {@link Router.addDefaultHandler} can pick it
|
|
39
|
+
* up; string labels (the ones {@link Router.addHandler} and the crawler-level typing accept) ignore it.
|
|
40
|
+
*/
|
|
41
|
+
export type RoutesFromSchemas<Schemas extends RouteSchemas> = {
|
|
42
|
+
[Label in Extract<keyof Schemas, string>]: SchemaUserData<Schemas[Label]>;
|
|
43
|
+
} & (Schemas extends {
|
|
44
|
+
[defaultRoute]: StandardSchemaV1;
|
|
45
|
+
} ? {
|
|
46
|
+
[defaultRoute]: SchemaUserData<Schemas[typeof defaultRoute]>;
|
|
47
|
+
} : {});
|
|
48
|
+
/**
|
|
49
|
+
* The `userData` type of the default route: inferred from the {@link defaultRoute} schema when the route map
|
|
50
|
+
* carries one, otherwise the provided `Fallback`.
|
|
51
|
+
*/
|
|
52
|
+
export type DefaultRouteUserData<Routes, Fallback extends Dictionary> = Routes extends {
|
|
53
|
+
[defaultRoute]: infer DefaultUserData extends Dictionary;
|
|
54
|
+
} ? DefaultUserData : Fallback;
|
|
55
|
+
/**
|
|
56
|
+
* Validates `userData` against a {@link RouteSchemas|Standard Schema}, returning the parsed (and coerced)
|
|
57
|
+
* value. Throws a {@link RequestValidationError} when validation fails.
|
|
58
|
+
* @internal
|
|
59
|
+
*/
|
|
60
|
+
export declare function validateUserData(label: string | symbol, schema: StandardSchemaV1, userData: unknown): Promise<Dictionary>;
|
|
61
|
+
/**
|
|
62
|
+
* The set of labels accepted by {@link Router.addHandler}. When the router declares a concrete
|
|
63
|
+
* route map (e.g. `{ PRODUCT: ...; CATEGORY: ... }`), only those labels (plus symbols) are
|
|
64
|
+
* allowed — unknown labels become a compile-time error. When the map is left open (the default
|
|
65
|
+
* `Record<string, ...>`), any string or symbol label is accepted, preserving the original behaviour.
|
|
66
|
+
*/
|
|
67
|
+
export type RouterLabel<Routes extends Record<keyof Routes, Dictionary>> = string extends keyof Routes ? string | symbol : (keyof Routes & string) | symbol;
|
|
68
|
+
export interface RouterHandler<Context extends RestrictedCrawlingContext = CrawlingContext, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>> extends Router<Context, Routes> {
|
|
6
69
|
(ctx: Context): Awaitable<void>;
|
|
7
70
|
}
|
|
8
71
|
export type GetUserDataFromRequest<T> = T extends Request<infer Y> ? Y : never;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Per-route overrides, passed as the last argument of {@link Router.addHandler|`addHandler`} and
|
|
74
|
+
* {@link Router.addDefaultHandler|`addDefaultHandler`}.
|
|
75
|
+
*/
|
|
76
|
+
export interface RouteOptions {
|
|
77
|
+
/**
|
|
78
|
+
* Overrides the crawler's `requestHandlerTimeoutSecs` for this route only. Useful when one kind of page
|
|
79
|
+
* needs markedly more time than the rest - a listing page behind an infinite scroll, say - and you do not
|
|
80
|
+
* want to raise the timeout for every other page to accommodate it.
|
|
81
|
+
*
|
|
82
|
+
* Applies only to this route's handler. The navigation and the navigation hooks keep their own timeouts.
|
|
83
|
+
*/
|
|
84
|
+
requestHandlerTimeoutSecs?: number;
|
|
85
|
+
}
|
|
86
|
+
export type RouterRoutes<Context, Routes extends Record<keyof Routes, Dictionary>> = {
|
|
87
|
+
[Label in keyof Routes]: (ctx: Omit<Context, 'request'> & {
|
|
88
|
+
request: Request<Routes[Label]>;
|
|
12
89
|
}) => Awaitable<void>;
|
|
13
90
|
};
|
|
14
91
|
/**
|
|
@@ -75,36 +152,129 @@ export type RouterRoutes<Context, UserData extends Dictionary> = {
|
|
|
75
152
|
* ctx.log.info('...');
|
|
76
153
|
* });
|
|
77
154
|
* ```
|
|
155
|
+
*
|
|
156
|
+
* To get `request.userData` typed per label, declare a route map and pass it as the second
|
|
157
|
+
* type argument. The label passed to {@link Router.addHandler} then drives the type of
|
|
158
|
+
* `request.userData`, and unknown labels are rejected at compile time:
|
|
159
|
+
*
|
|
160
|
+
* ```ts
|
|
161
|
+
* import { createCheerioRouter, CheerioCrawlingContext } from 'crawlee';
|
|
162
|
+
*
|
|
163
|
+
* interface Routes {
|
|
164
|
+
* PRODUCT: { sku: string; price: number };
|
|
165
|
+
* CATEGORY: { categoryId: string };
|
|
166
|
+
* }
|
|
167
|
+
*
|
|
168
|
+
* const router = createCheerioRouter<CheerioCrawlingContext, Routes>();
|
|
169
|
+
*
|
|
170
|
+
* router.addHandler('PRODUCT', async ({ request }) => {
|
|
171
|
+
* request.userData.sku; // string
|
|
172
|
+
* request.userData.price; // number
|
|
173
|
+
* });
|
|
174
|
+
*
|
|
175
|
+
* router.addHandler('TYPO', async () => {}); // compile error: not a known label
|
|
176
|
+
* ```
|
|
177
|
+
*
|
|
178
|
+
* Passing a [Standard Schema](https://standardschema.dev) per label instead of a plain type both infers the
|
|
179
|
+
* `request.userData` types *and* validates them at runtime — when the request is handled, and when it is
|
|
180
|
+
* added to the crawler (`crawler.addRequests`, `context.addRequests`, `enqueueLinks`). A failing request
|
|
181
|
+
* throws a {@link RequestValidationError}.
|
|
182
|
+
*
|
|
183
|
+
* ```ts
|
|
184
|
+
* import { z } from 'zod';
|
|
185
|
+
* import { createCheerioRouter } from 'crawlee';
|
|
186
|
+
*
|
|
187
|
+
* const router = createCheerioRouter({
|
|
188
|
+
* PRODUCT: z.object({ sku: z.string(), price: z.number() }),
|
|
189
|
+
* CATEGORY: z.object({ categoryId: z.string() }),
|
|
190
|
+
* });
|
|
191
|
+
*
|
|
192
|
+
* router.addHandler('PRODUCT', async ({ request }) => {
|
|
193
|
+
* request.userData.price; // number, inferred from the schema and validated at runtime
|
|
194
|
+
* });
|
|
195
|
+
* ```
|
|
196
|
+
*
|
|
197
|
+
* A single route can take longer than the rest without raising the crawler-wide
|
|
198
|
+
* `requestHandlerTimeoutSecs` for everything - pass a per-route timeout as the last argument:
|
|
199
|
+
*
|
|
200
|
+
* ```ts
|
|
201
|
+
* // LIST pages scroll through a lot of content, DETAIL pages are quick
|
|
202
|
+
* router.addHandler('LIST', async (ctx) => { ... }, { requestHandlerTimeoutSecs: 120 });
|
|
203
|
+
* router.addHandler('DETAIL', async (ctx) => { ... }); // keeps the crawler's default
|
|
204
|
+
* ```
|
|
205
|
+
*
|
|
206
|
+
* When the time a route needs is only apparent once it is already running, call
|
|
207
|
+
* {@link CrawlingContext.extendTimeout|`context.extendTimeout`} from inside the handler:
|
|
208
|
+
*
|
|
209
|
+
* ```ts
|
|
210
|
+
* router.addHandler('LIST', async ({ page, extendTimeout }) => {
|
|
211
|
+
* const pageCount = await countPages(page);
|
|
212
|
+
* extendTimeout(pageCount * 10); // ask for 10 more seconds per page
|
|
213
|
+
* await scrapeAllPages(page);
|
|
214
|
+
* });
|
|
215
|
+
* ```
|
|
78
216
|
*/
|
|
79
|
-
export declare class Router<Context extends
|
|
80
|
-
private
|
|
81
|
-
private readonly middlewares;
|
|
217
|
+
export declare class Router<Context extends RestrictedCrawlingContext, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>> {
|
|
218
|
+
#private;
|
|
82
219
|
/**
|
|
83
220
|
* use Router.create() instead!
|
|
84
221
|
* @ignore
|
|
85
222
|
*/
|
|
86
|
-
|
|
223
|
+
private constructor();
|
|
224
|
+
/**
|
|
225
|
+
* Registers new route handler for given label. When the router declares a route map, the
|
|
226
|
+
* `label` is restricted to the declared labels and `request.userData` is typed accordingly. Pass
|
|
227
|
+
* {@link RouteOptions|`options`} to give this route its own `requestHandlerTimeoutSecs`,
|
|
228
|
+
* overriding the crawler's default for requests with this label.
|
|
229
|
+
*/
|
|
230
|
+
addHandler<Label extends keyof Routes & string>(label: Label, handler: (ctx: RouterHandlerContext<Context, Routes[Label], Routes>) => Awaitable<void>, options?: RouteOptions): void;
|
|
231
|
+
/**
|
|
232
|
+
* Registers new route handler for given label, explicitly typing `request.userData` via the
|
|
233
|
+
* `UserData` type argument. Useful when the router has no declared route map (the open default)
|
|
234
|
+
* and you want to type a single handler, or to register a handler under a `symbol` label.
|
|
235
|
+
*/
|
|
236
|
+
addHandler<UserData extends Dictionary = GetUserDataFromRequest<Context['request']>>(label: RouterLabel<Routes>, handler: (ctx: RouterHandlerContext<Context, UserData, Routes>) => Awaitable<void>, options?: RouteOptions): void;
|
|
87
237
|
/**
|
|
88
|
-
* Registers
|
|
238
|
+
* Registers default route handler. As a fallback it can receive any request (including labels not
|
|
239
|
+
* declared in the route map). When the router was created with a {@link defaultRoute} schema,
|
|
240
|
+
* `request.userData` is typed from it; otherwise it defaults to the context's (loosely typed) `userData`.
|
|
241
|
+
* Pass an explicit `UserData` type argument to narrow it. Pass {@link RouteOptions|`options`} to give the
|
|
242
|
+
* default route its own `requestHandlerTimeoutSecs`, overriding the crawler's default for requests that fall
|
|
243
|
+
* through to it.
|
|
89
244
|
*/
|
|
90
|
-
|
|
91
|
-
request: LoadedRequest<Request<UserData>>;
|
|
92
|
-
}) => Awaitable<void>): void;
|
|
245
|
+
addDefaultHandler<UserData extends Dictionary = DefaultRouteUserData<Routes, GetUserDataFromRequest<Context['request']>>>(handler: (ctx: RouterHandlerContext<Context, UserData, Routes>) => Awaitable<void>, options?: RouteOptions): void;
|
|
93
246
|
/**
|
|
94
|
-
*
|
|
247
|
+
* Returns the {@link RouteSchemas|Standard Schema} registered for a label, if any. Used by the crawler
|
|
248
|
+
* to validate `request.userData` when requests are added.
|
|
249
|
+
* @internal
|
|
95
250
|
*/
|
|
96
|
-
|
|
97
|
-
request: LoadedRequest<Request<UserData>>;
|
|
98
|
-
}) => Awaitable<void>): void;
|
|
251
|
+
getSchema(label?: string | symbol): StandardSchemaV1 | undefined;
|
|
99
252
|
/**
|
|
100
253
|
* Registers a middleware that will be fired before the matching route handler.
|
|
101
254
|
* Multiple middlewares can be registered, they will be fired in the same order.
|
|
102
255
|
*/
|
|
103
256
|
use(middleware: (ctx: Context) => Awaitable<void>): void;
|
|
257
|
+
/**
|
|
258
|
+
* Returns the `requestHandlerTimeoutSecs` registered for a label, or `undefined` when the route did not
|
|
259
|
+
* override it and the crawler's own timeout should apply. Falls back to the default route the same way
|
|
260
|
+
* {@link Router.getHandler|`getHandler`} does, so a label with no route of its own inherits whatever
|
|
261
|
+
* the default route asked for. Used by the crawler; not meant to be called directly.
|
|
262
|
+
*/
|
|
263
|
+
getTimeoutSecs(label?: string | symbol): number | undefined;
|
|
264
|
+
/**
|
|
265
|
+
* The longest `requestHandlerTimeoutSecs` any route asked for, or `undefined` when no route overrides it.
|
|
266
|
+
* The crawler needs an upper bound up front, before it knows which routes a run will actually hit.
|
|
267
|
+
*/
|
|
268
|
+
getMaxTimeoutSecs(): number | undefined;
|
|
104
269
|
/**
|
|
105
270
|
* Returns route handler for given label. If no label is provided, the default request handler will be returned.
|
|
106
271
|
*/
|
|
107
272
|
getHandler(label?: string | symbol): (ctx: Context) => Awaitable<void>;
|
|
273
|
+
/**
|
|
274
|
+
* Validates `request.userData` against the schema registered for its label (if any), replacing it with
|
|
275
|
+
* the parsed value. Throws a {@link RequestValidationError} when validation fails.
|
|
276
|
+
*/
|
|
277
|
+
private validateRequest;
|
|
108
278
|
/**
|
|
109
279
|
* Throws when the label already exists in our registry.
|
|
110
280
|
*/
|
|
@@ -129,6 +299,8 @@ export declare class Router<Context extends Omit<RestrictedCrawlingContext, 'enq
|
|
|
129
299
|
* await crawler.run();
|
|
130
300
|
* ```
|
|
131
301
|
*/
|
|
132
|
-
static create<Context extends
|
|
302
|
+
static create<Context extends RestrictedCrawlingContext = CrawlingContext, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>>(routes?: RouterRoutes<Context, Routes>): RouterHandler<Context, Routes>;
|
|
303
|
+
static create<Context extends RestrictedCrawlingContext = CrawlingContext, UserData extends Dictionary = GetUserDataFromRequest<Context['request']>>(routes?: RouterRoutes<Context, Record<string, UserData>>): RouterHandler<Context, Record<string, UserData>>;
|
|
304
|
+
static create<Context extends RestrictedCrawlingContext = CrawlingContext, const Schemas extends RouteSchemas = RouteSchemas>(schemas: Schemas): RouterHandler<Context, RoutesFromSchemas<Schemas>>;
|
|
133
305
|
}
|
|
134
|
-
|
|
306
|
+
export {};
|