@crawlee/utils 4.0.0-beta.13 → 4.0.0-beta.131

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.
Files changed (75) hide show
  1. package/README.md +17 -13
  2. package/index.d.ts +6 -12
  3. package/index.js +5 -11
  4. package/internal.d.ts +9 -0
  5. package/internal.js +8 -0
  6. package/internals/blocked.d.ts +0 -1
  7. package/internals/blocked.js +0 -1
  8. package/internals/cheerio.d.ts +3 -2
  9. package/internals/cheerio.js +4 -5
  10. package/internals/extract-urls.d.ts +5 -1
  11. package/internals/extract-urls.js +23 -18
  12. package/internals/general.d.ts +0 -25
  13. package/internals/general.js +2 -110
  14. package/internals/iterables.d.ts +47 -0
  15. package/internals/iterables.js +96 -0
  16. package/internals/open_graph_parser.d.ts +2 -3
  17. package/internals/open_graph_parser.js +8 -9
  18. package/internals/robots.d.ts +38 -12
  19. package/internals/robots.js +72 -48
  20. package/internals/schemas.d.ts +114 -0
  21. package/internals/schemas.js +114 -0
  22. package/internals/sitemap.d.ts +74 -8
  23. package/internals/sitemap.js +251 -79
  24. package/internals/social.d.ts +1 -2
  25. package/internals/social.js +7 -5
  26. package/internals/url.d.ts +70 -2
  27. package/internals/url.js +120 -2
  28. package/internals/validation.d.ts +25 -0
  29. package/internals/validation.js +140 -0
  30. package/package.json +10 -8
  31. package/index.d.ts.map +0 -1
  32. package/index.js.map +0 -1
  33. package/internals/blocked.d.ts.map +0 -1
  34. package/internals/blocked.js.map +0 -1
  35. package/internals/cheerio.d.ts.map +0 -1
  36. package/internals/cheerio.js.map +0 -1
  37. package/internals/chunk.d.ts +0 -2
  38. package/internals/chunk.d.ts.map +0 -1
  39. package/internals/chunk.js +0 -40
  40. package/internals/chunk.js.map +0 -1
  41. package/internals/debug.d.ts +0 -31
  42. package/internals/debug.d.ts.map +0 -1
  43. package/internals/debug.js +0 -29
  44. package/internals/debug.js.map +0 -1
  45. package/internals/extract-urls.d.ts.map +0 -1
  46. package/internals/extract-urls.js.map +0 -1
  47. package/internals/general.d.ts.map +0 -1
  48. package/internals/general.js.map +0 -1
  49. package/internals/open_graph_parser.d.ts.map +0 -1
  50. package/internals/open_graph_parser.js.map +0 -1
  51. package/internals/robots.d.ts.map +0 -1
  52. package/internals/robots.js.map +0 -1
  53. package/internals/sitemap.d.ts.map +0 -1
  54. package/internals/sitemap.js.map +0 -1
  55. package/internals/social.d.ts.map +0 -1
  56. package/internals/social.js.map +0 -1
  57. package/internals/system-info/cpu-info.d.ts +0 -64
  58. package/internals/system-info/cpu-info.d.ts.map +0 -1
  59. package/internals/system-info/cpu-info.js +0 -211
  60. package/internals/system-info/cpu-info.js.map +0 -1
  61. package/internals/system-info/memory-info.d.ts +0 -28
  62. package/internals/system-info/memory-info.d.ts.map +0 -1
  63. package/internals/system-info/memory-info.js +0 -118
  64. package/internals/system-info/memory-info.js.map +0 -1
  65. package/internals/system-info/ps-tree.d.ts +0 -18
  66. package/internals/system-info/ps-tree.d.ts.map +0 -1
  67. package/internals/system-info/ps-tree.js +0 -145
  68. package/internals/system-info/ps-tree.js.map +0 -1
  69. package/internals/typedefs.d.ts +0 -5
  70. package/internals/typedefs.d.ts.map +0 -1
  71. package/internals/typedefs.js +0 -9
  72. package/internals/typedefs.js.map +0 -1
  73. package/internals/url.d.ts.map +0 -1
  74. package/internals/url.js.map +0 -1
  75. package/tsconfig.build.tsbuildinfo +0 -1
@@ -1,4 +1,3 @@
1
- import { load } from 'cheerio';
2
1
  /**
3
2
  * To be used with the spread operator. Ensures that the item is defined, and is not empty.
4
3
  *
@@ -255,32 +254,32 @@ const OPEN_GRAPH_PROPERTIES = [
255
254
  outputName: 'articleInfo',
256
255
  children: [
257
256
  {
258
- name: 'music:published_time',
257
+ name: 'article:published_time',
259
258
  outputName: 'publishedTime',
260
259
  children: [],
261
260
  },
262
261
  {
263
- name: 'music:modified_time',
262
+ name: 'article:modified_time',
264
263
  outputName: 'modifiedTime',
265
264
  children: [],
266
265
  },
267
266
  {
268
- name: 'music:expiration_time',
267
+ name: 'article:expiration_time',
269
268
  outputName: 'expirationTime',
270
269
  children: [],
271
270
  },
272
271
  {
273
- name: 'music:author',
272
+ name: 'article:author',
274
273
  outputName: 'author',
275
274
  children: [],
276
275
  },
277
276
  {
278
- name: 'music:section',
277
+ name: 'article:section',
279
278
  outputName: 'section',
280
279
  children: [],
281
280
  },
282
281
  {
283
- name: 'music:tag',
282
+ name: 'article:tag',
284
283
  outputName: 'tag',
285
284
  children: [],
286
285
  },
@@ -366,7 +365,8 @@ const parseOpenGraphProperty = (property, $) => {
366
365
  }, {}),
367
366
  };
368
367
  };
369
- export function parseOpenGraph(item, additionalProperties) {
368
+ export async function parseOpenGraph(item, additionalProperties) {
369
+ const { load } = await import('cheerio');
370
370
  const $ = typeof item === 'string' ? load(item) : item;
371
371
  return [...(additionalProperties || []), ...OPEN_GRAPH_PROPERTIES].reduce((acc, curr) => {
372
372
  return {
@@ -375,4 +375,3 @@ export function parseOpenGraph(item, additionalProperties) {
375
375
  };
376
376
  }, {});
377
377
  }
378
- //# sourceMappingURL=open_graph_parser.js.map
@@ -1,4 +1,15 @@
1
+ import type { BaseHttpClient } from '@crawlee/http-client';
2
+ import type { CrawleeLogger } from '@crawlee/types';
1
3
  import { Sitemap } from './sitemap.js';
4
+ import { type EnqueueStrategy } from './url.js';
5
+ export interface RobotsTxtFileSitemapsOptions {
6
+ /**
7
+ * Keep only sitemap URLs matching this strategy relative to the robots.txt host; non-`http(s)` schemes
8
+ * are always dropped. Pass `'all'` to disable host filtering.
9
+ * @default 'same-hostname'
10
+ */
11
+ enqueueStrategy?: EnqueueStrategy | `${EnqueueStrategy}`;
12
+ }
2
13
  /**
3
14
  * Loads and queries information from a [robots.txt file](https://en.wikipedia.org/wiki/Robots.txt).
4
15
  *
@@ -18,15 +29,23 @@ import { Sitemap } from './sitemap.js';
18
29
  * ```
19
30
  */
20
31
  export declare class RobotsTxtFile {
21
- private robots;
22
- private proxyUrl?;
32
+ #private;
23
33
  private constructor();
24
34
  /**
25
35
  * Determine the location of a robots.txt file for a URL and fetch it.
26
36
  * @param url the URL to fetch robots.txt for
27
- * @param [proxyUrl] a proxy to be used for fetching the robots.txt file
37
+ * @param [options] additional options
38
+ * @param [options.signal] an AbortSignal to cancel the request
39
+ * @param [options.timeoutMillis] timeout in milliseconds for the request
40
+ * @param [options.proxyUrl] a proxy to be used for fetching the robots.txt file
28
41
  */
29
- static find(url: string, proxyUrl?: string): Promise<RobotsTxtFile>;
42
+ static find(url: string, options?: {
43
+ signal?: AbortSignal;
44
+ timeoutMillis?: number;
45
+ proxyUrl?: string;
46
+ httpClient?: BaseHttpClient;
47
+ logger?: CrawleeLogger;
48
+ }): Promise<RobotsTxtFile>;
30
49
  /**
31
50
  * Allows providing the URL and robots.txt content explicitly instead of loading it from the target site.
32
51
  * @param url the URL for robots.txt file
@@ -34,7 +53,12 @@ export declare class RobotsTxtFile {
34
53
  * @param [proxyUrl] a proxy to be used for fetching the robots.txt file
35
54
  */
36
55
  static from(url: string, content: string, proxyUrl?: string): RobotsTxtFile;
37
- protected static load(url: string, proxyUrl?: string): Promise<RobotsTxtFile>;
56
+ private static load;
57
+ /**
58
+ * Get crawl delay for a given user agent.
59
+ * @param [userAgent] relevant user agent, default to `*`
60
+ */
61
+ getCrawlDelay(userAgent?: string): number | undefined;
38
62
  /**
39
63
  * Check if a URL should be crawled by robots.
40
64
  * @param url the URL to check against the rules in robots.txt
@@ -42,17 +66,19 @@ export declare class RobotsTxtFile {
42
66
  */
43
67
  isAllowed(url: string, userAgent?: string): boolean;
44
68
  /**
45
- * Get URLs of sitemaps referenced in the robots file.
69
+ * Get URLs of sitemaps referenced in the robots file, filtered by `options.enqueueStrategy` relative to
70
+ * the robots.txt host (default `'same-hostname'`; pass `'all'` to disable). Non-`http(s)` schemes are
71
+ * always dropped.
46
72
  */
47
- getSitemaps(): string[];
73
+ getSitemaps(options?: RobotsTxtFileSitemapsOptions): string[];
48
74
  /**
49
- * Parse all the sitemaps referenced in the robots file.
75
+ * Parse all the sitemaps referenced in the robots file. `options` are forwarded to `getSitemaps`
76
+ * and the sitemap parser.
50
77
  */
51
- parseSitemaps(): Promise<Sitemap>;
78
+ parseSitemaps(options?: RobotsTxtFileSitemapsOptions): Promise<Sitemap>;
52
79
  /**
53
80
  * Get all URLs from all the sitemaps referenced in the robots file. A shorthand for `(await robots.parseSitemaps()).urls`.
81
+ * `options` are forwarded to `parseSitemaps`.
54
82
  */
55
- parseUrlsFromSitemaps(): Promise<string[]>;
83
+ parseUrlsFromSitemaps(options?: RobotsTxtFileSitemapsOptions): Promise<string[]>;
56
84
  }
57
- export { RobotsTxtFile as RobotsFile };
58
- //# sourceMappingURL=robots.d.ts.map
@@ -1,7 +1,7 @@
1
- import { gotScraping } from 'got-scraping';
1
+ import { FetchHttpClient } from '@crawlee/http-client';
2
2
  import robotsParser from 'robots-parser';
3
3
  import { Sitemap } from './sitemap.js';
4
- let HTTPError;
4
+ import { filterUrl } from './url.js';
5
5
  /**
6
6
  * Loads and queries information from a [robots.txt file](https://en.wikipedia.org/wiki/Robots.txt).
7
7
  *
@@ -21,22 +21,29 @@ let HTTPError;
21
21
  * ```
22
22
  */
23
23
  export class RobotsTxtFile {
24
- robots;
25
- proxyUrl;
26
- constructor(robots, proxyUrl) {
27
- this.robots = robots;
28
- this.proxyUrl = proxyUrl;
24
+ #url;
25
+ #robots;
26
+ #proxyUrl;
27
+ #logger;
28
+ constructor(url, robots, proxyUrl, logger) {
29
+ this.#url = url;
30
+ this.#robots = robots;
31
+ this.#proxyUrl = proxyUrl;
32
+ this.#logger = logger;
29
33
  }
30
34
  /**
31
35
  * Determine the location of a robots.txt file for a URL and fetch it.
32
36
  * @param url the URL to fetch robots.txt for
33
- * @param [proxyUrl] a proxy to be used for fetching the robots.txt file
37
+ * @param [options] additional options
38
+ * @param [options.signal] an AbortSignal to cancel the request
39
+ * @param [options.timeoutMillis] timeout in milliseconds for the request
40
+ * @param [options.proxyUrl] a proxy to be used for fetching the robots.txt file
34
41
  */
35
- static async find(url, proxyUrl) {
42
+ static async find(url, options) {
36
43
  const robotsTxtFileUrl = new URL(url);
37
44
  robotsTxtFileUrl.pathname = '/robots.txt';
38
45
  robotsTxtFileUrl.search = '';
39
- return RobotsTxtFile.load(robotsTxtFileUrl.toString(), proxyUrl);
46
+ return RobotsTxtFile.load(robotsTxtFileUrl.toString(), options);
40
47
  }
41
48
  /**
42
49
  * Allows providing the URL and robots.txt content explicitly instead of loading it from the target site.
@@ -46,35 +53,40 @@ export class RobotsTxtFile {
46
53
  */
47
54
  static from(url, content, proxyUrl) {
48
55
  // @ts-ignore
49
- return new RobotsTxtFile(robotsParser(url, content), proxyUrl);
56
+ return new RobotsTxtFile(url, robotsParser(url, content), proxyUrl);
50
57
  }
51
- static async load(url, proxyUrl) {
52
- if (!HTTPError) {
53
- HTTPError = (await import('got-scraping')).HTTPError;
54
- }
55
- try {
56
- const response = await gotScraping({
57
- url,
58
- proxyUrl,
59
- method: 'GET',
60
- responseType: 'text',
61
- });
62
- // @ts-ignore
63
- return new RobotsTxtFile(robotsParser(url.toString(), response.body), proxyUrl);
58
+ static async load(url, options) {
59
+ const { proxyUrl, logger, httpClient = new FetchHttpClient() } = options || {};
60
+ const response = await httpClient.sendRequest(new Request(url, { method: 'GET' }), {
61
+ proxyUrl,
62
+ timeoutMillis: options?.timeoutMillis,
63
+ signal: options?.signal,
64
+ });
65
+ if (response.status < 200 || response.status >= 300) {
66
+ throw new Error(`Failed to load robots.txt from ${url}: HTTP ${response.status}`);
64
67
  }
65
- catch (e) {
66
- if (e instanceof HTTPError && e.response.statusCode === 404) {
67
- return new RobotsTxtFile({
68
- isAllowed() {
69
- return true;
70
- },
71
- getSitemaps() {
72
- return [];
73
- },
74
- }, proxyUrl);
75
- }
76
- throw e;
68
+ if (response.status === 404) {
69
+ return new RobotsTxtFile(url, {
70
+ isAllowed() {
71
+ return true;
72
+ },
73
+ getSitemaps() {
74
+ return [];
75
+ },
76
+ getCrawlDelay() {
77
+ return undefined;
78
+ },
79
+ }, proxyUrl, logger);
77
80
  }
81
+ // @ts-ignore
82
+ return new RobotsTxtFile(url, robotsParser(url.toString(), await response.text()), proxyUrl, logger);
83
+ }
84
+ /**
85
+ * Get crawl delay for a given user agent.
86
+ * @param [userAgent] relevant user agent, default to `*`
87
+ */
88
+ getCrawlDelay(userAgent = '*') {
89
+ return this.#robots.getCrawlDelay(userAgent);
78
90
  }
79
91
  /**
80
92
  * Check if a URL should be crawled by robots.
@@ -82,27 +94,39 @@ export class RobotsTxtFile {
82
94
  * @param [userAgent] relevant user agent, default to `*`
83
95
  */
84
96
  isAllowed(url, userAgent = '*') {
85
- return this.robots.isAllowed(url, userAgent) ?? true; // `undefined` means that there is no explicit rule for the requested URL - assume it's allowed
97
+ return this.#robots.isAllowed(url, userAgent) ?? true; // `undefined` means that there is no explicit rule for the requested URL - assume it's allowed
86
98
  }
87
99
  /**
88
- * Get URLs of sitemaps referenced in the robots file.
100
+ * Get URLs of sitemaps referenced in the robots file, filtered by `options.enqueueStrategy` relative to
101
+ * the robots.txt host (default `'same-hostname'`; pass `'all'` to disable). Non-`http(s)` schemes are
102
+ * always dropped.
89
103
  */
90
- getSitemaps() {
91
- return this.robots.getSitemaps();
104
+ getSitemaps(options = {}) {
105
+ const { enqueueStrategy = 'same-hostname' } = options;
106
+ const sitemaps = [];
107
+ for (const sitemapUrl of this.#robots.getSitemaps()) {
108
+ // `filterUrl` tolerates an unparseable origin (returns not-allowed) rather than throwing.
109
+ const { allowed, reason } = filterUrl(sitemapUrl, this.#url, enqueueStrategy);
110
+ if (!allowed) {
111
+ this.#logger?.warning(`Skipping sitemap ${sitemapUrl} listed in robots.txt at ${this.#url}: ${reason}.`);
112
+ continue;
113
+ }
114
+ sitemaps.push(sitemapUrl);
115
+ }
116
+ return sitemaps;
92
117
  }
93
118
  /**
94
- * Parse all the sitemaps referenced in the robots file.
119
+ * Parse all the sitemaps referenced in the robots file. `options` are forwarded to `getSitemaps`
120
+ * and the sitemap parser.
95
121
  */
96
- async parseSitemaps() {
97
- return Sitemap.load(this.robots.getSitemaps(), this.proxyUrl);
122
+ async parseSitemaps(options = {}) {
123
+ return Sitemap.load(this.getSitemaps(options), this.#proxyUrl, { ...options, logger: this.#logger });
98
124
  }
99
125
  /**
100
126
  * Get all URLs from all the sitemaps referenced in the robots file. A shorthand for `(await robots.parseSitemaps()).urls`.
127
+ * `options` are forwarded to `parseSitemaps`.
101
128
  */
102
- async parseUrlsFromSitemaps() {
103
- return (await this.parseSitemaps()).urls;
129
+ async parseUrlsFromSitemaps(options = {}) {
130
+ return (await this.parseSitemaps(options)).urls;
104
131
  }
105
132
  }
106
- // to stay backwards compatible
107
- export { RobotsTxtFile as RobotsFile };
108
- //# sourceMappingURL=robots.js.map
@@ -0,0 +1,114 @@
1
+ import { BaseHttpClient } from '@crawlee/http-client';
2
+ import type { Dictionary } from '@crawlee/types';
3
+ import { z } from 'zod';
4
+ /**
5
+ * Accepts any object (including arrays and functions).
6
+ * @internal
7
+ */
8
+ export declare const anyObject: z.ZodCustom<Dictionary, Dictionary>;
9
+ /**
10
+ * Accepts any array without validating its items (cheap for huge arrays).
11
+ * @internal
12
+ */
13
+ export declare const anyArray: z.ZodCustom<unknown[], unknown[]>;
14
+ /**
15
+ * Accepts any function.
16
+ * @internal
17
+ */
18
+ export declare const anyFunction: z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>;
19
+ /**
20
+ * Mirrors `ow.number`: `Infinity` is a valid number, `NaN` is not.
21
+ * @internal
22
+ */
23
+ export declare const anyNumber: z.ZodCustom<number, number>;
24
+ /**
25
+ * Accepts any object (including functions) that has all the given keys, own or inherited.
26
+ * @internal
27
+ */
28
+ export declare function objectWithKeys(keys: string[], message?: string): z.ZodType<Dictionary>;
29
+ /**
30
+ * Accepts only instances of {@link BaseHttpClient} (all Crawlee HTTP clients extend it).
31
+ * @internal
32
+ */
33
+ export declare const httpClient: z.ZodCustom<BaseHttpClient, BaseHttpClient>;
34
+ /**
35
+ * Accepts any object implementing the CrawleeLogger interface.
36
+ * @internal
37
+ */
38
+ export declare const logger: z.ZodType<Dictionary, unknown, z.core.$ZodTypeInternals<Dictionary, unknown>>;
39
+ /**
40
+ * Accepts any typed array (`Uint8Array`, `Float64Array`, ...), but not a `DataView`.
41
+ * @internal
42
+ */
43
+ export declare const typedArray: z.ZodCustom<NodeJS.TypedArray<ArrayBufferLike>, NodeJS.TypedArray<ArrayBufferLike>>;
44
+ /**
45
+ * Accepts any non-null, non-array object.
46
+ * @internal
47
+ */
48
+ export declare const plainObject: z.ZodCustom<Record<string, unknown>, Record<string, unknown>>;
49
+ /**
50
+ * Shape of a request stored in a request queue.
51
+ * @internal
52
+ */
53
+ export declare const storageRequest: z.ZodObject<{
54
+ id: z.ZodString;
55
+ url: z.ZodURL;
56
+ uniqueKey: z.ZodString;
57
+ method: z.ZodOptional<z.ZodString>;
58
+ retryCount: z.ZodOptional<z.ZodNumber>;
59
+ handledAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
60
+ }, z.core.$loose>;
61
+ /**
62
+ * {@link storageRequest} before an id is assigned.
63
+ * @internal
64
+ */
65
+ export declare const storageRequestWithoutId: z.ZodObject<{
66
+ url: z.ZodURL;
67
+ uniqueKey: z.ZodString;
68
+ method: z.ZodOptional<z.ZodString>;
69
+ retryCount: z.ZodOptional<z.ZodNumber>;
70
+ handledAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
71
+ }, z.core.$loose>;
72
+ /**
73
+ * `z.array(item)` whose top-level type error names the element type — ``expected an array of numbers`` —
74
+ * instead of zod's bare `expected array`. Element failures keep zod's per-index messages, and `elements`
75
+ * is a human-readable plural (`'numbers'`, `'URL patterns'`), since element types cannot be introspected.
76
+ * @internal
77
+ */
78
+ export declare function arrayOf<TItem extends z.ZodType>(item: TItem, elements: string): z.ZodArray<TItem>;
79
+ /**
80
+ * Batch of {@link storageRequestWithoutId}.
81
+ * @internal
82
+ */
83
+ export declare const storageRequestBatch: z.ZodArray<z.ZodObject<{
84
+ url: z.ZodURL;
85
+ uniqueKey: z.ZodString;
86
+ method: z.ZodOptional<z.ZodString>;
87
+ retryCount: z.ZodOptional<z.ZodNumber>;
88
+ handledAt: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodDate]>>;
89
+ }, z.core.$loose>>;
90
+ /**
91
+ * Options of request queue add/update operations.
92
+ * @internal
93
+ */
94
+ export declare const requestQueueOperationOptions: z.ZodObject<{
95
+ forefront: z.ZodOptional<z.ZodBoolean>;
96
+ }, z.core.$strip>;
97
+ /**
98
+ * Options of key-value store `listKeys`.
99
+ * @internal
100
+ */
101
+ export declare const keyValueStoreListKeysOptions: z.ZodObject<{
102
+ prefix: z.ZodOptional<z.ZodString>;
103
+ exclusiveStartKey: z.ZodOptional<z.ZodString>;
104
+ limit: z.ZodOptional<z.ZodNumber>;
105
+ }, z.core.$strip>;
106
+ /**
107
+ * Options of dataset item listing.
108
+ * @internal
109
+ */
110
+ export declare const datasetListItemsOptions: z.ZodObject<{
111
+ desc: z.ZodOptional<z.ZodBoolean>;
112
+ limit: z.ZodOptional<z.ZodNumber>;
113
+ offset: z.ZodOptional<z.ZodNumber>;
114
+ }, z.core.$strip>;
@@ -0,0 +1,114 @@
1
+ import { BaseHttpClient } from '@crawlee/http-client';
2
+ import { z } from 'zod';
3
+ /**
4
+ * Accepts any object (including arrays and functions).
5
+ * @internal
6
+ */
7
+ export const anyObject = z.custom((value) => (typeof value === 'object' && value !== null) || typeof value === 'function', { message: 'Invalid input: expected object' });
8
+ /**
9
+ * Accepts any array without validating its items (cheap for huge arrays).
10
+ * @internal
11
+ */
12
+ export const anyArray = z.custom(Array.isArray, { message: 'Invalid input: expected array' });
13
+ /**
14
+ * Accepts any function.
15
+ * @internal
16
+ */
17
+ export const anyFunction = z.custom((value) => typeof value === 'function', {
18
+ message: 'Invalid input: expected function',
19
+ });
20
+ /**
21
+ * Mirrors `ow.number`: `Infinity` is a valid number, `NaN` is not.
22
+ * @internal
23
+ */
24
+ export const anyNumber = z.custom((value) => typeof value === 'number' && !Number.isNaN(value), {
25
+ message: 'Invalid input: expected number',
26
+ });
27
+ /**
28
+ * Accepts any object (including functions) that has all the given keys, own or inherited.
29
+ * @internal
30
+ */
31
+ export function objectWithKeys(keys, message) {
32
+ return z.custom((value) => ((typeof value === 'object' && value !== null) || typeof value === 'function') &&
33
+ keys.every((key) => key in value), {
34
+ message: message ?? `Invalid input: expected an object with keys ${keys.map((key) => `'${key}'`).join(', ')}`,
35
+ });
36
+ }
37
+ /**
38
+ * Accepts only instances of {@link BaseHttpClient} (all Crawlee HTTP clients extend it).
39
+ * @internal
40
+ */
41
+ export const httpClient = z.instanceof(BaseHttpClient);
42
+ /**
43
+ * Accepts any object implementing the CrawleeLogger interface.
44
+ * @internal
45
+ */
46
+ export const logger = objectWithKeys(['child', 'info', 'error', 'warning'], "Expected an object implementing the CrawleeLogger interface (missing one of 'child', 'info', 'error', 'warning'), got something else.");
47
+ /**
48
+ * Accepts any typed array (`Uint8Array`, `Float64Array`, ...), but not a `DataView`.
49
+ * @internal
50
+ */
51
+ export const typedArray = z.custom((value) => ArrayBuffer.isView(value) && !(value instanceof DataView), { message: 'Invalid input: expected a typed array' });
52
+ /**
53
+ * Accepts any non-null, non-array object.
54
+ * @internal
55
+ */
56
+ export const plainObject = z.custom((value) => typeof value === 'object' && value !== null && !Array.isArray(value), { message: 'Invalid input: expected an object' });
57
+ /**
58
+ * Shape of a request stored in a request queue.
59
+ * @internal
60
+ */
61
+ export const storageRequest = z.looseObject({
62
+ id: z.string(),
63
+ url: z.url({ protocol: /^https?$/ }),
64
+ uniqueKey: z.string(),
65
+ method: z.string().optional(),
66
+ retryCount: z.number().int().optional(),
67
+ handledAt: z.union([z.string(), z.date()]).optional(),
68
+ });
69
+ /**
70
+ * {@link storageRequest} before an id is assigned.
71
+ * @internal
72
+ */
73
+ export const storageRequestWithoutId = storageRequest.omit({ id: true });
74
+ /**
75
+ * `z.array(item)` whose top-level type error names the element type — ``expected an array of numbers`` —
76
+ * instead of zod's bare `expected array`. Element failures keep zod's per-index messages, and `elements`
77
+ * is a human-readable plural (`'numbers'`, `'URL patterns'`), since element types cannot be introspected.
78
+ * @internal
79
+ */
80
+ export function arrayOf(item, elements) {
81
+ return z.array(item, {
82
+ error: (issue) => issue.code === 'invalid_type' ? `Invalid input: expected an array of ${elements}` : undefined,
83
+ });
84
+ }
85
+ /**
86
+ * Batch of {@link storageRequestWithoutId}.
87
+ * @internal
88
+ */
89
+ export const storageRequestBatch = arrayOf(storageRequestWithoutId, 'requests');
90
+ /**
91
+ * Options of request queue add/update operations.
92
+ * @internal
93
+ */
94
+ export const requestQueueOperationOptions = z.object({
95
+ forefront: z.boolean().optional(),
96
+ });
97
+ /**
98
+ * Options of key-value store `listKeys`.
99
+ * @internal
100
+ */
101
+ export const keyValueStoreListKeysOptions = z.object({
102
+ prefix: z.string().optional(),
103
+ exclusiveStartKey: z.string().optional(),
104
+ limit: z.number().int().gt(0).optional(),
105
+ });
106
+ /**
107
+ * Options of dataset item listing.
108
+ * @internal
109
+ */
110
+ export const datasetListItemsOptions = z.object({
111
+ desc: z.boolean().optional(),
112
+ limit: z.number().int().optional(),
113
+ offset: z.number().int().optional(),
114
+ });
@@ -1,5 +1,6 @@
1
- // @ts-ignore optional peer dependency or compatibility with es2022
2
- import type { Delays } from 'got-scraping';
1
+ import type { BaseHttpClient } from '@crawlee/http-client';
2
+ import type { CrawleeLogger } from '@crawlee/types';
3
+ import { type EnqueueStrategy } from './url.js';
3
4
  interface SitemapUrlData {
4
5
  loc: string;
5
6
  lastmod?: Date;
@@ -36,9 +37,36 @@ export interface ParseSitemapOptions {
36
37
  */
37
38
  sitemapRetries?: number;
38
39
  /**
39
- * Network timeouts for sitemap fetching. See [Got documentation](https://github.com/sindresorhus/got/blob/main/documentation/6-timeout.md) for more details.
40
+ * Timeout settings for network requests when fetching sitemaps. By default this is `30000` milliseconds (30 seconds).
40
41
  */
41
- networkTimeouts?: Delays;
42
+ timeoutMillis?: number;
43
+ /**
44
+ * If true, the parser will log a warning if it fails to fetch a sitemap due to a network error
45
+ * @default true
46
+ */
47
+ reportNetworkErrors?: boolean;
48
+ /**
49
+ * Custom HTTP client to be used for fetching sitemaps.
50
+ */
51
+ httpClient?: BaseHttpClient;
52
+ /**
53
+ * Optional filter for nested sitemap URLs discovered in sitemap index files.
54
+ * Called with the URL of each child sitemap before it is fetched.
55
+ * Return `true` to include the sitemap, `false` to skip it.
56
+ * If not provided, all nested sitemaps are followed.
57
+ */
58
+ nestedSitemapFilter?: (sitemapUrl: string) => boolean;
59
+ /**
60
+ * Keep only sitemap-derived URLs (nested `<sitemap>` and `<url>` entries) matching this strategy
61
+ * relative to the parent sitemap URL; non-`http(s)` schemes are always dropped. Skipped for raw string
62
+ * sources (no parent URL). Pass `'all'` to disable host filtering.
63
+ * @default 'same-hostname'
64
+ */
65
+ enqueueStrategy?: EnqueueStrategy | `${EnqueueStrategy}`;
66
+ /**
67
+ * Optional logger for reporting warnings during sitemap parsing.
68
+ */
69
+ logger?: CrawleeLogger;
42
70
  }
43
71
  export declare function parseSitemap<T extends ParseSitemapOptions>(initialSources: SitemapSource[], proxyUrl?: string, options?: T): AsyncIterable<T['emitNestedSitemaps'] extends true ? SitemapUrl | NestedSitemap : SitemapUrl>;
44
72
  /**
@@ -62,7 +90,7 @@ export declare class Sitemap {
62
90
  * @param url The domain URL to fetch the sitemap for.
63
91
  * @param proxyUrl A proxy to be used for fetching the sitemap file.
64
92
  */
65
- static tryCommonNames(url: string, proxyUrl?: string): Promise<Sitemap>;
93
+ static tryCommonNames(url: string, proxyUrl?: string, parseSitemapOptions?: ParseSitemapOptions): Promise<Sitemap>;
66
94
  /**
67
95
  * Fetch sitemap content from given URL or URLs and return URLs of referenced pages.
68
96
  * @param urls sitemap URL(s)
@@ -74,8 +102,46 @@ export declare class Sitemap {
74
102
  * @param content XML sitemap content
75
103
  * @param proxyUrl URL of a proxy to be used for fetching sitemap contents
76
104
  */
77
- static fromXmlString(content: string, proxyUrl?: string): Promise<Sitemap>;
78
- protected static parse(sources: SitemapSource[], proxyUrl?: string, parseSitemapOptions?: ParseSitemapOptions): Promise<Sitemap>;
105
+ static fromXmlString(content: string, proxyUrl?: string, parseSitemapOptions?: ParseSitemapOptions): Promise<Sitemap>;
106
+ private static parse;
79
107
  }
108
+ /**
109
+ * Given a list of URLs, discover related sitemap files for these domains by checking the `robots.txt` file,
110
+ * the default `sitemap.xml` & `sitemap.txt` files and the URLs themselves.
111
+ * @param `urls` The list of URLs to discover sitemaps for.
112
+ * @param `options` Options for sitemap discovery
113
+ * @returns An async iterable with the discovered sitemap URLs.
114
+ */
115
+ export declare function discoverValidSitemaps(urls: string[], options?: {
116
+ /**
117
+ * Proxy URL to be used for network requests.
118
+ */
119
+ proxyUrl?: string;
120
+ /**
121
+ * Timeout in milliseconds for the entire `discoverValidSitemaps` call.
122
+ * An `AbortController` is created internally and its signal is passed to every HTTP request,
123
+ * so the whole discovery operation is cancelled once the timeout elapses.
124
+ * Defaults to `60_000` ms (60 seconds) to prevent indefinite hangs.
125
+ */
126
+ timeoutMillis?: number;
127
+ /**
128
+ * An external `AbortSignal` to cancel the entire discovery operation.
129
+ * If both `signal` and `timeout` are provided, the operation is cancelled
130
+ * when either the signal is aborted or the timeout elapses (whichever comes first).
131
+ */
132
+ signal?: AbortSignal;
133
+ /**
134
+ * Timeout in milliseconds for each individual HTTP request during discovery.
135
+ * Defaults to `20000` ms (20 seconds).
136
+ */
137
+ requestTimeoutMillis?: number;
138
+ /**
139
+ * HTTP client to be used for network requests.
140
+ */
141
+ httpClient?: BaseHttpClient;
142
+ /**
143
+ * Optional logger for reporting warnings during sitemap discovery.
144
+ */
145
+ logger?: CrawleeLogger;
146
+ }): AsyncIterable<string>;
80
147
  export {};
81
- //# sourceMappingURL=sitemap.d.ts.map