@crawlee/core 4.0.0-rc.0 → 4.0.0-rc.1
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 +1 -1
- package/configuration.d.ts +15 -46
- package/configuration.js +8 -20
- package/errors.d.ts +12 -53
- package/errors.js +13 -66
- package/events/index.d.ts +1 -0
- package/events/local_event_manager.d.ts +0 -7
- package/events/local_event_manager.js +8 -8
- package/events/system_info.d.ts +38 -0
- package/index.d.ts +2 -8
- package/index.js +4 -8
- package/internal.d.ts +8 -0
- package/internal.js +9 -0
- package/log.d.ts +10 -11
- package/log.js +53 -25
- package/memory-storage/memory-storage.d.ts +12 -7
- package/memory-storage/memory-storage.js +45 -17
- package/memory-storage/resource-clients/dataset.d.ts +0 -5
- package/memory-storage/resource-clients/dataset.js +17 -20
- package/memory-storage/resource-clients/key-value-store.d.ts +0 -9
- package/memory-storage/resource-clients/key-value-store.js +11 -33
- package/memory-storage/resource-clients/request-queue.d.ts +0 -22
- package/memory-storage/resource-clients/request-queue.js +57 -53
- package/package.json +16 -18
- package/proxy_configuration.d.ts +20 -23
- package/proxy_configuration.js +18 -12
- package/recoverable_state.d.ts +28 -6
- package/recoverable_state.js +51 -14
- package/request.d.ts +18 -104
- package/request.js +41 -220
- package/serialization.js +3 -3
- package/service_locator.d.ts +3 -0
- package/service_locator.js +2 -0
- package/storages/dataset.d.ts +9 -15
- package/storages/dataset.js +22 -14
- package/storages/index.d.ts +3 -4
- package/storages/index.js +1 -4
- package/storages/key_value_store.d.ts +12 -46
- package/storages/key_value_store.js +31 -47
- package/storages/key_value_store_codec.js +6 -11
- package/storages/request_dedup_cache.d.ts +0 -2
- package/storages/request_dedup_cache.js +8 -8
- package/storages/request_list.d.ts +6 -82
- package/storages/request_list.js +175 -179
- package/storages/request_loader.d.ts +48 -22
- package/storages/request_loader.js +36 -1
- package/storages/request_manager.d.ts +86 -0
- package/storages/request_manager_tandem.d.ts +13 -28
- package/storages/request_manager_tandem.js +46 -43
- package/storages/request_queue.d.ts +19 -49
- package/storages/request_queue.js +92 -88
- package/storages/storage_instance_manager.d.ts +1 -2
- package/storages/storage_instance_manager.js +4 -4
- package/storages/transaction.d.ts +27 -9
- package/storages/transaction.js +56 -11
- package/storages/utils.d.ts +2 -2
- package/validators.d.ts +3 -2
- package/validators.js +3 -2
- package/autoscaling/autoscaled_pool.d.ts +0 -195
- package/autoscaling/autoscaled_pool.js +0 -386
- package/autoscaling/concurrency_system.d.ts +0 -268
- package/autoscaling/concurrency_system.js +0 -362
- package/autoscaling/cpu_load_signal.d.ts +0 -43
- package/autoscaling/cpu_load_signal.js +0 -47
- package/autoscaling/event_loop_load_signal.d.ts +0 -51
- package/autoscaling/event_loop_load_signal.js +0 -60
- package/autoscaling/index.d.ts +0 -9
- package/autoscaling/index.js +0 -9
- package/autoscaling/load_signal.d.ts +0 -100
- package/autoscaling/load_signal.js +0 -105
- package/autoscaling/memory_load_signal.d.ts +0 -47
- package/autoscaling/memory_load_signal.js +0 -106
- package/autoscaling/snapshotter.d.ts +0 -84
- package/autoscaling/snapshotter.js +0 -67
- package/autoscaling/storage_backend_load_signal.d.ts +0 -56
- package/autoscaling/storage_backend_load_signal.js +0 -73
- package/autoscaling/system_status.d.ts +0 -159
- package/autoscaling/system_status.js +0 -139
- package/autoscaling/weighted_avg.d.ts +0 -5
- package/autoscaling/weighted_avg.js +0 -14
- package/cookie_utils.d.ts +0 -44
- package/cookie_utils.js +0 -122
- package/crawlers/context_pipeline.d.ts +0 -70
- package/crawlers/context_pipeline.js +0 -122
- package/crawlers/crawler_commons.d.ts +0 -159
- package/crawlers/error_snapshotter.d.ts +0 -57
- package/crawlers/error_snapshotter.js +0 -117
- package/crawlers/error_tracker.d.ts +0 -54
- package/crawlers/error_tracker.js +0 -308
- package/crawlers/index.d.ts +0 -5
- package/crawlers/index.js +0 -4
- package/crawlers/internals/types.d.ts +0 -7
- package/crawlers/internals/types.js +0 -1
- package/crawlers/statistics.d.ts +0 -328
- package/crawlers/statistics.js +0 -536
- package/enqueue_links/enqueue_links.d.ts +0 -156
- package/enqueue_links/enqueue_links.js +0 -78
- package/enqueue_links/index.d.ts +0 -2
- package/enqueue_links/index.js +0 -2
- package/enqueue_links/shared.d.ts +0 -93
- package/enqueue_links/shared.js +0 -239
- package/http.d.ts +0 -9
- package/http.js +0 -28
- package/router.d.ts +0 -306
- package/router.js +0 -309
- package/session_pool/consts.d.ts +0 -3
- package/session_pool/consts.js +0 -3
- package/session_pool/errors.d.ts +0 -7
- package/session_pool/errors.js +0 -11
- package/session_pool/fingerprint.d.ts +0 -9
- package/session_pool/fingerprint.js +0 -30
- package/session_pool/index.d.ts +0 -4
- package/session_pool/index.js +0 -4
- package/session_pool/session.d.ts +0 -150
- package/session_pool/session.js +0 -220
- package/session_pool/session_pool.d.ts +0 -240
- package/session_pool/session_pool.js +0 -394
- package/storages/sitemap_request_loader.d.ts +0 -201
- package/storages/sitemap_request_loader.js +0 -438
- package/storages/throttling_request_manager.d.ts +0 -239
- package/storages/throttling_request_manager.js +0 -646
- /package/{crawlers/crawler_commons.js → events/system_info.js} +0 -0
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { EnqueueStrategy } from '@crawlee/utils';
|
|
2
|
-
import { getDomain } from 'tldts';
|
|
3
|
-
export { EnqueueStrategy };
|
|
4
|
-
/**
|
|
5
|
-
* @internal
|
|
6
|
-
* This method helps resolve the baseUrl that will be used for filtering in {@link enqueueLinks}.
|
|
7
|
-
* - If a user provides a base url, we always return it
|
|
8
|
-
* - If a user specifies {@link EnqueueStrategy.All} strategy, they do not care if the newly found urls are on the original
|
|
9
|
-
* request domain, or a redirected one
|
|
10
|
-
* - In all other cases, we return the domain of the original request as that's the one we need to use for filtering
|
|
11
|
-
*/
|
|
12
|
-
export function resolveBaseUrlForEnqueueLinksFiltering({ enqueueStrategy, finalRequestUrl, originalRequestUrl, userProvidedBaseUrl, }) {
|
|
13
|
-
// User provided base url takes priority
|
|
14
|
-
if (userProvidedBaseUrl) {
|
|
15
|
-
return userProvidedBaseUrl;
|
|
16
|
-
}
|
|
17
|
-
const originalUrlOrigin = new URL(originalRequestUrl).origin;
|
|
18
|
-
const finalUrlOrigin = new URL(finalRequestUrl ?? originalRequestUrl).origin;
|
|
19
|
-
// We can assume users want to go off the domain in this case
|
|
20
|
-
if (enqueueStrategy === EnqueueStrategy.All) {
|
|
21
|
-
return finalUrlOrigin;
|
|
22
|
-
}
|
|
23
|
-
// If the user wants to ensure the same domain is accessed, regardless of subdomains, we check to ensure the domains match
|
|
24
|
-
// Returning undefined here is intentional! If the domains don't match, having no baseUrl in enqueueLinks will cause it to not enqueue anything
|
|
25
|
-
// which is the intended behavior (since we went off domain)
|
|
26
|
-
if (enqueueStrategy === EnqueueStrategy.SameDomain) {
|
|
27
|
-
const originalHostname = getDomain(originalUrlOrigin, { mixedInputs: false });
|
|
28
|
-
const finalHostname = getDomain(finalUrlOrigin, { mixedInputs: false });
|
|
29
|
-
if (originalHostname === finalHostname) {
|
|
30
|
-
return finalUrlOrigin;
|
|
31
|
-
}
|
|
32
|
-
return undefined;
|
|
33
|
-
}
|
|
34
|
-
// Always enqueue urls that are from the same origin in all other cases, as the filtering happens on the original request url, even if there was a redirect
|
|
35
|
-
// before actually finding the urls
|
|
36
|
-
return originalUrlOrigin;
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* @internal
|
|
40
|
-
* Builds the glob patterns a URL must match to satisfy the given enqueue `strategy`, anchored at `baseUrl`.
|
|
41
|
-
*/
|
|
42
|
-
export function buildEnqueueStrategyPatterns(baseUrl, strategy) {
|
|
43
|
-
const url = new URL(baseUrl);
|
|
44
|
-
switch (strategy) {
|
|
45
|
-
case EnqueueStrategy.SameHostname:
|
|
46
|
-
// We need to get the origin of the passed in domain in the event someone sets baseUrl
|
|
47
|
-
// to an url like https://example.com/deep/default/path and one of the found urls is an
|
|
48
|
-
// absolute relative path (/path/to/page)
|
|
49
|
-
return [{ glob: ignoreHttpSchema(`${url.origin}/**`) }];
|
|
50
|
-
case EnqueueStrategy.SameDomain: {
|
|
51
|
-
// Get the actual hostname from the base url
|
|
52
|
-
const baseUrlHostname = getDomain(url.hostname, { mixedInputs: false });
|
|
53
|
-
if (baseUrlHostname) {
|
|
54
|
-
// We have a hostname, so we can use it to match all links on the page that point to it and any subdomains of it
|
|
55
|
-
url.hostname = baseUrlHostname;
|
|
56
|
-
return [
|
|
57
|
-
{ glob: ignoreHttpSchema(`${url.origin.replace(baseUrlHostname, `*.${baseUrlHostname}`)}/**`) },
|
|
58
|
-
{ glob: ignoreHttpSchema(`${url.origin}/**`) },
|
|
59
|
-
];
|
|
60
|
-
}
|
|
61
|
-
// We don't have a hostname (can happen for ips for instance), so reproduce the same behavior
|
|
62
|
-
// as SameDomainAndSubdomain
|
|
63
|
-
return [{ glob: ignoreHttpSchema(`${url.origin}/**`) }];
|
|
64
|
-
}
|
|
65
|
-
case EnqueueStrategy.SameOrigin:
|
|
66
|
-
// The same behavior as SameHostname, but respecting the protocol of the URL
|
|
67
|
-
return [{ glob: `${url.origin}/**` }];
|
|
68
|
-
case EnqueueStrategy.All:
|
|
69
|
-
default:
|
|
70
|
-
return [{ glob: `http{s,}://**` }];
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Internal function that changes the enqueue glob patterns to match both http and https
|
|
75
|
-
*/
|
|
76
|
-
function ignoreHttpSchema(pattern) {
|
|
77
|
-
return pattern.replace(/^(https?):\/\//, 'http{s,}://');
|
|
78
|
-
}
|
package/enqueue_links/index.d.ts
DELETED
package/enqueue_links/index.js
DELETED
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
import type { Awaitable, Dictionary } from '@crawlee/types';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import type { RequestOptions } from '../request.js';
|
|
4
|
-
import type { EnqueueStrategyOption } from './enqueue_links.js';
|
|
5
|
-
export { tryAbsoluteURL } from '@crawlee/utils/internal';
|
|
6
|
-
export interface UrlPatternObject {
|
|
7
|
-
glob?: string;
|
|
8
|
-
regexp?: RegExp;
|
|
9
|
-
}
|
|
10
|
-
export interface GlobObject {
|
|
11
|
-
glob: string;
|
|
12
|
-
}
|
|
13
|
-
export type GlobInput = string | GlobObject;
|
|
14
|
-
export interface RegExpObject {
|
|
15
|
-
regexp: RegExp;
|
|
16
|
-
}
|
|
17
|
-
export type RegExpInput = RegExp | RegExpObject;
|
|
18
|
-
/** Unified URL pattern input — accepts glob strings, glob objects, RegExp instances, or regexp objects. */
|
|
19
|
-
export type UrlPatternInput = GlobInput | RegExpInput;
|
|
20
|
-
/**
|
|
21
|
-
* Accepts one {@link UrlPatternInput} — a glob string, a RegExp instance, or a `{ glob }` / `{ regexp }` object.
|
|
22
|
-
* @internal
|
|
23
|
-
*/
|
|
24
|
-
export declare const urlPatternSchema: z.ZodType<UrlPatternInput>;
|
|
25
|
-
export type SkippedRequestReason = 'robotsTxt' | 'limit' | 'enqueueLimit' | 'filters' | 'transform' | 'redirect' | 'depth';
|
|
26
|
-
export type SkippedRequestCallback = (args: {
|
|
27
|
-
url: string;
|
|
28
|
-
reason: SkippedRequestReason;
|
|
29
|
-
}) => Awaitable<void>;
|
|
30
|
-
/**
|
|
31
|
-
* @ignore
|
|
32
|
-
*/
|
|
33
|
-
export declare function updateEnqueueLinksPatternCache(item: GlobInput | RegExpInput, pattern: RegExpObject | GlobObject): void;
|
|
34
|
-
/**
|
|
35
|
-
* Helper factory used in the `enqueueLinks()` and enqueueLinksByClickingElements() function
|
|
36
|
-
* to construct Glob objects from Glob pattern strings.
|
|
37
|
-
* @ignore
|
|
38
|
-
*/
|
|
39
|
-
export declare function constructGlobObjectsFromGlobs(globs: readonly GlobInput[]): GlobObject[];
|
|
40
|
-
/**
|
|
41
|
-
* @internal
|
|
42
|
-
*/
|
|
43
|
-
export declare function validateGlobPattern(glob: string): string;
|
|
44
|
-
/**
|
|
45
|
-
* Helper factory used in the `enqueueLinks()` and enqueueLinksByClickingElements() function
|
|
46
|
-
* to check RegExps input and return valid RegExps.
|
|
47
|
-
* @ignore
|
|
48
|
-
*/
|
|
49
|
-
export declare function constructRegExpObjectsFromRegExps(regexps: readonly RegExpInput[]): RegExpObject[];
|
|
50
|
-
/**
|
|
51
|
-
* Helper factory used in the `enqueueLinks()` function to construct UrlPatternObjects
|
|
52
|
-
* from a mixed array of glob strings, glob objects, RegExp instances, and regexp objects.
|
|
53
|
-
* @ignore
|
|
54
|
-
*/
|
|
55
|
-
export declare function constructUrlPatternObjects(patterns: readonly UrlPatternInput[]): UrlPatternObject[];
|
|
56
|
-
/**
|
|
57
|
-
* Filters request options by URL patterns.
|
|
58
|
-
*
|
|
59
|
-
* When `includePatterns` is empty/undefined, all options pass through (only exclude filtering applies).
|
|
60
|
-
* @ignore
|
|
61
|
-
*/
|
|
62
|
-
export declare function filterRequestOptionsByPatterns(requestOptions: RequestOptions[], includePatterns: UrlPatternObject[] | undefined, excludePatterns?: UrlPatternObject[], strategy?: EnqueueStrategyOption, onSkippedUrl?: (url: string) => void): RequestOptions[];
|
|
63
|
-
/**
|
|
64
|
-
* @ignore
|
|
65
|
-
*/
|
|
66
|
-
export declare function createRequestOptions(sources: readonly (string | Record<string, unknown>)[], options?: {
|
|
67
|
-
label?: string;
|
|
68
|
-
userData?: Dictionary;
|
|
69
|
-
baseUrl?: string;
|
|
70
|
-
skipNavigation?: boolean;
|
|
71
|
-
sessionId?: string;
|
|
72
|
-
strategy?: EnqueueStrategyOption;
|
|
73
|
-
}): RequestOptions[];
|
|
74
|
-
/**
|
|
75
|
-
* Takes a {@link RequestOptions} object and changes its attributes in a desired way. This user-function is used
|
|
76
|
-
* by {@link enqueueLinks} to modify request options before they are converted to {@link Request} instances.
|
|
77
|
-
*/
|
|
78
|
-
export interface RequestTransform {
|
|
79
|
-
/**
|
|
80
|
-
* @param original Request options to be modified.
|
|
81
|
-
* @returns The modified request options to enqueue, `'unchanged'` to keep the original options as-is,
|
|
82
|
-
* or a falsy value / `'skip'` to exclude the request from the queue.
|
|
83
|
-
*/
|
|
84
|
-
(original: RequestOptions): RequestOptions | false | undefined | null | 'skip' | 'unchanged';
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Applies a {@link RequestTransform} function to a list of request options.
|
|
88
|
-
* Options for which the transform returns a falsy value are removed from the list.
|
|
89
|
-
* @param onSkipped Called with the original request options when the transform returns a falsy value (i.e. the request is skipped).
|
|
90
|
-
* @ignore
|
|
91
|
-
* @internal
|
|
92
|
-
*/
|
|
93
|
-
export declare function applyRequestTransform(requestOptions: RequestOptions[], transformFn: RequestTransform, onSkipped?: (requestOptions: RequestOptions) => void): RequestOptions[];
|
package/enqueue_links/shared.js
DELETED
|
@@ -1,239 +0,0 @@
|
|
|
1
|
-
import { URL } from 'node:url';
|
|
2
|
-
import { Minimatch } from 'minimatch';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
import { schemas } from '../validators.js';
|
|
5
|
-
export { tryAbsoluteURL } from '@crawlee/utils/internal';
|
|
6
|
-
const MAX_ENQUEUE_LINKS_CACHE_SIZE = 1000;
|
|
7
|
-
/**
|
|
8
|
-
* To keep high performance when the same patterns are passed on every `enqueueLinks()` call,
|
|
9
|
-
* each glob/regexp is only compiled once and then kept in a cache.
|
|
10
|
-
* @ignore
|
|
11
|
-
*/
|
|
12
|
-
const enqueueLinksPatternCache = new Map();
|
|
13
|
-
/**
|
|
14
|
-
* Accepts one {@link UrlPatternInput} — a glob string, a RegExp instance, or a `{ glob }` / `{ regexp }` object.
|
|
15
|
-
* @internal
|
|
16
|
-
*/
|
|
17
|
-
export const urlPatternSchema = z.union([
|
|
18
|
-
z.string(),
|
|
19
|
-
z.instanceof(RegExp),
|
|
20
|
-
schemas.objectWithKeys(['glob']),
|
|
21
|
-
schemas.objectWithKeys(['regexp']),
|
|
22
|
-
]);
|
|
23
|
-
/**
|
|
24
|
-
* @ignore
|
|
25
|
-
*/
|
|
26
|
-
export function updateEnqueueLinksPatternCache(item, pattern) {
|
|
27
|
-
enqueueLinksPatternCache.set(item, pattern);
|
|
28
|
-
if (enqueueLinksPatternCache.size > MAX_ENQUEUE_LINKS_CACHE_SIZE) {
|
|
29
|
-
const key = enqueueLinksPatternCache.keys().next().value;
|
|
30
|
-
enqueueLinksPatternCache.delete(key);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Helper factory used in the `enqueueLinks()` and enqueueLinksByClickingElements() function
|
|
35
|
-
* to construct Glob objects from Glob pattern strings.
|
|
36
|
-
* @ignore
|
|
37
|
-
*/
|
|
38
|
-
export function constructGlobObjectsFromGlobs(globs) {
|
|
39
|
-
return globs
|
|
40
|
-
.filter((glob) => {
|
|
41
|
-
// Skip possibly nullish, empty strings
|
|
42
|
-
if (!glob) {
|
|
43
|
-
return false;
|
|
44
|
-
}
|
|
45
|
-
if (typeof glob === 'string') {
|
|
46
|
-
return glob.trim().length > 0;
|
|
47
|
-
}
|
|
48
|
-
if (glob.glob) {
|
|
49
|
-
return glob.glob.trim().length > 0;
|
|
50
|
-
}
|
|
51
|
-
return false;
|
|
52
|
-
})
|
|
53
|
-
.map((item) => {
|
|
54
|
-
// Get glob object from cache.
|
|
55
|
-
let globObject = enqueueLinksPatternCache.get(item);
|
|
56
|
-
if (globObject)
|
|
57
|
-
return globObject;
|
|
58
|
-
if (typeof item === 'string') {
|
|
59
|
-
globObject = { glob: validateGlobPattern(item) };
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
globObject = { glob: validateGlobPattern(item.glob) };
|
|
63
|
-
}
|
|
64
|
-
updateEnqueueLinksPatternCache(item, globObject);
|
|
65
|
-
return globObject;
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* @internal
|
|
70
|
-
*/
|
|
71
|
-
export function validateGlobPattern(glob) {
|
|
72
|
-
const globTrimmed = glob.trim();
|
|
73
|
-
if (globTrimmed.length === 0)
|
|
74
|
-
throw new Error(`Cannot parse Glob pattern '${globTrimmed}': it must be an non-empty string`);
|
|
75
|
-
return globTrimmed;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Helper factory used in the `enqueueLinks()` and enqueueLinksByClickingElements() function
|
|
79
|
-
* to check RegExps input and return valid RegExps.
|
|
80
|
-
* @ignore
|
|
81
|
-
*/
|
|
82
|
-
export function constructRegExpObjectsFromRegExps(regexps) {
|
|
83
|
-
return regexps.map((item) => {
|
|
84
|
-
// Get regexp object from cache.
|
|
85
|
-
let regexpObject = enqueueLinksPatternCache.get(item);
|
|
86
|
-
if (regexpObject)
|
|
87
|
-
return regexpObject;
|
|
88
|
-
if (item instanceof RegExp) {
|
|
89
|
-
regexpObject = { regexp: item };
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
regexpObject = { regexp: item.regexp };
|
|
93
|
-
}
|
|
94
|
-
updateEnqueueLinksPatternCache(item, regexpObject);
|
|
95
|
-
return regexpObject;
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
/**
|
|
99
|
-
* Helper factory used in the `enqueueLinks()` function to construct UrlPatternObjects
|
|
100
|
-
* from a mixed array of glob strings, glob objects, RegExp instances, and regexp objects.
|
|
101
|
-
* @ignore
|
|
102
|
-
*/
|
|
103
|
-
export function constructUrlPatternObjects(patterns) {
|
|
104
|
-
const result = [];
|
|
105
|
-
for (const item of patterns) {
|
|
106
|
-
if (typeof item === 'string' || 'glob' in item) {
|
|
107
|
-
result.push(...constructGlobObjectsFromGlobs([item]));
|
|
108
|
-
}
|
|
109
|
-
else if (item instanceof RegExp || 'regexp' in item) {
|
|
110
|
-
result.push(...constructRegExpObjectsFromRegExps([item]));
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
return result;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* Filters request options by URL patterns.
|
|
117
|
-
*
|
|
118
|
-
* When `includePatterns` is empty/undefined, all options pass through (only exclude filtering applies).
|
|
119
|
-
* @ignore
|
|
120
|
-
*/
|
|
121
|
-
export function filterRequestOptionsByPatterns(requestOptions, includePatterns, excludePatterns = [], strategy, onSkippedUrl) {
|
|
122
|
-
const excludeMatchers = excludePatterns.map(createPatternObjectMatcher);
|
|
123
|
-
const includeMatchers = includePatterns?.length ? includePatterns.map(createPatternObjectMatcher) : undefined;
|
|
124
|
-
return requestOptions
|
|
125
|
-
.filter(({ url }) => {
|
|
126
|
-
const matchesExclude = excludeMatchers.some(({ match }) => match(url));
|
|
127
|
-
if (matchesExclude) {
|
|
128
|
-
onSkippedUrl?.(url);
|
|
129
|
-
}
|
|
130
|
-
return !matchesExclude;
|
|
131
|
-
})
|
|
132
|
-
.map((opts) => {
|
|
133
|
-
if (!includeMatchers) {
|
|
134
|
-
return { ...opts, enqueueStrategy: strategy };
|
|
135
|
-
}
|
|
136
|
-
for (const { match } of includeMatchers) {
|
|
137
|
-
if (match(opts.url)) {
|
|
138
|
-
return { ...opts, enqueueStrategy: strategy };
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
// didn't match any positive pattern
|
|
142
|
-
onSkippedUrl?.(opts.url);
|
|
143
|
-
return null;
|
|
144
|
-
})
|
|
145
|
-
.filter((opts) => opts !== null);
|
|
146
|
-
}
|
|
147
|
-
function isAbsoluteUrl(url) {
|
|
148
|
-
try {
|
|
149
|
-
// eslint-disable-next-line no-new
|
|
150
|
-
new URL(url);
|
|
151
|
-
return true;
|
|
152
|
-
}
|
|
153
|
-
catch {
|
|
154
|
-
return false;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* @ignore
|
|
159
|
-
*/
|
|
160
|
-
export function createRequestOptions(sources, options = {}) {
|
|
161
|
-
return sources
|
|
162
|
-
.map((src) => typeof src === 'string'
|
|
163
|
-
? { url: src, enqueueStrategy: options.strategy }
|
|
164
|
-
: { ...src, enqueueStrategy: options.strategy })
|
|
165
|
-
.filter(({ url }) => {
|
|
166
|
-
try {
|
|
167
|
-
return new URL(url, options.baseUrl).href;
|
|
168
|
-
}
|
|
169
|
-
catch (err) {
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
})
|
|
173
|
-
.map((requestOptions) => {
|
|
174
|
-
// Leave already-absolute URLs untouched - re-deriving them via `new URL()` would normalize them
|
|
175
|
-
// (e.g. adding a trailing slash to a bare domain), which is surprising for URLs that didn't need
|
|
176
|
-
// resolving against `baseUrl` in the first place.
|
|
177
|
-
if (!isAbsoluteUrl(requestOptions.url)) {
|
|
178
|
-
requestOptions.url = new URL(requestOptions.url, options.baseUrl).href;
|
|
179
|
-
}
|
|
180
|
-
requestOptions.userData ??= options.userData ?? {};
|
|
181
|
-
if (typeof options.label === 'string') {
|
|
182
|
-
requestOptions.userData = {
|
|
183
|
-
...requestOptions.userData,
|
|
184
|
-
label: options.label,
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
if (options.skipNavigation) {
|
|
188
|
-
requestOptions.skipNavigation = true;
|
|
189
|
-
}
|
|
190
|
-
if (options.sessionId) {
|
|
191
|
-
requestOptions.sessionId = options.sessionId;
|
|
192
|
-
}
|
|
193
|
-
return requestOptions;
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
/**
|
|
197
|
-
* @ignore
|
|
198
|
-
*/
|
|
199
|
-
function createPatternObjectMatcher(urlPatternObject) {
|
|
200
|
-
const { regexp, glob } = urlPatternObject;
|
|
201
|
-
let match;
|
|
202
|
-
if (regexp) {
|
|
203
|
-
match = (url) => regexp.test(url);
|
|
204
|
-
}
|
|
205
|
-
else if (glob) {
|
|
206
|
-
const m = new Minimatch(glob, { nocase: true });
|
|
207
|
-
match = (url) => m.match(url);
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
match = () => false;
|
|
211
|
-
}
|
|
212
|
-
return { match };
|
|
213
|
-
}
|
|
214
|
-
/**
|
|
215
|
-
* Applies a {@link RequestTransform} function to a list of request options.
|
|
216
|
-
* Options for which the transform returns a falsy value are removed from the list.
|
|
217
|
-
* @param onSkipped Called with the original request options when the transform returns a falsy value (i.e. the request is skipped).
|
|
218
|
-
* @ignore
|
|
219
|
-
* @internal
|
|
220
|
-
*/
|
|
221
|
-
export function applyRequestTransform(requestOptions, transformFn, onSkipped) {
|
|
222
|
-
return requestOptions
|
|
223
|
-
.map((opts) => {
|
|
224
|
-
const transformed = transformFn(opts);
|
|
225
|
-
if (transformed === 'skip') {
|
|
226
|
-
onSkipped?.(opts);
|
|
227
|
-
return null;
|
|
228
|
-
}
|
|
229
|
-
if (transformed === 'unchanged') {
|
|
230
|
-
return opts;
|
|
231
|
-
}
|
|
232
|
-
if (!transformed) {
|
|
233
|
-
onSkipped?.(opts);
|
|
234
|
-
return null;
|
|
235
|
-
}
|
|
236
|
-
return transformed;
|
|
237
|
-
})
|
|
238
|
-
.filter((r) => r !== null);
|
|
239
|
-
}
|
package/http.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parses a `Retry-After` response header into a delay in milliseconds.
|
|
3
|
-
*
|
|
4
|
-
* The header holds either a non-negative number of seconds or an HTTP-date.
|
|
5
|
-
* See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After).
|
|
6
|
-
*
|
|
7
|
-
* @returns The delay in milliseconds, or `null` if the header is absent, unparseable, or already elapsed.
|
|
8
|
-
*/
|
|
9
|
-
export declare function parseRetryAfterHeader(value?: string | null): number | null;
|
package/http.js
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parses a `Retry-After` response header into a delay in milliseconds.
|
|
3
|
-
*
|
|
4
|
-
* The header holds either a non-negative number of seconds or an HTTP-date.
|
|
5
|
-
* See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Retry-After).
|
|
6
|
-
*
|
|
7
|
-
* @returns The delay in milliseconds, or `null` if the header is absent, unparseable, or already elapsed.
|
|
8
|
-
*/
|
|
9
|
-
export function parseRetryAfterHeader(value) {
|
|
10
|
-
if (!value) {
|
|
11
|
-
return null;
|
|
12
|
-
}
|
|
13
|
-
const trimmed = value.trim();
|
|
14
|
-
// Per the spec this is a `delay-seconds`: digits only, so a negative or fractional value is not one.
|
|
15
|
-
if (/^\d+$/.test(trimmed)) {
|
|
16
|
-
// `Retry-After: 0` names no future deadline, same as an HTTP-date that has already passed. Reporting it
|
|
17
|
-
// as a zero delay would leave the domain unthrottled while still counting as a rate-limit event, so the
|
|
18
|
-
// caller would defer the request for free and re-send it immediately.
|
|
19
|
-
const delayMs = Number(trimmed) * 1000;
|
|
20
|
-
return delayMs > 0 ? delayMs : null;
|
|
21
|
-
}
|
|
22
|
-
const date = Date.parse(trimmed);
|
|
23
|
-
if (!Number.isNaN(date)) {
|
|
24
|
-
const delayMs = date - Date.now();
|
|
25
|
-
return delayMs > 0 ? delayMs : null;
|
|
26
|
-
}
|
|
27
|
-
return null;
|
|
28
|
-
}
|