@crawlee/basic 4.0.0-beta.101 → 4.0.0-beta.103

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,5 +1,5 @@
1
- import type { AddRequestsBatchedOptions, AddRequestsBatchedResult, ConcurrencySystemOptions, Configuration, CrawleeLogger, CrawlingContext, DatasetExportOptions, EnqueueLinksOptions, EventManager, FinalStatistics, GetUserDataFromRequest, IConcurrencySystem, IProxyConfiguration, IRequestLoader, IRequestManager, Request, RequestsLike, RouterHandler, RouterRoutes, SkippedRequestCallback, Source, StatisticsOptions, StatisticState, StorageIdentifier, TaskLoopPredicates, TypedRequestsLike } from '@crawlee/core';
2
- import { ConcurrencySystem, ContextPipeline, Dataset, RequestQueue, Statistics } from '@crawlee/core';
1
+ import type { AddRequestsBatchedOptions, AddRequestsBatchedResult, ConcurrencySystemOptions, Configuration, CrawleeLogger, CrawlingContext, DatasetExportOptions, EnqueueLinksOptions, EventManager, FinalStatistics, GetUserDataFromRequest, IConcurrencySystem, IProxyConfiguration, IRequestLoader, IRequestManager, IStatistics, Request, RequestsLike, RouterHandler, RouterRoutes, SkippedRequestCallback, Source, StatisticState, StorageIdentifier, TaskLoopPredicates, TypedRequestsLike } from '@crawlee/core';
2
+ import { ConcurrencySystem, ContextPipeline, Dataset, RequestQueue } from '@crawlee/core';
3
3
  import type { Awaitable, BaseHttpClient, BatchAddRequestsResult, Dictionary, ISession, ISessionPool, ProxyInfo, SetStatusMessageOptions, StorageBackend } from '@crawlee/types';
4
4
  import { RobotsTxtFile } from '@crawlee/utils';
5
5
  import type { ReadonlyDeep, SetRequired } from 'type-fest';
@@ -267,10 +267,11 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
267
267
  */
268
268
  onSkippedRequest?: SkippedRequestCallback;
269
269
  /**
270
- * Customize the way statistics collecting works, such as logging interval or
271
- * whether to output them to the Key-Value store.
270
+ * A preconfigured statistics instance. When provided, the crawler records into it instead of building its own and
271
+ * will not `reset()` it between `run()` calls. Accepts the built-in {@link Statistics} (subclass it to track
272
+ * extra fields) or any object implementing {@link IStatistics}.
272
273
  */
273
- statisticsOptions?: StatisticsOptions;
274
+ statistics?: IStatistics;
274
275
  /**
275
276
  * HTTP client implementation for the `sendRequest` context helper and for plain HTTP crawling.
276
277
  * Defaults to {@link ImpitHttpClient} when `@crawlee/impit-client` is installed, otherwise {@link FetchHttpClient}.
@@ -422,10 +423,13 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
422
423
  * Used to detect and warn about multiple crawlers sharing the same state.
423
424
  */
424
425
  private static useStateAnonymousIndices;
426
+ /** Backs the {@link BasicCrawler.stats|`stats`} getter. */
427
+ private statsDep;
425
428
  /**
426
- * A reference to the underlying {@link Statistics} class that collects and logs run statistics for requests.
429
+ * The statistics instance collecting the crawler's run statistics - either the injected `statistics` option or a
430
+ * crawler-built default. Typed as {@link IStatistics} so custom implementations can be plugged in.
427
431
  */
428
- readonly stats: Statistics;
432
+ get stats(): IStatistics;
429
433
  /**
430
434
  * The main request-handling component of the crawler. It manages the requests that the crawler processes,
431
435
  * combining any provided request loader and/or queue. It's initialized during the crawler startup or lazily
@@ -608,7 +612,7 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
608
612
  // @ts-ignore optional peer dependency or compatibility with es2022
609
613
  keepAlive: import("ow").BooleanPredicate & import("ow").BasePredicate<boolean | undefined>;
610
614
  // @ts-ignore optional peer dependency or compatibility with es2022
611
- statisticsOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
615
+ statistics: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
612
616
  // @ts-ignore optional peer dependency or compatibility with es2022
613
617
  id: import("ow").StringPredicate & import("ow").BasePredicate<string | undefined>;
614
618
  };
@@ -52,10 +52,15 @@ export class BasicCrawler {
52
52
  * Used to detect and warn about multiple crawlers sharing the same state.
53
53
  */
54
54
  static useStateAnonymousIndices = new Set();
55
+ /** Backs the {@link BasicCrawler.stats|`stats`} getter. */
56
+ statsDep;
55
57
  /**
56
- * A reference to the underlying {@link Statistics} class that collects and logs run statistics for requests.
58
+ * The statistics instance collecting the crawler's run statistics - either the injected `statistics` option or a
59
+ * crawler-built default. Typed as {@link IStatistics} so custom implementations can be plugged in.
57
60
  */
58
- stats;
61
+ get stats() {
62
+ return this.statsDep.value;
63
+ }
59
64
  /**
60
65
  * The main request-handling component of the crawler. It manages the requests that the crawler processes,
61
66
  * combining any provided request loader and/or queue. It's initialized during the crawler startup or lazily
@@ -225,7 +230,7 @@ export class BasicCrawler {
225
230
  maxConcurrency: ow.optional.number,
226
231
  maxRequestsPerMinute: ow.optional.number.integerOrInfinite.positive.greaterThanOrEqual(1),
227
232
  keepAlive: ow.optional.boolean,
228
- statisticsOptions: ow.optional.object,
233
+ statistics: ow.optional.object,
229
234
  id: ow.optional.string,
230
235
  };
231
236
  /**
@@ -241,7 +246,7 @@ export class BasicCrawler {
241
246
  // Service locator options
242
247
  configuration, storageBackend, eventManager, logger,
243
248
  // AutoscaledPool shorthands
244
- minConcurrency, maxConcurrency, maxRequestsPerMinute, blockedStatusCodes: blockedStatusCodesInput, retryOnBlocked = false, respectRobotsTxtFile = false, onSkippedRequest, requestHandler, requestHandlerTimeoutSecs, errorHandler, failedRequestHandler, statusMessageLoggingInterval = 10, statusMessageCallback, statisticsOptions, httpClient, id, } = options;
249
+ minConcurrency, maxConcurrency, maxRequestsPerMinute, blockedStatusCodes: blockedStatusCodesInput, retryOnBlocked = false, respectRobotsTxtFile = false, onSkippedRequest, requestHandler, requestHandlerTimeoutSecs, errorHandler, failedRequestHandler, statusMessageLoggingInterval = 10, statusMessageCallback, statistics, httpClient, id, } = options;
245
250
  // All concurrency configuration lives on the `ConcurrencySystem`, so the shortcuts have nowhere to go once
246
251
  // one is supplied - and silently dropping a `maxConcurrency` the user asked for is how crawls end up
247
252
  // hammering a site.
@@ -323,12 +328,11 @@ export class BasicCrawler {
323
328
  this.maxRequestRetries = maxRequestRetries;
324
329
  this.maxCrawlDepth = maxCrawlDepth;
325
330
  this.sameDomainDelayMillis = sameDomainDelaySecs * 1000;
326
- this.stats = new Statistics({
331
+ this.statsDep = OwnedOrInjected.resolve(statistics, () => new Statistics({
327
332
  logMessage: `${this.constructor.name} request statistics:`,
328
333
  log: this.log,
329
334
  id: this.identity.id,
330
- ...statisticsOptions,
331
- });
335
+ }));
332
336
  if (sessionPool && proxyConfiguration) {
333
337
  this.log.warning('Both `sessionPool` and `proxyConfiguration` were provided to the crawler. ' +
334
338
  'The `proxyConfiguration` is ignored - sessions from the supplied pool keep whatever ' +
@@ -707,8 +711,11 @@ export class BasicCrawler {
707
711
  if (managerToPurge?.purge && shouldPurge) {
708
712
  await managerToPurge.purge();
709
713
  }
710
- this.stats.reset();
711
- await this.stats.resetStore();
714
+ // A supplied statistics instance keeps whatever state it was handed - only wipe a default we built.
715
+ await this.statsDep.ifOwned(async (stats) => {
716
+ stats.reset();
717
+ await stats.resetStore();
718
+ });
712
719
  await this.sessionPoolDep.ifOwned((pool) => pool.resetStore());
713
720
  }
714
721
  this.unexpectedStop = false;
@@ -1230,7 +1237,7 @@ export class BasicCrawler {
1230
1237
  });
1231
1238
  }
1232
1239
  })();
1233
- await Promise.all([requestManagerPersistPromise, this.stats.persistState()]);
1240
+ await Promise.all([requestManagerPersistPromise, this.stats.persistState?.()]);
1234
1241
  }
1235
1242
  /**
1236
1243
  * Fetches the next request to process from the underlying request provider.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crawlee/basic",
3
- "version": "4.0.0-beta.101",
3
+ "version": "4.0.0-beta.103",
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.101",
46
- "@crawlee/http-client": "4.0.0-beta.101",
47
- "@crawlee/types": "4.0.0-beta.101",
48
- "@crawlee/utils": "4.0.0-beta.101",
45
+ "@crawlee/core": "4.0.0-beta.103",
46
+ "@crawlee/http-client": "4.0.0-beta.103",
47
+ "@crawlee/types": "4.0.0-beta.103",
48
+ "@crawlee/utils": "4.0.0-beta.103",
49
49
  "csv-stringify": "^6.5.2",
50
50
  "ow": "^2.0.0",
51
51
  "tldts": "^7.0.6",
@@ -53,7 +53,7 @@
53
53
  "type-fest": "^4.41.0"
54
54
  },
55
55
  "optionalDependencies": {
56
- "@crawlee/impit-client": "^4.0.0-beta.101"
56
+ "@crawlee/impit-client": "^4.0.0-beta.103"
57
57
  },
58
58
  "lerna": {
59
59
  "command": {
@@ -62,5 +62,5 @@
62
62
  }
63
63
  }
64
64
  },
65
- "gitHead": "1fd886ee601c053d6fa8cada24b751f9cbe0a539"
65
+ "gitHead": "fe5d0ae11067683e27a2d17b4edd226ccf112cf5"
66
66
  }