@crawlee/core 4.0.0-beta.9 → 4.0.0-beta.90
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 +66 -153
- package/autoscaling/autoscaled_pool.js +95 -251
- package/autoscaling/client_load_signal.d.ts +59 -0
- package/autoscaling/client_load_signal.js +73 -0
- package/autoscaling/concurrency_system.d.ts +283 -0
- package/autoscaling/concurrency_system.js +350 -0
- package/autoscaling/cpu_load_signal.d.ts +44 -0
- package/autoscaling/cpu_load_signal.js +46 -0
- package/autoscaling/event_loop_load_signal.d.ts +54 -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 +99 -0
- package/autoscaling/load_signal.js +103 -0
- package/autoscaling/memory_load_signal.d.ts +56 -0
- package/autoscaling/memory_load_signal.js +106 -0
- package/autoscaling/snapshotter.d.ts +61 -163
- package/autoscaling/snapshotter.js +45 -263
- package/autoscaling/system_status.d.ts +63 -83
- package/autoscaling/system_status.js +90 -120
- package/configuration.d.ts +90 -223
- package/configuration.js +164 -222
- package/cookie_utils.d.ts +4 -3
- package/cookie_utils.js +20 -13
- package/crawlers/context_pipeline.d.ts +70 -0
- package/crawlers/context_pipeline.js +122 -0
- package/crawlers/crawler_commons.d.ts +76 -33
- package/crawlers/crawler_commons.js +15 -24
- package/crawlers/crawler_utils.d.ts +2 -3
- package/crawlers/crawler_utils.js +1 -2
- package/crawlers/error_snapshotter.d.ts +3 -3
- package/crawlers/error_snapshotter.js +2 -3
- package/crawlers/error_tracker.d.ts +2 -2
- package/crawlers/error_tracker.js +0 -1
- package/crawlers/index.d.ts +1 -2
- package/crawlers/index.js +1 -2
- package/crawlers/internals/types.d.ts +7 -0
- package/crawlers/internals/types.js +1 -0
- package/crawlers/statistics.d.ts +28 -23
- package/crawlers/statistics.js +38 -34
- package/debug.d.ts +36 -0
- package/debug.js +70 -0
- package/enqueue_links/enqueue_links.d.ts +44 -22
- package/enqueue_links/enqueue_links.js +51 -30
- package/enqueue_links/index.d.ts +0 -1
- package/enqueue_links/index.js +0 -1
- package/enqueue_links/shared.d.ts +25 -9
- package/enqueue_links/shared.js +69 -38
- package/errors.d.ts +53 -4
- package/errors.js +70 -5
- package/events/event_manager.d.ts +34 -8
- package/events/event_manager.js +8 -10
- 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 +37 -11
- package/index.d.ts +6 -3
- package/index.js +5 -2
- package/log.d.ts +82 -3
- package/log.js +102 -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 +46 -0
- package/memory-storage/memory-storage.js +136 -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 +113 -0
- package/memory-storage/resource-clients/key-value-store.d.ts +63 -0
- package/memory-storage/resource-clients/key-value-store.js +203 -0
- package/memory-storage/resource-clients/request-queue.d.ts +96 -0
- package/memory-storage/resource-clients/request-queue.js +421 -0
- package/memory-storage/utils.d.ts +17 -0
- package/memory-storage/utils.js +42 -0
- package/owned_or_injected.d.ts +60 -0
- package/owned_or_injected.js +98 -0
- package/package.json +12 -10
- package/proxy_configuration.d.ts +29 -152
- package/proxy_configuration.js +21 -173
- package/recoverable_state.d.ts +120 -0
- package/recoverable_state.js +143 -0
- package/request.d.ts +84 -13
- package/request.js +107 -28
- package/router.d.ts +143 -17
- package/router.js +125 -30
- package/serialization.d.ts +0 -1
- package/serialization.js +1 -2
- package/service_locator.d.ts +156 -0
- package/service_locator.js +238 -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 +37 -75
- package/session_pool/session.js +49 -102
- package/session_pool/session_pool.d.ts +85 -90
- package/session_pool/session_pool.js +131 -120
- package/storages/access_checking.d.ts +0 -1
- package/storages/access_checking.js +5 -2
- package/storages/dataset.d.ts +103 -53
- package/storages/dataset.js +174 -132
- package/storages/index.d.ts +8 -7
- package/storages/index.js +6 -7
- package/storages/key_value_store.d.ts +167 -38
- package/storages/key_value_store.js +274 -127
- 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 +23 -0
- package/storages/request_dedup_cache.js +48 -0
- package/storages/request_list.d.ts +54 -98
- package/storages/request_list.js +99 -75
- package/storages/request_loader.d.ts +96 -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 +106 -0
- package/storages/request_manager_tandem.js +197 -0
- package/storages/request_queue.d.ts +290 -47
- package/storages/request_queue.js +629 -215
- package/storages/{sitemap_request_list.d.ts → sitemap_request_loader.d.ts} +28 -24
- package/storages/{sitemap_request_list.js → sitemap_request_loader.js} +49 -47
- package/storages/storage_instance_manager.d.ts +91 -0
- package/storages/storage_instance_manager.js +258 -0
- package/storages/storage_stats.d.ts +48 -0
- package/storages/storage_stats.js +29 -0
- package/storages/utils.d.ts +54 -9
- package/storages/utils.js +64 -13
- 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 +1 -2
- package/typedefs.js +0 -1
- package/validators.d.ts +8 -1
- package/validators.js +10 -3
- 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/crawler_commons.d.ts.map +0 -1
- package/crawlers/crawler_commons.js.map +0 -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/crawlers/crawler_utils.d.ts.map +0 -1
- 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/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 -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/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/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.map +0 -1
- 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_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.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.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/tsconfig.build.tsbuildinfo +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/router.d.ts
CHANGED
|
@@ -1,14 +1,79 @@
|
|
|
1
1
|
import type { Dictionary } from '@crawlee/types';
|
|
2
|
-
import type {
|
|
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
|
import type { Awaitable } from './typedefs.js';
|
|
5
|
-
|
|
6
|
+
/**
|
|
7
|
+
* The key of the default route — the fallback handler registered via {@link Router.addDefaultHandler}.
|
|
8
|
+
* Use it in a {@link RouteSchemas} map to register a schema that validates the `userData` of every request
|
|
9
|
+
* that falls through to the default handler (i.e. whose label has no route of its own).
|
|
10
|
+
*/
|
|
11
|
+
export declare const defaultRoute: unique symbol;
|
|
12
|
+
/**
|
|
13
|
+
* The crawling context received by a route handler, with `request.userData` narrowed to `UserData`, and
|
|
14
|
+
* `addRequests`/`enqueueLinks` typed according to the router's route map (`Routes`) so that enqueuing a
|
|
15
|
+
* request under a declared label requires the matching `userData` shape.
|
|
16
|
+
*/
|
|
17
|
+
export type RouterHandlerContext<Context, UserData extends Dictionary, Routes extends Record<keyof Routes, Dictionary>> = Omit<Context, 'request' | 'addRequests' | 'enqueueLinks'> & {
|
|
18
|
+
request: LoadedRequest<Request<UserData>>;
|
|
19
|
+
addRequests: TypedContextAddRequests<Routes>;
|
|
20
|
+
} & (Context extends {
|
|
21
|
+
enqueueLinks: infer EnqueueLinks;
|
|
22
|
+
} ? {
|
|
23
|
+
enqueueLinks: TypedContextEnqueueLinks<EnqueueLinks, Routes>;
|
|
24
|
+
} : {});
|
|
25
|
+
/**
|
|
26
|
+
* A map of request labels to a [Standard Schema](https://standardschema.dev) (Zod, Valibot, ArkType, …)
|
|
27
|
+
* validating that label's `request.userData`. Pass it to {@link Router.create} or a `createXRouter`
|
|
28
|
+
* factory to derive the per-label `request.userData` types *and* validate them at runtime. The optional
|
|
29
|
+
* {@link defaultRoute} key registers a schema for requests handled by the default route.
|
|
30
|
+
*/
|
|
31
|
+
export type RouteSchemas = Record<string, StandardSchemaV1> & {
|
|
32
|
+
[defaultRoute]?: StandardSchemaV1;
|
|
33
|
+
};
|
|
34
|
+
/** Infers a label's `userData` type from its schema, falling back to a plain {@link Dictionary}. */
|
|
35
|
+
type SchemaUserData<Schema extends StandardSchemaV1> = StandardSchemaV1.InferOutput<Schema> extends Dictionary ? StandardSchemaV1.InferOutput<Schema> : Dictionary;
|
|
36
|
+
/**
|
|
37
|
+
* Derives a route map (label → `userData` type) from a {@link RouteSchemas} map by inferring each schema's
|
|
38
|
+
* output type. Outputs that are not object-shaped fall back to a plain {@link Dictionary}. The
|
|
39
|
+
* {@link defaultRoute} schema is kept under its symbol key so {@link Router.addDefaultHandler} can pick it
|
|
40
|
+
* up; string labels (the ones {@link Router.addHandler} and the crawler-level typing accept) ignore it.
|
|
41
|
+
*/
|
|
42
|
+
export type RoutesFromSchemas<Schemas extends RouteSchemas> = {
|
|
43
|
+
[Label in Extract<keyof Schemas, string>]: SchemaUserData<Schemas[Label]>;
|
|
44
|
+
} & (Schemas extends {
|
|
45
|
+
[defaultRoute]: StandardSchemaV1;
|
|
46
|
+
} ? {
|
|
47
|
+
[defaultRoute]: SchemaUserData<Schemas[typeof defaultRoute]>;
|
|
48
|
+
} : {});
|
|
49
|
+
/**
|
|
50
|
+
* The `userData` type of the default route: inferred from the {@link defaultRoute} schema when the route map
|
|
51
|
+
* carries one, otherwise the provided `Fallback`.
|
|
52
|
+
* @internal
|
|
53
|
+
*/
|
|
54
|
+
export type DefaultRouteUserData<Routes, Fallback extends Dictionary> = Routes extends {
|
|
55
|
+
[defaultRoute]: infer DefaultUserData extends Dictionary;
|
|
56
|
+
} ? DefaultUserData : Fallback;
|
|
57
|
+
/**
|
|
58
|
+
* Validates `userData` against a {@link RouteSchemas|Standard Schema}, returning the parsed (and coerced)
|
|
59
|
+
* value. Throws a {@link RequestValidationError} when validation fails.
|
|
60
|
+
* @internal
|
|
61
|
+
*/
|
|
62
|
+
export declare function validateUserData(label: string | symbol, schema: StandardSchemaV1, userData: unknown): Promise<Dictionary>;
|
|
63
|
+
/**
|
|
64
|
+
* The set of labels accepted by {@link Router.addHandler}. When the router declares a concrete
|
|
65
|
+
* route map (e.g. `{ PRODUCT: ...; CATEGORY: ... }`), only those labels (plus symbols) are
|
|
66
|
+
* allowed — unknown labels become a compile-time error. When the map is left open (the default
|
|
67
|
+
* `Record<string, ...>`), any string or symbol label is accepted, preserving the original behaviour.
|
|
68
|
+
*/
|
|
69
|
+
export type RouterLabel<Routes extends Record<keyof Routes, Dictionary>> = string extends keyof Routes ? string | symbol : (keyof Routes & string) | symbol;
|
|
70
|
+
export interface RouterHandler<Context extends Omit<RestrictedCrawlingContext, 'enqueueLinks'> = CrawlingContext, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>> extends Router<Context, Routes> {
|
|
6
71
|
(ctx: Context): Awaitable<void>;
|
|
7
72
|
}
|
|
8
73
|
export type GetUserDataFromRequest<T> = T extends Request<infer Y> ? Y : never;
|
|
9
|
-
export type RouterRoutes<Context,
|
|
10
|
-
[
|
|
11
|
-
request: Request<
|
|
74
|
+
export type RouterRoutes<Context, Routes extends Record<keyof Routes, Dictionary>> = {
|
|
75
|
+
[Label in keyof Routes]: (ctx: Omit<Context, 'request'> & {
|
|
76
|
+
request: Request<Routes[Label]>;
|
|
12
77
|
}) => Awaitable<void>;
|
|
13
78
|
};
|
|
14
79
|
/**
|
|
@@ -75,27 +140,81 @@ export type RouterRoutes<Context, UserData extends Dictionary> = {
|
|
|
75
140
|
* ctx.log.info('...');
|
|
76
141
|
* });
|
|
77
142
|
* ```
|
|
143
|
+
*
|
|
144
|
+
* To get `request.userData` typed per label, declare a route map and pass it as the second
|
|
145
|
+
* type argument. The label passed to {@link Router.addHandler} then drives the type of
|
|
146
|
+
* `request.userData`, and unknown labels are rejected at compile time:
|
|
147
|
+
*
|
|
148
|
+
* ```ts
|
|
149
|
+
* import { createCheerioRouter, CheerioCrawlingContext } from 'crawlee';
|
|
150
|
+
*
|
|
151
|
+
* interface Routes {
|
|
152
|
+
* PRODUCT: { sku: string; price: number };
|
|
153
|
+
* CATEGORY: { categoryId: string };
|
|
154
|
+
* }
|
|
155
|
+
*
|
|
156
|
+
* const router = createCheerioRouter<CheerioCrawlingContext, Routes>();
|
|
157
|
+
*
|
|
158
|
+
* router.addHandler('PRODUCT', async ({ request }) => {
|
|
159
|
+
* request.userData.sku; // string
|
|
160
|
+
* request.userData.price; // number
|
|
161
|
+
* });
|
|
162
|
+
*
|
|
163
|
+
* router.addHandler('TYPO', async () => {}); // compile error: not a known label
|
|
164
|
+
* ```
|
|
165
|
+
*
|
|
166
|
+
* Passing a [Standard Schema](https://standardschema.dev) per label instead of a plain type both infers the
|
|
167
|
+
* `request.userData` types *and* validates them at runtime — when the request is handled, and when it is
|
|
168
|
+
* added to the crawler (`crawler.addRequests`, `context.addRequests`, `enqueueLinks`). A failing request
|
|
169
|
+
* throws a {@link RequestValidationError}.
|
|
170
|
+
*
|
|
171
|
+
* ```ts
|
|
172
|
+
* import { z } from 'zod';
|
|
173
|
+
* import { createCheerioRouter } from 'crawlee';
|
|
174
|
+
*
|
|
175
|
+
* const router = createCheerioRouter({
|
|
176
|
+
* PRODUCT: z.object({ sku: z.string(), price: z.number() }),
|
|
177
|
+
* CATEGORY: z.object({ categoryId: z.string() }),
|
|
178
|
+
* });
|
|
179
|
+
*
|
|
180
|
+
* router.addHandler('PRODUCT', async ({ request }) => {
|
|
181
|
+
* request.userData.price; // number, inferred from the schema and validated at runtime
|
|
182
|
+
* });
|
|
183
|
+
* ```
|
|
78
184
|
*/
|
|
79
|
-
export declare class Router<Context extends Omit<RestrictedCrawlingContext, 'enqueueLinks'
|
|
185
|
+
export declare class Router<Context extends Omit<RestrictedCrawlingContext, 'enqueueLinks'>, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>> {
|
|
80
186
|
private readonly routes;
|
|
187
|
+
private readonly schemas;
|
|
81
188
|
private readonly middlewares;
|
|
82
189
|
/**
|
|
83
190
|
* use Router.create() instead!
|
|
84
191
|
* @ignore
|
|
85
192
|
*/
|
|
86
|
-
|
|
193
|
+
private constructor();
|
|
194
|
+
/**
|
|
195
|
+
* Registers new route handler for given label. When the router declares a route map, the
|
|
196
|
+
* `label` is restricted to the declared labels and `request.userData` is typed accordingly.
|
|
197
|
+
*/
|
|
198
|
+
addHandler<Label extends keyof Routes & string>(label: Label, handler: (ctx: RouterHandlerContext<Context, Routes[Label], Routes>) => Awaitable<void>): void;
|
|
87
199
|
/**
|
|
88
|
-
* Registers new route handler for given label.
|
|
200
|
+
* Registers new route handler for given label, explicitly typing `request.userData` via the
|
|
201
|
+
* `UserData` type argument. Useful when the router has no declared route map (the open default)
|
|
202
|
+
* and you want to type a single handler, or to register a handler under a `symbol` label.
|
|
89
203
|
*/
|
|
90
|
-
addHandler<UserData extends Dictionary = GetUserDataFromRequest<Context['request']>>(label:
|
|
91
|
-
request: LoadedRequest<Request<UserData>>;
|
|
92
|
-
}) => Awaitable<void>): void;
|
|
204
|
+
addHandler<UserData extends Dictionary = GetUserDataFromRequest<Context['request']>>(label: RouterLabel<Routes>, handler: (ctx: RouterHandlerContext<Context, UserData, Routes>) => Awaitable<void>): void;
|
|
93
205
|
/**
|
|
94
|
-
* Registers default route handler.
|
|
206
|
+
* Registers default route handler. As a fallback it can receive any request (including labels not
|
|
207
|
+
* declared in the route map). When the router was created with a {@link defaultRoute} schema,
|
|
208
|
+
* `request.userData` is typed from it; otherwise it defaults to the context's (loosely typed) `userData`.
|
|
209
|
+
* Pass an explicit `UserData` type argument to narrow it.
|
|
95
210
|
*/
|
|
96
|
-
addDefaultHandler<UserData extends Dictionary = GetUserDataFromRequest<Context['request']
|
|
97
|
-
|
|
98
|
-
|
|
211
|
+
addDefaultHandler<UserData extends Dictionary = DefaultRouteUserData<Routes, GetUserDataFromRequest<Context['request']>>>(handler: (ctx: RouterHandlerContext<Context, UserData, Routes>) => Awaitable<void>): void;
|
|
212
|
+
/**
|
|
213
|
+
* Returns the {@link RouteSchemas|Standard Schema} registered for a label, if any. Used by the crawler
|
|
214
|
+
* to validate `request.userData` when requests are added.
|
|
215
|
+
* @internal
|
|
216
|
+
*/
|
|
217
|
+
getSchema(label?: string | symbol): StandardSchemaV1 | undefined;
|
|
99
218
|
/**
|
|
100
219
|
* Registers a middleware that will be fired before the matching route handler.
|
|
101
220
|
* Multiple middlewares can be registered, they will be fired in the same order.
|
|
@@ -105,6 +224,11 @@ export declare class Router<Context extends Omit<RestrictedCrawlingContext, 'enq
|
|
|
105
224
|
* Returns route handler for given label. If no label is provided, the default request handler will be returned.
|
|
106
225
|
*/
|
|
107
226
|
getHandler(label?: string | symbol): (ctx: Context) => Awaitable<void>;
|
|
227
|
+
/**
|
|
228
|
+
* Validates `request.userData` against the schema registered for its label (if any), replacing it with
|
|
229
|
+
* the parsed value. Throws a {@link RequestValidationError} when validation fails.
|
|
230
|
+
*/
|
|
231
|
+
private validateRequest;
|
|
108
232
|
/**
|
|
109
233
|
* Throws when the label already exists in our registry.
|
|
110
234
|
*/
|
|
@@ -129,6 +253,8 @@ export declare class Router<Context extends Omit<RestrictedCrawlingContext, 'enq
|
|
|
129
253
|
* await crawler.run();
|
|
130
254
|
* ```
|
|
131
255
|
*/
|
|
132
|
-
static create<Context extends Omit<RestrictedCrawlingContext, 'enqueueLinks'> = CrawlingContext,
|
|
256
|
+
static create<Context extends Omit<RestrictedCrawlingContext, 'enqueueLinks'> = CrawlingContext, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>>(routes?: RouterRoutes<Context, Routes>): RouterHandler<Context, Routes>;
|
|
257
|
+
static create<Context extends Omit<RestrictedCrawlingContext, 'enqueueLinks'> = CrawlingContext, UserData extends Dictionary = GetUserDataFromRequest<Context['request']>>(routes?: RouterRoutes<Context, Record<string, UserData>>): RouterHandler<Context, Record<string, UserData>>;
|
|
258
|
+
static create<Context extends Omit<RestrictedCrawlingContext, 'enqueueLinks'> = CrawlingContext, const Schemas extends RouteSchemas = RouteSchemas>(schemas: Schemas): RouterHandler<Context, RoutesFromSchemas<Schemas>>;
|
|
133
259
|
}
|
|
134
|
-
|
|
260
|
+
export {};
|
package/router.js
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
|
-
import { MissingRouteError } from './errors.js';
|
|
2
|
-
|
|
1
|
+
import { MissingRouteError, RequestValidationError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* The key of the default route — the fallback handler registered via {@link Router.addDefaultHandler}.
|
|
4
|
+
* Use it in a {@link RouteSchemas} map to register a schema that validates the `userData` of every request
|
|
5
|
+
* that falls through to the default handler (i.e. whose label has no route of its own).
|
|
6
|
+
*/
|
|
7
|
+
export const defaultRoute = Symbol('default-route');
|
|
8
|
+
/** Whether a validation issue points at the top-level `label` key. */
|
|
9
|
+
function isLabelIssue(issue) {
|
|
10
|
+
if (issue.path?.length !== 1) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
const [segment] = issue.path;
|
|
14
|
+
return (typeof segment === 'object' ? segment.key : segment) === 'label';
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Validates `userData` against a {@link RouteSchemas|Standard Schema}, returning the parsed (and coerced)
|
|
18
|
+
* value. Throws a {@link RequestValidationError} when validation fails.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export async function validateUserData(label, schema, userData) {
|
|
22
|
+
const { label: _label, ...rest } = (userData ?? {});
|
|
23
|
+
// `label` is a Crawlee-managed key that lives inside `userData`, so validating it is opt-in: we validate
|
|
24
|
+
// without it first, letting schemas that don't describe it pass (including `.strict()` ones). A schema that
|
|
25
|
+
// *does* declare `label` reports an issue for the now-missing key — so we re-validate with it included,
|
|
26
|
+
// honouring the declaration. Unlike `userData.__crawlee`, `label` is enumerable, so schemas do see it.
|
|
27
|
+
let result = await schema['~standard'].validate(rest);
|
|
28
|
+
if (result.issues?.some(isLabelIssue)) {
|
|
29
|
+
result = await schema['~standard'].validate({ ...rest, label });
|
|
30
|
+
}
|
|
31
|
+
if (result.issues) {
|
|
32
|
+
throw new RequestValidationError(label, result.issues);
|
|
33
|
+
}
|
|
34
|
+
// Restore the label so it survives schemas that strip undeclared keys.
|
|
35
|
+
return { ...result.value, label };
|
|
36
|
+
}
|
|
3
37
|
/**
|
|
4
38
|
* Simple router that works based on request labels. This instance can then serve as a `requestHandler` of your crawler.
|
|
5
39
|
*
|
|
@@ -64,29 +98,91 @@ const defaultRoute = Symbol('default-route');
|
|
|
64
98
|
* ctx.log.info('...');
|
|
65
99
|
* });
|
|
66
100
|
* ```
|
|
101
|
+
*
|
|
102
|
+
* To get `request.userData` typed per label, declare a route map and pass it as the second
|
|
103
|
+
* type argument. The label passed to {@link Router.addHandler} then drives the type of
|
|
104
|
+
* `request.userData`, and unknown labels are rejected at compile time:
|
|
105
|
+
*
|
|
106
|
+
* ```ts
|
|
107
|
+
* import { createCheerioRouter, CheerioCrawlingContext } from 'crawlee';
|
|
108
|
+
*
|
|
109
|
+
* interface Routes {
|
|
110
|
+
* PRODUCT: { sku: string; price: number };
|
|
111
|
+
* CATEGORY: { categoryId: string };
|
|
112
|
+
* }
|
|
113
|
+
*
|
|
114
|
+
* const router = createCheerioRouter<CheerioCrawlingContext, Routes>();
|
|
115
|
+
*
|
|
116
|
+
* router.addHandler('PRODUCT', async ({ request }) => {
|
|
117
|
+
* request.userData.sku; // string
|
|
118
|
+
* request.userData.price; // number
|
|
119
|
+
* });
|
|
120
|
+
*
|
|
121
|
+
* router.addHandler('TYPO', async () => {}); // compile error: not a known label
|
|
122
|
+
* ```
|
|
123
|
+
*
|
|
124
|
+
* Passing a [Standard Schema](https://standardschema.dev) per label instead of a plain type both infers the
|
|
125
|
+
* `request.userData` types *and* validates them at runtime — when the request is handled, and when it is
|
|
126
|
+
* added to the crawler (`crawler.addRequests`, `context.addRequests`, `enqueueLinks`). A failing request
|
|
127
|
+
* throws a {@link RequestValidationError}.
|
|
128
|
+
*
|
|
129
|
+
* ```ts
|
|
130
|
+
* import { z } from 'zod';
|
|
131
|
+
* import { createCheerioRouter } from 'crawlee';
|
|
132
|
+
*
|
|
133
|
+
* const router = createCheerioRouter({
|
|
134
|
+
* PRODUCT: z.object({ sku: z.string(), price: z.number() }),
|
|
135
|
+
* CATEGORY: z.object({ categoryId: z.string() }),
|
|
136
|
+
* });
|
|
137
|
+
*
|
|
138
|
+
* router.addHandler('PRODUCT', async ({ request }) => {
|
|
139
|
+
* request.userData.price; // number, inferred from the schema and validated at runtime
|
|
140
|
+
* });
|
|
141
|
+
* ```
|
|
67
142
|
*/
|
|
68
143
|
export class Router {
|
|
69
144
|
routes = new Map();
|
|
145
|
+
schemas = new Map();
|
|
70
146
|
middlewares = [];
|
|
71
147
|
/**
|
|
72
148
|
* use Router.create() instead!
|
|
73
149
|
* @ignore
|
|
74
150
|
*/
|
|
75
151
|
constructor() { }
|
|
76
|
-
/**
|
|
77
|
-
* Registers new route handler for given label.
|
|
78
|
-
*/
|
|
79
152
|
addHandler(label, handler) {
|
|
80
153
|
this.validate(label);
|
|
81
154
|
this.routes.set(label, handler);
|
|
82
155
|
}
|
|
83
156
|
/**
|
|
84
|
-
* Registers default route handler.
|
|
157
|
+
* Registers default route handler. As a fallback it can receive any request (including labels not
|
|
158
|
+
* declared in the route map). When the router was created with a {@link defaultRoute} schema,
|
|
159
|
+
* `request.userData` is typed from it; otherwise it defaults to the context's (loosely typed) `userData`.
|
|
160
|
+
* Pass an explicit `UserData` type argument to narrow it.
|
|
85
161
|
*/
|
|
86
162
|
addDefaultHandler(handler) {
|
|
87
163
|
this.validate(defaultRoute);
|
|
88
164
|
this.routes.set(defaultRoute, handler);
|
|
89
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Returns the {@link RouteSchemas|Standard Schema} registered for a label, if any. Used by the crawler
|
|
168
|
+
* to validate `request.userData` when requests are added.
|
|
169
|
+
* @internal
|
|
170
|
+
*/
|
|
171
|
+
getSchema(label) {
|
|
172
|
+
if (label != null) {
|
|
173
|
+
const schema = this.schemas.get(label);
|
|
174
|
+
if (schema) {
|
|
175
|
+
return schema;
|
|
176
|
+
}
|
|
177
|
+
// A label with its own route is fully specified; don't fall back to the default-route schema.
|
|
178
|
+
if (this.routes.has(label)) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
// Requests with no route of their own fall through to the default handler, so validate their
|
|
183
|
+
// `userData` against the default-route schema, if one was registered.
|
|
184
|
+
return this.schemas.get(defaultRoute);
|
|
185
|
+
}
|
|
90
186
|
/**
|
|
91
187
|
* Registers a middleware that will be fired before the matching route handler.
|
|
92
188
|
* Multiple middlewares can be registered, they will be fired in the same order.
|
|
@@ -108,6 +204,17 @@ export class Router {
|
|
|
108
204
|
' You must set up a route for this label or a default route.' +
|
|
109
205
|
' Use `requestHandler`, `router.addHandler` or `router.addDefaultHandler`.');
|
|
110
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Validates `request.userData` against the schema registered for its label (if any), replacing it with
|
|
209
|
+
* the parsed value. Throws a {@link RequestValidationError} when validation fails.
|
|
210
|
+
*/
|
|
211
|
+
async validateRequest(context) {
|
|
212
|
+
const label = context.request.label;
|
|
213
|
+
const schema = this.getSchema(label);
|
|
214
|
+
if (schema) {
|
|
215
|
+
context.request.userData = (await validateUserData(label, schema, context.request.userData));
|
|
216
|
+
}
|
|
217
|
+
}
|
|
111
218
|
/**
|
|
112
219
|
* Throws when the label already exists in our registry.
|
|
113
220
|
*/
|
|
@@ -119,39 +226,28 @@ export class Router {
|
|
|
119
226
|
throw new Error(message);
|
|
120
227
|
}
|
|
121
228
|
}
|
|
122
|
-
|
|
123
|
-
* Creates new router instance. This instance can then serve as a `requestHandler` of your crawler.
|
|
124
|
-
*
|
|
125
|
-
* ```ts
|
|
126
|
-
* import { Router, CheerioCrawler, CheerioCrawlingContext } from 'crawlee';
|
|
127
|
-
*
|
|
128
|
-
* const router = Router.create<CheerioCrawlingContext>();
|
|
129
|
-
* router.addHandler('label-a', async (ctx) => {
|
|
130
|
-
* ctx.log.info('...');
|
|
131
|
-
* });
|
|
132
|
-
* router.addDefaultHandler(async (ctx) => {
|
|
133
|
-
* ctx.log.info('...');
|
|
134
|
-
* });
|
|
135
|
-
*
|
|
136
|
-
* const crawler = new CheerioCrawler({
|
|
137
|
-
* requestHandler: router,
|
|
138
|
-
* });
|
|
139
|
-
* await crawler.run();
|
|
140
|
-
* ```
|
|
141
|
-
*/
|
|
142
|
-
static create(routes) {
|
|
229
|
+
static create(routesOrSchemas) {
|
|
143
230
|
const router = new Router();
|
|
144
231
|
const obj = Object.create(Function.prototype);
|
|
145
232
|
obj.addHandler = router.addHandler.bind(router);
|
|
146
233
|
obj.addDefaultHandler = router.addDefaultHandler.bind(router);
|
|
234
|
+
obj.getSchema = router.getSchema.bind(router);
|
|
147
235
|
obj.getHandler = router.getHandler.bind(router);
|
|
148
236
|
obj.use = router.use.bind(router);
|
|
149
|
-
|
|
150
|
-
|
|
237
|
+
// `Reflect.ownKeys` (unlike `Object.entries`) also yields the `defaultRoute` symbol key.
|
|
238
|
+
for (const label of Reflect.ownKeys(routesOrSchemas ?? {})) {
|
|
239
|
+
const value = routesOrSchemas[label];
|
|
240
|
+
if (typeof value === 'function') {
|
|
241
|
+
router.addHandler(label, value);
|
|
242
|
+
}
|
|
243
|
+
else {
|
|
244
|
+
router.schemas.set(label, value);
|
|
245
|
+
}
|
|
151
246
|
}
|
|
152
247
|
const func = async function (context) {
|
|
153
248
|
const { url, loadedUrl, label } = context.request;
|
|
154
249
|
context.log.debug('Page opened.', { label, url: loadedUrl ?? url });
|
|
250
|
+
await router.validateRequest(context);
|
|
155
251
|
for (const middleware of router.middlewares) {
|
|
156
252
|
await middleware(context);
|
|
157
253
|
}
|
|
@@ -161,4 +257,3 @@ export class Router {
|
|
|
161
257
|
return func;
|
|
162
258
|
}
|
|
163
259
|
}
|
|
164
|
-
//# sourceMappingURL=router.js.map
|
package/serialization.d.ts
CHANGED
package/serialization.js
CHANGED
|
@@ -116,7 +116,6 @@ function createChunkCollector(options = {}) {
|
|
|
116
116
|
}
|
|
117
117
|
function pluckValue(streamArray) {
|
|
118
118
|
const realPush = streamArray.push.bind(streamArray);
|
|
119
|
-
streamArray.push = (obj) => realPush(obj
|
|
119
|
+
streamArray.push = (obj) => realPush(obj?.value ?? null);
|
|
120
120
|
return streamArray;
|
|
121
121
|
}
|
|
122
|
-
//# sourceMappingURL=serialization.js.map
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import type { StorageBackend } from '@crawlee/types';
|
|
2
|
+
import { Configuration } from './configuration.js';
|
|
3
|
+
import type { EventManager } from './events/event_manager.js';
|
|
4
|
+
import type { CrawleeLogger } from './log.js';
|
|
5
|
+
import { StorageInstanceManager } from './storages/storage_instance_manager.js';
|
|
6
|
+
interface ServiceLocatorInterface {
|
|
7
|
+
/**
|
|
8
|
+
* Get the configuration.
|
|
9
|
+
* Creates a default Configuration instance if none has been set.
|
|
10
|
+
*/
|
|
11
|
+
getConfiguration(): Configuration;
|
|
12
|
+
/**
|
|
13
|
+
* Set the configuration.
|
|
14
|
+
*
|
|
15
|
+
* @param configuration The configuration to set
|
|
16
|
+
* @throws {ServiceConflictError} If a different configuration has already been retrieved
|
|
17
|
+
*/
|
|
18
|
+
setConfiguration(configuration: Configuration): void;
|
|
19
|
+
/**
|
|
20
|
+
* Get the event manager.
|
|
21
|
+
* Creates a default LocalEventManager instance if none has been set.
|
|
22
|
+
*/
|
|
23
|
+
getEventManager(): EventManager;
|
|
24
|
+
/**
|
|
25
|
+
* Set the event manager.
|
|
26
|
+
*
|
|
27
|
+
* @param eventManager The event manager to set
|
|
28
|
+
* @throws {ServiceConflictError} If a different event manager has already been retrieved
|
|
29
|
+
*/
|
|
30
|
+
setEventManager(eventManager: EventManager): void;
|
|
31
|
+
/**
|
|
32
|
+
* Get the storage backend.
|
|
33
|
+
* Creates a default storage backend if none has been set — `FileSystemStorageBackend` when
|
|
34
|
+
* `persistStorage` is enabled (the default), `MemoryStorageBackend` otherwise.
|
|
35
|
+
*/
|
|
36
|
+
getStorageBackend(): StorageBackend;
|
|
37
|
+
/**
|
|
38
|
+
* Set the storage backend.
|
|
39
|
+
*
|
|
40
|
+
* @param storageBackend The storage backend to set
|
|
41
|
+
* @throws {ServiceConflictError} If a different storage backend has already been retrieved
|
|
42
|
+
*/
|
|
43
|
+
setStorageBackend(storageBackend: StorageBackend): void;
|
|
44
|
+
/**
|
|
45
|
+
* Get the logger.
|
|
46
|
+
* Returns the default `@apify/log` logger if none has been set.
|
|
47
|
+
*/
|
|
48
|
+
getLogger(): CrawleeLogger;
|
|
49
|
+
/**
|
|
50
|
+
* Set the logger.
|
|
51
|
+
*
|
|
52
|
+
* @param logger The logger to set
|
|
53
|
+
* @throws {ServiceConflictError} If a different logger has already been retrieved
|
|
54
|
+
*/
|
|
55
|
+
setLogger(logger: CrawleeLogger): void;
|
|
56
|
+
/**
|
|
57
|
+
* Get a child logger with the given prefix.
|
|
58
|
+
* Equivalent to `getLogger().child({ prefix })`.
|
|
59
|
+
*/
|
|
60
|
+
getChildLog(prefix: string): CrawleeLogger;
|
|
61
|
+
/**
|
|
62
|
+
* Get the storage instance manager (shared across all storage types).
|
|
63
|
+
*/
|
|
64
|
+
getStorageInstanceManager(): StorageInstanceManager;
|
|
65
|
+
/**
|
|
66
|
+
* Resets the service locator to its initial state.
|
|
67
|
+
* Used mainly for testing purposes.
|
|
68
|
+
* @internal
|
|
69
|
+
*/
|
|
70
|
+
reset(): void;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Service locator for managing the services used by Crawlee.
|
|
74
|
+
*
|
|
75
|
+
* All services are initialized to their default value lazily.
|
|
76
|
+
*
|
|
77
|
+
* There are two primary usage patterns:
|
|
78
|
+
*
|
|
79
|
+
* **1. Global service locator (for default services):**
|
|
80
|
+
* ```typescript
|
|
81
|
+
* import { serviceLocator, BasicCrawler } from 'crawlee';
|
|
82
|
+
*
|
|
83
|
+
* // Optionally configure global services before creating crawlers
|
|
84
|
+
* serviceLocator.setStorageBackend(myCustomClient);
|
|
85
|
+
*
|
|
86
|
+
* // Crawler uses global services
|
|
87
|
+
* const crawler = new BasicCrawler({ ... });
|
|
88
|
+
* ```
|
|
89
|
+
*
|
|
90
|
+
* **2. Per-crawler services (recommended for isolation):**
|
|
91
|
+
* ```typescript
|
|
92
|
+
* import { BasicCrawler, Configuration, LocalEventManager, MemoryStorageBackend } from 'crawlee';
|
|
93
|
+
*
|
|
94
|
+
* const crawler = new BasicCrawler({
|
|
95
|
+
* requestHandler: async ({ request }) => { ... },
|
|
96
|
+
* configuration: new Configuration({ ... }), // custom configuration
|
|
97
|
+
* storageBackend: new MemoryStorageBackend(), // custom storage
|
|
98
|
+
* eventManager: LocalEventManager.fromConfiguration(), // custom events
|
|
99
|
+
* });
|
|
100
|
+
* // Crawler has its own isolated ServiceLocator instance
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
export declare class ServiceLocator implements ServiceLocatorInterface {
|
|
104
|
+
private configuration?;
|
|
105
|
+
private eventManager?;
|
|
106
|
+
private storageBackend?;
|
|
107
|
+
private logger?;
|
|
108
|
+
/**
|
|
109
|
+
* Unified storage instance manager for Dataset, KeyValueStore, and RequestQueue.
|
|
110
|
+
* Shared across all ServiceLocator instances (global singleton), matching crawlee-python.
|
|
111
|
+
* Per-crawler isolation is achieved via `clientCacheKey`, not separate manager instances.
|
|
112
|
+
*/
|
|
113
|
+
private static storageInstanceManager?;
|
|
114
|
+
/**
|
|
115
|
+
* Creates a new ServiceLocator instance.
|
|
116
|
+
*
|
|
117
|
+
* @param configuration Optional configuration instance to use
|
|
118
|
+
* @param eventManager Optional event manager instance to use
|
|
119
|
+
* @param storageBackend Optional storage backend instance to use
|
|
120
|
+
* @param logger Optional logger instance to use
|
|
121
|
+
*/
|
|
122
|
+
constructor(configuration?: Configuration, eventManager?: EventManager, storageBackend?: StorageBackend, logger?: CrawleeLogger);
|
|
123
|
+
getConfiguration(): Configuration;
|
|
124
|
+
setConfiguration(configuration: Configuration): void;
|
|
125
|
+
getEventManager(): EventManager;
|
|
126
|
+
setEventManager(eventManager: EventManager): void;
|
|
127
|
+
getStorageBackend(): StorageBackend;
|
|
128
|
+
setStorageBackend(storageBackend: StorageBackend): void;
|
|
129
|
+
getLogger(): CrawleeLogger;
|
|
130
|
+
setLogger(logger: CrawleeLogger): void;
|
|
131
|
+
getChildLog(prefix: string): CrawleeLogger;
|
|
132
|
+
getStorageInstanceManager(): StorageInstanceManager;
|
|
133
|
+
reset(): void;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Wraps all methods on `target` so that any code they invoke will see the given
|
|
137
|
+
* `serviceLocator` via `AsyncLocalStorage`, rather than the global one.
|
|
138
|
+
*
|
|
139
|
+
* Walks the prototype chain and replaces each method on the *instance* (not the prototype)
|
|
140
|
+
* with a wrapper that calls `serviceLocatorStorage.run(serviceLocator, originalMethod)`.
|
|
141
|
+
*
|
|
142
|
+
* The `AsyncLocalStorage` context propagates through the entire sync/async call tree of each
|
|
143
|
+
* wrapped method — including `super` calls, since the prototype methods execute within the
|
|
144
|
+
* context established by the instance-level wrapper.
|
|
145
|
+
*
|
|
146
|
+
* @internal
|
|
147
|
+
* @returns Scope control functions: `run` executes a callback within the scoped context,
|
|
148
|
+
* `enterScope`/`exitScope` allow entering/leaving the scope imperatively (e.g., for constructor bodies).
|
|
149
|
+
*/
|
|
150
|
+
export declare function bindMethodsToServiceLocator(serviceLocator: ServiceLocator, target: {}): {
|
|
151
|
+
run: <T>(fn: () => T) => T;
|
|
152
|
+
enterScope: () => void;
|
|
153
|
+
exitScope: () => void;
|
|
154
|
+
};
|
|
155
|
+
export declare const serviceLocator: ServiceLocatorInterface;
|
|
156
|
+
export {};
|