@crawlee/puppeteer 4.0.0-beta.121 → 4.0.0-beta.122

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.
@@ -1,9 +1,25 @@
1
1
  import { URL } from 'node:url';
2
- import { applyRequestTransform, constructUrlPatternObjects, createRequestOptions, filterRequestOptionsByPatterns, Request, serviceLocator, } from '@crawlee/browser';
3
- import ow from 'ow';
2
+ import { applyRequestTransform, constructUrlPatternObjects, createRequestOptions, filterRequestOptionsByPatterns, parseArgument, urlPatternSchema, Request, schemas, serviceLocator, } from '@crawlee/browser';
3
+ import { z } from 'zod';
4
4
  import { addInterceptRequestHandler, removeInterceptRequestHandler } from '../utils/puppeteer_request_interception.js';
5
5
  const STARTING_Z_INDEX = 2147400000;
6
6
  const getLog = () => serviceLocator.getChildLog('Puppeteer Click Elements');
7
+ const enqueueLinksByClickingElementsOptionsSchema = z.strictObject({
8
+ page: schemas.objectWithKeys(['goto', 'evaluate']),
9
+ requestManager: schemas.objectWithKeys(['fetchNextRequest', 'addRequestsBatched']),
10
+ selector: z.string(),
11
+ userData: schemas.anyObject.optional(),
12
+ clickOptions: schemas.anyObject.optional(),
13
+ include: schemas.arrayOf(urlPatternSchema, 'URL patterns').optional(),
14
+ exclude: schemas.arrayOf(urlPatternSchema, 'URL patterns').optional(),
15
+ transformRequestFunction: schemas.anyFunction.optional(),
16
+ waitForPageIdleSecs: schemas.anyNumber.default(1),
17
+ maxWaitForPageIdleSecs: schemas.anyNumber.default(5),
18
+ label: z.string().optional(),
19
+ forefront: z.boolean().optional(),
20
+ skipNavigation: z.boolean().optional(),
21
+ onSkippedRequest: schemas.anyFunction.optional(),
22
+ });
7
23
  /**
8
24
  * The function finds elements matching a specific CSS selector in a Puppeteer page,
9
25
  * clicks all those elements using a mouse move and a left mouse button click and intercepts
@@ -45,24 +61,8 @@ const getLog = () => serviceLocator.getChildLog('Puppeteer Click Elements');
45
61
  * @returns Promise that resolves to {@link BatchAddRequestsResult} object.
46
62
  */
47
63
  export async function enqueueLinksByClickingElements(options) {
48
- const urlPatternValidator = ow.any(ow.string, ow.regExp, ow.object.hasKeys('glob'), ow.object.hasKeys('regexp'));
49
- ow(options, ow.object.exactShape({
50
- page: ow.object.hasKeys('goto', 'evaluate'),
51
- requestManager: ow.object.hasKeys('fetchNextRequest', 'addRequestsBatched'),
52
- selector: ow.string,
53
- userData: ow.optional.object,
54
- clickOptions: ow.optional.object,
55
- include: ow.optional.array.ofType(urlPatternValidator),
56
- exclude: ow.optional.array.ofType(urlPatternValidator),
57
- transformRequestFunction: ow.optional.function,
58
- waitForPageIdleSecs: ow.optional.number,
59
- maxWaitForPageIdleSecs: ow.optional.number,
60
- label: ow.optional.string,
61
- forefront: ow.optional.boolean,
62
- skipNavigation: ow.optional.boolean,
63
- onSkippedRequest: ow.optional.function,
64
- }));
65
- const { page, requestManager, selector, clickOptions, include, exclude, transformRequestFunction, waitForPageIdleSecs = 1, maxWaitForPageIdleSecs = 5, forefront, onSkippedRequest, } = options;
64
+ const parsedOptions = parseArgument(options, enqueueLinksByClickingElementsOptionsSchema, 'EnqueueLinksByClickingElementsOptions');
65
+ const { page, requestManager, selector, clickOptions, include, exclude, transformRequestFunction, waitForPageIdleSecs, maxWaitForPageIdleSecs, forefront, onSkippedRequest, } = parsedOptions;
66
66
  const waitForPageIdleMillis = waitForPageIdleSecs * 1000;
67
67
  const maxWaitForPageIdleMillis = maxWaitForPageIdleSecs * 1000;
68
68
  const urlExcludePatternObjects = exclude?.length ? constructUrlPatternObjects(exclude) : [];
@@ -74,7 +74,7 @@ export async function enqueueLinksByClickingElements(options) {
74
74
  maxWaitForPageIdleMillis,
75
75
  clickOptions,
76
76
  });
77
- const requestOptions = createRequestOptions(interceptedRequests, options);
77
+ const requestOptions = createRequestOptions(interceptedRequests, parsedOptions);
78
78
  const skippedByFilters = [];
79
79
  let filteredOptions = filterRequestOptionsByPatterns(requestOptions, urlPatternObjects.length > 0 ? urlPatternObjects : undefined, urlExcludePatternObjects, undefined, (url) => skippedByFilters.push(url));
80
80
  if (onSkippedRequest && skippedByFilters.length > 0) {
@@ -4,6 +4,7 @@ import type { PuppeteerPlugin } from '@crawlee/browser-pool';
4
4
  import type { Dictionary } from '@crawlee/types';
5
5
  // @ts-ignore optional peer dependency or compatibility with es2022
6
6
  import type { HTTPResponse, LaunchOptions, Page } from 'puppeteer';
7
+ import { z } from 'zod';
7
8
  import type { EnqueueLinksByClickingElementsOptions } from './enqueue-links/click-elements.js';
8
9
  import type { PuppeteerLaunchContext } from './puppeteer-launcher.js';
9
10
  import type { InterceptHandler } from './utils/puppeteer_request_interception.js';
@@ -123,99 +124,121 @@ export declare class PuppeteerCrawler<ContextExtension = Dictionary<never>, Exte
123
124
  browserPlugins: [PuppeteerPlugin];
124
125
  }, LaunchOptions, PuppeteerCrawlingContext, ContextExtension, ExtendedContext, Routes> {
125
126
  protected static optionsShape: {
126
- // @ts-ignore optional peer dependency or compatibility with es2022
127
- browserPoolOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
128
- // @ts-ignore optional peer dependency or compatibility with es2022
129
- navigationTimeoutSecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
130
- // @ts-ignore optional peer dependency or compatibility with es2022
131
- preNavigationHooks: import("ow").ArrayPredicate<unknown> & import("ow").BasePredicate<unknown[] | undefined>;
132
- // @ts-ignore optional peer dependency or compatibility with es2022
133
- postNavigationHooks: import("ow").ArrayPredicate<unknown> & import("ow").BasePredicate<unknown[] | undefined>;
134
- // @ts-ignore optional peer dependency or compatibility with es2022
135
- launchContext: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
136
- // @ts-ignore optional peer dependency or compatibility with es2022
137
- headless: import("ow").AnyPredicate<string | boolean>;
138
- // @ts-ignore optional peer dependency or compatibility with es2022
139
- browserPool: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
140
- // @ts-ignore optional peer dependency or compatibility with es2022
141
- remoteBrowser: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
142
- // @ts-ignore optional peer dependency or compatibility with es2022
143
- saveResponseCookies: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
144
- // @ts-ignore optional peer dependency or compatibility with es2022
145
- proxyConfiguration: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
146
- // @ts-ignore optional peer dependency or compatibility with es2022
147
- contextPipelineBuilder: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
148
- // @ts-ignore optional peer dependency or compatibility with es2022
149
- extendContext: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
150
- // @ts-ignore optional peer dependency or compatibility with es2022
151
- requestList: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
152
- // @ts-ignore optional peer dependency or compatibility with es2022
153
- requestQueue: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
154
- // @ts-ignore optional peer dependency or compatibility with es2022
155
- requestManager: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
156
- // @ts-ignore optional peer dependency or compatibility with es2022
157
- requestHandler: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
158
- // @ts-ignore optional peer dependency or compatibility with es2022
159
- requestHandlerTimeoutSecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
160
- // @ts-ignore optional peer dependency or compatibility with es2022
161
- errorHandler: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
162
- // @ts-ignore optional peer dependency or compatibility with es2022
163
- failedRequestHandler: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
164
- // @ts-ignore optional peer dependency or compatibility with es2022
165
- maxRequestRetries: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
166
- // @ts-ignore optional peer dependency or compatibility with es2022
167
- sameDomainDelaySecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
168
- // @ts-ignore optional peer dependency or compatibility with es2022
169
- maxRequestsPerCrawl: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
170
- // @ts-ignore optional peer dependency or compatibility with es2022
171
- maxCrawlDepth: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
172
- // @ts-ignore optional peer dependency or compatibility with es2022
173
- taskLoopOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
174
- // @ts-ignore optional peer dependency or compatibility with es2022
175
- concurrencySystem: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
176
- // @ts-ignore optional peer dependency or compatibility with es2022
177
- sessionPool: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
178
- // @ts-ignore optional peer dependency or compatibility with es2022
179
- statusMessageLoggingInterval: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
180
- // @ts-ignore optional peer dependency or compatibility with es2022
181
- statusMessageCallback: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
182
- // @ts-ignore optional peer dependency or compatibility with es2022
183
- additionalHttpErrorStatusCodes: import("ow").ArrayPredicate<number>;
184
- // @ts-ignore optional peer dependency or compatibility with es2022
185
- ignoreHttpErrorStatusCodes: import("ow").ArrayPredicate<number>;
186
- // @ts-ignore optional peer dependency or compatibility with es2022
187
- blockedStatusCodes: import("ow").ArrayPredicate<number>;
188
- // @ts-ignore optional peer dependency or compatibility with es2022
189
- retryOnBlocked: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
190
- // @ts-ignore optional peer dependency or compatibility with es2022
191
- respectRobotsTxtFile: import("ow").AnyPredicate<boolean | object>;
192
- // @ts-ignore optional peer dependency or compatibility with es2022
193
- transactionalStorage: import("ow").BasePredicate<boolean | Partial<import("@crawlee/browser").StorageWritePolicy> | undefined>;
194
- // @ts-ignore optional peer dependency or compatibility with es2022
195
- onSkippedRequest: import("ow").Predicate<Function> & import("ow").BasePredicate<Function | undefined>;
196
- // @ts-ignore optional peer dependency or compatibility with es2022
197
- httpClient: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
198
- // @ts-ignore optional peer dependency or compatibility with es2022
199
- configuration: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
200
- // @ts-ignore optional peer dependency or compatibility with es2022
201
- storageBackend: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
202
- // @ts-ignore optional peer dependency or compatibility with es2022
203
- eventManager: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
204
- // @ts-ignore optional peer dependency or compatibility with es2022
205
- logger: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
206
- // @ts-ignore optional peer dependency or compatibility with es2022
207
- minConcurrency: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
208
- // @ts-ignore optional peer dependency or compatibility with es2022
209
- maxConcurrency: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
210
- // @ts-ignore optional peer dependency or compatibility with es2022
211
- maxRequestsPerMinute: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
212
- // @ts-ignore optional peer dependency or compatibility with es2022
213
- keepAlive: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
214
- // @ts-ignore optional peer dependency or compatibility with es2022
215
- statistics: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
216
- // @ts-ignore optional peer dependency or compatibility with es2022
217
- id: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
127
+ browserPoolOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
128
+ navigationTimeoutSecs: z.ZodDefault<z.ZodCustom<number, number>>;
129
+ preNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
130
+ postNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
131
+ launchContext: z.ZodDefault<z.ZodCustom<Dictionary, Dictionary>>;
132
+ headless: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>;
133
+ browserPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
134
+ remoteBrowser: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
135
+ saveResponseCookies: z.ZodDefault<z.ZodBoolean>;
136
+ proxyConfiguration: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
137
+ ignoreIframes: z.ZodDefault<z.ZodBoolean>;
138
+ ignoreShadowRoots: z.ZodDefault<z.ZodBoolean>;
139
+ contextPipelineBuilder: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
140
+ extendContext: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
141
+ requestList: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
142
+ requestQueue: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
143
+ requestManager: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
144
+ requestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
145
+ requestHandlerTimeoutSecs: z.ZodOptional<z.ZodCustom<number, number>>;
146
+ errorHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
147
+ failedRequestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
148
+ maxRequestRetries: z.ZodDefault<z.ZodCustom<number, number>>;
149
+ sameDomainDelaySecs: z.ZodDefault<z.ZodCustom<number, number>>;
150
+ maxRequestsPerCrawl: z.ZodOptional<z.ZodCustom<number, number>>;
151
+ maxCrawlDepth: z.ZodOptional<z.ZodCustom<number, number>>;
152
+ taskLoopOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
153
+ concurrencySystem: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
154
+ sessionPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
155
+ statusMessageLoggingInterval: z.ZodDefault<z.ZodCustom<number, number>>;
156
+ statusMessageCallback: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
157
+ additionalHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
158
+ ignoreHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
159
+ blockedStatusCodes: z.ZodOptional<z.ZodArray<z.ZodCustom<number, number>>>;
160
+ retryOnBlocked: z.ZodDefault<z.ZodBoolean>;
161
+ respectRobotsTxtFile: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCustom<Dictionary, Dictionary>]>>;
162
+ transactionalStorage: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
163
+ requestQueue: z.ZodOptional<z.ZodEnum<{
164
+ deferred: "deferred";
165
+ writeThrough: "writeThrough";
166
+ }>>;
167
+ }, z.core.$strict>]>>;
168
+ onSkippedRequest: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
169
+ // @ts-ignore optional peer dependency or compatibility with es2022
170
+ httpClient: z.ZodOptional<z.ZodCustom<import("@crawlee/http-client").BaseHttpClient, import("@crawlee/http-client").BaseHttpClient>>;
171
+ // @ts-ignore optional peer dependency or compatibility with es2022
172
+ configuration: z.ZodOptional<z.ZodCustom<import("@crawlee/browser").Configuration, import("@crawlee/browser").Configuration>>;
173
+ storageBackend: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
174
+ // @ts-ignore optional peer dependency or compatibility with es2022
175
+ eventManager: z.ZodOptional<z.ZodCustom<import("@crawlee/browser").EventManager, import("@crawlee/browser").EventManager>>;
176
+ logger: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
177
+ minConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
178
+ maxConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
179
+ maxRequestsPerMinute: z.ZodOptional<z.ZodCustom<number, number>>;
180
+ keepAlive: z.ZodOptional<z.ZodBoolean>;
181
+ statistics: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
182
+ id: z.ZodOptional<z.ZodString>;
218
183
  };
184
+ protected static optionsSchema: z.ZodObject<{
185
+ browserPoolOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
186
+ navigationTimeoutSecs: z.ZodDefault<z.ZodCustom<number, number>>;
187
+ preNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
188
+ postNavigationHooks: z.ZodDefault<z.ZodCustom<unknown[], unknown[]>>;
189
+ launchContext: z.ZodDefault<z.ZodCustom<Dictionary, Dictionary>>;
190
+ headless: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>;
191
+ browserPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
192
+ remoteBrowser: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
193
+ saveResponseCookies: z.ZodDefault<z.ZodBoolean>;
194
+ proxyConfiguration: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
195
+ ignoreIframes: z.ZodDefault<z.ZodBoolean>;
196
+ ignoreShadowRoots: z.ZodDefault<z.ZodBoolean>;
197
+ contextPipelineBuilder: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
198
+ extendContext: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
199
+ requestList: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
200
+ requestQueue: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
201
+ requestManager: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
202
+ requestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
203
+ requestHandlerTimeoutSecs: z.ZodOptional<z.ZodCustom<number, number>>;
204
+ errorHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
205
+ failedRequestHandler: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
206
+ maxRequestRetries: z.ZodDefault<z.ZodCustom<number, number>>;
207
+ sameDomainDelaySecs: z.ZodDefault<z.ZodCustom<number, number>>;
208
+ maxRequestsPerCrawl: z.ZodOptional<z.ZodCustom<number, number>>;
209
+ maxCrawlDepth: z.ZodOptional<z.ZodCustom<number, number>>;
210
+ taskLoopOptions: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
211
+ concurrencySystem: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
212
+ sessionPool: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
213
+ statusMessageLoggingInterval: z.ZodDefault<z.ZodCustom<number, number>>;
214
+ statusMessageCallback: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
215
+ additionalHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
216
+ ignoreHttpErrorStatusCodes: z.ZodDefault<z.ZodArray<z.ZodCustom<number, number>>>;
217
+ blockedStatusCodes: z.ZodOptional<z.ZodArray<z.ZodCustom<number, number>>>;
218
+ retryOnBlocked: z.ZodDefault<z.ZodBoolean>;
219
+ respectRobotsTxtFile: z.ZodDefault<z.ZodUnion<readonly [z.ZodBoolean, z.ZodCustom<Dictionary, Dictionary>]>>;
220
+ transactionalStorage: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
221
+ requestQueue: z.ZodOptional<z.ZodEnum<{
222
+ deferred: "deferred";
223
+ writeThrough: "writeThrough";
224
+ }>>;
225
+ }, z.core.$strict>]>>;
226
+ onSkippedRequest: z.ZodOptional<z.ZodCustom<(...args: any[]) => unknown, (...args: any[]) => unknown>>;
227
+ // @ts-ignore optional peer dependency or compatibility with es2022
228
+ httpClient: z.ZodOptional<z.ZodCustom<import("@crawlee/http-client").BaseHttpClient, import("@crawlee/http-client").BaseHttpClient>>;
229
+ // @ts-ignore optional peer dependency or compatibility with es2022
230
+ configuration: z.ZodOptional<z.ZodCustom<import("@crawlee/browser").Configuration, import("@crawlee/browser").Configuration>>;
231
+ storageBackend: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
232
+ // @ts-ignore optional peer dependency or compatibility with es2022
233
+ eventManager: z.ZodOptional<z.ZodCustom<import("@crawlee/browser").EventManager, import("@crawlee/browser").EventManager>>;
234
+ logger: z.ZodOptional<z.ZodType<Dictionary<any>, unknown, z.core.$ZodTypeInternals<Dictionary<any>, unknown>>>;
235
+ minConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
236
+ maxConcurrency: z.ZodOptional<z.ZodCustom<number, number>>;
237
+ maxRequestsPerMinute: z.ZodOptional<z.ZodCustom<number, number>>;
238
+ keepAlive: z.ZodOptional<z.ZodBoolean>;
239
+ statistics: z.ZodOptional<z.ZodCustom<Dictionary, Dictionary>>;
240
+ id: z.ZodOptional<z.ZodString>;
241
+ }, z.core.$strict>;
219
242
  /**
220
243
  * All `PuppeteerCrawler` parameters are passed via an options object.
221
244
  */
@@ -1,6 +1,6 @@
1
1
  import { BrowserCrawler, RequestState, Router } from '@crawlee/browser';
2
- import { serviceLocator } from '@crawlee/core';
3
- import ow from 'ow';
2
+ import { parseArgument, schemas, serviceLocator } from '@crawlee/core';
3
+ import { z } from 'zod';
4
4
  import { PuppeteerLauncher } from './puppeteer-launcher.js';
5
5
  import { gotoExtended, puppeteerUtils } from './utils/puppeteer_utils.js';
6
6
  /**
@@ -71,16 +71,17 @@ import { gotoExtended, puppeteerUtils } from './utils/puppeteer_utils.js';
71
71
  export class PuppeteerCrawler extends BrowserCrawler {
72
72
  static optionsShape = {
73
73
  ...BrowserCrawler.optionsShape,
74
- browserPoolOptions: ow.optional.object,
74
+ browserPoolOptions: schemas.anyObject.optional(),
75
75
  };
76
+ static optionsSchema = z.strictObject(PuppeteerCrawler.optionsShape);
76
77
  /**
77
78
  * All `PuppeteerCrawler` parameters are passed via an options object.
78
79
  */
79
80
  constructor(options = {}) {
80
- ow(options, 'PuppeteerCrawlerOptions', ow.object.exactShape(PuppeteerCrawler.optionsShape));
81
- const { launchContext = {}, headless, proxyConfiguration, contextPipelineBuilder, ...browserCrawlerOptions } = options;
81
+ const parsedOptions = parseArgument(options, PuppeteerCrawler.optionsSchema, 'PuppeteerCrawlerOptions');
82
+ const { launchContext, headless, proxyConfiguration, contextPipelineBuilder, ...browserCrawlerOptions } = parsedOptions;
82
83
  const browserPoolOptions = {
83
- ...options.browserPoolOptions,
84
+ ...parsedOptions.browserPoolOptions,
84
85
  };
85
86
  if (launchContext.proxyUrl) {
86
87
  throw new Error('PuppeteerCrawlerOptions.launchContext.proxyUrl is not allowed in PuppeteerCrawler.' +
@@ -95,7 +96,7 @@ export class PuppeteerCrawler extends BrowserCrawler {
95
96
  launchContext.launchOptions ??= {};
96
97
  launchContext.launchOptions.headless = headless;
97
98
  }
98
- const puppeteerLauncher = new PuppeteerLauncher(launchContext, options.configuration);
99
+ const puppeteerLauncher = new PuppeteerLauncher(launchContext, parsedOptions.configuration);
99
100
  browserPoolOptions.browserPlugins = [puppeteerLauncher.createBrowserPlugin()];
100
101
  super({
101
102
  ...browserCrawlerOptions,
@@ -3,6 +3,7 @@ import { BrowserLauncher, Configuration } from '@crawlee/browser';
3
3
  import { PuppeteerPlugin } from '@crawlee/browser-pool';
4
4
  // @ts-ignore optional peer dependency or compatibility with es2022
5
5
  import type { Browser } from 'puppeteer';
6
+ import { z } from 'zod';
6
7
  /**
7
8
  * Apify extends the launch options of Puppeteer.
8
9
  * You can use any of the Puppeteer compatible
@@ -69,24 +70,30 @@ export declare class PuppeteerLauncher extends BrowserLauncher<PuppeteerPlugin,
69
70
  readonly configuration: Configuration;
70
71
  protected static optionsShape: {
71
72
  // @ts-ignore optional peer dependency or compatibility with es2022
72
- launcher: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
73
+ launcher: z.ZodOptional<z.ZodCustom<import("@crawlee/types").Dictionary, import("@crawlee/types").Dictionary>>;
74
+ proxyUrl: z.ZodOptional<z.ZodURL>;
75
+ useChrome: z.ZodOptional<z.ZodBoolean>;
76
+ useIncognitoPages: z.ZodOptional<z.ZodBoolean>;
77
+ browserPerProxy: z.ZodOptional<z.ZodBoolean>;
78
+ ignoreProxyCertificate: z.ZodOptional<z.ZodBoolean>;
79
+ userDataDir: z.ZodOptional<z.ZodString>;
73
80
  // @ts-ignore optional peer dependency or compatibility with es2022
74
- proxyUrl: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
75
- // @ts-ignore optional peer dependency or compatibility with es2022
76
- useChrome: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
77
- // @ts-ignore optional peer dependency or compatibility with es2022
78
- useIncognitoPages: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
79
- // @ts-ignore optional peer dependency or compatibility with es2022
80
- browserPerProxy: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
81
- // @ts-ignore optional peer dependency or compatibility with es2022
82
- ignoreProxyCertificate: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
83
- // @ts-ignore optional peer dependency or compatibility with es2022
84
- userDataDir: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
81
+ launchOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types").Dictionary, import("@crawlee/types").Dictionary>>;
82
+ userAgent: z.ZodOptional<z.ZodString>;
83
+ };
84
+ protected static optionsSchema: z.ZodObject<{
85
85
  // @ts-ignore optional peer dependency or compatibility with es2022
86
- launchOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
86
+ launcher: z.ZodOptional<z.ZodCustom<import("@crawlee/types").Dictionary, import("@crawlee/types").Dictionary>>;
87
+ proxyUrl: z.ZodOptional<z.ZodURL>;
88
+ useChrome: z.ZodOptional<z.ZodBoolean>;
89
+ useIncognitoPages: z.ZodOptional<z.ZodBoolean>;
90
+ browserPerProxy: z.ZodOptional<z.ZodBoolean>;
91
+ ignoreProxyCertificate: z.ZodOptional<z.ZodBoolean>;
92
+ userDataDir: z.ZodOptional<z.ZodString>;
87
93
  // @ts-ignore optional peer dependency or compatibility with es2022
88
- userAgent: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
89
- };
94
+ launchOptions: z.ZodOptional<z.ZodCustom<import("@crawlee/types").Dictionary, import("@crawlee/types").Dictionary>>;
95
+ userAgent: z.ZodOptional<z.ZodString>;
96
+ }, z.core.$strict>;
90
97
  /**
91
98
  * All `PuppeteerLauncher` parameters are passed via an launchContext object.
92
99
  */
@@ -1,6 +1,6 @@
1
- import { BrowserLauncher, Configuration } from '@crawlee/browser';
1
+ import { BrowserLauncher, Configuration, parseArgument, schemas } from '@crawlee/browser';
2
2
  import { PuppeteerPlugin } from '@crawlee/browser-pool';
3
- import ow from 'ow';
3
+ import { z } from 'zod';
4
4
  /**
5
5
  * `PuppeteerLauncher` is based on the `BrowserLauncher`. It launches `puppeteer` browser instance.
6
6
  * @ignore
@@ -9,14 +9,14 @@ export class PuppeteerLauncher extends BrowserLauncher {
9
9
  configuration;
10
10
  static optionsShape = {
11
11
  ...BrowserLauncher.optionsShape,
12
- launcher: ow.optional.object,
12
+ launcher: schemas.anyObject.optional(),
13
13
  };
14
+ static optionsSchema = z.strictObject(PuppeteerLauncher.optionsShape);
14
15
  /**
15
16
  * All `PuppeteerLauncher` parameters are passed via an launchContext object.
16
17
  */
17
18
  constructor(launchContext = {}, configuration = Configuration.getGlobalConfiguration()) {
18
- ow(launchContext, 'PuppeteerLauncher', ow.object.exactShape(PuppeteerLauncher.optionsShape));
19
- const { launcher = BrowserLauncher.requireLauncherOrThrow('puppeteer', 'apify/actor-node-puppeteer-chrome'), ...browserLauncherOptions } = launchContext;
19
+ const { launcher = BrowserLauncher.requireLauncherOrThrow('puppeteer', 'apify/actor-node-puppeteer-chrome'), ...browserLauncherOptions } = parseArgument(launchContext, PuppeteerLauncher.optionsSchema, 'PuppeteerLaunchContext');
20
20
  super({
21
21
  ...browserLauncherOptions,
22
22
  launcher,
@@ -1,6 +1,6 @@
1
1
  import { EventEmitter } from 'node:events';
2
- import { serviceLocator } from '@crawlee/browser';
3
- import ow from 'ow';
2
+ import { parseArgument, schemas, serviceLocator } from '@crawlee/browser';
3
+ const pageSchema = schemas.objectWithKeys(['goto', 'evaluate']);
4
4
  // We use weak maps here so that the content gets discarded after page gets closed.
5
5
  const pageInterceptRequestHandlersMap = new WeakMap(); // Maps page to an array of request interception handlers.
6
6
  const pageInterceptRequestMasterHandlerMap = new WeakMap(); // Maps page to master request interception handler.
@@ -137,8 +137,8 @@ async function handleRequest(request, interceptRequestHandlers) {
137
137
  * @param handler Request interception handler.
138
138
  */
139
139
  export async function addInterceptRequestHandler(page, handler) {
140
- ow(page, ow.object.hasKeys('goto', 'evaluate'));
141
- ow(handler, ow.function);
140
+ parseArgument(page, pageSchema);
141
+ parseArgument(handler, schemas.anyFunction);
142
142
  if (!pageInterceptRequestHandlersMap.has(page)) {
143
143
  pageInterceptRequestHandlersMap.set(page, []);
144
144
  }
@@ -174,8 +174,8 @@ export async function addInterceptRequestHandler(page, handler) {
174
174
  * @param handler Request interception handler.
175
175
  */
176
176
  export async function removeInterceptRequestHandler(page, handler) {
177
- ow(page, ow.object.hasKeys('goto', 'evaluate'));
178
- ow(handler, ow.function);
177
+ parseArgument(page, pageSchema);
178
+ parseArgument(handler, schemas.anyFunction);
179
179
  const handlersArray = pageInterceptRequestHandlersMap.get(page).filter((item) => item !== handler);
180
180
  pageInterceptRequestHandlersMap.set(page, handlersArray);
181
181
  if (handlersArray.length === 0) {
@@ -20,9 +20,9 @@
20
20
  import { readFile } from 'node:fs/promises';
21
21
  import { createRequire } from 'node:module';
22
22
  import vm from 'node:vm';
23
- import { Configuration, KeyValueStore, serviceLocator, validators } from '@crawlee/browser';
23
+ import { Configuration, KeyValueStore, parseArgument, schemas, serviceLocator, validators } from '@crawlee/browser';
24
24
  import { expandShadowRoots, sleep } from '@crawlee/utils';
25
- import ow from 'ow';
25
+ import { z } from 'zod';
26
26
  import { LruCache } from '@apify/datastructures';
27
27
  import { enqueueLinksByClickingElements } from '../enqueue-links/click-elements.js';
28
28
  import { addInterceptRequestHandler, removeInterceptRequestHandler } from './puppeteer_request_interception.js';
@@ -30,6 +30,37 @@ const require = createRequire(import.meta.url);
30
30
  const jqueryPath = require.resolve('jquery');
31
31
  const MAX_INJECT_FILE_CACHE_SIZE = 10;
32
32
  const DEFAULT_BLOCK_REQUEST_URL_PATTERNS = ['.css', '.jpg', '.jpeg', '.png', '.svg', '.gif', '.woff', '.pdf', '.zip'];
33
+ const filePathSchema = z.string();
34
+ const injectFileOptionsSchema = z.strictObject({
35
+ surviveNavigations: z.boolean().optional(),
36
+ });
37
+ const responseUrlRulesSchema = schemas.arrayOf(z.union([z.string(), z.instanceof(RegExp)]), 'strings or RegExps');
38
+ const gotoExtendedRequestSchema = z.looseObject({
39
+ url: z.url(),
40
+ method: z.string().optional(),
41
+ headers: schemas.anyObject.optional(),
42
+ payload: z.union([z.string(), z.instanceof(Uint8Array)]).optional(),
43
+ });
44
+ const blockRequestsOptionsSchema = z.strictObject({
45
+ urlPatterns: schemas.arrayOf(z.string(), 'strings').default(DEFAULT_BLOCK_REQUEST_URL_PATTERNS),
46
+ extraUrlPatterns: schemas.arrayOf(z.string(), 'strings').default(() => []),
47
+ });
48
+ const infiniteScrollOptionsSchema = z.strictObject({
49
+ timeoutSecs: schemas.anyNumber.default(0),
50
+ maxScrollHeight: schemas.anyNumber.default(0),
51
+ waitForSecs: schemas.anyNumber.default(4),
52
+ scrollDownAndUp: z.boolean().default(false),
53
+ buttonSelector: z.string().optional(),
54
+ stopScrollCallback: schemas.anyFunction.optional(),
55
+ });
56
+ const saveSnapshotOptionsSchema = z.strictObject({
57
+ key: z.string().min(1).default('SNAPSHOT'),
58
+ screenshotQuality: schemas.anyNumber.default(50),
59
+ saveScreenshot: z.boolean().default(true),
60
+ saveHtml: z.boolean().default(true),
61
+ keyValueStoreName: z.string().optional(),
62
+ configuration: schemas.anyObject.optional(),
63
+ });
33
64
  const getLog = () => serviceLocator.getChildLog('Puppeteer Utils');
34
65
  /**
35
66
  * Cache contents of previously injected files to limit file system access.
@@ -47,18 +78,16 @@ const injectedFilesCache = new LruCache({ maxLength: MAX_INJECT_FILE_CACHE_SIZE
47
78
  * @param [options]
48
79
  */
49
80
  export async function injectFile(page, filePath, options = {}) {
50
- ow(page, ow.object.validate(validators.browserPage));
51
- ow(filePath, ow.string);
52
- ow(options, ow.object.exactShape({
53
- surviveNavigations: ow.optional.boolean,
54
- }));
81
+ parseArgument(page, validators.browserPage);
82
+ parseArgument(filePath, filePathSchema);
83
+ const { surviveNavigations } = parseArgument(options, injectFileOptionsSchema);
55
84
  let contents = injectedFilesCache.get(filePath);
56
85
  if (!contents) {
57
86
  contents = await readFile(filePath, 'utf8');
58
87
  injectedFilesCache.add(filePath, contents);
59
88
  }
60
89
  const evalP = page.evaluate(contents);
61
- if (options.surviveNavigations) {
90
+ if (surviveNavigations) {
62
91
  page.on('framenavigated', async () => page
63
92
  .evaluate(contents)
64
93
  .catch((error) => getLog().warning('An error occurred during the script injection!', { error })));
@@ -92,7 +121,7 @@ export async function injectFile(page, filePath, options = {}) {
92
121
  * @param [options.surviveNavigations] Opt-out option to disable the JQuery reinjection after navigation.
93
122
  */
94
123
  export async function injectJQuery(page, options) {
95
- ow(page, ow.object.validate(validators.browserPage));
124
+ parseArgument(page, validators.browserPage);
96
125
  return injectFile(page, jqueryPath, { surviveNavigations: options?.surviveNavigations ?? true });
97
126
  }
98
127
  /**
@@ -108,7 +137,7 @@ export async function injectJQuery(page, options) {
108
137
  * @param ignoreShadowRoots
109
138
  */
110
139
  export async function parseWithCheerio(page, ignoreShadowRoots = false, ignoreIframes = false) {
111
- ow(page, ow.object.validate(validators.browserPage));
140
+ parseArgument(page, validators.browserPage);
112
141
  if (page.frames().length > 1 && !ignoreIframes) {
113
142
  const frames = await page.$$('iframe');
114
143
  await Promise.all(frames.map(async (frame) => {
@@ -187,12 +216,8 @@ export async function parseWithCheerio(page, ignoreShadowRoots = false, ignoreIf
187
216
  * @param [options]
188
217
  */
189
218
  export async function blockRequests(page, options = {}) {
190
- ow(page, ow.object.validate(validators.browserPage));
191
- ow(options, ow.object.exactShape({
192
- urlPatterns: ow.optional.array.ofType(ow.string),
193
- extraUrlPatterns: ow.optional.array.ofType(ow.string),
194
- }));
195
- const { urlPatterns = DEFAULT_BLOCK_REQUEST_URL_PATTERNS, extraUrlPatterns = [] } = options;
219
+ parseArgument(page, validators.browserPage);
220
+ const { urlPatterns, extraUrlPatterns } = parseArgument(options, blockRequestsOptionsSchema);
196
221
  const patternsToBlock = [...urlPatterns, ...extraUrlPatterns];
197
222
  // We use CDP commands instead of request interception as the latter disables caching, which is not ideal
198
223
  await sendCDPCommand(page, 'Network.setBlockedURLs', { urls: patternsToBlock });
@@ -249,9 +274,9 @@ export const blockResources = async (page, resourceTypes = ['stylesheet', 'font'
249
274
  * @deprecated
250
275
  */
251
276
  export async function cacheResponses(page, cache, responseUrlRules) {
252
- ow(page, ow.object.validate(validators.browserPage));
253
- ow(cache, ow.object);
254
- ow(responseUrlRules, ow.array.ofType(ow.any(ow.string, ow.regExp)));
277
+ parseArgument(page, validators.browserPage);
278
+ parseArgument(cache, schemas.anyObject);
279
+ parseArgument(responseUrlRules, responseUrlRulesSchema);
255
280
  serviceLocator
256
281
  .getLogger()
257
282
  .deprecated('utils.puppeteer.cacheResponses() has a high impact on performance ' +
@@ -344,14 +369,9 @@ export function compileScript(scriptString, context = Object.create(null)) {
344
369
  * @param [gotoOptions] Custom options for `page.goto()`.
345
370
  */
346
371
  export async function gotoExtended(page, request, gotoOptions = {}) {
347
- ow(page, ow.object.validate(validators.browserPage));
348
- ow(request, ow.object.partialShape({
349
- url: ow.string.url,
350
- method: ow.optional.string,
351
- headers: ow.optional.object,
352
- payload: ow.optional.any(ow.string, ow.uint8Array),
353
- }));
354
- ow(gotoOptions, ow.object);
372
+ parseArgument(page, validators.browserPage);
373
+ parseArgument(request, gotoExtendedRequestSchema);
374
+ parseArgument(gotoOptions, schemas.anyObject);
355
375
  gotoOptions = { ...gotoOptions };
356
376
  if (gotoOptions.waitUntil === 'networkidle') {
357
377
  gotoOptions.waitUntil = 'networkidle0';
@@ -407,16 +427,8 @@ export async function gotoExtended(page, request, gotoOptions = {}) {
407
427
  * @param [options]
408
428
  */
409
429
  export async function infiniteScroll(page, options = {}) {
410
- ow(page, ow.object.validate(validators.browserPage));
411
- ow(options, ow.object.exactShape({
412
- timeoutSecs: ow.optional.number,
413
- maxScrollHeight: ow.optional.number,
414
- waitForSecs: ow.optional.number,
415
- scrollDownAndUp: ow.optional.boolean,
416
- buttonSelector: ow.optional.string,
417
- stopScrollCallback: ow.optional.function,
418
- }));
419
- const { timeoutSecs = 0, maxScrollHeight = 0, waitForSecs = 4, scrollDownAndUp = false, buttonSelector, stopScrollCallback, } = options;
430
+ parseArgument(page, validators.browserPage);
431
+ const { timeoutSecs, maxScrollHeight, waitForSecs, scrollDownAndUp, buttonSelector, stopScrollCallback } = parseArgument(options, infiniteScrollOptionsSchema);
420
432
  let finished;
421
433
  const startTime = Date.now();
422
434
  const CHECK_INTERVAL_MILLIS = 1000;
@@ -508,16 +520,8 @@ export async function infiniteScroll(page, options = {}) {
508
520
  * @param [options]
509
521
  */
510
522
  export async function saveSnapshot(page, options = {}) {
511
- ow(page, ow.object.validate(validators.browserPage));
512
- ow(options, ow.object.exactShape({
513
- key: ow.optional.string.nonEmpty,
514
- screenshotQuality: ow.optional.number,
515
- saveScreenshot: ow.optional.boolean,
516
- saveHtml: ow.optional.boolean,
517
- keyValueStoreName: ow.optional.string,
518
- configuration: ow.optional.object,
519
- }));
520
- const { key = 'SNAPSHOT', screenshotQuality = 50, saveScreenshot = true, saveHtml = true, keyValueStoreName, configuration, } = options;
523
+ parseArgument(page, validators.browserPage);
524
+ const { key, screenshotQuality, saveScreenshot, saveHtml, keyValueStoreName, configuration } = parseArgument(options, saveSnapshotOptionsSchema);
521
525
  try {
522
526
  const store = await KeyValueStore.open(keyValueStoreName ? { name: keyValueStoreName } : null, {
523
527
  configuration: configuration ?? Configuration.getGlobalConfiguration(),
@@ -564,7 +568,7 @@ ${error.message}
564
568
  return idcacPlaywright;
565
569
  }
566
570
  export async function closeCookieModals(page) {
567
- ow(page, ow.object.validate(validators.browserPage));
571
+ parseArgument(page, validators.browserPage);
568
572
  const idcac = await getIdcacPlaywright();
569
573
  if (idcac?.getInjectableScript()) {
570
574
  await page.evaluate(idcac.getInjectableScript());
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/puppeteer",
3
- "version": "4.0.0-beta.121",
3
+ "version": "4.0.0-beta.122",
4
4
  "description": "The scalable web crawling and scraping library for JavaScript/Node.js. Enables development of data extraction and web automation jobs (not only) with headless Chrome and Puppeteer.",
5
5
  "engines": {
6
6
  "node": ">=22.0.0"
@@ -48,16 +48,16 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@apify/datastructures": "^2.0.3",
51
- "@crawlee/browser": "4.0.0-beta.121",
52
- "@crawlee/browser-pool": "4.0.0-beta.121",
53
- "@crawlee/core": "4.0.0-beta.121",
54
- "@crawlee/types": "4.0.0-beta.121",
55
- "@crawlee/utils": "4.0.0-beta.121",
51
+ "@crawlee/browser": "4.0.0-beta.122",
52
+ "@crawlee/browser-pool": "4.0.0-beta.122",
53
+ "@crawlee/core": "4.0.0-beta.122",
54
+ "@crawlee/types": "4.0.0-beta.122",
55
+ "@crawlee/utils": "4.0.0-beta.122",
56
56
  "cheerio": "^1.0.0",
57
57
  "devtools-protocol": "*",
58
58
  "jquery": "^3.7.1",
59
- "ow": "^2.0.0",
60
- "tslib": "^2.8.1"
59
+ "tslib": "^2.8.1",
60
+ "zod": "^4.4.3"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "idcac-playwright": "^0.2.0",
@@ -78,5 +78,5 @@
78
78
  }
79
79
  }
80
80
  },
81
- "gitHead": "5027317de626f5ba6de5047ae9341a898258cc5a"
81
+ "gitHead": "2c3e87fefdb9e1fca4c144f03167d8524cfdc2e5"
82
82
  }