@crawlee/browser 4.0.0-beta.105 → 4.0.0-beta.107

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.
@@ -227,8 +227,7 @@ export interface BrowserCrawlerOptions<Page extends CommonPage = CommonPage, Res
227
227
  * @category Crawlers
228
228
  */
229
229
  export declare abstract class BrowserCrawler<Page extends CommonPage = CommonPage, Response extends BaseResponse = BaseResponse, InternalBrowserPoolOptions extends BrowserPoolOptions = BrowserPoolOptions, LaunchOptions extends Dictionary | undefined = Dictionary, Context extends BrowserCrawlingContext<Page, Response> = BrowserCrawlingContext<Page, Response>, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, GoToOptions extends Dictionary = Dictionary> extends BasicCrawler<Context, ContextExtension, ExtendedContext, Routes> {
230
- /** Backs the {@link BrowserCrawler.browserPool|`browserPool`} getter. */
231
- private browserPoolDep;
230
+ #private;
232
231
  /**
233
232
  * A reference to the underlying browser pool that manages the crawler's browsers. Typed as
234
233
  * {@link IBrowserPool} so custom implementations can be plugged in via the `browserPool` constructor option.
@@ -237,10 +236,6 @@ export declare abstract class BrowserCrawler<Page extends CommonPage = CommonPag
237
236
  launchContext: BrowserLaunchContext<LaunchOptions, unknown>;
238
237
  protected readonly ignoreShadowRoots: boolean;
239
238
  protected readonly ignoreIframes: boolean;
240
- private readonly navigationTimeoutMillis;
241
- private readonly preNavigationHooks;
242
- private readonly postNavigationHooks;
243
- private readonly saveResponseCookies;
244
239
  protected static optionsShape: {
245
240
  // @ts-ignore optional peer dependency or compatibility with es2022
246
241
  navigationTimeoutSecs: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
@@ -367,7 +362,7 @@ export declare abstract class BrowserCrawler<Page extends CommonPage = CommonPag
367
362
  * Transforms proxy-related errors to `SessionError`.
368
363
  */
369
364
  private throwIfProxyError;
370
- protected abstract _navigationHandler(crawlingContext: BrowserCrawlingContext<Page, Response>, gotoOptions: GoToOptions): Promise<Context['response'] | null | undefined>;
365
+ protected abstract navigationHandler(crawlingContext: BrowserCrawlingContext<Page, Response>, gotoOptions: GoToOptions): Promise<Context['response'] | null | undefined>;
371
366
  private processResponse;
372
367
  /**
373
368
  * Function for cleaning up after all requests are processed.
@@ -58,21 +58,21 @@ function isNavigationTimeoutError(error) {
58
58
  */
59
59
  export class BrowserCrawler extends BasicCrawler {
60
60
  /** Backs the {@link BrowserCrawler.browserPool|`browserPool`} getter. */
61
- browserPoolDep;
61
+ #browserPoolDep;
62
62
  /**
63
63
  * A reference to the underlying browser pool that manages the crawler's browsers. Typed as
64
64
  * {@link IBrowserPool} so custom implementations can be plugged in via the `browserPool` constructor option.
65
65
  */
66
66
  get browserPool() {
67
- return this.browserPoolDep.value;
67
+ return this.#browserPoolDep.value;
68
68
  }
69
69
  launchContext;
70
70
  ignoreShadowRoots;
71
71
  ignoreIframes;
72
- navigationTimeoutMillis;
73
- preNavigationHooks;
74
- postNavigationHooks;
75
- saveResponseCookies;
72
+ #navigationTimeoutMillis;
73
+ #preNavigationHooks;
74
+ #postNavigationHooks;
75
+ #saveResponseCookies;
76
76
  static optionsShape = {
77
77
  ...BasicCrawler.optionsShape,
78
78
  navigationTimeoutSecs: ow.optional.number.greaterThan(0),
@@ -103,18 +103,18 @@ export class BrowserCrawler extends BasicCrawler {
103
103
  // hook eats into the same window the navigation uses. The navigation itself is bounded by
104
104
  // capping its `gotoOptions.timeout` to the remaining budget.
105
105
  const windowGuard = (step) => skipGuard(async (ctx) => {
106
- const remaining = remainingNavigationWindowMillis(ctx, this.navigationTimeoutMillis);
106
+ const remaining = remainingNavigationWindowMillis(ctx, this.#navigationTimeoutMillis);
107
107
  if (remaining <= 0) {
108
- throw new TimeoutError(`Navigation timed out after ${this.navigationTimeoutMillis / 1000} seconds.`);
108
+ throw new TimeoutError(`Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
109
109
  }
110
- return addTimeoutToPromise(async () => step(ctx), remaining, `Navigation timed out after ${this.navigationTimeoutMillis / 1000} seconds.`);
110
+ return addTimeoutToPromise(async () => step(ctx), remaining, `Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
111
111
  });
112
112
  let pipeline = contextPipelineBuilder().compose({ action: this.prepareNavigation.bind(this) });
113
- for (const hook of this.preNavigationHooks) {
113
+ for (const hook of this.#preNavigationHooks) {
114
114
  pipeline = pipeline.compose(windowGuard(hook));
115
115
  }
116
116
  pipeline = pipeline.compose(skipGuard(this.navigate.bind(this)));
117
- for (const hook of this.postNavigationHooks) {
117
+ for (const hook of this.#postNavigationHooks) {
118
118
  pipeline = pipeline.compose(windowGuard(hook));
119
119
  }
120
120
  return pipeline
@@ -125,23 +125,23 @@ export class BrowserCrawler extends BasicCrawler {
125
125
  extendContext,
126
126
  });
127
127
  this.launchContext = launchContext;
128
- this.navigationTimeoutMillis = navigationTimeoutSecs * 1000;
128
+ this.#navigationTimeoutMillis = navigationTimeoutSecs * 1000;
129
129
  // The public option hooks are extension-aware; internal storage uses the base context type
130
130
  // (the pipeline composes hooks against the concrete context, which does not statically carry
131
131
  // `ContextExtension`). The extension members are present at runtime regardless.
132
- this.preNavigationHooks = preNavigationHooks;
133
- this.postNavigationHooks = postNavigationHooks;
132
+ this.#preNavigationHooks = preNavigationHooks;
133
+ this.#postNavigationHooks = postNavigationHooks;
134
134
  this.ignoreIframes = ignoreIframes;
135
135
  this.ignoreShadowRoots = ignoreShadowRoots;
136
136
  if (headless != null) {
137
137
  this.launchContext.launchOptions ??= {};
138
138
  this.launchContext.launchOptions.headless = headless;
139
139
  }
140
- this.saveResponseCookies = saveResponseCookies;
140
+ this.#saveResponseCookies = saveResponseCookies;
141
141
  // `browserPool` wins over `remoteBrowser` — a passed-in pool is used as-is (borrowed), the sugar is ignored.
142
142
  // The default is only built when no pool was injected, so all the option/launchContext fiddling below stays
143
143
  // inside the factory.
144
- this.browserPoolDep = OwnedOrInjected.resolve(browserPool, () => {
144
+ this.#browserPoolDep = OwnedOrInjected.resolve(browserPool, () => {
145
145
  const resolvedBrowserPoolOptions = browserPoolOptions ?? {};
146
146
  if (launchContext?.userAgent) {
147
147
  if (resolvedBrowserPoolOptions.useFingerprints)
@@ -168,7 +168,7 @@ export class BrowserCrawler extends BasicCrawler {
168
168
  });
169
169
  }
170
170
  getNavigationTimeoutMillis() {
171
- return this.navigationTimeoutMillis;
171
+ return this.#navigationTimeoutMillis;
172
172
  }
173
173
  buildContextPipeline() {
174
174
  return ContextPipeline.create().compose({
@@ -263,31 +263,31 @@ export class BrowserCrawler extends BasicCrawler {
263
263
  return {
264
264
  // Default to the full navigation timeout so a pre-navigation hook can read it; `navigate` narrows it
265
265
  // to the remaining shared window unless a hook overrode it (see there).
266
- gotoOptions: { timeout: this.navigationTimeoutMillis },
267
- [COOKIES_BEFORE_HOOKS]: this._getCookieHeaderFromRequest(crawlingContext.request),
266
+ gotoOptions: { timeout: this.#navigationTimeoutMillis },
267
+ [COOKIES_BEFORE_HOOKS]: this.getCookieHeaderFromRequest(crawlingContext.request),
268
268
  };
269
269
  }
270
270
  async navigate(crawlingContext) {
271
271
  tryCancel();
272
272
  const gotoOptions = crawlingContext.gotoOptions;
273
- const remaining = remainingNavigationWindowMillis(crawlingContext, this.navigationTimeoutMillis);
273
+ const remaining = remainingNavigationWindowMillis(crawlingContext, this.#navigationTimeoutMillis);
274
274
  if (remaining <= 0) {
275
- throw new TimeoutError(`Navigation timed out after ${this.navigationTimeoutMillis / 1000} seconds.`);
275
+ throw new TimeoutError(`Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
276
276
  }
277
277
  // If a hook left the default `navigationTimeoutMillis` in place, bound the goto to whatever is left of the
278
278
  // shared navigation window. If it overrode the value - including `0`, Playwright's "no timeout" - honour
279
279
  // that verbatim as the goto's own timeout. The driver enforces this natively (so a timed-out goto is
280
280
  // aborted, not left lingering) and `handleNavigationTimeout` turns its error into our own message.
281
281
  const gotoTimeout = gotoOptions;
282
- if (gotoTimeout.timeout === this.navigationTimeoutMillis) {
282
+ if (gotoTimeout.timeout === this.#navigationTimeoutMillis) {
283
283
  gotoTimeout.timeout = remaining;
284
284
  }
285
285
  const cookiesBeforeHooks = readContextField(crawlingContext, COOKIES_BEFORE_HOOKS);
286
- const cookiesAfterHooks = this._getCookieHeaderFromRequest(crawlingContext.request);
286
+ const cookiesAfterHooks = this.getCookieHeaderFromRequest(crawlingContext.request);
287
287
  await this.applyCookies(crawlingContext, cookiesBeforeHooks, cookiesAfterHooks);
288
288
  let response;
289
289
  try {
290
- response = (await this._navigationHandler(crawlingContext, gotoOptions)) ?? undefined;
290
+ response = (await this.navigationHandler(crawlingContext, gotoOptions)) ?? undefined;
291
291
  }
292
292
  catch (error) {
293
293
  await this.handleNavigationTimeout(crawlingContext, error);
@@ -320,7 +320,7 @@ export class BrowserCrawler extends BasicCrawler {
320
320
  * Copies cookies from the live browser page into the session cookie jar.
321
321
  */
322
322
  async persistCookiesFromPage(crawlingContext) {
323
- if (!this.saveResponseCookies || !crawlingContext.session) {
323
+ if (!this.#saveResponseCookies || !crawlingContext.session) {
324
324
  return;
325
325
  }
326
326
  const { cookies } = await this.browserPool.extractPageState(crawlingContext.page);
@@ -329,7 +329,7 @@ export class BrowserCrawler extends BasicCrawler {
329
329
  const url = (await crawlingContext.page.url()) || crawlingContext.request.loadedUrl || crawlingContext.request.url;
330
330
  for (const cookie of cookies) {
331
331
  try {
332
- crawlingContext.session.cookieJar.setCookieSync(browserPoolCookieToToughCookie(cookie), url, {
332
+ await crawlingContext.session.cookieJar.setCookie(browserPoolCookieToToughCookie(cookie), url, {
333
333
  ignoreError: false,
334
334
  });
335
335
  }
@@ -370,7 +370,9 @@ export class BrowserCrawler extends BasicCrawler {
370
370
  return {};
371
371
  }
372
372
  async applyCookies({ session, request, page }, preHooksCookies, postHooksCookies) {
373
- const sessionCookie = session?.cookieJar.getCookiesSync(request.url).map(toughCookieToBrowserPoolCookie) ?? [];
373
+ const sessionCookie = session
374
+ ? (await session.cookieJar.getCookies(request.url)).map(toughCookieToBrowserPoolCookie)
375
+ : [];
374
376
  const parsedPreHooksCookies = preHooksCookies.split(/ *; */).map((c) => cookieStringToToughCookie(c));
375
377
  const parsedPostHooksCookies = postHooksCookies.split(/ *; */).map((c) => cookieStringToToughCookie(c));
376
378
  const cookies = [...sessionCookie, ...parsedPreHooksCookies, ...parsedPostHooksCookies]
@@ -390,7 +392,7 @@ export class BrowserCrawler extends BasicCrawler {
390
392
  session?.markBad();
391
393
  // The driver was handed the remaining window (usually shorter than `navigationTimeoutSecs` once the
392
394
  // hooks have run), so it names that value in its own error; report the configured window instead.
393
- throw new TimeoutError(`Navigation timed out after ${this.navigationTimeoutMillis / 1000} seconds.`);
395
+ throw new TimeoutError(`Navigation timed out after ${this.#navigationTimeoutMillis / 1000} seconds.`);
394
396
  }
395
397
  }
396
398
  /**
@@ -398,7 +400,7 @@ export class BrowserCrawler extends BasicCrawler {
398
400
  */
399
401
  throwIfProxyError(error) {
400
402
  if (this.isProxyError(error)) {
401
- throw new SessionError(this._getMessageFromError(error));
403
+ throw new SessionError(this.getMessageFromError(error));
402
404
  }
403
405
  }
404
406
  async processResponse(response, crawlingContext) {
@@ -415,7 +417,7 @@ export class BrowserCrawler extends BasicCrawler {
415
417
  }
416
418
  if (this.sessionPool && response && session) {
417
419
  if (typeof response === 'object' && typeof response.status === 'function') {
418
- this._throwOnBlockedRequest(response.status());
420
+ this.throwOnBlockedRequest(response.status());
419
421
  }
420
422
  else {
421
423
  this.log.debug('Got a malformed Browser response.', { request, response });
@@ -428,7 +430,7 @@ export class BrowserCrawler extends BasicCrawler {
428
430
  * @ignore
429
431
  */
430
432
  async teardown() {
431
- await this.browserPoolDep.ifOwned((pool) => pool.destroy());
433
+ await this.#browserPoolDep.ifOwned((pool) => pool.destroy());
432
434
  await super.teardown();
433
435
  }
434
436
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/browser",
3
- "version": "4.0.0-beta.105",
3
+ "version": "4.0.0-beta.107",
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,10 +48,10 @@
48
48
  },
49
49
  "dependencies": {
50
50
  "@apify/timeout": "^0.4.4",
51
- "@crawlee/basic": "4.0.0-beta.105",
52
- "@crawlee/browser-pool": "4.0.0-beta.105",
53
- "@crawlee/types": "4.0.0-beta.105",
54
- "@crawlee/utils": "4.0.0-beta.105",
51
+ "@crawlee/basic": "4.0.0-beta.107",
52
+ "@crawlee/browser-pool": "4.0.0-beta.107",
53
+ "@crawlee/types": "4.0.0-beta.107",
54
+ "@crawlee/utils": "4.0.0-beta.107",
55
55
  "ow": "^2.0.0",
56
56
  "tslib": "^2.8.1",
57
57
  "type-fest": "^4.41.0"
@@ -75,5 +75,5 @@
75
75
  }
76
76
  }
77
77
  },
78
- "gitHead": "26073a822c7699ac487931383a39192bc3daae7a"
78
+ "gitHead": "5a3cb6242d0ae261df93c5e03cfebbb9b736e6b7"
79
79
  }