@crawlee/basic 4.0.0-beta.124 → 4.0.0-beta.126

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.
@@ -29,7 +29,7 @@ export type StatusMessageCallback<Context extends CrawlingContext = BasicCrawlin
29
29
  export type RequireContextPipeline<DefaultContextType extends CrawlingContext, FinalContextType extends DefaultContextType> = DefaultContextType extends FinalContextType ? {} : {
30
30
  contextPipelineBuilder: () => ContextPipeline<CrawlingContext, FinalContextType>;
31
31
  };
32
- export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>> {
32
+ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, StatisticStateExtension extends object = {}> {
33
33
  /**
34
34
  * User-provided function that performs the logic of the crawler. It is called for each URL to crawl.
35
35
  *
@@ -278,10 +278,28 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
278
278
  onSkippedRequest?: SkippedRequestCallback;
279
279
  /**
280
280
  * A preconfigured statistics instance. When provided, the crawler records into it instead of building its own and
281
- * will not `reset()` it between `run()` calls. Accepts the built-in {@link Statistics} (subclass it to track
282
- * extra fields) or any object implementing {@link IStatistics}.
281
+ * will not `reset()` it between `run()` calls. Accepts the built-in {@link Statistics} or any object
282
+ * implementing {@link IStatistics}.
283
+ *
284
+ * Custom fields declared via {@link StatisticsOptions.stateExtension|`stateExtension`} are carried over to
285
+ * {@link BasicCrawler.stats|`crawler.stats.state`}:
286
+ *
287
+ * ```ts
288
+ * const statistics = new Statistics({ stateExtension: { defaultState: { productsFound: 0 } } });
289
+ *
290
+ * const crawler = new BasicCrawler({
291
+ * statistics,
292
+ * requestHandler: async () => {
293
+ * statistics.state.productsFound++;
294
+ * },
295
+ * });
296
+ *
297
+ * await crawler.run();
298
+ * // the custom fields are typed on `crawler.stats` too
299
+ * console.log(crawler.stats.state.productsFound);
300
+ * ```
283
301
  */
284
- statistics?: IStatistics;
302
+ statistics?: IStatistics<StatisticStateExtension>;
285
303
  /**
286
304
  * HTTP client implementation for the `sendRequest` context helper and for plain HTTP crawling.
287
305
  * Defaults to {@link ImpitHttpClient} when `@crawlee/impit-client` is installed, otherwise {@link FetchHttpClient}.
@@ -433,7 +451,7 @@ interface CrawlerIdentity {
433
451
  /** Whether `id` came from the user (as opposed to being derived from `instanceIndex`). */
434
452
  readonly hasExplicitId: boolean;
435
453
  }
436
- export declare class BasicCrawler<Context extends CrawlingContext = CrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>> {
454
+ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingContext, ContextExtension = Dictionary<never>, ExtendedContext extends Context = Context & ContextExtension, Routes extends Record<keyof Routes, Dictionary> = Record<string, GetUserDataFromRequest<Context['request']>>, StatisticStateExtension extends object = {}> {
437
455
  #private;
438
456
  protected static readonly CRAWLEE_STATE_KEY = "CRAWLEE_STATE";
439
457
  /**
@@ -446,7 +464,7 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
446
464
  * The statistics instance collecting the crawler's run statistics - either the injected `statistics` option or a
447
465
  * crawler-built default. Typed as {@link IStatistics} so custom implementations can be plugged in.
448
466
  */
449
- get stats(): IStatistics;
467
+ get stats(): IStatistics<StatisticStateExtension>;
450
468
  /**
451
469
  * The main request-handling component of the crawler. It manages the requests that the crawler processes,
452
470
  * combining any provided request loader and/or queue. It's initialized during the crawler startup or lazily
@@ -609,7 +627,7 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
609
627
  /**
610
628
  * All `BasicCrawler` parameters are passed via an options object.
611
629
  */
612
- constructor(options?: BasicCrawlerOptions<Context, ContextExtension, ExtendedContext, Routes> & RequireContextPipeline<CrawlingContext, Context>);
630
+ constructor(options?: BasicCrawlerOptions<Context, ContextExtension, ExtendedContext, Routes, StatisticStateExtension> & RequireContextPipeline<CrawlingContext, Context>);
613
631
  /**
614
632
  * Builds the crawler-owned default {@link ConcurrencySystem} from the resolved
615
633
  * `minConcurrency`/`maxConcurrency`/`maxRequestsPerMinute` shortcuts. Not called when a
@@ -387,7 +387,11 @@ export class BasicCrawler {
387
387
  this.maxRequestRetries = maxRequestRetries;
388
388
  this.maxCrawlDepth = maxCrawlDepth;
389
389
  this.#sameDomainDelaySecs = sameDomainDelaySecs;
390
- this.#statsDep = OwnedOrInjected.resolve(statistics, () => new Statistics({
390
+ this.#statsDep = OwnedOrInjected.resolve(statistics,
391
+ // A crawler-built default tracks the built-in fields only. A non-empty `StatisticStateExtension` can
392
+ // only be satisfied by an injected instance carrying the matching `state`, so this branch does
393
+ // not run in that case - hence the cast.
394
+ () => new Statistics({
391
395
  logMessage: `${this.constructor.name} request statistics:`,
392
396
  log: this.log,
393
397
  id: this.identity.id,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/basic",
3
- "version": "4.0.0-beta.124",
3
+ "version": "4.0.0-beta.126",
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"
@@ -42,10 +42,10 @@
42
42
  "@apify/datastructures": "^2.0.0",
43
43
  "@apify/timeout": "^0.4.4",
44
44
  "@apify/utilities": "^2.15.5",
45
- "@crawlee/core": "4.0.0-beta.124",
46
- "@crawlee/http-client": "4.0.0-beta.124",
47
- "@crawlee/types": "4.0.0-beta.124",
48
- "@crawlee/utils": "4.0.0-beta.124",
45
+ "@crawlee/core": "4.0.0-beta.126",
46
+ "@crawlee/http-client": "4.0.0-beta.126",
47
+ "@crawlee/types": "4.0.0-beta.126",
48
+ "@crawlee/utils": "4.0.0-beta.126",
49
49
  "csv-stringify": "^6.5.2",
50
50
  "tldts": "^7.0.6",
51
51
  "tslib": "^2.8.1",
@@ -53,7 +53,7 @@
53
53
  "zod": "^4.4.3"
54
54
  },
55
55
  "optionalDependencies": {
56
- "@crawlee/impit-client": "^4.0.0-beta.124"
56
+ "@crawlee/impit-client": "^4.0.0-beta.126"
57
57
  },
58
58
  "lerna": {
59
59
  "command": {
@@ -62,5 +62,5 @@
62
62
  }
63
63
  }
64
64
  },
65
- "gitHead": "0694ee1b94c755b98141671baa93cc363f2bf8e3"
65
+ "gitHead": "5f0a8c1a43d4587f8640881fc55836a23e1c4f30"
66
66
  }