@crawlee/basic 4.0.0-beta.91 → 4.0.0-beta.93
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.
- package/internals/basic-crawler.d.ts +49 -23
- package/internals/basic-crawler.js +60 -21
- package/package.json +7 -7
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AddRequestsBatchedOptions, AddRequestsBatchedResult,
|
|
2
|
-
import {
|
|
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';
|
|
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';
|
|
@@ -151,13 +151,14 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
151
151
|
*/
|
|
152
152
|
maxCrawlDepth?: number;
|
|
153
153
|
/**
|
|
154
|
-
* Lets you override the task
|
|
155
|
-
*
|
|
154
|
+
* Lets you override the predicates that steer the crawler's task loop: `isTaskReadyFunction` (may another request
|
|
155
|
+
* start?) and `isFinishedFunction` (is the crawl over?). The task itself — fetching a request and running it
|
|
156
|
+
* through the pipeline — is owned by the crawler and cannot be overridden.
|
|
156
157
|
*
|
|
157
158
|
* Concurrency is configured elsewhere — through the `minConcurrency`/`maxConcurrency`/`maxRequestsPerMinute`
|
|
158
159
|
* shortcuts, or a {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} for finer control.
|
|
159
160
|
*/
|
|
160
|
-
|
|
161
|
+
taskLoopOptions?: TaskLoopPredicates;
|
|
161
162
|
/**
|
|
162
163
|
* A pre-configured concurrency governor — the component that decides whether there is free compute for one more
|
|
163
164
|
* task. Typically a {@link ConcurrencySystem}, though any {@link IConcurrencySystem} is accepted. All
|
|
@@ -353,8 +354,8 @@ export interface BasicCrawlerOptions<Context extends CrawlingContext = CrawlingC
|
|
|
353
354
|
*
|
|
354
355
|
* The crawler finishes if there are no more {@link Request} objects to crawl.
|
|
355
356
|
*
|
|
356
|
-
* New requests are only dispatched when there is enough free CPU and memory available,
|
|
357
|
-
*
|
|
357
|
+
* New requests are only dispatched when there is enough free CPU and memory available, as judged by the crawler's
|
|
358
|
+
* {@link ConcurrencySystem}.
|
|
358
359
|
* Concurrency is tuned via the {@link BasicCrawlerOptions.minConcurrency|`minConcurrency`},
|
|
359
360
|
* {@link BasicCrawlerOptions.maxConcurrency|`maxConcurrency`} and
|
|
360
361
|
* {@link BasicCrawlerOptions.maxRequestsPerMinute|`maxRequestsPerMinute`} shortcuts, or, for finer control, by
|
|
@@ -458,16 +459,26 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
458
459
|
/** As resolved by `_init()`. Absent until the first run, so a `teardown()` before it is a no-op. */
|
|
459
460
|
private concurrencySystemDep?;
|
|
460
461
|
/**
|
|
461
|
-
*
|
|
462
|
-
*
|
|
463
|
-
*
|
|
464
|
-
* or to abort it by calling {@link AutoscaledPool.abort|`autoscaledPool.abort()`}.
|
|
462
|
+
* The concurrency governor this run is booking its requests against — either the
|
|
463
|
+
* {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} that was injected, or the default the
|
|
464
|
+
* crawler built for itself. Read it for telemetry: `desiredConcurrency`, `currentConcurrency`, `isRunning`.
|
|
465
465
|
*
|
|
466
|
-
*
|
|
467
|
-
*
|
|
468
|
-
*
|
|
466
|
+
* > *NOTE:* `undefined` until {@link BasicCrawler.run|`crawler.run()`} has resolved it. A crawler-owned default
|
|
467
|
+
* is also rebuilt for every run, so the instance is not stable across runs.
|
|
468
|
+
*
|
|
469
|
+
* {@link IConcurrencySystem} is deliberately read-only. Tuning concurrency *while a crawl is running* means
|
|
470
|
+
* owning the instance: build a {@link ConcurrencySystem} yourself and inject it, then set
|
|
471
|
+
* `minConcurrency`/`maxConcurrency`/`desiredConcurrency` on your own reference.
|
|
472
|
+
*/
|
|
473
|
+
get concurrencySystem(): IConcurrencySystem | undefined;
|
|
474
|
+
/**
|
|
475
|
+
* The task loop that dispatches this run's requests. Private on purpose — it is a bare parallel task runner with
|
|
476
|
+
* no configuration left of its own (see {@link ConcurrencySystem}), and everything a caller legitimately did
|
|
477
|
+
* with it now has a crawler-level counterpart: {@link BasicCrawler.pause|`pause()`},
|
|
478
|
+
* {@link BasicCrawler.resume|`resume()`}, {@link BasicCrawler.teardown|`teardown()`} and
|
|
479
|
+
* {@link BasicCrawler.concurrencySystem|`concurrencySystem`}.
|
|
469
480
|
*/
|
|
470
|
-
autoscaledPool
|
|
481
|
+
private autoscaledPool?;
|
|
471
482
|
/**
|
|
472
483
|
* A reference to the underlying {@link IProxyConfiguration} instance that manages the crawler's proxies.
|
|
473
484
|
* Only available if used by the crawler.
|
|
@@ -513,12 +524,12 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
513
524
|
protected readonly additionalHttpErrorStatusCodes: Set<number>;
|
|
514
525
|
private ignoreHttpErrorStatusCodes;
|
|
515
526
|
/**
|
|
516
|
-
* The resolved
|
|
517
|
-
*
|
|
518
|
-
*
|
|
519
|
-
*
|
|
527
|
+
* The resolved options for the crawler's own task loop — the crawler-owned `runTaskFunction`, the (possibly
|
|
528
|
+
* user-overridden) ready/finished predicates and cadence/logging. Concurrency configuration lives on the
|
|
529
|
+
* {@link ConcurrencySystem} instead, and the loop's `consumer` identity is the crawler's own, so neither is
|
|
530
|
+
* settable here.
|
|
520
531
|
*/
|
|
521
|
-
private
|
|
532
|
+
private taskLoopOptions;
|
|
522
533
|
protected readonly httpClient: BaseHttpClient;
|
|
523
534
|
protected readonly retryOnBlocked: boolean;
|
|
524
535
|
private respectRobotsTxtFile;
|
|
@@ -554,7 +565,7 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
554
565
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
555
566
|
maxCrawlDepth: import("ow").NumberPredicate & import("ow").BasePredicate<number | undefined>;
|
|
556
567
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
557
|
-
|
|
568
|
+
taskLoopOptions: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
558
569
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
559
570
|
concurrencySystem: import("ow").ObjectPredicate<object> & import("ow").BasePredicate<object | undefined>;
|
|
560
571
|
// @ts-ignore optional peer dependency or compatibility with es2022
|
|
@@ -655,8 +666,9 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
655
666
|
setStatusMessage(message: string, options?: SetStatusMessageOptions): void;
|
|
656
667
|
private getPeriodicLogger;
|
|
657
668
|
/**
|
|
658
|
-
* Runs the crawler. Returns a promise that resolves once
|
|
659
|
-
*
|
|
669
|
+
* Runs the crawler. Returns a promise that resolves once every request has been processed and the crawler's
|
|
670
|
+
* finished-check ({@link BasicCrawlerOptions.taskLoopOptions|`taskLoopOptions.isFinishedFunction`}, or the
|
|
671
|
+
* default "the request manager is empty") reports that the crawl is over.
|
|
660
672
|
*
|
|
661
673
|
* We can use the `requests` parameter to enqueue the initial requests — it is a shortcut for
|
|
662
674
|
* running {@link BasicCrawler.addRequests|`crawler.addRequests()`} before {@link BasicCrawler.run|`crawler.run()`}.
|
|
@@ -673,6 +685,20 @@ export declare class BasicCrawler<Context extends CrawlingContext = CrawlingCont
|
|
|
673
685
|
* To stop the crawler immediately, use {@link BasicCrawler.teardown|`crawler.teardown()`} instead.
|
|
674
686
|
*/
|
|
675
687
|
stop(reason?: string): void;
|
|
688
|
+
/**
|
|
689
|
+
* Stops dispatching new requests, letting the in-progress ones finish. Resolves once they have settled, or rejects
|
|
690
|
+
* after `timeoutSecs` if they take too long. Unlike {@link BasicCrawler.stop|`stop()`}, this does not end the
|
|
691
|
+
* run — {@link BasicCrawler.run|`run()`} stays pending until {@link BasicCrawler.resume|`resume()`}.
|
|
692
|
+
*
|
|
693
|
+
* > *NOTE:* The {@link BasicCrawler.concurrencySystem|concurrency system} keeps monitoring and autoscaling
|
|
694
|
+
* throughout, since a shared one may still be serving other crawlers.
|
|
695
|
+
*/
|
|
696
|
+
pause(timeoutSecs?: number): Promise<void>;
|
|
697
|
+
/**
|
|
698
|
+
* Resumes a run suspended with {@link BasicCrawler.pause|`pause()`}, letting the crawler dispatch requests
|
|
699
|
+
* again. A no-op on a crawler that is not paused.
|
|
700
|
+
*/
|
|
701
|
+
resume(): void;
|
|
676
702
|
/**
|
|
677
703
|
* Returns the crawler's {@link IRequestManager|request manager}, opening the default {@link RequestQueue}
|
|
678
704
|
* if none has been configured or opened yet.
|
|
@@ -90,14 +90,26 @@ export class BasicCrawler {
|
|
|
90
90
|
/** As resolved by `_init()`. Absent until the first run, so a `teardown()` before it is a no-op. */
|
|
91
91
|
concurrencySystemDep;
|
|
92
92
|
/**
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* or to abort it by calling {@link AutoscaledPool.abort|`autoscaledPool.abort()`}.
|
|
93
|
+
* The concurrency governor this run is booking its requests against — either the
|
|
94
|
+
* {@link BasicCrawlerOptions.concurrencySystem|`concurrencySystem`} that was injected, or the default the
|
|
95
|
+
* crawler built for itself. Read it for telemetry: `desiredConcurrency`, `currentConcurrency`, `isRunning`.
|
|
97
96
|
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
97
|
+
* > *NOTE:* `undefined` until {@link BasicCrawler.run|`crawler.run()`} has resolved it. A crawler-owned default
|
|
98
|
+
* is also rebuilt for every run, so the instance is not stable across runs.
|
|
99
|
+
*
|
|
100
|
+
* {@link IConcurrencySystem} is deliberately read-only. Tuning concurrency *while a crawl is running* means
|
|
101
|
+
* owning the instance: build a {@link ConcurrencySystem} yourself and inject it, then set
|
|
102
|
+
* `minConcurrency`/`maxConcurrency`/`desiredConcurrency` on your own reference.
|
|
103
|
+
*/
|
|
104
|
+
get concurrencySystem() {
|
|
105
|
+
return this.concurrencySystemDep?.maybeValue;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* The task loop that dispatches this run's requests. Private on purpose — it is a bare parallel task runner with
|
|
109
|
+
* no configuration left of its own (see {@link ConcurrencySystem}), and everything a caller legitimately did
|
|
110
|
+
* with it now has a crawler-level counterpart: {@link BasicCrawler.pause|`pause()`},
|
|
111
|
+
* {@link BasicCrawler.resume|`resume()`}, {@link BasicCrawler.teardown|`teardown()`} and
|
|
112
|
+
* {@link BasicCrawler.concurrencySystem|`concurrencySystem`}.
|
|
101
113
|
*/
|
|
102
114
|
autoscaledPool;
|
|
103
115
|
/**
|
|
@@ -158,12 +170,12 @@ export class BasicCrawler {
|
|
|
158
170
|
additionalHttpErrorStatusCodes;
|
|
159
171
|
ignoreHttpErrorStatusCodes;
|
|
160
172
|
/**
|
|
161
|
-
* The resolved
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
173
|
+
* The resolved options for the crawler's own task loop — the crawler-owned `runTaskFunction`, the (possibly
|
|
174
|
+
* user-overridden) ready/finished predicates and cadence/logging. Concurrency configuration lives on the
|
|
175
|
+
* {@link ConcurrencySystem} instead, and the loop's `consumer` identity is the crawler's own, so neither is
|
|
176
|
+
* settable here.
|
|
165
177
|
*/
|
|
166
|
-
|
|
178
|
+
taskLoopOptions;
|
|
167
179
|
httpClient;
|
|
168
180
|
retryOnBlocked;
|
|
169
181
|
respectRobotsTxtFile;
|
|
@@ -189,7 +201,7 @@ export class BasicCrawler {
|
|
|
189
201
|
sameDomainDelaySecs: ow.optional.number,
|
|
190
202
|
maxRequestsPerCrawl: ow.optional.number,
|
|
191
203
|
maxCrawlDepth: ow.optional.number,
|
|
192
|
-
|
|
204
|
+
taskLoopOptions: ow.optional.object,
|
|
193
205
|
concurrencySystem: ow.optional.object,
|
|
194
206
|
sessionPool: ow.optional.object.validate(validators.sessionPool),
|
|
195
207
|
proxyConfiguration: ow.optional.object.validate(validators.proxyConfiguration),
|
|
@@ -223,7 +235,7 @@ export class BasicCrawler {
|
|
|
223
235
|
// oxlint-disable-next-line typescript/no-deprecated -- still accepted and folded into `requestManager` for back-compat
|
|
224
236
|
requestList,
|
|
225
237
|
// oxlint-disable-next-line typescript/no-deprecated -- still accepted and folded into `requestManager` for back-compat
|
|
226
|
-
requestQueue, requestManager, maxRequestRetries = 3, sameDomainDelaySecs = 0, maxRequestsPerCrawl, maxCrawlDepth,
|
|
238
|
+
requestQueue, requestManager, maxRequestRetries = 3, sameDomainDelaySecs = 0, maxRequestsPerCrawl, maxCrawlDepth, taskLoopOptions = {}, concurrencySystem, keepAlive, sessionPool, proxyConfiguration, additionalHttpErrorStatusCodes = [], ignoreHttpErrorStatusCodes = [],
|
|
227
239
|
// Service locator options
|
|
228
240
|
configuration, storageBackend, eventManager, logger,
|
|
229
241
|
// AutoscaledPool shorthands
|
|
@@ -338,12 +350,12 @@ export class BasicCrawler {
|
|
|
338
350
|
this.maxRequestsPerCrawl = maxRequestsPerCrawl;
|
|
339
351
|
const isMaxPagesExceeded = () => this.maxRequestsPerCrawl && this.maxRequestsPerCrawl <= this.handledRequestsCount;
|
|
340
352
|
// eslint-disable-next-line prefer-const
|
|
341
|
-
let { isFinishedFunction, isTaskReadyFunction } =
|
|
353
|
+
let { isFinishedFunction, isTaskReadyFunction } = taskLoopOptions;
|
|
342
354
|
// override even if `isFinishedFunction` provided by user - `keepAlive` has higher priority
|
|
343
355
|
if (keepAlive) {
|
|
344
356
|
isFinishedFunction = async () => false;
|
|
345
357
|
}
|
|
346
|
-
const
|
|
358
|
+
const crawlerOwnedTaskLoopConfiguration = {
|
|
347
359
|
runTaskFunction: async () => {
|
|
348
360
|
const source = this.requestManager;
|
|
349
361
|
if (!source)
|
|
@@ -428,7 +440,7 @@ export class BasicCrawler {
|
|
|
428
440
|
},
|
|
429
441
|
log: this.log,
|
|
430
442
|
};
|
|
431
|
-
this.
|
|
443
|
+
this.taskLoopOptions = { ...taskLoopOptions, ...crawlerOwnedTaskLoopConfiguration };
|
|
432
444
|
this.resolveConcurrencySystem = () => OwnedOrInjected.resolve(concurrencySystem, () => this.createDefaultConcurrencySystem({
|
|
433
445
|
minConcurrency,
|
|
434
446
|
maxConcurrency,
|
|
@@ -630,7 +642,7 @@ export class BasicCrawler {
|
|
|
630
642
|
}
|
|
631
643
|
else {
|
|
632
644
|
const total = await this.requestManager?.getTotalCount();
|
|
633
|
-
message = `Crawled ${this.stats.state.requestsFinished}${total ? `/${total}` : ''} pages, ${this.stats.state.requestsFailed} failed requests, desired concurrency ${this.
|
|
645
|
+
message = `Crawled ${this.stats.state.requestsFinished}${total ? `/${total}` : ''} pages, ${this.stats.state.requestsFailed} failed requests, desired concurrency ${this.concurrencySystem?.desiredConcurrency ?? 0}.`;
|
|
634
646
|
}
|
|
635
647
|
if (this.statusMessageCallback) {
|
|
636
648
|
await this.statusMessageCallback({
|
|
@@ -647,8 +659,9 @@ export class BasicCrawler {
|
|
|
647
659
|
return { log, stop: () => clearInterval(interval) };
|
|
648
660
|
}
|
|
649
661
|
/**
|
|
650
|
-
* Runs the crawler. Returns a promise that resolves once
|
|
651
|
-
*
|
|
662
|
+
* Runs the crawler. Returns a promise that resolves once every request has been processed and the crawler's
|
|
663
|
+
* finished-check ({@link BasicCrawlerOptions.taskLoopOptions|`taskLoopOptions.isFinishedFunction`}, or the
|
|
664
|
+
* default "the request manager is empty") reports that the crawl is over.
|
|
652
665
|
*
|
|
653
666
|
* We can use the `requests` parameter to enqueue the initial requests — it is a shortcut for
|
|
654
667
|
* running {@link BasicCrawler.addRequests|`crawler.addRequests()`} before {@link BasicCrawler.run|`crawler.run()`}.
|
|
@@ -773,6 +786,32 @@ export class BasicCrawler {
|
|
|
773
786
|
this.log.info(reason);
|
|
774
787
|
this.unexpectedStop = true;
|
|
775
788
|
}
|
|
789
|
+
/**
|
|
790
|
+
* Stops dispatching new requests, letting the in-progress ones finish. Resolves once they have settled, or rejects
|
|
791
|
+
* after `timeoutSecs` if they take too long. Unlike {@link BasicCrawler.stop|`stop()`}, this does not end the
|
|
792
|
+
* run — {@link BasicCrawler.run|`run()`} stays pending until {@link BasicCrawler.resume|`resume()`}.
|
|
793
|
+
*
|
|
794
|
+
* > *NOTE:* The {@link BasicCrawler.concurrencySystem|concurrency system} keeps monitoring and autoscaling
|
|
795
|
+
* throughout, since a shared one may still be serving other crawlers.
|
|
796
|
+
*/
|
|
797
|
+
async pause(timeoutSecs) {
|
|
798
|
+
if (!this.autoscaledPool) {
|
|
799
|
+
this.log.warning('Cannot pause a crawler that is not running.');
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
await this.autoscaledPool.pause(timeoutSecs);
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Resumes a run suspended with {@link BasicCrawler.pause|`pause()`}, letting the crawler dispatch requests
|
|
806
|
+
* again. A no-op on a crawler that is not paused.
|
|
807
|
+
*/
|
|
808
|
+
resume() {
|
|
809
|
+
if (!this.autoscaledPool) {
|
|
810
|
+
this.log.warning('Cannot resume a crawler that is not running.');
|
|
811
|
+
return;
|
|
812
|
+
}
|
|
813
|
+
this.autoscaledPool.resume();
|
|
814
|
+
}
|
|
776
815
|
/**
|
|
777
816
|
* Returns the crawler's {@link IRequestManager|request manager}, opening the default {@link RequestQueue}
|
|
778
817
|
* if none has been configured or opened yet.
|
|
@@ -1035,7 +1074,7 @@ export class BasicCrawler {
|
|
|
1035
1074
|
this.concurrencySystemDep = this.resolveConcurrencySystem();
|
|
1036
1075
|
await this.concurrencySystemDep.ifOwned((system) => system.start());
|
|
1037
1076
|
this.autoscaledPool = new AutoscaledPool({
|
|
1038
|
-
...this.
|
|
1077
|
+
...this.taskLoopOptions,
|
|
1039
1078
|
concurrencySystem: this.concurrencySystemDep.value,
|
|
1040
1079
|
consumer: this.identity,
|
|
1041
1080
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crawlee/basic",
|
|
3
|
-
"version": "4.0.0-beta.
|
|
3
|
+
"version": "4.0.0-beta.93",
|
|
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.3.2",
|
|
44
44
|
"@apify/utilities": "^2.15.5",
|
|
45
|
-
"@crawlee/core": "4.0.0-beta.
|
|
46
|
-
"@crawlee/http-client": "4.0.0-beta.
|
|
47
|
-
"@crawlee/types": "4.0.0-beta.
|
|
48
|
-
"@crawlee/utils": "4.0.0-beta.
|
|
45
|
+
"@crawlee/core": "4.0.0-beta.93",
|
|
46
|
+
"@crawlee/http-client": "4.0.0-beta.93",
|
|
47
|
+
"@crawlee/types": "4.0.0-beta.93",
|
|
48
|
+
"@crawlee/utils": "4.0.0-beta.93",
|
|
49
49
|
"csv-stringify": "^6.5.2",
|
|
50
50
|
"fs-extra": "^11.3.0",
|
|
51
51
|
"ow": "^2.0.0",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"type-fest": "^4.41.0"
|
|
55
55
|
},
|
|
56
56
|
"optionalDependencies": {
|
|
57
|
-
"@crawlee/impit-client": "^4.0.0-beta.
|
|
57
|
+
"@crawlee/impit-client": "^4.0.0-beta.93"
|
|
58
58
|
},
|
|
59
59
|
"lerna": {
|
|
60
60
|
"command": {
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "b9d21e80d94d01e21d4e1c19191610d0157dd172"
|
|
67
67
|
}
|