diff --git a/packages/core/core/src/AssetGraph.js b/packages/core/core/src/AssetGraph.js index 7166dbc97f3..a861a3fd5fd 100644 --- a/packages/core/core/src/AssetGraph.js +++ b/packages/core/core/src/AssetGraph.js @@ -63,7 +63,6 @@ export function nodeFromAssetGroup(assetGroup: AssetGroup): AssetGroupNode { code: assetGroup.code, pipeline: assetGroup.pipeline, query: assetGroup.query ? objectSortedEntries(assetGroup.query) : null, - invalidations: assetGroup.invalidations, }), type: 'asset_group', value: assetGroup, diff --git a/packages/core/core/src/ConfigLoader.js b/packages/core/core/src/ConfigLoader.js deleted file mode 100644 index 871b8a0437d..00000000000 --- a/packages/core/core/src/ConfigLoader.js +++ /dev/null @@ -1,132 +0,0 @@ -// @flow - -import type {Config, ConfigRequestDesc, ParcelOptions} from './types'; -import type ParcelConfig from './ParcelConfig'; - -import invariant from 'assert'; -import nullthrows from 'nullthrows'; -import {md5FromString, PromiseQueue} from '@parcel/utils'; -import {PluginLogger} from '@parcel/logger'; -import path from 'path'; -import ThrowableDiagnostic, {errorToDiagnostic} from '@parcel/diagnostic'; - -import {createConfig} from './InternalConfig'; -import PublicConfig from './public/Config'; - -export default class ConfigLoader { - options: ParcelOptions; - parcelConfig: ParcelConfig; - queue: PromiseQueue; - - constructor({ - options, - config, - }: {| - options: ParcelOptions, - config: ParcelConfig, - |}) { - this.options = options; - this.parcelConfig = config; - this.queue = new PromiseQueue({maxConcurrent: 32}); - } - - load(configRequest: ConfigRequestDesc): Promise { - let promise = this.queue.add(() => this._load(configRequest)); - this.queue.run().catch(() => { - // Do nothing. Promises returned from `add` that will reject if the underlying - // promise rejects. - }); - return promise; - } - - _load(configRequest: ConfigRequestDesc): Promise { - if (!configRequest.plugin) { - return Promise.resolve().then(() => this.loadParcelConfig(configRequest)); - } - - return this.loadPluginConfig(configRequest); - } - - loadParcelConfig(configRequest: ConfigRequestDesc): Config { - let {filePath, isSource, env, pipeline, isURL} = configRequest; - let dir = isSource ? path.dirname(filePath) : this.options.projectRoot; - let searchPath = path.join(dir, 'index'); - let config = createConfig({ - isSource, - searchPath, - env, - }); - let publicConfig = new PublicConfig(config, this.options); - publicConfig.addIncludedFile(this.parcelConfig.filePath); - let devDeps = []; - switch (configRequest.meta.actionType) { - case 'transformation': - devDeps = this.parcelConfig.getTransformerNames( - filePath, - pipeline, - isURL, - ); - break; - case 'validation': - devDeps = this.parcelConfig.getValidatorNames(filePath); - break; - case 'dependency': - devDeps = this.parcelConfig.getResolverNames(); - break; - } - devDeps.forEach(devDep => publicConfig.addDevDependency(devDep)); - - publicConfig.setResultHash(md5FromString(JSON.stringify(devDeps))); - - publicConfig.invalidateOnFileCreate({ - fileName: '.parcelrc', - aboveFilePath: filePath, - }); - - // TODO: get included files from plugin nodes - // TODO: if extended config comes from a package, yarn.lock change should invalidate config request - - return config; - } - - async loadPluginConfig({ - plugin, - env, - isSource, - filePath, - meta: {parcelConfigPath, parcelConfigKeyPath}, - }: ConfigRequestDesc): Promise { - let config = createConfig({ - isSource, - searchPath: filePath, - env, - }); - - invariant(typeof parcelConfigPath === 'string'); - invariant(typeof parcelConfigKeyPath === 'string'); - let packageName = nullthrows(plugin); - let {plugin: pluginInstance} = await this.parcelConfig.loadPlugin({ - packageName, - resolveFrom: parcelConfigPath, - keyPath: parcelConfigKeyPath, - }); - - if (pluginInstance.loadConfig != null) { - try { - await pluginInstance.loadConfig({ - config: new PublicConfig(config, this.options), - options: this.options, - logger: new PluginLogger({origin: nullthrows(plugin)}), - }); - } catch (e) { - throw new ThrowableDiagnostic({ - diagnostic: errorToDiagnostic(e, { - origin: packageName, - }), - }); - } - } - - return config; - } -} diff --git a/packages/core/core/src/InternalConfig.js b/packages/core/core/src/InternalConfig.js index 6ab97829b77..2f4d12b79ab 100644 --- a/packages/core/core/src/InternalConfig.js +++ b/packages/core/core/src/InternalConfig.js @@ -5,23 +5,25 @@ import type { FilePath, PackageName, ConfigResult, + DevDepOptions, } from '@parcel/types'; +import {md5FromString} from '@parcel/utils'; import type {Config, Environment} from './types'; type ConfigOpts = {| + plugin: PackageName, isSource: boolean, searchPath: FilePath, env: Environment, result?: ConfigResult, includedFiles?: Set, invalidateOnFileCreate?: Array, - devDeps?: Map, - shouldRehydrate?: boolean, - shouldReload?: boolean, + devDeps?: Array, shouldInvalidateOnStartup?: boolean, |}; export function createConfig({ + plugin, isSource, searchPath, env, @@ -29,11 +31,10 @@ export function createConfig({ includedFiles, invalidateOnFileCreate, devDeps, - shouldRehydrate, - shouldReload, shouldInvalidateOnStartup, }: ConfigOpts): Config { return { + id: md5FromString(plugin + searchPath + env.id + String(isSource)), isSource, searchPath, env, @@ -41,19 +42,7 @@ export function createConfig({ resultHash: null, includedFiles: includedFiles ?? new Set(), invalidateOnFileCreate: invalidateOnFileCreate ?? [], - pkg: null, - pkgFilePath: null, - devDeps: devDeps ?? new Map(), - shouldRehydrate: shouldRehydrate ?? false, - shouldReload: shouldReload ?? false, + devDeps: devDeps ?? [], shouldInvalidateOnStartup: shouldInvalidateOnStartup ?? false, }; } - -export function addDevDependency( - config: Config, - name: PackageName, - version?: string, -) { - config.devDeps.set(name, version); -} diff --git a/packages/core/core/src/ParcelConfig.js b/packages/core/core/src/ParcelConfig.js index 11db4d984b3..6bda2db3175 100644 --- a/packages/core/core/src/ParcelConfig.js +++ b/packages/core/core/src/ParcelConfig.js @@ -33,7 +33,7 @@ type SerializedParcelConfig = {| options: ParcelOptions, |}; -type LoadedPlugin = {| +export type LoadedPlugin = {| name: string, version: Semver, plugin: T, @@ -101,7 +101,7 @@ export default class ParcelConfig { loadPlugin( node: ParcelPluginNode, - ): Promise<{|plugin: T, version: Semver|}> { + ): Promise<{|plugin: T, version: Semver, resolveFrom: FilePath|}> { let plugin = this.pluginCache.get(node.packageName); if (plugin) { return plugin; @@ -113,22 +113,27 @@ export default class ParcelConfig { node.keyPath, this.options, ); + this.pluginCache.set(node.packageName, plugin); return plugin; } + invalidatePlugin(packageName: PackageName) { + this.pluginCache.delete(packageName); + } + loadPlugins( plugins: PureParcelConfigPipeline, ): Promise>> { return Promise.all( plugins.map(async p => { - let {plugin, version} = await this.loadPlugin(p); + let {plugin, version, resolveFrom} = await this.loadPlugin(p); return { name: p.packageName, plugin, version, - resolveFrom: p.resolveFrom, keyPath: p.keyPath, + resolveFrom, }; }), ); @@ -231,7 +236,11 @@ export default class ParcelConfig { return this.bundler.packageName; } - getBundler(): Promise<{|version: Semver, plugin: Bundler|}> { + getBundler(): Promise<{| + version: Semver, + plugin: Bundler, + resolveFrom: FilePath, + |}> { if (!this.bundler) { throw new Error('No bundler specified in .parcelrc config'); } diff --git a/packages/core/core/src/RequestTracker.js b/packages/core/core/src/RequestTracker.js index 65b1acfe341..f3735670152 100644 --- a/packages/core/core/src/RequestTracker.js +++ b/packages/core/core/src/RequestTracker.js @@ -113,6 +113,8 @@ export type RunAPI = {| invalidateOnOptionChange: string => void, getInvalidations(): Array, storeResult: (result: mixed, cacheKey?: string) => void, + getRequestResult(id: string): Async, + getSubRequests(): Array, canSkipSubrequest(string): boolean, runRequest: ( subRequest: Request, @@ -478,11 +480,27 @@ export class RequestGraph extends Graph< return {type: 'file', filePath: node.value.filePath}; case 'env': return {type: 'env', key: node.value.key}; + case 'option': + return {type: 'option', key: node.value.key}; } }) .filter(Boolean); } + getSubRequests(requestId: string): Array { + if (!this.hasNode(requestId)) { + return []; + } + + let requestNode = this.getRequestNode(requestId); + let subRequests = this.getNodesConnectedFrom(requestNode, 'subrequest'); + + return subRequests.map(node => { + invariant(node.type === 'request'); + return node.value; + }); + } + invalidateFileNameNode( node: FileNameNode, filePath: FilePath, @@ -753,7 +771,7 @@ export default class RequestTracker { createAPI(requestId: string): {|api: RunAPI, subRequests: Set|} { let subRequests = new Set(); let invalidations = this.graph.getInvalidations(requestId); - let api = { + let api: RunAPI = { invalidateOnFileCreate: input => this.graph.invalidateOnFileCreate(requestId, input), invalidateOnFileDelete: filePath => @@ -773,6 +791,8 @@ export default class RequestTracker { storeResult: (result, cacheKey) => { this.storeResult(requestId, result, cacheKey); }, + getSubRequests: () => this.graph.getSubRequests(requestId), + getRequestResult: (id): Async => this.getRequestResult(id), canSkipSubrequest: id => { if (this.hasValidResult(id)) { subRequests.add(id); diff --git a/packages/core/core/src/Transformation.js b/packages/core/core/src/Transformation.js index 187219ef2ea..de7e8acf942 100644 --- a/packages/core/core/src/Transformation.js +++ b/packages/core/core/src/Transformation.js @@ -8,19 +8,20 @@ import type { Transformer, TransformerResult, PackageName, + DevDepOptions, } from '@parcel/types'; import type {WorkerApi} from '@parcel/workers'; import type { Asset as AssetValue, - AssetRequestInput, + TransformationRequest, RequestInvalidation, Config, - ConfigRequestDesc, + DevDepRequest, ParcelOptions, ReportFn, } from './types'; +import type {LoadedPlugin} from './ParcelConfig'; -import invariant from 'assert'; import path from 'path'; import nullthrows from 'nullthrows'; import { @@ -36,8 +37,9 @@ import ThrowableDiagnostic, { md, } from '@parcel/diagnostic'; import {SOURCEMAP_EXTENSIONS} from '@parcel/utils'; +import crypto from 'crypto'; +import v8 from 'v8'; -import ConfigLoader from './ConfigLoader'; import {createDependency} from './Dependency'; import ParcelConfig from './ParcelConfig'; // TODO: eventually call path request as sub requests @@ -57,6 +59,9 @@ import summarizeRequest from './summarizeRequest'; import PluginOptions from './public/PluginOptions'; import {PARCEL_VERSION, FILE_CREATE} from './constants'; import {optionsProxy} from './utils'; +import {createBuildCache} from './buildCache'; +import {createConfig} from './InternalConfig'; +import PublicConfig from './public/Config'; type GenerateFunc = (input: UncommittedAsset) => Promise; @@ -64,27 +69,34 @@ export type TransformationOpts = {| options: ParcelOptions, config: ParcelConfig, report: ReportFn, - request: AssetRequestInput, + request: TransformationRequest, workerApi: WorkerApi, |}; +export type ConfigRequest = {| + id: string, + includedFiles: Set, + invalidateOnFileCreate: Array, + shouldInvalidateOnStartup: boolean, +|}; + export type TransformationResult = {| assets: Array, - configRequests: Array, + configRequests: Array, invalidations: Array, invalidateOnFileCreate: Array, + devDepRequests: Array, |}; -type ConfigMap = Map; -type ConfigRequestAndResult = {| - request: ConfigRequestDesc, - result: Config, -|}; +// A cache of plugin dependency hashes that we've already sent to the main thread. +// Automatically cleared before each build. +const pluginCache = createBuildCache(); +const invalidatedPlugins = createBuildCache(); export default class Transformation { - request: AssetRequestInput; - configLoader: ConfigLoader; - configRequests: Array; + request: TransformationRequest; + configs: Map; + devDepRequests: Map; options: ParcelOptions; pluginOptions: PluginOptions; workerApi: WorkerApi; @@ -100,8 +112,7 @@ export default class Transformation { config, workerApi, }: TransformationOpts) { - this.configRequests = []; - this.configLoader = new ConfigLoader({options, config}); + this.configs = new Map(); this.parcelConfig = config; this.options = options; this.report = report; @@ -109,6 +120,7 @@ export default class Transformation { this.workerApi = workerApi; this.invalidations = new Map(); this.invalidateOnFileCreate = []; + this.devDepRequests = new Map(); this.pluginOptions = new PluginOptions( optionsProxy(this.options, option => { @@ -122,12 +134,6 @@ export default class Transformation { ); } - async loadConfig(configRequest: ConfigRequestDesc): Promise { - let result = await this.configLoader.load(configRequest); - this.configRequests.push({request: configRequest, result}); - return result; - } - async run(): Promise { await initSourcemaps; @@ -162,6 +168,15 @@ export default class Transformation { } } + for (let {moduleSpecifier, resolveFrom} of this.request.invalidDevDeps) { + let key = `${moduleSpecifier}:${resolveFrom}`; + if (!invalidatedPlugins.has(key)) { + this.parcelConfig.invalidatePlugin(moduleSpecifier); + this.options.packageManager.invalidate(moduleSpecifier, resolveFrom); + invalidatedPlugins.set(key, true); + } + } + let pipeline = await this.loadPipeline( this.request.filePath, asset.value.isSource, @@ -170,36 +185,41 @@ export default class Transformation { let results = await this.runPipelines(pipeline, asset); let assets = results.map(a => a.value); - for (let {request, result} of this.configRequests) { - if (request.plugin != null) { - let resolveFrom = request.meta.parcelConfigPath; - let keyPath = request.meta.parcelConfigKeyPath; - invariant( - typeof resolveFrom === 'string', - 'request.meta.parcelConfigPath should be a string!', - ); - invariant( - typeof keyPath === 'string', - 'request.meta.parcelConfigKeyPath should be a string!', + let configRequests = [...this.configs.values()] + .filter(config => { + // No need to send to the graph if there are no invalidations. + return ( + config.includedFiles.size > 0 || + config.invalidateOnFileCreate.length > 0 || + config.shouldInvalidateOnStartup ); - - let {plugin} = await this.parcelConfig.loadPlugin({ - packageName: request.plugin, - resolveFrom, - keyPath, - }); - - if (plugin && plugin.preSerializeConfig) { - plugin.preSerializeConfig({config: result}); - } + }) + .map(config => ({ + id: config.id, + includedFiles: config.includedFiles, + invalidateOnFileCreate: config.invalidateOnFileCreate, + shouldInvalidateOnStartup: config.shouldInvalidateOnStartup, + })); + + let devDepRequests = []; + for (let devDepRequest of this.devDepRequests.values()) { + // If we've already sent a matching transformer + hash to the main thread during this build, + // there's no need to repeat ourselves. + let {moduleSpecifier, resolveFrom, hash} = devDepRequest; + if (hash === pluginCache.get(moduleSpecifier)) { + devDepRequests.push({moduleSpecifier, resolveFrom, hash}); + } else { + pluginCache.set(moduleSpecifier, hash); + devDepRequests.push(devDepRequest); } } return { assets, - configRequests: this.configRequests, + configRequests, invalidateOnFileCreate: this.invalidateOnFileCreate, invalidations: [...this.invalidations.values()], + devDepRequests, }; } @@ -260,26 +280,39 @@ export default class Transformation { initialAsset: UncommittedAsset, ): Promise> { let initialType = initialAsset.value.type; + let initialPipelineHash = await this.getPipelineHash(pipeline); let initialAssetCacheKey = this.getCacheKey( [initialAsset], - pipeline.configs, - await getInvalidationHash(this.request.invalidations || [], this.options), + await getInvalidationHash(this.request.invalidations, this.options), // TODO: should be per-pipeline + initialPipelineHash, ); let initialCacheEntry = await this.readFromCache(initialAssetCacheKey); let assets: Array = initialCacheEntry || (await this.runPipeline(pipeline, initialAsset)); + // Add dev dep requests for each transformer + for (let transformer of pipeline.transformers) { + await this.addDevDependency( + { + moduleSpecifier: transformer.name, + resolveFrom: transformer.resolveFrom, + }, + transformer, + ); + } + if (!initialCacheEntry) { + let pipelineHash = await this.getPipelineHash(pipeline); let resultCacheKey = this.getCacheKey( [initialAsset], - pipeline.configs, await getInvalidationHash( assets.flatMap(asset => asset.getInvalidations()), this.options, ), + pipelineHash, ); - await this.writeToCache(resultCacheKey, assets, pipeline.configs); + await this.writeToCache(resultCacheKey, assets, pipelineHash); } let finalAssets: Array = []; @@ -306,6 +339,125 @@ export default class Transformation { return finalAssets; } + async getPipelineHash(pipeline: Pipeline): Promise { + let hash = crypto.createHash('md5'); + for (let transformer of pipeline.transformers) { + let key = `${transformer.name}:${transformer.resolveFrom}`; + hash.update( + this.request.devDeps.get(key) ?? + this.devDepRequests.get(key)?.hash ?? + '', + ); + + let config = this.configs.get(transformer.name); + if (config) { + hash.update(config.id); + + // If there is no result hash set by the transformer, default to hashing the included + // files if any, otherwise try to hash the config result itself. + if (config.resultHash == null) { + if (config.includedFiles.size > 0) { + hash.update( + await getInvalidationHash( + [...config.includedFiles].map(filePath => ({ + type: 'file', + filePath, + })), + this.options, + ), + ); + } else if (config.result != null) { + try { + // $FlowFixMe + hash.update(v8.serialize(config.result)); + } catch (err) { + throw new ThrowableDiagnostic({ + diagnostic: { + message: + 'Config result is not hashable because it contains non-serializable objects. Please use config.setResultHash to set the hash manually.', + origin: transformer.name, + }, + }); + } + } + } else { + hash.update(config.resultHash ?? ''); + } + + for (let devDep of config.devDeps) { + let key = `${devDep.moduleSpecifier}:${devDep.resolveFrom}`; + hash.update(nullthrows(this.devDepRequests.get(key)).hash); + } + } + } + + return hash.digest('hex'); + } + + async addDevDependency( + opts: DevDepOptions, + transformer: LoadedPlugin | TransformerWithNameAndConfig, + ): Promise { + let {moduleSpecifier, resolveFrom, invalidateParcelPlugin} = opts; + let key = `${moduleSpecifier}:${resolveFrom}`; + if (this.devDepRequests.has(key)) { + return; + } + + // If the request sent us a hash, we know the dev dep and all of its dependencies didn't change. + // Reuse the same hash in the response. No need to send back invalidations as the request won't + // be re-run anyway. + let hash = this.request.devDeps.get(key); + if (hash != null) { + this.devDepRequests.set(key, { + moduleSpecifier, + resolveFrom, + hash, + }); + return; + } + + // Ensure that the package manager has an entry for this resolution. + await this.options.packageManager.resolve(moduleSpecifier, resolveFrom); + let invalidations = this.options.packageManager.getInvalidations( + moduleSpecifier, + resolveFrom, + ); + + // It is possible for a transformer to have multiple different hashes due to + // different dependencies (e.g. conditional requires) so we must always + // recompute the hash and compare rather than only sending a transformer + // dev dependency once. + hash = await getInvalidationHash( + [...invalidations.invalidateOnFileChange].map(f => ({ + type: 'file', + filePath: f, + })), + this.options, + ); + + let devDepRequest: DevDepRequest = { + moduleSpecifier, + resolveFrom, + hash, + invalidateOnFileCreate: invalidations.invalidateOnFileCreate, + invalidateOnFileChange: invalidations.invalidateOnFileChange, + }; + + // Optionally also invalidate the parcel plugin that is loading the config + // when this dev dep changes (e.g. to invalidate local caches). + if (invalidateParcelPlugin) { + devDepRequest.additionalInvalidations = [ + { + moduleSpecifier: transformer.name, + resolveFrom: transformer.resolveFrom, + }, + ]; + } + + this.devDepRequests.set(key, devDepRequest); + } + async runPipeline( pipeline: Pipeline, initialAsset: UncommittedAsset, @@ -404,7 +556,7 @@ export default class Transformation { if ( this.options.shouldDisableCache || this.request.code != null || - (this.request.invalidateReason || 0) & FILE_CREATE + this.request.invalidateReason & FILE_CREATE ) { return null; } @@ -444,17 +596,9 @@ export default class Transformation { async writeToCache( cacheKey: string, assets: Array, - configs: ConfigMap, + pipelineHash: string, ): Promise { - await Promise.all( - assets.map(asset => - asset.commit( - md5FromOrderedObject({ - configs: getImpactfulConfigInfo(configs), - }), - ), - ), - ); + await Promise.all(assets.map(asset => asset.commit(pipelineHash))); this.options.cache.set( cacheKey, @@ -464,8 +608,8 @@ export default class Transformation { getCacheKey( assets: Array, - configs: ConfigMap, invalidationHash: string, + pipelineHash: string, ): string { let assetsKeyInfo = assets.map(a => ({ filePath: a.value.filePath, @@ -478,9 +622,9 @@ export default class Transformation { return md5FromOrderedObject({ parcelVersion: PARCEL_VERSION, assets: assetsKeyInfo, - configs: getImpactfulConfigInfo(configs), env: this.request.env, invalidationHash, + pipelineHash, }); } @@ -489,49 +633,32 @@ export default class Transformation { isSource: boolean, pipeline: ?string, ): Promise { - let configRequest = { - filePath, - env: this.request.env, - isSource, - pipeline: pipeline, - isURL: this.request.isURL, - meta: { - actionType: 'transformation', - }, - }; - let configs = new Map(); - - let config = await this.loadConfig(configRequest); - - configs.set('parcel', config); - let transformers = await this.parcelConfig.getTransformers( filePath, pipeline, this.request.isURL, ); - for (let {name, resolveFrom, keyPath} of transformers) { - let thirdPartyConfig = await this.loadTransformerConfig({ + for (let transformer of transformers) { + let config = await this.loadTransformerConfig( filePath, - plugin: name, - parcelConfigPath: resolveFrom, - parcelConfigKeyPath: keyPath, + transformer, isSource, - }); - - configs.set(name, thirdPartyConfig); + ); + if (config) { + this.configs.set(transformer.name, config); + } } return { id: transformers.map(t => t.name).join(':'), transformers: transformers.map(transformer => ({ name: transformer.name, - config: configs.get(transformer.name)?.result, + resolveFrom: transformer.resolveFrom, + config: this.configs.get(transformer.name)?.result, configKeyPath: transformer.keyPath, plugin: transformer.plugin, })), - configs, options: this.options, resolverRunner: new ResolverRunner({ config: this.parcelConfig, @@ -571,31 +698,42 @@ export default class Transformation { return nextPipeline; } - loadTransformerConfig({ - filePath, - plugin, - parcelConfigPath, - parcelConfigKeyPath, - isSource, - }: {| + async loadTransformerConfig( filePath: FilePath, - plugin: PackageName, - parcelConfigPath: FilePath, - parcelConfigKeyPath: string, + transformer: LoadedPlugin, isSource: boolean, - |}): Promise { - let configRequest = { - filePath, - env: this.request.env, - plugin, + ): Promise { + let loadConfig = transformer.plugin.loadConfig; + if (!loadConfig) { + return; + } + + let config = createConfig({ + plugin: transformer.name, isSource, - meta: { - parcelConfigPath, - parcelConfigKeyPath, - }, - }; + searchPath: filePath, + env: this.request.env, + }); + + try { + await loadConfig({ + config: new PublicConfig(config, this.options), + options: this.options, + logger: new PluginLogger({origin: transformer.name}), + }); + } catch (e) { + throw new ThrowableDiagnostic({ + diagnostic: errorToDiagnostic(e, { + origin: transformer.name, + }), + }); + } + + for (let devDep of config.devDeps) { + await this.addDevDependency(devDep, transformer); + } - return this.loadConfig(configRequest); + return config; } async runTransformer( @@ -710,7 +848,6 @@ export default class Transformation { type Pipeline = {| id: string, transformers: Array, - configs: ConfigMap, options: ParcelOptions, pluginOptions: PluginOptions, resolverRunner: ResolverRunner, @@ -723,6 +860,7 @@ type TransformerWithNameAndConfig = {| plugin: Transformer, config: ?Config, configKeyPath: string, + resolveFrom: FilePath, |}; function normalizeAssets( @@ -757,22 +895,3 @@ function normalizeAssets( }), ); } - -function getImpactfulConfigInfo(configs: ConfigMap) { - let impactfulConfigInfo = {}; - - for (let [configType, {devDeps, resultHash}] of configs) { - let devDepsObject = {}; - - for (let [moduleName, version] of devDeps) { - devDepsObject[moduleName] = version; - } - - impactfulConfigInfo[configType] = { - devDeps: devDepsObject, - resultHash, - }; - } - - return impactfulConfigInfo; -} diff --git a/packages/core/core/src/Validation.js b/packages/core/core/src/Validation.js index be193b4dd33..2481d721d21 100644 --- a/packages/core/core/src/Validation.js +++ b/packages/core/core/src/Validation.js @@ -1,12 +1,7 @@ // @flow strict-local import type {WorkerApi} from '@parcel/workers'; -import type { - AssetGroup, - ConfigRequestDesc, - ParcelOptions, - ReportFn, -} from './types'; +import type {AssetGroup, ParcelOptions, ReportFn} from './types'; import type {Validator, ValidateResult} from '@parcel/types'; import type {Diagnostic} from '@parcel/diagnostic'; @@ -15,7 +10,6 @@ import {resolveConfig, normalizeSeparators} from '@parcel/utils'; import logger, {PluginLogger} from '@parcel/logger'; import ThrowableDiagnostic, {errorToDiagnostic} from '@parcel/diagnostic'; import ParcelConfig from './ParcelConfig'; -import ConfigLoader from './ConfigLoader'; import UncommittedAsset from './UncommittedAsset'; import {createAsset} from './assetUtils'; import {Asset} from './public/Asset'; @@ -39,8 +33,6 @@ export default class Validation { allAssets: {[validatorName: string]: UncommittedAsset[], ...} = {}; allValidators: {[validatorName: string]: Validator, ...} = {}; dedicatedThread: boolean; - configRequests: Array; - configLoader: ConfigLoader; impactfulOptions: $Shape; options: ParcelOptions; parcelConfig: ParcelConfig; @@ -56,7 +48,6 @@ export default class Validation { report, workerApi, }: ValidationOpts) { - this.configLoader = new ConfigLoader({options, config}); this.dedicatedThread = dedicatedThread ?? false; this.options = options; this.parcelConfig = config; diff --git a/packages/core/core/src/assetUtils.js b/packages/core/core/src/assetUtils.js index 378f7077768..fd48fb9201f 100644 --- a/packages/core/core/src/assetUtils.js +++ b/packages/core/core/src/assetUtils.js @@ -38,6 +38,7 @@ import { md5FromFilePath, } from '@parcel/utils'; import {hashFromOption} from './utils'; +import {createBuildCache} from './buildCache'; type AssetOptions = {| id?: string, @@ -220,6 +221,8 @@ export function getInvalidationId(invalidation: RequestInvalidation): string { } } +const hashCache = createBuildCache(); + export async function getInvalidationHash( invalidations: Array, options: ParcelOptions, @@ -235,11 +238,19 @@ export async function getInvalidationHash( let hash = crypto.createHash('md5'); for (let invalidation of sortedInvalidations) { switch (invalidation.type) { - case 'file': - hash.update( - await md5FromFilePath(options.inputFS, invalidation.filePath), - ); + case 'file': { + // Only recompute the hash of this file if we haven't seen it already during this build. + let fileHash = hashCache.get(invalidation.filePath); + if (fileHash == null) { + fileHash = await md5FromFilePath( + options.inputFS, + invalidation.filePath, + ); + hashCache.set(invalidation.filePath, fileHash); + } + hash.update(fileHash); break; + } case 'env': hash.update( invalidation.key + ':' + (options.env[invalidation.key] || ''), diff --git a/packages/core/core/src/buildCache.js b/packages/core/core/src/buildCache.js new file mode 100644 index 00000000000..95c481c346a --- /dev/null +++ b/packages/core/core/src/buildCache.js @@ -0,0 +1,15 @@ +// @flow + +const buildCaches: Array> = []; + +export function createBuildCache(): Map { + let cache = new Map(); + buildCaches.push(cache); + return cache; +} + +export function clearBuildCaches() { + for (let cache of buildCaches) { + cache.clear(); + } +} diff --git a/packages/core/core/src/loadParcelPlugin.js b/packages/core/core/src/loadParcelPlugin.js index 778c988e21d..f44ed2087a2 100644 --- a/packages/core/core/src/loadParcelPlugin.js +++ b/packages/core/core/src/loadParcelPlugin.js @@ -25,7 +25,7 @@ export default async function loadPlugin( configPath: FilePath, keyPath: string, options: ParcelOptions, -): Promise<{|plugin: T, version: Semver|}> { +): Promise<{|plugin: T, version: Semver, resolveFrom: FilePath|}> { let resolveFrom = configPath; let range; if (resolveFrom.includes(NODE_MODULES)) { @@ -156,7 +156,7 @@ export default async function loadPlugin( }); } - let plugin = await options.packageManager.require(resolved, resolveFrom, { + let plugin = await options.packageManager.require(pluginName, resolveFrom, { shouldAutoInstall: options.shouldAutoInstall, }); plugin = plugin.default ? plugin.default : plugin; @@ -169,5 +169,5 @@ export default async function loadPlugin( `Plugin ${pluginName} is not a valid Parcel plugin, should export an instance of a Parcel plugin ex. "export default new Reporter({ ... })".`, ); } - return {plugin, version: nullthrows(pkg).version}; + return {plugin, version: nullthrows(pkg).version, resolveFrom}; } diff --git a/packages/core/core/src/public/Config.js b/packages/core/core/src/public/Config.js index e6acac515d6..8b042685b2a 100644 --- a/packages/core/core/src/public/Config.js +++ b/packages/core/core/src/public/Config.js @@ -5,13 +5,12 @@ import type { FileCreateInvalidation, FilePath, PackageJSON, - PackageName, ConfigResultWithFilePath, + DevDepOptions, } from '@parcel/types'; import type {Config, ParcelOptions} from '../types'; import {DefaultWeakMap, loadConfig} from '@parcel/utils'; - import Environment from './Environment'; const internalConfigToConfig: DefaultWeakMap< @@ -21,6 +20,8 @@ const internalConfigToConfig: DefaultWeakMap< export default class PublicConfig implements IConfig { #config /*: Config */; + #pkg /*: ?PackageJSON */; + #pkgFilePath /*: ?FilePath */; #options /*: ParcelOptions */; constructor(config: Config, options: ParcelOptions): PublicConfig { @@ -68,29 +69,21 @@ export default class PublicConfig implements IConfig { this.#config.includedFiles.add(filePath); } - addDevDependency(name: PackageName, version?: string) { - this.#config.devDeps.set(name, version); + addDevDependency(devDep: DevDepOptions) { + this.#config.devDeps.push(devDep); } invalidateOnFileCreate(invalidation: FileCreateInvalidation) { this.#config.invalidateOnFileCreate.push(invalidation); } - shouldRehydrate() { - this.#config.shouldRehydrate = true; - } - - shouldReload() { - this.#config.shouldReload = true; - } - shouldInvalidateOnStartup() { this.#config.shouldInvalidateOnStartup = true; } async getConfigFrom( searchPath: FilePath, - filePaths: Array, + fileNames: Array, options: ?{| packageKey?: string, parse?: boolean, @@ -104,20 +97,28 @@ export default class PublicConfig implements IConfig { return { contents: pkg[packageKey], // This should be fine as pkgFilePath should be defined by getPackage() - filePath: this.#config.pkgFilePath || '', + filePath: this.#pkgFilePath || '', }; } } - if (filePaths.length === 0) { + if (fileNames.length === 0) { return null; } + // Invalidate when any of the file names are created above the search path. + for (let fileName of fileNames) { + this.invalidateOnFileCreate({ + fileName, + aboveFilePath: searchPath, + }); + } + let parse = options && options.parse; let conf = await loadConfig( this.#options.inputFS, searchPath, - filePaths, + fileNames, parse == null ? null : {parse}, ); if (conf == null) { @@ -147,8 +148,8 @@ export default class PublicConfig implements IConfig { } async getPackage(): Promise { - if (this.#config.pkg) { - return this.#config.pkg; + if (this.#pkg) { + return this.#pkg; } let pkgConfig = await this.getConfig(['package.json']); @@ -156,9 +157,9 @@ export default class PublicConfig implements IConfig { return null; } - this.#config.pkg = pkgConfig.contents; - this.#config.pkgFilePath = pkgConfig.filePath; + this.#pkg = pkgConfig.contents; + this.#pkgFilePath = pkgConfig.filePath; - return this.#config.pkg; + return this.#pkg; } } diff --git a/packages/core/core/src/requests/AssetRequest.js b/packages/core/core/src/requests/AssetRequest.js index 9823505b3ed..20de1676d1d 100644 --- a/packages/core/core/src/requests/AssetRequest.js +++ b/packages/core/core/src/requests/AssetRequest.js @@ -2,7 +2,12 @@ import type {Async} from '@parcel/types'; import type {StaticRunOpts} from '../RequestTracker'; -import type {AssetRequestInput, AssetRequestResult} from '../types'; +import type { + AssetRequestInput, + AssetRequestResult, + DevDepRequest, + TransformationRequest, +} from '../types'; import type {ConfigAndCachePath} from './ParcelConfigRequest'; import type {TransformationResult} from '../Transformation'; @@ -22,10 +27,6 @@ export type AssetRequest = {| input: AssetRequestInput, |}; -function generateRequestId(type, obj) { - return `${type}:${md5FromOrderedObject(obj)}`; -} - export default function createAssetRequest( input: AssetRequestInput, ): AssetRequest { @@ -51,34 +52,69 @@ function getId(input: AssetRequestInput) { code: input.code, pipeline: input.pipeline, query: input.query ? objectSortedEntries(input.query) : null, - invalidations: input.invalidations, }); } -async function run({input, api, options, farm, invalidateReason}: RunInput) { +async function run({input, api, farm, invalidateReason}: RunInput) { api.invalidateOnFileUpdate(input.filePath); let start = Date.now(); - let {optionsRef, ...request} = input; + let {optionsRef, ...rest} = input; let {cachePath} = nullthrows( await api.runRequest(createParcelConfigRequest()), ); - // Add invalidations to the request if a node already exists in the graph. - // These are used to compute the cache key for assets during transformation. - request.invalidations = api.getInvalidations().filter(invalidation => { - // Filter out invalidation node for the input file itself. - return ( - invalidation.type !== 'file' || invalidation.filePath !== input.filePath - ); - }); + let previousDevDepRequests = new Map( + await Promise.all( + api + .getSubRequests() + .filter(req => req.type === 'dev_dep_request') + .map(async req => [ + req.id, + nullthrows(await api.getRequestResult(req.id)), + ]), + ), + ); - request.invalidateReason = invalidateReason; + let request: TransformationRequest = { + ...rest, + invalidateReason, + // Add invalidations to the request if a node already exists in the graph. + // These are used to compute the cache key for assets during transformation. + invalidations: api.getInvalidations().filter(invalidation => { + // Filter out invalidation node for the input file itself. + return ( + invalidation.type !== 'file' || invalidation.filePath !== input.filePath + ); + }), + devDeps: new Map( + [...previousDevDepRequests.entries()] + .filter(([id]) => api.canSkipSubrequest(id)) + .map(([, req]) => [ + `${req.moduleSpecifier}:${req.resolveFrom}`, + req.hash, + ]), + ), + invalidDevDeps: await Promise.all( + [...previousDevDepRequests.entries()] + .filter(([id]) => !api.canSkipSubrequest(id)) + .flatMap(([, req]) => { + return [ + { + moduleSpecifier: req.moduleSpecifier, + resolveFrom: req.resolveFrom, + }, + ...(req.additionalInvalidations ?? []), + ]; + }), + ), + }; let { assets, configRequests, invalidations, invalidateOnFileCreate, + devDepRequests, } = (await farm.createHandle('runTransform')({ configCachePath: cachePath, optionsRef, @@ -111,18 +147,48 @@ async function run({input, api, options, farm, invalidateReason}: RunInput) { } } + for (let devDepRequest of devDepRequests) { + await api.runRequest({ + id: + 'dev_dep_request:' + + devDepRequest.moduleSpecifier + + ':' + + devDepRequest.hash, + type: 'dev_dep_request', + run: ({api}) => { + for (let filePath of nullthrows(devDepRequest.invalidateOnFileChange)) { + api.invalidateOnFileUpdate(filePath); + api.invalidateOnFileDelete(filePath); + } + + for (let invalidation of nullthrows( + devDepRequest.invalidateOnFileCreate, + )) { + api.invalidateOnFileCreate(invalidation); + } + + api.storeResult({ + moduleSpecifier: devDepRequest.moduleSpecifier, + resolveFrom: devDepRequest.resolveFrom, + hash: devDepRequest.hash, + additionalInvalidations: devDepRequest.additionalInvalidations, + }); + }, + input: null, + }); + } + // Add config requests - for (let {request, result} of configRequests) { - let id = generateRequestId('config_request', request); + for (let configRequest of configRequests) { await api.runRequest({ - id, + id: 'config_request:' + configRequest.id, type: 'config_request', run: ({api}) => { let { includedFiles, invalidateOnFileCreate, shouldInvalidateOnStartup, - } = result; + } = configRequest; for (let filePath of includedFiles) { api.invalidateOnFileUpdate(filePath); api.invalidateOnFileDelete(filePath); @@ -138,26 +204,6 @@ async function run({input, api, options, farm, invalidateReason}: RunInput) { }, input: null, }); - - // Add dep version requests - for (let [moduleSpecifier] of result.devDeps) { - let depVersionRequst = { - moduleSpecifier, - resolveFrom: - result.pkgFilePath != null ? result.pkgFilePath : result.searchPath, - }; - let id = generateRequestId('dep_version_request', depVersionRequst); - await api.runRequest({ - id, - type: 'version_request', - run: ({api}) => { - if (options.lockFile != null) { - api.invalidateOnFileUpdate(options.lockFile); - } - }, - input: null, - }); - } } return assets; diff --git a/packages/core/core/src/types.js b/packages/core/core/src/types.js index f90c2a1bead..70460e25d3d 100644 --- a/packages/core/core/src/types.js +++ b/packages/core/core/src/types.js @@ -10,12 +10,10 @@ import type { FileCreateInvalidation, FilePath, Glob, - JSONObject, LogLevel, Meta, ModuleSpecifier, PackageName, - PackageJSON, ReporterEvent, Semver, ServerOptions, @@ -29,6 +27,7 @@ import type { HMROptions, QueryParameters, DetailedReportOptions, + DevDepOptions, } from '@parcel/types'; import type {SharedReference} from '@parcel/workers'; import type {FileSystem} from '@parcel/fs'; @@ -158,6 +157,18 @@ export type RequestInvalidation = | EnvInvalidation | OptionInvalidation; +export type DevDepRequest = {| + moduleSpecifier: ModuleSpecifier, + resolveFrom: FilePath, + hash: string, + invalidateOnFileCreate?: Array, + invalidateOnFileChange?: Set, + additionalInvalidations?: Array<{| + moduleSpecifier: ModuleSpecifier, + resolveFrom: FilePath, + |}>, +|}; + export type ParcelOptions = {| entries: Array, entryRoot: FilePath, @@ -258,8 +269,6 @@ export type AssetRequestInput = {| optionsRef: SharedReference, isURL?: boolean, query?: ?QueryParameters, - invalidations?: Array, - invalidateReason?: number, |}; export type AssetRequestResult = Array; @@ -279,6 +288,17 @@ export type AssetGroupNode = {| usedSymbolsDownDirty: boolean, |}; +export type TransformationRequest = {| + ...AssetGroup, + invalidations: Array, + invalidateReason: number, + devDeps: Map, + invalidDevDeps: Array<{| + moduleSpecifier: ModuleSpecifier, + resolveFrom: FilePath, + |}>, +|}; + export type DepPathRequestNode = {| id: string, +type: 'dep_path_request', @@ -328,38 +348,19 @@ export type BundleGraphNode = | BundleGroupNode | BundleNode; -export type ConfigRequestNode = {| - id: string, - +type: 'config_request', - value: ConfigRequestDesc, -|}; - export type Config = {| + id: string, isSource: boolean, searchPath: FilePath, env: Environment, resultHash: ?string, result: ConfigResult, includedFiles: Set, - pkg: ?PackageJSON, - pkgFilePath: ?FilePath, invalidateOnFileCreate: Array, - devDeps: Map, - shouldRehydrate: boolean, - shouldReload: boolean, + devDeps: Array, shouldInvalidateOnStartup: boolean, |}; -export type ConfigRequestDesc = {| - filePath: FilePath, - env: Environment, - isSource: boolean, - pipeline?: ?string, - isURL?: boolean, - plugin?: PackageName, - meta: JSONObject, -|}; - export type DepVersionRequestNode = {| id: string, +type: 'dep_version_request', diff --git a/packages/core/core/src/worker.js b/packages/core/core/src/worker.js index b6bd370afa9..a008392e41b 100644 --- a/packages/core/core/src/worker.js +++ b/packages/core/core/src/worker.js @@ -16,6 +16,7 @@ import PackagerRunner, {type BundleInfo} from './PackagerRunner'; import Validation, {type ValidationOpts} from './Validation'; import ParcelConfig from './ParcelConfig'; import {registerCoreWithSerializer} from './utils'; +import {clearBuildCaches} from './buildCache'; import '@parcel/cache'; // register with serializer import '@parcel/package-manager'; @@ -50,7 +51,7 @@ function loadOptions(ref, workerApi) { async function loadConfig(cachePath, options) { let config = parcelConfigCache.get(cachePath); - if (config) { + if (config && config.options === options) { return config; } @@ -66,6 +67,7 @@ async function loadConfig(cachePath, options) { export function clearConfigCache() { configCache.clear(); + clearBuildCaches(); } export async function runTransform( @@ -152,7 +154,7 @@ export async function runPackage( ); } -const PKG_RE = /node_modules[/\\]((?:@[^/\\]+\/[^/\\]+)|[^/\\]+)(?!.*[/\\]node_modules[/\\])/; +const PKG_RE = /node_modules[/\\]((?:@[^/\\]+[/\\][^/\\]+)|[^/\\]+)(?!.*[/\\]node_modules[/\\])/; export function invalidateRequireCache(workerApi: WorkerApi, file: string) { if (process.env.PARCEL_BUILD_ENV === 'test') { // Delete this module and all children in the same node_modules folder diff --git a/packages/core/core/test/TargetRequest.test.js b/packages/core/core/test/TargetRequest.test.js index eacc92b78e8..cbcd8a6d620 100644 --- a/packages/core/core/test/TargetRequest.test.js +++ b/packages/core/core/test/TargetRequest.test.js @@ -86,6 +86,10 @@ describe('TargetResolver', () => { canSkipSubrequest() { return false; }, + getRequestResult() {}, + getSubRequests() { + return []; + }, }; it('resolves exactly specified targets', async () => { diff --git a/packages/core/diagnostic/test/markdown.test.js b/packages/core/diagnostic/test/markdown.test.js index c4657a510b5..a882b1a0440 100644 --- a/packages/core/diagnostic/test/markdown.test.js +++ b/packages/core/diagnostic/test/markdown.test.js @@ -1,7 +1,7 @@ // @flow import assert from 'assert'; -import {escapeMarkdown, md} from '../'; +import {escapeMarkdown, md} from '../src/diagnostic'; describe('escapeMarkdown', () => { it('returns an escaped string 01', () => { diff --git a/packages/core/integration-tests/test/cache.js b/packages/core/integration-tests/test/cache.js index 96c0d8ec806..1eab11a3549 100644 --- a/packages/core/integration-tests/test/cache.js +++ b/packages/core/integration-tests/test/cache.js @@ -16,6 +16,7 @@ import { import {md} from '@parcel/diagnostic'; import fs from 'fs'; import {NodePackageManager} from '@parcel/package-manager'; +import {createWorkerFarm} from '@parcel/core'; let inputDir: string; let packageManager = new NodePackageManager(inputFS); @@ -194,43 +195,19 @@ describe('cache', function() { // {name: 'babel.config.mjs', formatter: mjs, nesting: false} ]; - let testBabelCache = async (opts: TestConfig) => { - await workerFarm.callAllWorkers('invalidateRequireCache', [ - packageManager.resolveSync('@parcel/transformer-babel', __filename) - ?.resolved, - ]); - + before(async () => { + // Invalidate @babel/core before any of these tests run so that it is required + // through NodePackageManager and we are able to track module children. + // Otherwise, it will already have been loaded by @babel/register. await workerFarm.callAllWorkers('invalidateRequireCache', [ packageManager.resolveSync('@babel/core', __filename)?.resolved, ]); - - return testCache({ - ...opts, - async update(...args) { - await opts.update(...args); - - // invalidate babel's caches since we're simulating a process restart - await workerFarm.callAllWorkers('invalidateRequireCache', [ - packageManager.resolveSync('@parcel/transformer-babel', __filename) - ?.resolved, - ]); - await workerFarm.callAllWorkers('invalidateRequireCache', [ - packageManager.resolveSync('@babel/core', __filename)?.resolved, - ]); - }, - }); - }; + }); for (let {name, formatter, nesting} of configs) { describe(name, function() { - beforeEach(async () => { - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, name), - ]); - }); - it(`should support adding a ${name}`, async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -277,7 +254,7 @@ describe('cache', function() { }); it(`should support updating a ${name}`, async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -313,10 +290,6 @@ describe('cache', function() { }), ); - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, name), - ]); - await sleep(100); }, }); @@ -332,7 +305,7 @@ describe('cache', function() { }); it(`should support deleting a ${name}`, async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -376,7 +349,7 @@ describe('cache', function() { it(`should support updating an extended ${name}`, async function() { let extendedName = '.babelrc-extended' + path.extname(name); - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -400,9 +373,6 @@ describe('cache', function() { extends: `./${extendedName}`, }), ); - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, extendedName), - ]); }, async update(b) { let contents = await overlayFS.readFile( @@ -421,10 +391,6 @@ describe('cache', function() { }), ); - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, extendedName), - ]); - await sleep(100); }, }); @@ -441,7 +407,7 @@ describe('cache', function() { if (nesting) { it(`should support adding a nested ${name}`, async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -496,7 +462,7 @@ describe('cache', function() { }); it(`should support updating a nested ${name}`, async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -514,9 +480,6 @@ describe('cache', function() { ], }), ); - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, `src/nested/${name}`), - ]); }, async update(b) { let contents = await overlayFS.readFile( @@ -539,10 +502,6 @@ describe('cache', function() { }), ); - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, `src/nested/${name}`), - ]); - await sleep(100); }, }); @@ -562,7 +521,7 @@ describe('cache', function() { }); it(`should support deleting a nested ${name}`, async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -617,7 +576,7 @@ describe('cache', function() { describe('.babelignore', function() { it('should support adding a .babelignore', async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -672,7 +631,7 @@ describe('cache', function() { }); it('should support updating a .babelignore', async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -727,7 +686,7 @@ describe('cache', function() { }); it('should support deleting a .babelignore', async function() { - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -780,8 +739,8 @@ describe('cache', function() { }); describe('plugins', function() { - it('should invalidate when plugins change versions', async function() { - let b = await testBabelCache({ + it('should invalidate when plugins are updated', async function() { + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -842,21 +801,6 @@ describe('cache', function() { source.replace('hello there', 'replaced'), ); - await inputFS.writeFile( - path.join( - inputDir, - 'node_modules/babel-plugin-dummy/package.json', - ), - JSON.stringify({ - name: 'babel-plugin-dummy', - version: '2.0.0', - }), - ); - - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, 'node_modules/babel-plugin-dummy/index.js'), - ]); - await sleep(100); }, }); @@ -868,8 +812,8 @@ describe('cache', function() { assert(contents.includes('replaced'), 'string should be replaced'); }); - it('should invalidate on startup when there are relative plugins', async function() { - let b = await testBabelCache({ + it('should invalidate when there are relative plugins', async function() { + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -914,10 +858,6 @@ describe('cache', function() { source.replace('hello there', 'replaced'), ); - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, 'babel-plugin-dummy.js'), - ]); - await sleep(100); }, }); @@ -929,14 +869,14 @@ describe('cache', function() { assert(contents.includes('replaced'), 'string should be replaced'); }); - it('should invalidate on startup when there are symlinked plugins', async function() { + it('should invalidate when there are symlinked plugins', async function() { // Symlinks don't work consistently on windows. Skip this test. if (process.platform === 'win32') { this.skip(); return; } - let b = await testBabelCache({ + let b = await testCache({ // Babel's config loader only works with the node filesystem inputFS, outputFS: inputFS, @@ -999,10 +939,6 @@ describe('cache', function() { source.replace('hello there', 'replaced'), ); - await workerFarm.callAllWorkers('invalidateRequireCache', [ - path.join(inputDir, 'packages/babel-plugin-dummy/index.js'), - ]); - await sleep(100); }, }); @@ -3598,6 +3534,547 @@ describe('cache', function() { }); }); + describe('dev deps', function() { + it('should invalidate when updating a parcel transformer plugin', async function() { + let b = await testCache({ + async setup() { + await overlayFS.writeFile( + path.join(inputDir, '.parcelrc'), + JSON.stringify({ + extends: '@parcel/config-default', + transformers: { + '*.js': ['parcel-transformer-mock'], + }, + }), + ); + }, + async update(b) { + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('TRANSFORMED CODE')); + + let transformerDir = path.join( + inputDir, + 'node_modules', + 'parcel-transformer-mock', + ); + await overlayFS.writeFile( + path.join(transformerDir, 'constants.js'), + 'exports.message = "UPDATED"', + ); + }, + }); + + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('UPDATED')); + }); + + it('should resolve to package.json#main over an index.js', async function() { + let b = await testCache({ + async setup() { + await overlayFS.writeFile( + path.join(inputDir, '.parcelrc'), + JSON.stringify({ + extends: '@parcel/config-default', + transformers: { + '*.js': ['parcel-transformer-mock'], + }, + }), + ); + }, + async update(b) { + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('TRANSFORMED CODE')); + + let transformerDir = path.join( + inputDir, + 'node_modules', + 'parcel-transformer-mock', + ); + await overlayFS.writeFile( + path.join(transformerDir, 'MockTransformer.js'), + ` + const Transformer = require('@parcel/plugin').Transformer; + module.exports = new Transformer({ + transform({asset}) { + return [ + { + type: 'js', + content: 'UPDATED', + }, + ]; + } + }); + `, + ); + + await overlayFS.writeFile( + path.join(transformerDir, 'package.json'), + JSON.stringify({main: 'MockTransformer.js'}), + ); + }, + }); + + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('UPDATED')); + }); + + it('should resolve to a file over a directory with an index.js', async function() { + let transformerDir = path.join( + inputDir, + 'node_modules', + 'parcel-transformer-mock', + ); + let b = await testCache({ + async setup() { + await overlayFS.writeFile( + path.join(inputDir, '.parcelrc'), + JSON.stringify({ + extends: '@parcel/config-default', + transformers: { + '*.js': ['parcel-transformer-mock'], + }, + }), + ); + + await overlayFS.unlink(path.join(transformerDir, 'constants.js')); + await overlayFS.mkdirp(path.join(transformerDir, 'constants')); + await overlayFS.writeFile( + path.join(transformerDir, 'constants', 'index.js'), + 'exports.message = "TRANSFORMED"', + ); + }, + async update(b) { + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('TRANSFORMED')); + + await overlayFS.writeFile( + path.join(transformerDir, 'constants.js'), + 'exports.message = "UPDATED"', + ); + }, + }); + + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('UPDATED')); + }); + + it('should support adding a deeper node_modules folder', async function() {}); + + it('should support yarn pnp', async function() { + // $FlowFixMe + let Module = require('module'); + let origPnpVersion = process.versions.pnp; + let origModuleResolveFilename = Module._resolveFilename; + + // We must create a worker farm that only uses a single thread because our process.versions.pnp + // mock won't be available in the workers of the existing farm. + let workerFarm = createWorkerFarm({ + maxConcurrentWorkers: 0, + }); + + try { + let b = await testCache({ + inputFS, + outputFS: inputFS, + workerFarm, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/cache'), + inputDir, + ); + + // $FlowFixMe + process.versions.pnp = 42; + + fs.renameSync( + path.join(inputDir, 'node_modules'), + path.join(inputDir, 'pnp'), + ); + + await inputFS.ncp( + path.join(inputDir, 'pnp'), + path.join(inputDir, 'pnp2'), + ); + + await inputFS.writeFile( + path.join(inputDir, 'pnp', 'parcel-transformer-mock', 'index.js'), + ` + const Transformer = require('@parcel/plugin').Transformer; + module.exports = new Transformer({ + transform({asset}) { + return [ + { + type: 'js', + content: 'TRANSFORMED CODE', + }, + ]; + } + }); + `, + ); + + await inputFS.writeFile( + path.join( + inputDir, + 'pnp2', + 'parcel-transformer-mock', + 'index.js', + ), + ` + const Transformer = require('@parcel/plugin').Transformer; + module.exports = new Transformer({ + transform({asset}) { + return [ + { + type: 'js', + content: 'UPDATED', + }, + ]; + } + }); + `, + ); + + await inputFS.writeFile( + path.join(inputDir, '.pnp.js'), + ` + const path = require('path'); + const resolve = request => { + if (request === 'parcel-transformer-mock' || request === 'foo') { + return path.join(__dirname, 'pnp', request); + } else if (request === 'pnpapi') { + return __filename; + } else { + return require.resolve(request); + } + }; + + module.exports = {resolveToUnqualified: resolve, resolveRequest: resolve}; + `, + ); + + Module.findPnpApi = () => + // $FlowFixMe + require(path.join(inputDir, '.pnp.js')); + + await inputFS.writeFile( + path.join(inputDir, '.parcelrc'), + JSON.stringify({ + extends: '@parcel/config-default', + transformers: { + '*.js': ['parcel-transformer-mock'], + }, + }), + ); + }, + async update(b) { + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('TRANSFORMED CODE')); + + await inputFS.writeFile( + path.join(inputDir, '.pnp.js'), + ` + const path = require('path'); + const resolve = request => { + if (request === 'parcel-transformer-mock' || request === 'foo') { + return path.join(__dirname, 'pnp2', request); + } else if (request === 'pnpapi') { + return __filename; + } else { + return require.resolve(request); + } + }; + + module.exports = {resolveToUnqualified: resolve, resolveRequest: resolve}; + `, + ); + + delete require.cache[path.join(inputDir, '.pnp.js')]; + await sleep(100); + }, + }); + + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('UPDATED')); + } finally { + process.versions.pnp = origPnpVersion; + Module._resolveFilename = origModuleResolveFilename; + await workerFarm.end(); + } + }); + + describe('postcss', function() { + it('should invalidate when a postcss plugin changes', async function() { + let b = await testCache( + { + entries: ['index.css'], + async setup() { + await overlayFS.mkdirp(path.join(inputDir, 'node_modules')); + await ncp( + path.join( + path.join( + __dirname, + 'integration', + 'postcss-autoinstall', + 'postcss-test', + ), + ), + path.join(inputDir, 'node_modules', 'postcss-test'), + ); + }, + async update(b) { + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('background: green')); + + let plugin = path.join( + inputDir, + 'node_modules', + 'postcss-test', + 'index.js', + ); + let pluginContents = await overlayFS.readFile(plugin, 'utf8'); + await overlayFS.writeFile( + plugin, + pluginContents.replace('green', 'blue'), + ); + }, + }, + 'postcss-autoinstall/npm', + ); + + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('background: blue')); + }); + + it('should invalidate when a JS postcss config changes', async function() { + let b = await testCache( + { + entries: ['style.css'], + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/postcss-js-config-7'), + inputDir, + ); + }, + async update(b) { + let output = await inputFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('background-color: red;')); + + let config = path.join(inputDir, 'postcss.config.js'); + let configContents = await inputFS.readFile(config, 'utf8'); + await inputFS.writeFile( + config, + configContents.replace('red', 'blue'), + ); + await sleep(100); + }, + }, + 'postcss-js-config-7', + ); + + let output = await inputFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('background-color: blue')); + }); + + it('should invalidate when a JSON postcss config changes', async function() { + let b = await testCache( + { + entries: ['nested/index.css'], + async update(b) { + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('background-color: green;')); + + let configContents = await overlayFS.readFile( + path.join(inputDir, '.postcssrc'), + 'utf8', + ); + await overlayFS.writeFile( + path.join(inputDir, '.postcssrc'), + configContents.replace('green', 'blue'), + ); + }, + }, + 'postcss-import', + ); + + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('background-color: blue')); + }); + + it('should invalidate when a closer postcss config is added', async function() { + let b = await testCache( + { + entries: ['nested/index.css'], + async update(b) { + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('background-color: green;')); + + let configContents = await overlayFS.readFile( + path.join(inputDir, '.postcssrc'), + 'utf8', + ); + await overlayFS.writeFile( + path.join(inputDir, 'nested', '.postcssrc'), + configContents.replace('green', 'blue'), + ); + }, + }, + 'postcss-import', + ); + + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('background-color: blue')); + }); + }); + + describe('posthtml', function() { + it('should invalidate when a posthtml plugin changes', async function() { + let b = await testCache( + { + entries: ['index.html'], + async setup() { + await overlayFS.mkdirp(path.join(inputDir, 'node_modules')); + await ncp( + path.join( + path.join( + __dirname, + 'integration', + 'posthtml-autoinstall', + 'posthtml-test', + ), + ), + path.join(inputDir, 'node_modules', 'posthtml-test'), + ); + }, + async update(b) { + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('Test')); + + let plugin = path.join( + inputDir, + 'node_modules', + 'posthtml-test', + 'index.js', + ); + let pluginContents = await overlayFS.readFile(plugin, 'utf8'); + await overlayFS.writeFile( + plugin, + pluginContents.replace('span', 'section'), + ); + }, + }, + 'posthtml-autoinstall', + ); + + let output = await overlayFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('
Test
')); + }); + + it('should invalidate when a JS postcss config changes', async function() { + let b = await testCache( + { + entries: ['index.html'], + inputFS, + outputFS: inputFS, + async setup() { + await inputFS.mkdirp(inputDir); + await inputFS.ncp( + path.join(__dirname, '/integration/posthtml'), + inputDir, + ); + + await inputFS.mkdirp(path.join(inputDir, 'include')); + await inputFS.writeFile( + path.join(inputDir, 'include', 'other.html'), + '

Another great page

', + ); + }, + async update(b) { + let output = await inputFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('

Other page

')); + + let config = path.join(inputDir, '.posthtmlrc.js'); + let configContents = await inputFS.readFile(config, 'utf8'); + await inputFS.writeFile( + config, + configContents.replace('__dirname', '__dirname + "/include"'), + ); + await sleep(100); + }, + }, + 'posthtml', + ); + + let output = await inputFS.readFile( + b.bundleGraph.getBundles()[0].filePath, + 'utf8', + ); + assert(output.includes('

Another great page

')); + }); + }); + }); + describe('bundler config', function() { it('should support adding bundler config', function() {}); diff --git a/packages/core/integration-tests/test/integration/cache/node_modules/parcel-transformer-mock/constants.js b/packages/core/integration-tests/test/integration/cache/node_modules/parcel-transformer-mock/constants.js new file mode 100644 index 00000000000..53da0d25499 --- /dev/null +++ b/packages/core/integration-tests/test/integration/cache/node_modules/parcel-transformer-mock/constants.js @@ -0,0 +1 @@ +exports.message = 'TRANSFORMED CODE'; diff --git a/packages/core/integration-tests/test/integration/cache/node_modules/parcel-transformer-mock/index.js b/packages/core/integration-tests/test/integration/cache/node_modules/parcel-transformer-mock/index.js index b78f1a9fdcc..0083740b73b 100644 --- a/packages/core/integration-tests/test/integration/cache/node_modules/parcel-transformer-mock/index.js +++ b/packages/core/integration-tests/test/integration/cache/node_modules/parcel-transformer-mock/index.js @@ -1,12 +1,20 @@ const Transformer = require('@parcel/plugin').Transformer; module.exports = new Transformer({ - transform() { + transform({asset}) { + if (asset.isSource) { + asset.addDependency({ + moduleSpecifier: 'foo' + }); + return [asset]; + } + + const {message} = require('./constants'); return [ { type: 'js', - content: 'TRANSFORMED CODE', + content: message, }, ]; } -}) +}); diff --git a/packages/core/integration-tests/test/integration/postcss-import/.postcssrc b/packages/core/integration-tests/test/integration/postcss-import/.postcssrc index e30e576e333..319dbe65a32 100644 --- a/packages/core/integration-tests/test/integration/postcss-import/.postcssrc +++ b/packages/core/integration-tests/test/integration/postcss-import/.postcssrc @@ -1,6 +1,12 @@ { "plugins": { "postcss-import": {}, - "postcss-custom-properties": {} + "postcss-custom-properties": { + "importFrom": [{ + "customProperties": { + "--varColor": "green" + } + }] + } } } diff --git a/packages/core/integration-tests/test/integration/postcss-import/nested/index.css b/packages/core/integration-tests/test/integration/postcss-import/nested/index.css new file mode 100644 index 00000000000..3d9d7b505b4 --- /dev/null +++ b/packages/core/integration-tests/test/integration/postcss-import/nested/index.css @@ -0,0 +1,3 @@ +body { + background-color: var(--varColor); +} diff --git a/packages/core/integration-tests/test/integration/posthtml-autoinstall/.posthtmlrc b/packages/core/integration-tests/test/integration/posthtml-autoinstall/.posthtmlrc new file mode 100644 index 00000000000..1d758936f1e --- /dev/null +++ b/packages/core/integration-tests/test/integration/posthtml-autoinstall/.posthtmlrc @@ -0,0 +1,5 @@ +{ + "plugins": { + "posthtml-test": {} + } +} diff --git a/packages/core/integration-tests/test/integration/posthtml-autoinstall/index.html b/packages/core/integration-tests/test/integration/posthtml-autoinstall/index.html new file mode 100644 index 00000000000..0bcb5959907 --- /dev/null +++ b/packages/core/integration-tests/test/integration/posthtml-autoinstall/index.html @@ -0,0 +1 @@ +
Test
diff --git a/packages/core/integration-tests/test/integration/posthtml-autoinstall/package.json b/packages/core/integration-tests/test/integration/posthtml-autoinstall/package.json new file mode 100644 index 00000000000..0f3015c86f8 --- /dev/null +++ b/packages/core/integration-tests/test/integration/posthtml-autoinstall/package.json @@ -0,0 +1,4 @@ +{ + "name": "posthtml-autoinstall", + "private": true +} diff --git a/packages/core/integration-tests/test/integration/posthtml-autoinstall/posthtml-test/index.js b/packages/core/integration-tests/test/integration/posthtml-autoinstall/posthtml-test/index.js new file mode 100644 index 00000000000..f4e5555b5bf --- /dev/null +++ b/packages/core/integration-tests/test/integration/posthtml-autoinstall/posthtml-test/index.js @@ -0,0 +1,8 @@ +module.exports = () => (tree) => { + tree.match({tag: 'div'}, node => { + node.tag = 'span'; + return node; + }); + + return tree; +}; diff --git a/packages/core/integration-tests/test/integration/posthtml-autoinstall/posthtml-test/package.json b/packages/core/integration-tests/test/integration/posthtml-autoinstall/posthtml-test/package.json new file mode 100644 index 00000000000..97aa9e24a7e --- /dev/null +++ b/packages/core/integration-tests/test/integration/posthtml-autoinstall/posthtml-test/package.json @@ -0,0 +1,4 @@ +{ + "name": "posthtml-test", + "private": true +} diff --git a/packages/core/integration-tests/test/integration/posthtml-autoinstall/yarn.lock b/packages/core/integration-tests/test/integration/posthtml-autoinstall/yarn.lock new file mode 100644 index 00000000000..e69de29bb2d diff --git a/packages/core/integration-tests/test/posthtml.js b/packages/core/integration-tests/test/posthtml.js index 0d7c674bcdc..517bd3cf6e2 100644 --- a/packages/core/integration-tests/test/posthtml.js +++ b/packages/core/integration-tests/test/posthtml.js @@ -4,9 +4,16 @@ import { assertBundles, removeDistDirectory, distDir, + inputFS, outputFS, + overlayFS, + ncp, } from '@parcel/test-utils'; import path from 'path'; +import { + NodePackageManager, + MockPackageInstaller, +} from '@parcel/package-manager'; describe('posthtml', function() { afterEach(async () => { @@ -95,4 +102,50 @@ describe('posthtml', function() { assert(asset.dependencies.has(other)); assert(asset.dependencies.get(other).includedInParent); }); + + it('should automatically install posthtml plugins if needed', async () => { + await outputFS.rimraf(path.join(__dirname, '/input')); + await ncp( + path.join(__dirname, '/integration/posthtml-autoinstall'), + path.join(__dirname, '/input'), + ); + + let packageInstaller = new MockPackageInstaller(); + packageInstaller.register( + 'posthtml-test', + inputFS, + path.join(__dirname, '/integration/posthtml-autoinstall/posthtml-test'), + ); + + // The package manager uses an overlay filesystem, which performs writes to + // an in-memory fs and reads first from memory, then falling back to the real fs. + let packageManager = new NodePackageManager(overlayFS, packageInstaller); + + let distDir = path.join(outputFS.cwd(), 'dist'); + + await bundle(path.join(__dirname, '/input/index.html'), { + inputFS: overlayFS, + packageManager, + shouldAutoInstall: true, + defaultTargetOptions: { + distDir, + }, + }); + + // posthtml-test was installed + let pkg = JSON.parse( + await outputFS.readFile( + path.join(__dirname, '/input/package.json'), + 'utf8', + ), + ); + assert(pkg.devDependencies['posthtml-test']); + + // posthtml-test is applied + let html = await outputFS.readFile( + path.join(distDir, 'index.html'), + 'utf8', + ); + assert(html.includes('Test')); + }); }); diff --git a/packages/core/package-manager/src/NodePackageManager.js b/packages/core/package-manager/src/NodePackageManager.js index 018b0e09ca1..19907544077 100644 --- a/packages/core/package-manager/src/NodePackageManager.js +++ b/packages/core/package-manager/src/NodePackageManager.js @@ -6,6 +6,7 @@ import type { PackageManager, PackageInstaller, InstallOptions, + Invalidations, } from './types'; import type {ResolveResult} from './NodeResolverBase'; @@ -28,6 +29,11 @@ import pkg from '../package.json'; import {NodeResolver} from './NodeResolver'; import {NodeResolverSync} from './NodeResolverSync'; +// There can be more than one instance of NodePackageManager, but node has only a single module cache. +// Therefore, the resolution cache and the map of parent to child modules should also be global. +const cache = new Map(); +const children = new Map>(); + // This implements a package manager for Node by monkey patching the Node require // algorithm so that it uses the specified FileSystem instead of the native one. // It also handles installing packages when they are required if not already installed. @@ -36,7 +42,6 @@ import {NodeResolverSync} from './NodeResolverSync'; export class NodePackageManager implements PackageManager { fs: FileSystem; installer: ?PackageInstaller; - cache: Map = new Map(); resolver: NodeResolver; syncResolver: NodeResolverSync; @@ -131,10 +136,10 @@ export class NodePackageManager implements PackageManager { ): Promise { let basedir = path.dirname(from); let key = basedir + ':' + name; - let resolved = this.cache.get(key); + let resolved = cache.get(key); if (!resolved) { try { - resolved = await this.resolver.resolve(name, basedir); + resolved = await this.resolver.resolve(name, from); } catch (e) { if ( e.code !== 'MODULE_NOT_FOUND' || @@ -252,7 +257,20 @@ export class NodePackageManager implements PackageManager { } } - this.cache.set(key, resolved); + cache.set(key, resolved); + + // Add the specifier as a child to the parent module. + // Don't do this if the specifier was an absolute path, as this was likely a dynamically resolved path + // (e.g. babel uses require() to load .babelrc.js configs and we don't want them to be added as children of babel itself). + if (!path.isAbsolute(name)) { + let moduleChildren = children.get(from); + if (!moduleChildren) { + moduleChildren = new Set(); + children.set(from, moduleChildren); + } + + moduleChildren.add(name); + } } return resolved; @@ -260,7 +278,24 @@ export class NodePackageManager implements PackageManager { resolveSync(name: ModuleSpecifier, from: FilePath): ResolveResult { let basedir = path.dirname(from); - return this.syncResolver.resolve(name, basedir); + let key = basedir + ':' + name; + let resolved = cache.get(key); + if (!resolved) { + resolved = this.syncResolver.resolve(name, from); + cache.set(key, resolved); + + if (!path.isAbsolute(name)) { + let moduleChildren = children.get(from); + if (!moduleChildren) { + moduleChildren = new Set(); + children.set(from, moduleChildren); + } + + moduleChildren.add(name); + } + } + + return resolved; } async install( @@ -273,6 +308,82 @@ export class NodePackageManager implements PackageManager { ...opts, }); } + + getInvalidations(name: ModuleSpecifier, from: FilePath): Invalidations { + let res = { + invalidateOnFileCreate: [], + invalidateOnFileChange: new Set(), + }; + + let seen = new Set(); + let addKey = (name, from) => { + let basedir = path.dirname(from); + let key = basedir + ':' + name; + if (seen.has(key)) { + return; + } + + seen.add(key); + let resolved = cache.get(key); + if (!resolved || !path.isAbsolute(resolved.resolved)) { + return; + } + + res.invalidateOnFileCreate.push(...resolved.invalidateOnFileCreate); + res.invalidateOnFileChange.add(resolved.resolved); + + for (let file of resolved.invalidateOnFileChange) { + res.invalidateOnFileChange.add(file); + } + + let moduleChildren = children.get(resolved.resolved); + if (moduleChildren) { + for (let specifier of moduleChildren) { + addKey(specifier, resolved.resolved); + } + } + }; + + addKey(name, from); + return res; + } + + invalidate(name: ModuleSpecifier, from: FilePath) { + let seen = new Set(); + + let invalidate = (name, from) => { + let basedir = path.dirname(from); + let key = basedir + ':' + name; + if (seen.has(key)) { + return; + } + + seen.add(key); + let resolved = cache.get(key); + if (!resolved || !path.isAbsolute(resolved.resolved)) { + return; + } + + let module = require.cache[resolved.resolved]; + if (module) { + delete require.cache[resolved.resolved]; + } + + let moduleChildren = children.get(resolved.resolved); + if (moduleChildren) { + for (let specifier of moduleChildren) { + invalidate(specifier, resolved.resolved); + } + } + + children.delete(resolved.resolved); + cache.delete(key); + this.resolver.invalidate(resolved.resolved); + this.syncResolver.invalidate(resolved.resolved); + }; + + invalidate(name, from); + } } registerSerializableClass( diff --git a/packages/core/package-manager/src/NodeResolver.js b/packages/core/package-manager/src/NodeResolver.js index cfdb8e7691c..fe221ff4f09 100644 --- a/packages/core/package-manager/src/NodeResolver.js +++ b/packages/core/package-manager/src/NodeResolver.js @@ -1,21 +1,26 @@ // @flow import type {FilePath, ModuleSpecifier, PackageJSON} from '@parcel/types'; -import type {ResolveResult} from './NodeResolverBase'; +import type {ResolveResult, ResolverContext} from './NodeResolverBase'; import path from 'path'; import {NodeResolverBase} from './NodeResolverBase'; export class NodeResolver extends NodeResolverBase> { async resolve(id: ModuleSpecifier, from: FilePath): Promise { + let ctx = { + invalidateOnFileCreate: [], + invalidateOnFileChange: new Set(), + }; + if (id[0] === '.') { - id = path.resolve(from, id); + id = path.resolve(path.dirname(from), id); } let res; if (path.isAbsolute(id)) { - res = await this.loadRelative(id); + res = await this.loadRelative(id, ctx); } else { - res = await this.loadNodeModules(id, from); + res = await this.loadNodeModules(id, from, ctx); } if (!res) { @@ -32,44 +37,100 @@ export class NodeResolver extends NodeResolverBase> { return res; } - async loadRelative(id: FilePath): Promise { - // Find a package.json file in the current package. - let pkg = await this.findPackage(path.dirname(id)); - + async loadRelative( + id: FilePath, + ctx: ResolverContext, + ): Promise { // First try as a file, then as a directory. return ( - this.loadAsFile(id, pkg) || (await this.loadDirectory(id, pkg)) // eslint-disable-line no-return-await + (await this.loadAsFile(id, null, ctx)) || + (await this.loadDirectory(id, null, ctx)) // eslint-disable-line no-return-await ); } - findPackage(dir: FilePath): Promise { + findPackage( + sourceFile: FilePath, + ctx: ResolverContext, + ): Promise { + // If in node_modules, take a shortcut to find the package.json in the root of the package. + let pkgPath = this.getNodeModulesPackagePath(sourceFile); + if (pkgPath) { + return this.readPackage(pkgPath, ctx); + } + + ctx.invalidateOnFileCreate.push({ + fileName: 'package.json', + aboveFilePath: sourceFile, + }); + + let dir = path.dirname(sourceFile); let pkgFile = this.fs.findAncestorFile(['package.json'], dir); if (pkgFile != null) { - return this.readPackage(pkgFile); + return this.readPackage(pkgFile, ctx); } return Promise.resolve(null); } - async readPackage(file: FilePath): Promise { + async readPackage( + file: FilePath, + ctx: ResolverContext, + ): Promise { let cached = this.packageCache.get(file); if (cached) { + ctx.invalidateOnFileChange.add(file); return cached; } - let json = await this.fs.readFile(file, 'utf8'); - let pkg = JSON.parse(json); + let json; + try { + json = await this.fs.readFile(file, 'utf8'); + } catch (err) { + ctx.invalidateOnFileCreate.push({ + filePath: file, + }); + throw err; + } + + // Add the invalidation *before* we try to parse the JSON in case of errors + // so that changes are picked up if the file is edited to fix the error. + ctx.invalidateOnFileChange.add(file); + let pkg = JSON.parse(json); this.packageCache.set(file, pkg); return pkg; } - loadAsFile(file: FilePath, pkg: ?PackageJSON): ?ResolveResult { + async loadAsFile( + file: FilePath, + pkg: ?PackageJSON, + ctx: ResolverContext, + ): Promise { // Try all supported extensions - let found = this.fs.findFirstFile(this.expandFile(file)); + let files = this.expandFile(file); + let found = this.fs.findFirstFile(files); + + // Add invalidations for higher priority files so we + // re-resolve if any of them are created. + for (let file of files) { + if (file === found) { + break; + } + + ctx.invalidateOnFileCreate.push({ + filePath: file, + }); + } + if (found) { - return {resolved: found, pkg}; + return { + resolved: await this.fs.realpath(found), + // Find a package.json file in the current package. + pkg: pkg ?? (await this.findPackage(file, ctx)), + invalidateOnFileCreate: ctx.invalidateOnFileCreate, + invalidateOnFileChange: ctx.invalidateOnFileChange, + }; } return null; @@ -78,9 +139,10 @@ export class NodeResolver extends NodeResolverBase> { async loadDirectory( dir: FilePath, pkg: ?PackageJSON = null, + ctx: ResolverContext, ): Promise { try { - pkg = await this.readPackage(dir + '/package.json'); + pkg = await this.readPackage(path.join(dir, 'package.json'), ctx); // Get a list of possible package entry points. let entries = this.getPackageEntries(dir, pkg); @@ -88,7 +150,8 @@ export class NodeResolver extends NodeResolverBase> { for (let file of entries) { // First try loading package.main as a file, then try as a directory. const res = - this.loadAsFile(file, pkg) || (await this.loadDirectory(file, pkg)); + (await this.loadAsFile(file, pkg, ctx)) || + (await this.loadDirectory(file, pkg, ctx)); if (res) { return res; } @@ -98,15 +161,16 @@ export class NodeResolver extends NodeResolverBase> { } // Fall back to an index file inside the directory. - return this.loadAsFile(path.join(dir, 'index'), pkg); + return this.loadAsFile(path.join(dir, 'index'), pkg, ctx); } async loadNodeModules( id: ModuleSpecifier, from: FilePath, + ctx: ResolverContext, ): Promise { try { - let module = this.findNodeModulePath(id, from); + let module = this.findNodeModulePath(id, from, ctx); if (!module || module.resolved) { return module; } @@ -114,8 +178,11 @@ export class NodeResolver extends NodeResolverBase> { // If a module was specified as a module sub-path (e.g. some-module/some/path), // it is likely a file. Try loading it as a file first. if (module.subPath) { - let pkg = await this.readPackage(module.moduleDir + '/package.json'); - let res = this.loadAsFile(module.filePath, pkg); + let pkg = await this.readPackage( + path.join(module.moduleDir, 'package.json'), + ctx, + ); + let res = await this.loadAsFile(module.filePath, pkg, ctx); if (res) { return res; } @@ -123,7 +190,7 @@ export class NodeResolver extends NodeResolverBase> { // Otherwise, load as a directory. if (module.filePath) { - return await this.loadDirectory(module.filePath); + return await this.loadDirectory(module.filePath, null, ctx); } } catch (e) { // ignore diff --git a/packages/core/package-manager/src/NodeResolverBase.js b/packages/core/package-manager/src/NodeResolverBase.js index 9024720d430..2117a0678dc 100644 --- a/packages/core/package-manager/src/NodeResolverBase.js +++ b/packages/core/package-manager/src/NodeResolverBase.js @@ -1,11 +1,17 @@ // @flow -import type {PackageJSON, FilePath, ModuleSpecifier} from '@parcel/types'; +import type { + PackageJSON, + FileCreateInvalidation, + FilePath, + ModuleSpecifier, +} from '@parcel/types'; import type {FileSystem} from '@parcel/fs'; // $FlowFixMe import Module from 'module'; import path from 'path'; import invariant from 'assert'; +import {normalizeSeparators} from '@parcel/utils'; const builtins = {pnpapi: true}; for (let builtin of Module.builtinModules) { @@ -15,6 +21,8 @@ for (let builtin of Module.builtinModules) { export type ResolveResult = {| resolved: FilePath | ModuleSpecifier, pkg?: ?PackageJSON, + invalidateOnFileCreate: Array, + invalidateOnFileChange: Set, |}; export type ModuleInfo = {| @@ -25,6 +33,13 @@ export type ModuleInfo = {| code?: string, |}; +export type ResolverContext = {| + invalidateOnFileCreate: Array, + invalidateOnFileChange: Set, +|}; + +const NODE_MODULES = `${path.sep}node_modules${path.sep}`; + export class NodeResolverBase { fs: FileSystem; extensions: Array; @@ -81,14 +96,20 @@ export class NodeResolverBase { }); } - getModuleParts(name: ModuleSpecifier): Array { - let parts = path.normalize(name).split(path.sep); - if (parts[0].charAt(0) === '@') { - // Scoped module (e.g. @scope/module). Merge the first two parts back together. - parts.splice(0, 2, `${parts[0]}/${parts[1]}`); + getModuleParts(name: string): [FilePath, ?string] { + name = path.normalize(name); + let splitOn = name.indexOf(path.sep); + if (name.charAt(0) === '@') { + splitOn = name.indexOf(path.sep, splitOn + 1); + } + if (splitOn < 0) { + return [normalizeSeparators(name), undefined]; + } else { + return [ + normalizeSeparators(name.substring(0, splitOn)), + name.substring(splitOn + 1) || undefined, + ]; } - - return parts; } isBuiltin(name: ModuleSpecifier): boolean { @@ -97,25 +118,40 @@ export class NodeResolverBase { findNodeModulePath( id: ModuleSpecifier, - dir: FilePath, + sourceFile: FilePath, + ctx: ResolverContext, ): ?ResolveResult | ?ModuleInfo { if (this.isBuiltin(id)) { - return {resolved: id}; + return { + resolved: id, + invalidateOnFileChange: new Set(), + invalidateOnFileCreate: [], + }; } - let [moduleName, ...parts] = this.getModuleParts(id); + let [moduleName, subPath] = this.getModuleParts(id); + let dir = path.dirname(sourceFile); let moduleDir = this.fs.findNodeModule(moduleName, dir); + ctx.invalidateOnFileCreate.push({ + fileName: `node_modules/${moduleName}`, + aboveFilePath: sourceFile, + }); + if (!moduleDir && process.versions.pnp != null) { try { let pnp = Module.findPnpApi(dir + '/'); - moduleDir = pnp.resolveToUnqualified( moduleName + // retain slash in `require('assert/')` to force loading builtin from npm (id[moduleName.length] === '/' ? '/' : ''), dir + '/', ); + + // Invalidate whenever the .pnp.js file changes. + ctx.invalidateOnFileChange.add( + pnp.resolveToUnqualified('pnpapi', null), + ); } catch (e) { if (e.code !== 'MODULE_NOT_FOUND') { throw e; @@ -126,12 +162,42 @@ export class NodeResolverBase { if (moduleDir) { return { moduleName, - subPath: path.join(...parts), + subPath, moduleDir: moduleDir, - filePath: parts.length > 0 ? path.join(moduleDir, ...parts) : moduleDir, + filePath: subPath ? path.join(moduleDir, subPath) : moduleDir, }; } return null; } + + getNodeModulesPackagePath(sourceFile: FilePath): ?FilePath { + // If the file is in node_modules, we can find the package.json in the root of the package + // by slicing from the start of the string until 1-2 path segments after node_modules. + let index = sourceFile.lastIndexOf(NODE_MODULES); + if (index >= 0) { + index += NODE_MODULES.length; + + // If a scoped path, add an extra path segment. + if (sourceFile[index] === '@') { + index = sourceFile.indexOf(path.sep, index) + 1; + } + + index = sourceFile.indexOf(path.sep, index); + return path.join( + sourceFile.slice(0, index >= 0 ? index : undefined), + 'package.json', + ); + } + } + + invalidate(filePath: FilePath) { + // Invalidate the package.jsons above `filePath` + let dir = path.dirname(filePath); + let {root} = path.parse(dir); + while (dir !== root && path.basename(dir) !== 'node_modules') { + this.packageCache.delete(path.join(dir, 'package.json')); + dir = path.dirname(dir); + } + } } diff --git a/packages/core/package-manager/src/NodeResolverSync.js b/packages/core/package-manager/src/NodeResolverSync.js index a4028c8f463..93b0b45481c 100644 --- a/packages/core/package-manager/src/NodeResolverSync.js +++ b/packages/core/package-manager/src/NodeResolverSync.js @@ -1,21 +1,26 @@ // @flow import type {FilePath, ModuleSpecifier, PackageJSON} from '@parcel/types'; -import type {ResolveResult} from './NodeResolverBase'; +import type {ResolveResult, ResolverContext} from './NodeResolverBase'; import path from 'path'; import {NodeResolverBase} from './NodeResolverBase'; export class NodeResolverSync extends NodeResolverBase { resolve(id: ModuleSpecifier, from: FilePath): ResolveResult { + let ctx = { + invalidateOnFileCreate: [], + invalidateOnFileChange: new Set(), + }; + if (id[0] === '.') { - id = path.resolve(from, id); + id = path.resolve(path.dirname(from), id); } let res; if (path.isAbsolute(id)) { - res = this.loadRelative(id); + res = this.loadRelative(id, ctx); } else { - res = this.loadNodeModules(id, from); + res = this.loadNodeModules(id, from, ctx); } if (!res) { @@ -32,56 +37,103 @@ export class NodeResolverSync extends NodeResolverBase { return res; } - loadRelative(id: FilePath): ?ResolveResult { - // Find a package.json file in the current package. - let pkg = this.findPackage(path.dirname(id)); - + loadRelative(id: FilePath, ctx: ResolverContext): ?ResolveResult { // First try as a file, then as a directory. - return this.loadAsFile(id, pkg) || this.loadDirectory(id, pkg); + return this.loadAsFile(id, null, ctx) || this.loadDirectory(id, null, ctx); } - findPackage(dir: FilePath): ?PackageJSON { + findPackage(sourceFile: FilePath, ctx: ResolverContext): ?PackageJSON { + // If in node_modules, take a shortcut to find the package.json in the root of the package. + let pkgPath = this.getNodeModulesPackagePath(sourceFile); + if (pkgPath) { + return this.readPackage(pkgPath, ctx); + } + // Find the nearest package.json file within the current node_modules folder + let dir = path.dirname(sourceFile); let pkgFile = this.fs.findAncestorFile(['package.json'], dir); if (pkgFile != null) { - return this.readPackage(pkgFile); + return this.readPackage(pkgFile, ctx); } } - readPackage(file: FilePath): PackageJSON { + readPackage(file: FilePath, ctx: ResolverContext): PackageJSON { let cached = this.packageCache.get(file); if (cached) { + ctx.invalidateOnFileChange.add(file); return cached; } - let json = this.fs.readFileSync(file, 'utf8'); + let json; + try { + json = this.fs.readFileSync(file, 'utf8'); + } catch (err) { + ctx.invalidateOnFileCreate.push({ + filePath: file, + }); + throw err; + } + + // Add the invalidation *before* we try to parse the JSON in case of errors + // so that changes are picked up if the file is edited to fix the error. + ctx.invalidateOnFileChange.add(file); + let pkg = JSON.parse(json); this.packageCache.set(file, pkg); return pkg; } - loadAsFile(file: FilePath, pkg: ?PackageJSON): ?ResolveResult { + loadAsFile( + file: FilePath, + pkg: ?PackageJSON, + ctx: ResolverContext, + ): ?ResolveResult { // Try all supported extensions - let found = this.fs.findFirstFile(this.expandFile(file)); + let files = this.expandFile(file); + let found = this.fs.findFirstFile(files); + + // Add invalidations for higher priority files so we + // re-resolve if any of them are created. + for (let file of files) { + if (file === found) { + break; + } + + ctx.invalidateOnFileCreate.push({ + filePath: file, + }); + } + if (found) { - return {resolved: found, pkg}; + return { + resolved: this.fs.realpathSync(found), + // Find a package.json file in the current package. + pkg: pkg ?? this.findPackage(file, ctx), + invalidateOnFileCreate: ctx.invalidateOnFileCreate, + invalidateOnFileChange: ctx.invalidateOnFileChange, + }; } return null; } - loadDirectory(dir: FilePath, pkg: ?PackageJSON = null): ?ResolveResult { + loadDirectory( + dir: FilePath, + pkg: ?PackageJSON = null, + ctx: ResolverContext, + ): ?ResolveResult { try { - pkg = this.readPackage(dir + '/package.json'); + pkg = this.readPackage(path.join(dir, 'package.json'), ctx); // Get a list of possible package entry points. let entries = this.getPackageEntries(dir, pkg); for (let file of entries) { // First try loading package.main as a file, then try as a directory. - const res = this.loadAsFile(file, pkg) || this.loadDirectory(file, pkg); + const res = + this.loadAsFile(file, pkg, ctx) || this.loadDirectory(file, pkg, ctx); if (res) { return res; } @@ -91,12 +143,16 @@ export class NodeResolverSync extends NodeResolverBase { } // Fall back to an index file inside the directory. - return this.loadAsFile(path.join(dir, 'index'), pkg); + return this.loadAsFile(path.join(dir, 'index'), pkg, ctx); } - loadNodeModules(id: ModuleSpecifier, from: FilePath): ?ResolveResult { + loadNodeModules( + id: ModuleSpecifier, + from: FilePath, + ctx: ResolverContext, + ): ?ResolveResult { try { - let module = this.findNodeModulePath(id, from); + let module = this.findNodeModulePath(id, from, ctx); if (!module || module.resolved) { return module; } @@ -104,8 +160,11 @@ export class NodeResolverSync extends NodeResolverBase { // If a module was specified as a module sub-path (e.g. some-module/some/path), // it is likely a file. Try loading it as a file first. if (module.subPath) { - let pkg = this.readPackage(module.moduleDir + '/package.json'); - let res = this.loadAsFile(module.filePath, pkg); + let pkg = this.readPackage( + path.join(module.moduleDir, 'package.json'), + ctx, + ); + let res = this.loadAsFile(module.filePath, pkg, ctx); if (res) { return res; } @@ -113,7 +172,7 @@ export class NodeResolverSync extends NodeResolverBase { // Otherwise, load as a directory. if (module.filePath) { - return this.loadDirectory(module.filePath); + return this.loadDirectory(module.filePath, null, ctx); } } catch (e) { // ignore diff --git a/packages/core/package-manager/src/types.js b/packages/core/package-manager/src/types.js index c4d19c0df4b..a0547bffb3d 100644 --- a/packages/core/package-manager/src/types.js +++ b/packages/core/package-manager/src/types.js @@ -1,6 +1,11 @@ // @flow -import type {FilePath, SemverRange, ModuleSpecifier} from '@parcel/types'; +import type { + FilePath, + FileCreateInvalidation, + SemverRange, + ModuleSpecifier, +} from '@parcel/types'; import type {FileSystem} from '@parcel/fs'; import type {ResolveResult} from './NodeResolverBase'; @@ -23,6 +28,11 @@ export interface PackageInstaller { install(opts: InstallerOptions): Promise; } +export type Invalidations = {| + invalidateOnFileCreate: Array, + invalidateOnFileChange: Set, +|}; + export interface PackageManager { require( id: ModuleSpecifier, @@ -34,6 +44,8 @@ export interface PackageManager { from: FilePath, ?{|range?: SemverRange, shouldAutoInstall?: boolean, saveDev?: boolean|}, ): Promise; + getInvalidations(id: ModuleSpecifier, from: FilePath): Invalidations; + invalidate(id: ModuleSpecifier, from: FilePath): void; } export type ModuleRequest = {| diff --git a/packages/core/package-manager/test/NodePackageManager.test.js b/packages/core/package-manager/test/NodePackageManager.test.js index c2885fa58bd..c676c2e875b 100644 --- a/packages/core/package-manager/test/NodePackageManager.test.js +++ b/packages/core/package-manager/test/NodePackageManager.test.js @@ -8,7 +8,7 @@ import sinon from 'sinon'; import ThrowableDiagnostic from '@parcel/diagnostic'; import {loadConfig} from '@parcel/utils'; import WorkerFarm from '@parcel/workers'; -import {MockPackageInstaller, NodePackageManager} from '../'; +import {MockPackageInstaller, NodePackageManager} from '../src'; const FIXTURES_DIR = path.join(__dirname, 'fixtures'); @@ -46,6 +46,15 @@ describe('NodePackageManager', function() { version: '1.1.0', }, resolved: path.join(FIXTURES_DIR, 'has-foo/node_modules/foo/index.js'), + invalidateOnFileChange: new Set([ + path.join(FIXTURES_DIR, 'has-foo/node_modules/foo/package.json'), + ]), + invalidateOnFileCreate: [ + { + fileName: 'node_modules/foo', + aboveFilePath: path.join(FIXTURES_DIR, 'has-foo/index.js'), + }, + ], }, ); }); @@ -74,6 +83,15 @@ describe('NodePackageManager', function() { name: 'a', }, resolved: path.join(FIXTURES_DIR, 'has-foo/node_modules/a/index.js'), + invalidateOnFileChange: new Set([ + path.join(FIXTURES_DIR, 'has-foo/node_modules/a/package.json'), + ]), + invalidateOnFileCreate: [ + { + fileName: 'node_modules/a', + aboveFilePath: path.join(FIXTURES_DIR, 'has-foo/index.js'), + }, + ], }, ); }); @@ -165,6 +183,11 @@ describe('NodePackageManager', function() { describe('range mismatch', () => { it("cannot autoinstall if there's a local requirement", async () => { + packageManager.invalidate( + 'foo', + path.join(FIXTURES_DIR, 'has-foo/index.js'), + ); + // $FlowFixMe assert.rejects is Node 10+ await assert.rejects( () => @@ -212,6 +235,21 @@ describe('NodePackageManager', function() { FIXTURES_DIR, 'has-foo/subpackage/node_modules/foo/index.js', ), + invalidateOnFileChange: new Set([ + path.join( + FIXTURES_DIR, + 'has-foo/subpackage/node_modules/foo/package.json', + ), + ]), + invalidateOnFileCreate: [ + { + fileName: 'node_modules/foo', + aboveFilePath: path.join( + FIXTURES_DIR, + 'has-foo/subpackage/index.js', + ), + }, + ], }, ); @@ -232,6 +270,10 @@ describe('NodePackageManager', function() { }); it("cannot autoinstall peer dependencies if there's an incompatible local requirement", async () => { + packageManager.invalidate( + 'peers', + path.join(FIXTURES_DIR, 'has-foo/index.js'), + ); packageInstaller.register( 'foo', fs, diff --git a/packages/core/types/index.js b/packages/core/types/index.js index 58e954fc438..13b204afd14 100644 --- a/packages/core/types/index.js +++ b/packages/core/types/index.js @@ -595,6 +595,17 @@ export interface Asset extends BaseAsset { +stats: Stats; } +export type DevDepOptions = {| + moduleSpecifier: ModuleSpecifier, + resolveFrom: FilePath, + /** + * Whether to also invalidate the parcel plugin that loaded this dev dependency + * when it changes. This is useful if the parcel plugin or another parent dependency + * has its own cache for this dev dependency other than Node's require cache. + */ + invalidateParcelPlugin?: boolean, +|}; + /** * @section transformer */ @@ -608,7 +619,7 @@ export interface Config { setResult(result: ConfigResult): void; // TODO: fix setResultHash(resultHash: string): void; addIncludedFile(filePath: FilePath): void; - addDevDependency(name: PackageName, version?: Semver): void; + addDevDependency(devDep: DevDepOptions): void; invalidateOnFileCreate(invalidation: FileCreateInvalidation): void; getConfigFrom( searchPath: FilePath, @@ -628,8 +639,6 @@ export interface Config { |}, ): Promise; getPackage(): Promise; - shouldRehydrate(): void; - shouldReload(): void; shouldInvalidateOnStartup(): void; } @@ -746,10 +755,6 @@ export type Transformer = {| options: PluginOptions, logger: PluginLogger, |}) => Async, - preSerializeConfig?: ({| - config: Config, - options: PluginOptions, - |}) => Async, /** Whether an AST from a previous transformer can be reused (to prevent double-parsing) */ canReuseAST?: ({| ast: AST, diff --git a/packages/core/utils/src/blob.js b/packages/core/utils/src/blob.js index 477c976bf24..c84acd2a2c8 100644 --- a/packages/core/utils/src/blob.js +++ b/packages/core/utils/src/blob.js @@ -2,7 +2,7 @@ import type {Blob} from '@parcel/types'; -import {bufferStream} from '../'; +import {bufferStream} from './'; import {Readable} from 'stream'; export function blobToBuffer(blob: Blob): Promise { diff --git a/packages/core/utils/src/http-server.js b/packages/core/utils/src/http-server.js index 0e49e13f5f5..1500a57e0e6 100644 --- a/packages/core/utils/src/http-server.js +++ b/packages/core/utils/src/http-server.js @@ -9,7 +9,7 @@ import type {FileSystem} from '@parcel/fs'; import http from 'http'; import https from 'https'; import nullthrows from 'nullthrows'; -import {getCertificate, generateCertificate} from '../'; +import {getCertificate, generateCertificate} from './'; type CreateHTTPServerOpts = {| https: ?(HTTPSOptions | boolean), diff --git a/packages/core/utils/src/replaceBundleReferences.js b/packages/core/utils/src/replaceBundleReferences.js index 7cd19ad9b82..8842e3a225a 100644 --- a/packages/core/utils/src/replaceBundleReferences.js +++ b/packages/core/utils/src/replaceBundleReferences.js @@ -13,7 +13,7 @@ import type { import {Readable} from 'stream'; import nullthrows from 'nullthrows'; import URL from 'url'; -import {bufferStream, relativeBundlePath, urlJoin} from '../'; +import {bufferStream, relativeBundlePath, urlJoin} from './'; type ReplacementMap = Map< string /* dependency id */, diff --git a/packages/core/workers/test/integration/workerfarm/console.js b/packages/core/workers/test/integration/workerfarm/console.js index ef8183d166a..9236647f552 100644 --- a/packages/core/workers/test/integration/workerfarm/console.js +++ b/packages/core/workers/test/integration/workerfarm/console.js @@ -1,4 +1,4 @@ -const WorkerFarm = require('../../../').default; +const WorkerFarm = require('../../../src/WorkerFarm').default; function run() { if (WorkerFarm.isWorker()) { diff --git a/packages/core/workers/test/integration/workerfarm/logging.js b/packages/core/workers/test/integration/workerfarm/logging.js index 55957c48f46..291c7fc6108 100644 --- a/packages/core/workers/test/integration/workerfarm/logging.js +++ b/packages/core/workers/test/integration/workerfarm/logging.js @@ -1,4 +1,4 @@ -const WorkerFarm = require('../../../').default; +const WorkerFarm = require('../../../src/WorkerFarm').default; const Logger = require('@parcel/logger').default; function run() { diff --git a/packages/core/workers/test/workerfarm.js b/packages/core/workers/test/workerfarm.js index ff23f7d8e92..a37de830641 100644 --- a/packages/core/workers/test/workerfarm.js +++ b/packages/core/workers/test/workerfarm.js @@ -1,6 +1,6 @@ import Logger from '@parcel/logger'; import assert from 'assert'; -import WorkerFarm from '../'; +import WorkerFarm from '../src'; describe('WorkerFarm', function() { this.timeout(30000); diff --git a/packages/dev/babel-register/babel-plugin-module-translate.js b/packages/dev/babel-register/babel-plugin-module-translate.js index cf0269b73f9..df5da1e1e59 100644 --- a/packages/dev/babel-register/babel-plugin-module-translate.js +++ b/packages/dev/babel-register/babel-plugin-module-translate.js @@ -32,7 +32,7 @@ module.exports = ({types: t}) => ({ visitor: { ImportDeclaration({node}, state) { let source = node.source; - if (t.isStringLiteral(source)) { + if (t.isStringLiteral(source) && source.value.startsWith('@parcel/')) { source.value = getSourceField( source.value, state.file.opts.filename || process.cwd(), @@ -45,7 +45,8 @@ module.exports = ({types: t}) => ({ t.isIdentifier(node.callee, {name: 'require'}) && !path.scope.hasBinding(node.callee.value) && node.arguments.length === 1 && - t.isStringLiteral(node.arguments[0]) + t.isStringLiteral(node.arguments[0]) && + node.arguments[0].value.startsWith('@parcel/') ) { try { node.arguments[0].value = getSourceField( diff --git a/packages/shared/babel-ast-utils/test/index.js b/packages/shared/babel-ast-utils/test/index.js index 7cd6fb7ff19..5f29a7fac72 100644 --- a/packages/shared/babel-ast-utils/test/index.js +++ b/packages/shared/babel-ast-utils/test/index.js @@ -2,7 +2,7 @@ import fs from 'fs'; import path from 'path'; import assert from 'assert'; import {parse as babelParse} from '@babel/parser'; -import {generateAST} from '../'; +import {generateAST} from '../src'; const FIXTURES_FOLDER = path.join(__dirname, 'fixtures'); const files = fs.readdirSync(FIXTURES_FOLDER).sort(); diff --git a/packages/transformers/babel/src/BabelTransformer.js b/packages/transformers/babel/src/BabelTransformer.js index dd78164cb5a..becf2219782 100644 --- a/packages/transformers/babel/src/BabelTransformer.js +++ b/packages/transformers/babel/src/BabelTransformer.js @@ -4,17 +4,13 @@ import {generate, babelErrorEnhancer} from '@parcel/babel-ast-utils'; import {Transformer} from '@parcel/plugin'; import semver from 'semver'; import babel7 from './babel7'; -import {load, preSerialize} from './config'; +import {load} from './config'; export default (new Transformer({ async loadConfig({config, options, logger}) { await load(config, options, logger); }, - preSerializeConfig({config}) { - return preSerialize(config); - }, - canReuseAST({ast}) { return ast.type === 'babel' && semver.satisfies(ast.version, '^7.0.0'); }, diff --git a/packages/transformers/babel/src/config.js b/packages/transformers/babel/src/config.js index 840c32031c0..bda4109b661 100644 --- a/packages/transformers/babel/src/config.js +++ b/packages/transformers/babel/src/config.js @@ -4,10 +4,9 @@ import type {Config, PluginOptions} from '@parcel/types'; import type {BabelConfig} from './types'; import type {PluginLogger} from '@parcel/logger'; -import nullthrows from 'nullthrows'; import path from 'path'; import * as babelCore from '@babel/core'; -import {md5FromObject} from '@parcel/utils'; +import {md5FromObject, relativePath} from '@parcel/utils'; import getEnvOptions from './env'; import getJSXOptions from './jsx'; @@ -68,6 +67,8 @@ export async function load( let addIncludedFile = file => { if (JS_EXTNAME_RE.test(path.extname(file))) { + // We need to invalidate on startup in case the config is non-static, + // e.g. uses unknown environment variables, reads from the filesystem, etc. logger.warn({ message: `It looks like you're using a JavaScript Babel config file. This means the config cannot be watched for changes, and Babel transformations cannot be cached. You'll need to restart Parcel for changes to this config to take effect. Try using a ${path.basename( file, @@ -75,6 +76,15 @@ export async function load( ) + '.json'} file instead.`, }); config.shouldInvalidateOnStartup(); + + // But also add the config as a dev dependency so we can at least attempt invalidation in watch mode. + config.addDevDependency({ + moduleSpecifier: relativePath(options.projectRoot, file), + resolveFrom: path.join(options.projectRoot, 'index'), + // Also invalidate @parcel/transformer-babel when the config or a dependency updates. + // This ensures that the caches in @babel/core are also invalidated. + invalidateParcelPlugin: true, + }); } else { config.addIncludedFile(file); } @@ -126,29 +136,18 @@ export async function load( targets: enginesToBabelTargets(config.env), }); - let {hasRequire, dependsOnLocal} = getStats(partialConfig.options, options); - - // If the config depends on local plugins or has plugins loaded with require(), - // we can't cache the result of the compilation. If the config references local plugins, - // we can't know what dependencies those plugins might have. If the config has require() - // calls in it to load plugins we can't know where they came from. - if (dependsOnLocal || hasRequire) { - config.setResultHash(JSON.stringify(Date.now())); - config.shouldInvalidateOnStartup(); - } - - if (dependsOnLocal) { - logger.warn({ - message: - "It looks like you are using local Babel plugins or presets. This means Babel transformations cannot be cached and will run on each build. You'll need to restart Parcel for changes to local plugins to take effect.", - }); - } else if (hasRequire) { + // If the config has plugins loaded with require(), or inline plugins in the config, + // we can't cache the result of the compilation because we don't know where they came from. + if (hasRequire(partialConfig.options)) { logger.warn({ message: 'It looks like you are using `require` to configure Babel plugins or presets. This means Babel transformations cannot be cached and will run on each build. Please use strings to configure Babel instead.', }); + + config.setResultHash(JSON.stringify(Date.now())); + config.shouldInvalidateOnStartup(); } else { - await definePluginDependencies(config); + definePluginDependencies(config, options); config.setResultHash(md5FromObject(partialConfig.options)); } } else { @@ -198,7 +197,7 @@ async function buildDefaultBabelConfig(options: PluginOptions, config: Config) { config: babelOptions, targets: babelTargets, }); - await definePluginDependencies(config); + definePluginDependencies(config, options); } function mergeOptions(result, config?: null | BabelConfig) { @@ -221,71 +220,31 @@ function mergeOptions(result, config?: null | BabelConfig) { return result; } -function getStats(options, parcelOptions) { - let hasRequire = false; - let dependsOnLocal = false; - +function hasRequire(options) { let configItems = [...options.presets, ...options.plugins]; - - for (let configItem of configItems) { - if (!configItem.file) { - hasRequire = true; - } else if ( - configItem.file.request.startsWith('.') || - isLocal(configItem.file.resolved, parcelOptions.inputFS) - ) { - dependsOnLocal = true; - } - } - - return {hasRequire, dependsOnLocal}; + return configItems.some(item => !item.file); } -function isLocal(configItemPath, fs) { - return fs.realpathSync(configItemPath) !== configItemPath; -} - -export function preSerialize(config: Config) { - let babelConfig = config.result?.config; - if (babelConfig == null) { - return; - } - - // ConfigItem.value is a function which the v8 serializer chokes on - // It is being ommited here and will be rehydrated later using the path provided by ConfigItem.file - babelConfig.presets = (babelConfig.presets || []).map( - ({options, dirname, name, file}) => ({ - options, - dirname, - name, - file, - }), - ); - babelConfig.plugins = (babelConfig.plugins || []).map( - ({options, dirname, name, file}) => ({ - options, - dirname, - name, - file, - }), - ); -} - -async function definePluginDependencies(config) { +function definePluginDependencies(config, options) { let babelConfig = config.result.config; if (babelConfig == null) { return; } let configItems = [...babelConfig.presets, ...babelConfig.plugins]; - await Promise.all( - configItems.map(async configItem => { - let pkg = nullthrows( - await config.getConfigFrom(configItem.file.resolved, ['package.json'], { - parse: true, - }), - ).contents; - config.addDevDependency(pkg.name, pkg.version); - }), - ); + for (let configItem of configItems) { + // FIXME: this uses a relative path from the project root rather than resolving + // from the config location because configItem.file.request can be a shorthand + // rather than a full package name. + config.addDevDependency({ + moduleSpecifier: relativePath( + options.projectRoot, + configItem.file.resolved, + ), + resolveFrom: path.join(options.projectRoot, 'index'), + // Also invalidate @parcel/transformer-babel when the plugin or a dependency updates. + // This ensures that the caches in @babel/core are also invalidated. + invalidateParcelPlugin: true, + }); + } } diff --git a/packages/transformers/less/src/LessTransformer.js b/packages/transformers/less/src/LessTransformer.js index 77fd3adff96..bb540d8b1b9 100644 --- a/packages/transformers/less/src/LessTransformer.js +++ b/packages/transformers/less/src/LessTransformer.js @@ -5,7 +5,7 @@ import {Transformer} from '@parcel/plugin'; import SourceMap from '@parcel/source-map'; import less from 'less'; -import {load, preSerialize} from './loadConfig'; +import {load} from './loadConfig'; // E.g: ~library/file.less const WEBPACK_ALIAS_RE = /^~[^/]/; @@ -22,10 +22,6 @@ export default (new Transformer({ return load({config}); }, - preSerializeConfig({config}) { - return preSerialize(config); - }, - async transform({asset, options, config, resolve}) { asset.type = 'css'; asset.meta.hasDependencies = false; diff --git a/packages/transformers/less/src/loadConfig.js b/packages/transformers/less/src/loadConfig.js index 96925e162af..a8f0b4303b0 100644 --- a/packages/transformers/less/src/loadConfig.js +++ b/packages/transformers/less/src/loadConfig.js @@ -27,17 +27,7 @@ export async function load({config}: {|config: Config|}): Promise { let isDynamic = configFile && path.extname(configFile.filePath) === '.js'; if (isDynamic) { config.shouldInvalidateOnStartup(); - config.shouldReload(); } return config.setResult({isStatic: !isDynamic, config: configContents}); } - -export function preSerialize(config: Config) { - if (!config.result) return; - - // Ensure we dont pass functions to the serialiser - if (!config.result.isStatic) { - config.result.config = {}; - } -} diff --git a/packages/transformers/postcss/src/PostCSSTransformer.js b/packages/transformers/postcss/src/PostCSSTransformer.js index 4307a348d15..a43ea49ebc0 100644 --- a/packages/transformers/postcss/src/PostCSSTransformer.js +++ b/packages/transformers/postcss/src/PostCSSTransformer.js @@ -12,7 +12,7 @@ import valueParser from 'postcss-value-parser'; import postcss from 'postcss'; import postcssModules from 'postcss-modules'; -import {load, preSerialize} from './loadConfig'; +import {load} from './loadConfig'; const COMPOSES_RE = /composes:.+from\s*("|').*("|')\s*;?/; const FROM_IMPORT_RE = /.+from\s*(?:"|')(.*)(?:"|')\s*;?/; @@ -22,10 +22,6 @@ export default (new Transformer({ return load({config, options, logger}); }, - preSerializeConfig({config}) { - return preSerialize(config); - }, - canReuseAST({ast}) { return ast.type === 'postcss' && semver.satisfies(ast.version, '^8.2.1'); }, diff --git a/packages/transformers/postcss/src/loadConfig.js b/packages/transformers/postcss/src/loadConfig.js index 60d83043acf..63b0c210752 100644 --- a/packages/transformers/postcss/src/loadConfig.js +++ b/packages/transformers/postcss/src/loadConfig.js @@ -1,7 +1,9 @@ // @flow -import type {Config, PluginOptions} from '@parcel/types'; +import type {Config, FilePath, PluginOptions} from '@parcel/types'; import type {PluginLogger} from '@parcel/logger'; import path from 'path'; +import {relativePath} from '@parcel/utils'; +import nullthrows from 'nullthrows'; import loadExternalPlugins from './loadPlugins'; @@ -10,6 +12,7 @@ const MODULE_BY_NAME_RE = /\.module\./; async function configHydrator( configFile: any, config: Config, + resolveFrom: ?FilePath, options: PluginOptions, ) { // Use a basic, modules-only PostCSS config if the file opts in by a name @@ -20,6 +23,7 @@ async function configHydrator( 'postcss-modules': {}, }, }; + resolveFrom = __filename; } if (configFile == null) { @@ -44,10 +48,26 @@ async function configHydrator( let plugins = await loadExternalPlugins( configFilePlugins, - config.searchPath, + nullthrows(resolveFrom), options, ); + // contents is either: + // from JSON: { plugins: { 'postcss-foo': { ...opts } } } + // from JS (v8): { plugins: [ { postcssPlugin: 'postcss-foo', ...visitor callback functions } ] + // from JS (v7): { plugins: [ [Function: ...] ] + let pluginArray = Array.isArray(configFilePlugins) + ? configFilePlugins + : Object.keys(configFilePlugins); + for (let p of pluginArray) { + if (typeof p === 'string') { + config.addDevDependency({ + moduleSpecifier: p, + resolveFrom: nullthrows(resolveFrom), + }); + } + } + config.setResult({ raw: configFile, hydrated: { @@ -78,15 +98,23 @@ export async function load({ contents = configFile.contents; let isDynamic = configFile && path.extname(configFile.filePath) === '.js'; if (isDynamic) { + // We have to invalidate on startup in case the config is non-deterministic, + // e.g. using unknown environment variables, reading from the filesystem, etc. logger.warn({ message: 'WARNING: Using a JavaScript PostCSS config file means losing out on caching features of Parcel. Use a .postcssrc(.json) file whenever possible.', }); - // JavaScript configs can use an array of functions... opt out of all caching... config.shouldInvalidateOnStartup(); - config.shouldReload(); - contents.__contains_functions = true; + + // Also add the config as a dev dependency so we attempt to reload in watch mode. + config.addDevDependency({ + moduleSpecifier: relativePath( + path.dirname(config.searchPath), + configFile.filePath, + ), + resolveFrom: config.searchPath, + }); } if (typeof contents !== 'object') { @@ -100,42 +128,7 @@ export async function load({ ) { throw new Error('PostCSS config must have plugins'); } - - // contents is either: - // from JSON: { plugins: { 'postcss-foo': { ...opts } } } - // from JS (v8): { plugins: [ { postcssPlugin: 'postcss-foo', ...visitor callback functions } ] - // from JS (v7): { plugins: [ [Function: ...] ] - let configFilePlugins = Array.isArray(contents.plugins) - ? contents.plugins - : Object.keys(contents.plugins); - for (let p of configFilePlugins) { - if (typeof p === 'string') { - if (p.startsWith('.')) { - logger.warn({ - message: - 'WARNING: Using relative PostCSS plugins means losing out on caching features of Parcel. Bundle this plugin up in a package or use a monorepo to resolve this issue.', - }); - - config.shouldInvalidateOnStartup(); - } - - config.addDevDependency(p); - } - } - } - - return configHydrator(contents, config, options); -} - -export function preSerialize(config: Config) { - if (!config.result) return; - - // Ensure we dont pass functions to the serialiser - if (config.result.raw.__contains_functions) { - config.result.raw = {}; } - // This gets re-hydrated in Deserialize, so never store this. - // It also usually contains a bunch of functions so bad idea anyway... - config.result.hydrated = {}; + return configHydrator(contents, config, configFile?.filePath, options); } diff --git a/packages/transformers/posthtml/package.json b/packages/transformers/posthtml/package.json index 54a91bd4275..2981a8d58f3 100644 --- a/packages/transformers/posthtml/package.json +++ b/packages/transformers/posthtml/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@parcel/plugin": "2.0.0-beta.1", + "@parcel/utils": "2.0.0-beta.1", "nullthrows": "^1.1.1", "posthtml": "^0.15.1", "posthtml-parser": "^0.6.0", diff --git a/packages/transformers/posthtml/src/PostHTMLTransformer.js b/packages/transformers/posthtml/src/PostHTMLTransformer.js index caa5f0910a2..c2fd9055a38 100644 --- a/packages/transformers/posthtml/src/PostHTMLTransformer.js +++ b/packages/transformers/posthtml/src/PostHTMLTransformer.js @@ -8,10 +8,11 @@ import parse from 'posthtml-parser'; import render from 'posthtml-render'; import nullthrows from 'nullthrows'; import semver from 'semver'; +import {relativePath} from '@parcel/utils'; import loadPlugins from './loadPlugins'; export default (new Transformer({ - async loadConfig({config}) { + async loadConfig({config, options, logger}) { let configFile = await config.getConfig( ['.posthtmlrc', '.posthtmlrc.js', 'posthtml.config.js'], { @@ -22,27 +23,52 @@ export default (new Transformer({ if (configFile) { let isJavascript = path.extname(configFile.filePath) === '.js'; if (isJavascript) { + // We have to invalidate on startup in case the config is non-deterministic, + // e.g. using unknown environment variables, reading from the filesystem, etc. + logger.warn({ + message: + 'WARNING: Using a JavaScript PostHTML config file means losing out on caching features of Parcel. Use a .posthtmlrc (JSON) file whenever possible.', + }); + config.shouldInvalidateOnStartup(); - config.shouldReload(); + + // Also add the config as a dev dependency so we attempt to reload in watch mode. + config.addDevDependency({ + moduleSpecifier: relativePath( + path.dirname(config.searchPath), + configFile.filePath, + ), + resolveFrom: config.searchPath, + }); } + // Load plugins. This must be done before adding dev dependencies so we auto install. + let plugins = await loadPlugins( + configFile.contents.plugins, + config.searchPath, + options, + ); + + // Now add dev dependencies so we invalidate when they change. + let pluginArray = Array.isArray(configFile.contents.plugins) + ? configFile.contents.plugins + : Object.keys(configFile.contents.plugins); + for (let p of pluginArray) { + if (typeof p === 'string') { + config.addDevDependency({ + moduleSpecifier: p, + resolveFrom: configFile.filePath, + }); + } + } + + configFile.contents.plugins = plugins; + // tells posthtml that we have already called parse configFile.contents.skipParse = true; delete configFile.contents.render; - config.setResult({ - contents: configFile.contents, - isSerialisable: !isJavascript, - }); - } - }, - - preSerializeConfig({config}) { - if (!config.result) return; - - // Ensure we dont try to serialise functions - if (!config.result.isSerialisable) { - config.result.contents = {}; + config.setResult(configFile.contents); } }, @@ -65,22 +91,15 @@ export default (new Transformer({ }; }, - async transform({asset, config, options}) { + async transform({asset, config}) { if (!config) { return [asset]; } - // load plugins - const plugins = await loadPlugins( - config.contents.plugins, - asset.filePath, - options, - ); - let ast = nullthrows(await asset.getAST()); - let res = await posthtml(plugins).process(ast.program, { - ...config.contents, - plugins, + let res = await posthtml(config.plugins).process(ast.program, { + ...config, + plugins: config.plugins, }); if (res.messages) { diff --git a/packages/transformers/pug/src/PugTransformer.js b/packages/transformers/pug/src/PugTransformer.js index 29486096390..bc7366c8b53 100644 --- a/packages/transformers/pug/src/PugTransformer.js +++ b/packages/transformers/pug/src/PugTransformer.js @@ -16,27 +16,14 @@ export default (new Transformer({ let isJavascript = path.extname(configFile.filePath) === '.js'; if (isJavascript) { config.shouldInvalidateOnStartup(); - config.shouldReload(); } - config.setResult({ - contents: configFile.contents, - isSerialisable: !isJavascript, - }); - } - }, - - preSerializeConfig({config}) { - if (!config.result) return; - - // Ensure we dont try to serialise functions - if (!config.result.isSerialisable) { - config.result.contents = {}; + config.setResult(configFile.contents); } }, async transform({asset, config}) { - const pugConfig = config ? config.contents : {}; + const pugConfig = config ?? {}; const content = await asset.getCode(); const render = pug.compile(content, { compileDebug: false, diff --git a/packages/transformers/sass/src/SassTransformer.js b/packages/transformers/sass/src/SassTransformer.js index bb705e5c56f..3de0356c71d 100644 --- a/packages/transformers/sass/src/SassTransformer.js +++ b/packages/transformers/sass/src/SassTransformer.js @@ -16,55 +16,37 @@ export default (new Transformer({ packageKey: 'sass', }); - let configResult = { - contents: configFile ? configFile.contents : {}, - isSerialisable: true, - }; + let configResult = configFile ? configFile.contents : {}; // Resolve relative paths from config file - if (configFile && configResult.contents.includePaths) { - configResult.contents.includePaths = configResult.contents.includePaths.map( - p => path.resolve(path.dirname(configFile.filePath), p), + if (configFile && configResult.includePaths) { + configResult.includePaths = configResult.includePaths.map(p => + path.resolve(path.dirname(configFile.filePath), p), ); } if (configFile && path.extname(configFile.filePath) === '.js') { config.shouldInvalidateOnStartup(); - config.shouldReload(); - - configResult.isSerialisable = false; } - if (configResult.contents.importer === undefined) { - configResult.contents.importer = []; - } else if (!Array.isArray(configResult.contents.importer)) { - configResult.contents.importer = [configResult.contents.importer]; + if (configResult.importer === undefined) { + configResult.importer = []; + } else if (!Array.isArray(configResult.importer)) { + configResult.importer = [configResult.importer]; } // Always emit sourcemap - configResult.contents.sourceMap = true; + configResult.sourceMap = true; // sources are created relative to the directory of outFile - configResult.contents.outFile = path.join( - options.projectRoot, - 'style.css.map', - ); - configResult.contents.omitSourceMapUrl = true; - configResult.contents.sourceMapContents = false; + configResult.outFile = path.join(options.projectRoot, 'style.css.map'); + configResult.omitSourceMapUrl = true; + configResult.sourceMapContents = false; config.setResult(configResult); }, - preSerializeConfig({config}) { - if (!config.result) return; - - // Ensure we dont try to serialise functions - if (!config.result.isSerialisable) { - config.result.contents = {}; - } - }, - async transform({asset, options, config, resolve}) { - let rawConfig = config ? config.contents : {}; + let rawConfig = config ?? {}; let sassRender = promisify(sass.render.bind(sass)); let css; try { diff --git a/packages/transformers/stylus/src/StylusTransformer.js b/packages/transformers/stylus/src/StylusTransformer.js index 1f8640139a4..203d5b280bb 100644 --- a/packages/transformers/stylus/src/StylusTransformer.js +++ b/packages/transformers/stylus/src/StylusTransformer.js @@ -23,7 +23,6 @@ export default (new Transformer({ let isJavascript = path.extname(configFile.filePath) === '.js'; if (isJavascript) { config.shouldInvalidateOnStartup(); - config.shouldReload(); } // Resolve relative paths from config file @@ -33,24 +32,12 @@ export default (new Transformer({ ); } - config.setResult({ - contents: configFile.contents, - isSerialisable: !isJavascript, - }); - } - }, - - preSerializeConfig({config}) { - if (!config.result) return; - - // Ensure we dont try to serialise functions - if (!config.result.isSerialisable) { - config.result.contents = {}; + config.setResult(configFile.contents); } }, async transform({asset, resolve, config, options}) { - let stylusConfig = config ? config.contents : {}; + let stylusConfig = config ?? {}; let code = await asset.getCode(); let style = stylus(code, {...stylusConfig}); style.set('filename', asset.filePath); @@ -68,7 +55,7 @@ export default (new Transformer({ let {resolved: stylusPath} = await options.packageManager.resolve( 'stylus', - asset.filePath, + __filename, ); let nativeGlob = await options.packageManager.require('glob', stylusPath); @@ -307,7 +294,7 @@ function patchNativeFS(fs, nativeGlob) { let glob = nativeGlob.sync; nativeGlob.sync = p => { let res = globSync(p, fs); - if (!p.includes('node_modules/stylus')) { + if (!p.includes(`node_modules${path.sep}stylus`)) { // Sometimes stylus passes file paths with no glob parts to the `glob` module. // We want to avoid treating these as globs for performance. if (isGlob(p)) { diff --git a/packages/transformers/svgo/src/SVGOTransformer.js b/packages/transformers/svgo/src/SVGOTransformer.js index 5ad02e143f7..722bc303535 100644 --- a/packages/transformers/svgo/src/SVGOTransformer.js +++ b/packages/transformers/svgo/src/SVGOTransformer.js @@ -29,29 +29,15 @@ export default (new Transformer({ let isJavascript = path.extname(configFile.filePath) === '.js'; if (isJavascript) { config.shouldInvalidateOnStartup(); - config.shouldReload(); } - config.setResult({ - contents: configFile.contents, - isSerialisable: !isJavascript, - }); - } - }, - - preSerializeConfig({config}) { - if (!config.result) return; - - // Ensure we dont try to serialise functions - if (!config.result.isSerialisable) { - config.result.contents = {}; + config.setResult(configFile.contents); } }, async transform({asset, config}) { - let svgoConfig = config ? config.contents : {}; let code = await asset.getCode(); - let svgo = new SVGO({...defaultConfig, ...svgoConfig}); + let svgo = new SVGO({...defaultConfig, ...config}); let res = await svgo.optimize(code, {path: asset.id}); asset.setCode(res.data); diff --git a/packages/utils/babel-preset-env/test/preset-env.test.js b/packages/utils/babel-preset-env/test/preset-env.test.js index 64fbee8b968..3ce72b525ca 100644 --- a/packages/utils/babel-preset-env/test/preset-env.test.js +++ b/packages/utils/babel-preset-env/test/preset-env.test.js @@ -19,7 +19,7 @@ export default class Foo { } `; -const preset = require.resolve('../'); +const preset = require.resolve('../src'); describe('@parcel/babel-preset-env', () => { it('compiles against targets passed through caller when the caller is parcel 2.x', () => { diff --git a/packages/utils/node-resolver-core/test/resolver.js b/packages/utils/node-resolver-core/test/resolver.js index 6fd42c4e561..5210c51b101 100644 --- a/packages/utils/node-resolver-core/test/resolver.js +++ b/packages/utils/node-resolver-core/test/resolver.js @@ -1,5 +1,5 @@ // @flow strict-local -import NodeResolver from '..'; +import NodeResolver from '../src/NodeResolver'; import path from 'path'; import assert from 'assert'; import nullthrows from 'nullthrows'; diff --git a/yarn.lock b/yarn.lock index 92d434dd7fd..c4864e79f1f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,26 +2,31 @@ # yarn lockfile v1 -"@babel/code-frame@7.12.11", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11": +"@babel/code-frame@7.12.11", "@babel/code-frame@^7.0.0": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.12.13": +"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.11", "@babel/code-frame@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== dependencies: "@babel/highlight" "^7.12.13" -"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7", "@babel/compat-data@^7.8.6": +"@babel/compat-data@^7.12.5", "@babel/compat-data@^7.12.7": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.12.13.tgz#27e19e0ed3726ccf54067ced4109501765e7e2e8" integrity sha512-U/hshG5R+SIoW7HVWIdmy1cB7s3ki+r3FpyEZiCgpi4tFgPnX/vynY80ZGSASOIrUM6O7VxOgCZgdt7h97bUGg== -"@babel/core@7.12.9", "@babel/core@^7.12.0", "@babel/core@^7.12.2": +"@babel/compat-data@^7.13.8": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.8.tgz#5b783b9808f15cef71547f1b691f34f8ff6003a6" + integrity sha512-EaI33z19T4qN3xLXsGf48M2cDqa6ei9tPZlfLdb2HC+e/cFtREiRd8hdSqDbwdLB0/+gLwqJmCYASH0z2bUdog== + +"@babel/core@7.12.9", "@babel/core@^7.12.2": version "7.12.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.9.tgz#fd450c4ec10cdbb980e2928b7aa7a28484593fc8" integrity sha512-gTXYh3M5wb7FRXQy+FErKFAv90BnlOuNn1QkCK2lREoPAjrQCO49+HVSrFoe5uakFAF5eenS75KbO2vQiLrTMQ== @@ -43,6 +48,28 @@ semver "^5.4.1" source-map "^0.5.0" +"@babel/core@^7.12.0": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.8.tgz#c191d9c5871788a591d69ea1dc03e5843a3680fb" + integrity sha512-oYapIySGw1zGhEFRd6lzWNLWFX2s5dA/jm+Pw/+59ZdXtjyIuwlXbrId22Md0rgZVop+aVoqow2riXhBLNyuQg== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.0" + "@babel/helper-compilation-targets" "^7.13.8" + "@babel/helper-module-transforms" "^7.13.0" + "@babel/helpers" "^7.13.0" + "@babel/parser" "^7.13.4" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^6.3.0" + source-map "^0.5.0" + "@babel/core@^7.12.3": version "7.12.16" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.16.tgz#8c6ba456b23b680a6493ddcfcd9d3c3ad51cab7c" @@ -73,12 +100,12 @@ eslint-visitor-keys "^1.3.0" semver "^6.3.0" -"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.9.0": - version "7.12.11" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" - integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== +"@babel/generator@^7.12.11", "@babel/generator@^7.12.5", "@babel/generator@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.0.tgz#bd00d4394ca22f220390c56a0b5b85568ec1ec0c" + integrity sha512-zBZfgvBB/ywjx0Rgc2+BwoH/3H+lDtlgD4hBOpEv5LxRnYsm/753iRuLepqnYlynpjC3AdQxtxsoeHJoEEwOAw== dependencies: - "@babel/types" "^7.12.11" + "@babel/types" "^7.13.0" jsesc "^2.5.1" source-map "^0.5.0" @@ -91,20 +118,22 @@ jsesc "^2.5.1" source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.4": +"@babel/generator@^7.9.0": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.11.tgz#98a7df7b8c358c9a37ab07a24056853016aba3af" + integrity sha512-Ggg6WPOJtSi8yYQvLVjG8F/TlpWDlKx0OpS4Kt+xMQPs5OaGYWy+v1A+1TvxI6sAMGZpKWWoAQ1DaeQbImlItA== + dependencies: + "@babel/types" "^7.12.11" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.8.3": version "7.12.10" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.10.tgz#54ab9b000e60a93644ce17b3f37d313aaf1d115d" integrity sha512-XplmVbC1n+KY6jL8/fgLVXXUauDIB+lD5+GsQEh6F6GBF1dq1qy4DP4yXWzDKcoqXB3X58t61e85Fitoww4JVQ== dependencies: "@babel/types" "^7.12.10" -"@babel/helper-annotate-as-pure@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" - integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== - dependencies: - "@babel/types" "^7.8.3" - "@babel/helper-builder-binary-assignment-operator-visitor@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz#bb0b75f31bf98cbf9ff143c1ae578b87274ae1a3" @@ -130,7 +159,7 @@ "@babel/helper-annotate-as-pure" "^7.8.3" "@babel/types" "^7.9.0" -"@babel/helper-compilation-targets@^7.12.5": +"@babel/helper-compilation-targets@^7.12.5", "@babel/helper-compilation-targets@^7.8.4": version "7.12.5" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.5.tgz#cb470c76198db6a24e9dbc8987275631e5d29831" integrity sha512-+qH6NrscMolUlzOYngSBMIOQpKUGPPsc61Bu5W10mg84LxZ7cmvnBHzARKbDoFxVvqqAbj6Tg6N7bSrWSPXMyw== @@ -140,18 +169,17 @@ browserslist "^4.14.5" semver "^5.5.0" -"@babel/helper-compilation-targets@^7.8.4": - version "7.8.7" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.7.tgz#dac1eea159c0e4bd46e309b5a1b04a66b53c1dde" - integrity sha512-4mWm8DCK2LugIS+p1yArqvG1Pf162upsIsjE7cNBjez+NjliQpVhj20obE520nao0o14DaTnFJv+Fw5a0JpoUw== +"@babel/helper-compilation-targets@^7.13.8": + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.8.tgz#02bdb22783439afb11b2f009814bdd88384bd468" + integrity sha512-pBljUGC1y3xKLn1nrx2eAhurLMA8OqBtBP/JwG4U8skN7kf8/aqwwxpV1N6T0e7r6+7uNitIa/fUxPFagSXp3A== dependencies: - "@babel/compat-data" "^7.8.6" - browserslist "^4.9.1" - invariant "^2.2.4" - levenary "^1.1.1" - semver "^5.5.0" + "@babel/compat-data" "^7.13.8" + "@babel/helper-validator-option" "^7.12.17" + browserslist "^4.14.5" + semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.12.1": +"@babel/helper-create-class-features-plugin@^7.12.1", "@babel/helper-create-class-features-plugin@^7.8.3": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.12.1.tgz#3c45998f431edd4a9214c5f1d3ad1448a6137f6e" integrity sha512-hkL++rWeta/OVOBTRJc9a5Azh5mt5WgZUGAKMD8JM141YsE08K//bp1unBBieO6rUKkIPyUE0USQ30jAy3Sk1w== @@ -162,18 +190,6 @@ "@babel/helper-replace-supers" "^7.12.1" "@babel/helper-split-export-declaration" "^7.10.4" -"@babel/helper-create-class-features-plugin@^7.8.3": - version "7.9.5" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.9.5.tgz#79753d44017806b481017f24b02fd4113c7106ea" - integrity sha512-IipaxGaQmW4TfWoXdqjY0TzoXQ1HRS0kPpEgvjosb3u7Uedcq297xFqDQiCcQtRRwzIMif+N1MLVI8C5a4/PAA== - dependencies: - "@babel/helper-function-name" "^7.9.5" - "@babel/helper-member-expression-to-functions" "^7.8.3" - "@babel/helper-optimise-call-expression" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-replace-supers" "^7.8.6" - "@babel/helper-split-export-declaration" "^7.8.3" - "@babel/helper-create-regexp-features-plugin@^7.12.1": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.7.tgz#2084172e95443fa0a09214ba1bb328f9aea1278f" @@ -182,15 +198,6 @@ "@babel/helper-annotate-as-pure" "^7.10.4" regexpu-core "^4.7.1" -"@babel/helper-create-regexp-features-plugin@^7.8.3", "@babel/helper-create-regexp-features-plugin@^7.8.8": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.8.tgz#5d84180b588f560b7864efaeea89243e58312087" - integrity sha512-LYVPdwkrQEiX9+1R29Ld/wTrmQu1SSKYnuOk3g0CkcZMA1p0gsNxJFj/3gBdaJ7Cg0Fnek5z0DsMULePP7Lrqg== - dependencies: - "@babel/helper-annotate-as-pure" "^7.8.3" - "@babel/helper-regex" "^7.8.3" - regexpu-core "^4.7.0" - "@babel/helper-define-map@^7.10.4": version "7.10.5" resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz#b53c10db78a640800152692b13393147acb9bb30" @@ -208,15 +215,6 @@ "@babel/types" "^7.12.1" "@babel/helper-function-name@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz#d2d3b20c59ad8c47112fa7d2a94bc09d5ef82f1a" - integrity sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ== - dependencies: - "@babel/helper-get-function-arity" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/types" "^7.10.4" - -"@babel/helper-function-name@^7.12.11", "@babel/helper-function-name@^7.9.5": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.11.tgz#1fd7738aee5dcf53c3ecff24f1da9c511ec47b42" integrity sha512-AtQKjtYNolKNi6nNNVLQ27CP6D9oFR6bq/HPYSizlzbp7uC1M59XJe8L+0uXjbIaZaUJF99ruHqVGiKXU/7ybA== @@ -225,7 +223,7 @@ "@babel/template" "^7.12.7" "@babel/types" "^7.12.11" -"@babel/helper-function-name@^7.12.13": +"@babel/helper-function-name@^7.12.11", "@babel/helper-function-name@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== @@ -234,21 +232,7 @@ "@babel/template" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-get-function-arity@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz#98c1cbea0e2332f33f9a4661b8ce1505b2c19ba2" - integrity sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-get-function-arity@^7.12.10": - version "7.12.10" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.10.tgz#b158817a3165b5faa2047825dfa61970ddcc16cf" - integrity sha512-mm0n5BPjR06wh9mPQaDdXWDoll/j5UpCAPl1x8fS71GHm7HA6Ua2V4ylG1Ju8lvcTOietbPNNPaSilKj+pj+Ag== - dependencies: - "@babel/types" "^7.12.10" - -"@babel/helper-get-function-arity@^7.12.13": +"@babel/helper-get-function-arity@^7.12.10", "@babel/helper-get-function-arity@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== @@ -262,12 +246,12 @@ dependencies: "@babel/types" "^7.10.4" -"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.8.3": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.1.tgz#fba0f2fcff3fba00e6ecb664bb5e6e26e2d6165c" - integrity sha512-k0CIe3tXUKTRSoEx1LQEPFU9vRQfqHtl+kf8eNnDqb4AUJEy5pz6aIiog+YWtVm2jpggjS1laH68bPsR+KWWPQ== +"@babel/helper-member-expression-to-functions@^7.12.1", "@babel/helper-member-expression-to-functions@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.0.tgz#6aa4bb678e0f8c22f58cdb79451d30494461b091" + integrity sha512-yvRf8Ivk62JwisqV1rFRMxiSMDGnN6KH1/mDMmIrij4jztpQNRoHqqMG3U6apYbGRPJpgPalhva9Yd06HlUxJQ== dependencies: - "@babel/types" "^7.12.1" + "@babel/types" "^7.13.0" "@babel/helper-member-expression-to-functions@^7.12.13": version "7.12.16" @@ -276,14 +260,7 @@ dependencies: "@babel/types" "^7.12.13" -"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.8.3": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz#1644c01591a15a2f084dd6d092d9430eb1d1216c" - integrity sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA== - dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-module-imports@^7.12.13": +"@babel/helper-module-imports@^7.12.1", "@babel/helper-module-imports@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0" integrity sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g== @@ -297,19 +274,26 @@ dependencies: "@babel/types" "^7.12.5" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.9.0": +"@babel/helper-module-imports@^7.8.3": version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.1.tgz#7954fec71f5b32c48e4b303b437c34453fd7247c" - integrity sha512-QQzehgFAZ2bbISiCpmVGfiGux8YVFXQ0abBic2Envhej22DVXV9nCFaS5hIQbkyo1AdGb+gNME2TSh3hYJVV/w== + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.1.tgz#1644c01591a15a2f084dd6d092d9430eb1d1216c" + integrity sha512-ZeC1TlMSvikvJNy1v/wPIazCu3NdOwgYZLIkmIyAsGhqkNpiDoQQRmaCK8YP4Pq3GPTLPV9WXaPCJKvx06JxKA== dependencies: - "@babel/helper-module-imports" "^7.12.1" - "@babel/helper-replace-supers" "^7.12.1" - "@babel/helper-simple-access" "^7.12.1" - "@babel/helper-split-export-declaration" "^7.11.0" - "@babel/helper-validator-identifier" "^7.10.4" - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.1" "@babel/types" "^7.12.1" + +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.13.0.tgz#42eb4bd8eea68bab46751212c357bfed8b40f6f1" + integrity sha512-Ls8/VBwH577+pw7Ku1QkUWIyRRNHpYlts7+qSqBBFCW3I8QteB9DxfcZ5YJpOwH6Ihe/wn8ch7fMGOP1OhEIvw== + dependencies: + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-replace-supers" "^7.13.0" + "@babel/helper-simple-access" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/helper-validator-identifier" "^7.12.11" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" lodash "^4.17.19" "@babel/helper-module-transforms@^7.12.13": @@ -327,14 +311,7 @@ "@babel/types" "^7.12.13" lodash "^4.17.19" -"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.8.3": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz#50dc96413d594f995a77905905b05893cd779673" - integrity sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg== - dependencies: - "@babel/types" "^7.10.4" - -"@babel/helper-optimise-call-expression@^7.12.13": +"@babel/helper-optimise-call-expression@^7.10.4", "@babel/helper-optimise-call-expression@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== @@ -346,13 +323,6 @@ resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-regex@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" - integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== - dependencies: - lodash "^4.17.13" - "@babel/helper-remap-async-to-generator@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.12.1.tgz#8c4dbbf916314f6047dc05e6a2217074238347fd" @@ -362,15 +332,15 @@ "@babel/helper-wrap-function" "^7.10.4" "@babel/types" "^7.12.1" -"@babel/helper-replace-supers@^7.12.1", "@babel/helper-replace-supers@^7.8.6": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.1.tgz#f15c9cc897439281891e11d5ce12562ac0cf3fa9" - integrity sha512-zJjTvtNJnCFsCXVi5rUInstLd/EIVNmIKA1Q9ynESmMBWPWd+7sdR+G4/wdu+Mppfep0XLyG2m7EBPvjCeFyrw== +"@babel/helper-replace-supers@^7.12.1", "@babel/helper-replace-supers@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.0.tgz#6034b7b51943094cb41627848cb219cb02be1d24" + integrity sha512-Segd5me1+Pz+rmN/NFBOplMbZG3SqRJOBlY+mA0SxAv6rjj7zJqr1AVr3SfzUVTLCv7ZLU5FycOM/SBGuLPbZw== dependencies: - "@babel/helper-member-expression-to-functions" "^7.12.1" - "@babel/helper-optimise-call-expression" "^7.10.4" - "@babel/traverse" "^7.12.1" - "@babel/types" "^7.12.1" + "@babel/helper-member-expression-to-functions" "^7.13.0" + "@babel/helper-optimise-call-expression" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" "@babel/helper-replace-supers@^7.12.13": version "7.12.13" @@ -382,14 +352,7 @@ "@babel/traverse" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helper-simple-access@^7.12.1", "@babel/helper-simple-access@^7.8.3": - version "7.12.1" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.1.tgz#32427e5aa61547d38eb1e6eaf5fd1426fdad9136" - integrity sha512-OxBp7pMrjVewSSC8fXDFrHrBcJATOOFssZwv16F3/6Xtc138GHybBfPbm9kfiqQHKhYQrlamWILwlDCeyMFEaA== - dependencies: - "@babel/types" "^7.12.1" - -"@babel/helper-simple-access@^7.12.13": +"@babel/helper-simple-access@^7.12.1", "@babel/helper-simple-access@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz#8478bcc5cacf6aa1672b251c1d2dde5ccd61a6c4" integrity sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA== @@ -403,14 +366,14 @@ dependencies: "@babel/types" "^7.12.1" -"@babel/helper-split-export-declaration@^7.10.4", "@babel/helper-split-export-declaration@^7.11.0", "@babel/helper-split-export-declaration@^7.12.11", "@babel/helper-split-export-declaration@^7.8.3": +"@babel/helper-split-export-declaration@^7.10.4": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.11.tgz#1b4cc424458643c47d37022223da33d76ea4603a" integrity sha512-LsIVN8j48gHgwzfocYUSkO/hjYAOJqlpJEc7tGXcIm4cubjVUf8LGW6eWRyxEu7gA25q02p0rQUWoCI33HNS5g== dependencies: "@babel/types" "^7.12.11" -"@babel/helper-split-export-declaration@^7.12.13": +"@babel/helper-split-export-declaration@^7.12.11", "@babel/helper-split-export-declaration@^7.12.13": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== @@ -427,6 +390,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.11.tgz#d66cb8b7a3e7fe4c6962b32020a131ecf0847f4f" integrity sha512-TBFCyj939mFSdeX7U7DDj32WtzYY7fDcalgq8v3fBZMNOJQNn7nOYzMaUCiPxPYfCup69mtIpqlKgMZLvQ8Xhw== +"@babel/helper-validator-option@^7.12.17": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" + integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== + "@babel/helper-wrap-function@^7.10.4": version "7.12.3" resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.12.3.tgz#3332339fc4d1fbbf1c27d7958c27d34708e990d9" @@ -446,21 +414,21 @@ "@babel/traverse" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/helpers@^7.12.5": - version "7.12.5" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.5.tgz#1a1ba4a768d9b58310eda516c449913fe647116e" - integrity sha512-lgKGMQlKqA8meJqKsW6rUnc4MdUk35Ln0ATDqdM1a/UpARODdI4j5Y5lVfUScnSNkJcdCRAaWkspykNoFg9sJA== +"@babel/helpers@^7.12.5", "@babel/helpers@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.0.tgz#7647ae57377b4f0408bf4f8a7af01c42e41badc0" + integrity sha512-aan1MeFPxFacZeSz6Ld7YZo5aPuqnKlD7+HZY75xQsueczFccP9A7V05+oe0XpLwHK3oLorPe9eaAUljL7WEaQ== dependencies: - "@babel/template" "^7.10.4" - "@babel/traverse" "^7.12.5" - "@babel/types" "^7.12.5" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.0" "@babel/highlight@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" - integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== + version "7.13.8" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.8.tgz#10b2dac78526424dfc1f47650d0e415dfd9dc481" + integrity sha512-4vrIhfJyfNf+lCtXC2ck1rKSzDwciqF7IWFhXXrSOUC2O5DrVp+w4c6ed4AllTxhTkUP5x2tYj41VaxdVMMRDw== dependencies: - "@babel/helper-validator-identifier" "^7.10.4" + "@babel/helper-validator-identifier" "^7.12.11" chalk "^2.0.0" js-tokens "^4.0.0" @@ -473,11 +441,16 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.0.0", "@babel/parser@^7.12.0", "@babel/parser@^7.12.11", "@babel/parser@^7.12.7": +"@babel/parser@^7.0.0", "@babel/parser@^7.12.0": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.11.tgz#9ce3595bcd74bc5c466905e86c535b8b25011e79" integrity sha512-N3UxG+uuF4CMYoNj8AhnbAcJF0PiuJ9KHuy1lQmkYsxTer/MAH9UBNHsBoAX/4s6NvlDD047No8mYVGGzLL4hg== +"@babel/parser@^7.12.11", "@babel/parser@^7.12.7", "@babel/parser@^7.13.0", "@babel/parser@^7.13.4": + version "7.13.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.4.tgz#340211b0da94a351a6f10e63671fa727333d13ab" + integrity sha512-uvoOulWHhI+0+1f9L4BoozY7U5cIkZ9PgJqvb041d6vypgUmtVPG4vmGm4pSggjl8BELzvHyUeJSUyEMY6b+qA== + "@babel/parser@^7.12.13", "@babel/parser@^7.12.16": version "7.12.16" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4" @@ -492,15 +465,7 @@ "@babel/helper-remap-async-to-generator" "^7.12.1" "@babel/plugin-syntax-async-generators" "^7.8.0" -"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.2.1": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.8.3.tgz#5e06654af5cd04b608915aada9b2a6788004464e" - integrity sha512-EqFhbo7IosdgPgZggHaNObkmO1kNUe3slaKu54d5OWvy+p9QIKOzK1GAEpAIsZtWVtPXUHSMcT4smvDrCfY4AA== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - -"@babel/plugin-proposal-class-properties@^7.12.1": +"@babel/plugin-proposal-class-properties@^7.1.0", "@babel/plugin-proposal-class-properties@^7.12.1", "@babel/plugin-proposal-class-properties@^7.2.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.12.1.tgz#a082ff541f2a29a4821065b8add9346c0c16e5de" integrity sha512-cKp3dlQsFsEs5CWKnN7BnSHOd0EOW8EKpEjkoz1pO2E5KzIDNV9Ros1b0CnmbVgAGXJubOYVBOGCT1OmJwOI7w== @@ -540,7 +505,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1": +"@babel/plugin-proposal-nullish-coalescing-operator@^7.12.1", "@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.12.1.tgz#3ed4fff31c015e7f3f1467f190dbe545cd7b046c" integrity sha512-nZY0ESiaQDI1y96+jk6VxMOaL4LPo/QDHBqL+SF3/vl6dHkTwHlOI8L4ZwuRBHgakRBw5zsVylel7QPbbGuYgg== @@ -548,14 +513,6 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.4.4": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" - integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" - "@babel/plugin-proposal-numeric-separator@^7.12.7": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.12.7.tgz#8bf253de8139099fea193b297d23a9d406ef056b" @@ -581,7 +538,7 @@ "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.12.7": +"@babel/plugin-proposal-optional-chaining@^7.12.7", "@babel/plugin-proposal-optional-chaining@^7.2.0": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.12.7.tgz#e02f0ea1b5dc59d401ec16fb824679f683d3303c" integrity sha512-4ovylXZ0PWmwoOvhU2vhnzVNnm88/Sm9nx7V8BPgMvAzn5zDou3/Awy0EjglyubVHasJj+XCEkr/r1X3P5elCA== @@ -590,14 +547,6 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.12.1" "@babel/plugin-syntax-optional-chaining" "^7.8.0" -"@babel/plugin-proposal-optional-chaining@^7.2.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.9.0.tgz#31db16b154c39d6b8a645292472b98394c292a58" - integrity sha512-NDn5tu3tcv4W30jNhmc2hyD5c56G6cXx4TesJubhxrJeCvuuMpttxr0OnNCqbZGhFjLrg+NIhxxC+BK5F6yS3w== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.0" - "@babel/plugin-proposal-private-methods@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.12.1.tgz#86814f6e7a21374c980c10d38b4493e703f4a389" @@ -606,7 +555,7 @@ "@babel/helper-create-class-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.12.1": +"@babel/plugin-proposal-unicode-property-regex@^7.12.1", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.12.1.tgz#2a183958d417765b9eae334f47758e5d6a82e072" integrity sha512-MYq+l+PvHuw/rKUz1at/vb6nCnQ2gmJBNaM62z0OgH7B2W1D9pvkpYtlti9bGtizNIU1K3zm4bZF9F91efVY0w== @@ -614,14 +563,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.8.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.8.tgz#ee3a95e90cdc04fe8cd92ec3279fa017d68a0d1d" - integrity sha512-EVhjVsMpbhLw9ZfHWSx2iy13Q8Z/eg8e8ccVWt23sWQK5l1UdkoLJPN5w69UA4uITGBnEZD2JOe4QOHycYKv8A== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.8" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-async-generators@^7.8.0": version "7.8.4" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" @@ -799,7 +740,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.12.1": +"@babel/plugin-transform-dotall-regex@^7.12.1", "@babel/plugin-transform-dotall-regex@^7.4.4": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.12.1.tgz#a1d16c14862817b6409c0a678d6f9373ca9cd975" integrity sha512-B2pXeRKoLszfEW7J4Hg9LoFaWEbr/kzo3teWHmtFCszjRNa/b40f9mfeqZsIDLLt/FjwQ6pz/Gdlwy85xNckBA== @@ -807,14 +748,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.12.1" "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" - integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.8.3" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-transform-duplicate-keys@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.12.1.tgz#745661baba295ac06e686822797a69fbaa2ca228" @@ -876,17 +809,7 @@ "@babel/helper-plugin-utils" "^7.10.4" babel-plugin-dynamic-import-node "^2.3.3" -"@babel/plugin-transform-modules-commonjs@^7.0.0": - version "7.9.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.9.0.tgz#e3e72f4cbc9b4a260e30be0ea59bdf5a39748940" - integrity sha512-qzlCrLnKqio4SlgJ6FMMLBe4bySNis8DFn1VkGmOcxG9gqEyPIOzeQrA//u0HAKrWpJlpZbZMPB1n/OPa4+n8g== - dependencies: - "@babel/helper-module-transforms" "^7.9.0" - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/helper-simple-access" "^7.8.3" - babel-plugin-dynamic-import-node "^2.3.0" - -"@babel/plugin-transform-modules-commonjs@^7.12.1": +"@babel/plugin-transform-modules-commonjs@^7.0.0", "@babel/plugin-transform-modules-commonjs@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.12.1.tgz#fa403124542636c786cf9b460a0ffbb48a86e648" integrity sha512-dY789wq6l0uLY8py9c1B48V8mVL5gZh/+PQ5ZPrylPYsnAvnEMjqsUXkuoDVPeVK+0VyGar+D08107LzDQ6pag== @@ -1198,16 +1121,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/template@^7.10.4", "@babel/template@^7.12.7", "@babel/template@^7.4.0", "@babel/template@^7.8.6": - version "7.12.7" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" - integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== - dependencies: - "@babel/code-frame" "^7.10.4" - "@babel/parser" "^7.12.7" - "@babel/types" "^7.12.7" - -"@babel/template@^7.12.13": +"@babel/template@^7.10.4", "@babel/template@^7.12.13", "@babel/template@^7.12.7": version "7.12.13" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== @@ -1216,7 +1130,16 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.2.3": +"@babel/template@^7.4.0", "@babel/template@^7.8.6": + version "7.12.7" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.7.tgz#c817233696018e39fbb6c491d2fb684e05ed43bc" + integrity sha512-GkDzmHS6GV7ZeXfJZ0tLRBhZcMcY0/Lnb+eEbXDBfCAcZCjrZKe6p3J4we/D24O9Y8enxWAg1cWwof59yLh2ow== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + +"@babel/traverse@^7.0.0", "@babel/traverse@^7.10.4", "@babel/traverse@^7.2.3": version "7.12.12" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.12.tgz#d0cd87892704edd8da002d674bc811ce64743376" integrity sha512-s88i0X0lPy45RrLM8b9mz8RPH5FqO9G9p7ti59cToE44xFm1Q+Pjh5Gq4SXBbtb88X7Uy7pexeqRIQDDMNkL0w== @@ -1246,10 +1169,25 @@ globals "^11.1.0" lodash "^4.17.19" -"@babel/types@^7.10.4", "@babel/types@^7.12.0", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.4.4", "@babel/types@^7.8.3", "@babel/types@^7.9.0", "@babel/types@^7.9.5": - version "7.12.12" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" - integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== +"@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.0.tgz#6d95752475f86ee7ded06536de309a65fc8966cc" + integrity sha512-xys5xi5JEhzC3RzEmSGrs/b3pJW/o87SypZ+G/PhaE7uqVQNv/jlmVIBXuoh5atqQ434LfXV+sf23Oxj0bchJQ== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.0" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.13.0" + "@babel/types" "^7.13.0" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/types@^7.10.4", "@babel/types@^7.12.1", "@babel/types@^7.12.10", "@babel/types@^7.12.11", "@babel/types@^7.12.12", "@babel/types@^7.12.5", "@babel/types@^7.12.7", "@babel/types@^7.13.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.0.tgz#74424d2816f0171b4100f0ab34e9a374efdf7f80" + integrity sha512-hE+HE8rnG1Z6Wzo+MhaKE5lM5eMx71T4EHJgku2E3xIfaULhDcxiiRxUYgwX8qwP1BBSlag+TdGOt6JAidIZTA== dependencies: "@babel/helper-validator-identifier" "^7.12.11" lodash "^4.17.19" @@ -1264,6 +1202,15 @@ lodash "^4.17.19" to-fast-properties "^2.0.0" +"@babel/types@^7.12.0", "@babel/types@^7.4.4", "@babel/types@^7.9.0", "@babel/types@^7.9.5": + version "7.12.12" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.12.tgz#4608a6ec313abbd87afa55004d373ad04a96c299" + integrity sha512-lnIX7piTxOH22xE7fDXDbSHg9MM1/6ORnafpJmov5rs0kX5g4BZxeXNJLXsMRiO0U5Rb8/FvMS6xlTnTHvxonQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + "@choojs/findup@^0.2.0": version "0.2.1" resolved "https://registry.yarnpkg.com/@choojs/findup/-/findup-0.2.1.tgz#ac13c59ae7be6e1da64de0779a0a7f03d75615a3" @@ -2085,9 +2032,9 @@ unist-util-visit "2.0.3" "@mdx-js/react@^1.5.3": - version "1.5.5" - resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.5.5.tgz#0036e65ec59521059f33292f535b9ef0d67bd0e6" - integrity sha512-Qwvri4zyU9ZbhhXsH0wfSZ/J9b8mARRTB6GSCTnyKRffO2CaQXl9oLsvRAeQSLRei/onEARc+RexH+jMeNS1rw== + version "1.6.22" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" + integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== "@mdx-js/util@1.6.22": version "1.6.22" @@ -2102,6 +2049,22 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@napi-rs/cli@1.0.0-alpha.10": + version "1.0.0-alpha.10" + resolved "https://registry.yarnpkg.com/@napi-rs/cli/-/cli-1.0.0-alpha.10.tgz#7d6d3f77a5728fb62c9bca28128451e1b58be810" + integrity sha512-T9uxMZOdo/3rotlz6d3ECbVbBIXPpHHC+Ta3N87EvA93ZPWIQIUvskc28WBit/bWAX4xDtfBZRLA9gtWX0b8kw== + dependencies: + "@octokit/rest" "^18.0.12" + chalk "^4.1.0" + clipanion "^2.6.2" + debug "^4.3.1" + fdir "^4.1.0" + inquirer "^7.3.3" + lodash "^4.17.20" + putasset "^5.0.3" + toml "^3.0.0" + tslib "^2.0.3" + "@nodelib/fs.scandir@2.1.3": version "2.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" @@ -2135,6 +2098,37 @@ dependencies: "@octokit/types" "^6.0.0" +"@octokit/auth-token@^2.4.4": + version "2.4.5" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.5.tgz#568ccfb8cb46f36441fac094ce34f7a875b197f3" + integrity sha512-BpGYsPgJt05M7/L/5FoE1PiAbdxXFZkX/3kDYcsvd1v6UhlnE5e96dTDr0ezX/EFwciQxf3cNV0loipsURU+WA== + dependencies: + "@octokit/types" "^6.0.3" + +"@octokit/core@^2.4.3": + version "2.5.4" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-2.5.4.tgz#f7fbf8e4f86c5cc2497a8887ba2561ec8d358054" + integrity sha512-HCp8yKQfTITYK+Nd09MHzAlP1v3Ii/oCohv0/TW9rhSLvzb98BOVs2QmVYuloE6a3l6LsfyGIwb6Pc4ycgWlIQ== + dependencies: + "@octokit/auth-token" "^2.4.0" + "@octokit/graphql" "^4.3.1" + "@octokit/request" "^5.4.0" + "@octokit/types" "^5.0.0" + before-after-hook "^2.1.0" + universal-user-agent "^5.0.0" + +"@octokit/core@^3.2.3": + version "3.2.5" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.2.5.tgz#57becbd5fd789b0592b915840855f3a5f233d554" + integrity sha512-+DCtPykGnvXKWWQI0E1XD+CCeWSBhB6kwItXqfFmNBlIlhczuDPbg+P6BtLnVBaRJDAjv+1mrUJuRsFSjktopg== + dependencies: + "@octokit/auth-token" "^2.4.4" + "@octokit/graphql" "^4.5.8" + "@octokit/request" "^5.4.12" + "@octokit/types" "^6.0.3" + before-after-hook "^2.1.0" + universal-user-agent "^6.0.0" + "@octokit/endpoint@^6.0.1": version "6.0.11" resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.11.tgz#082adc2aebca6dcefa1fb383f5efb3ed081949d1" @@ -2144,6 +2138,15 @@ is-plain-object "^5.0.0" universal-user-agent "^6.0.0" +"@octokit/graphql@^4.3.1", "@octokit/graphql@^4.5.8": + version "4.6.0" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.6.0.tgz#f9abca55f82183964a33439d5264674c701c3327" + integrity sha512-CJ6n7izLFXLvPZaWzCQDjU/RP+vHiZmWdOunaCS87v+2jxMsW9FB5ktfIxybRBxZjxuJGRnxk7xJecWTVxFUYQ== + dependencies: + "@octokit/request" "^5.3.0" + "@octokit/types" "^6.0.3" + universal-user-agent "^6.0.0" + "@octokit/openapi-types@^2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-2.3.0.tgz#075c4e5a1d05d0b62cd8048b71764537aa870c00" @@ -2154,11 +2157,44 @@ resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-4.0.0.tgz#40af33247d6acb17d942c513ec361ba9fe37d38f" integrity sha512-o4Q9VPYaIdzxskfVuWk7Dcb6Ldq2xbd1QKmPCRx29nFdFxm+2Py74QLfbB3CgankZerHnNJ9wgINOkwa/O2qRg== +"@octokit/openapi-types@^5.1.0": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@octokit/openapi-types/-/openapi-types-5.1.1.tgz#d01ae6e2879c589edcea7800e3a427455ece619f" + integrity sha512-yMyaX9EDWCiyv7m85/K8L7bLFj1wrLdfDkKcZEZ6gNmepSW5mfSMFJnYwRINN7lF58wvevKPWvw0MYy6sxcFlQ== + "@octokit/plugin-enterprise-rest@^3.6.1": version "3.6.2" resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-3.6.2.tgz#74de25bef21e0182b4fa03a8678cd00a4e67e561" integrity sha512-3wF5eueS5OHQYuAEudkpN+xVeUsg8vYEMMenEzLphUZ7PRZ8OJtDcsreL3ad9zxXmBbaFWzLmFcdob5CLyZftA== +"@octokit/plugin-paginate-rest@^2.2.0", "@octokit/plugin-paginate-rest@^2.6.2": + version "2.10.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.10.0.tgz#5925156d809c94b7bfc47b28e17488415548fa67" + integrity sha512-71OsKBSMcQEu/6lfVbhv5C5ikU1rn10rKot/WiV7do7fyfElQ2eCUQFogHPbj0ci5lnKAjvahOiMAr6lcvL8Qw== + dependencies: + "@octokit/types" "^6.10.0" + +"@octokit/plugin-request-log@^1.0.0", "@octokit/plugin-request-log@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.3.tgz#70a62be213e1edc04bb8897ee48c311482f9700d" + integrity sha512-4RFU4li238jMJAzLgAwkBAw+4Loile5haQMQr+uhFq27BmyJXcXSKvoQKqh0agsZEiUlW6iSv3FAgvmGkur7OQ== + +"@octokit/plugin-rest-endpoint-methods@3.17.0": + version "3.17.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-3.17.0.tgz#d8ba04eb883849dd98666c55bf49d8c9fe7be055" + integrity sha512-NFV3vq7GgoO2TrkyBRUOwflkfTYkFKS0tLAPym7RNpkwLCttqShaEGjthOsPEEL+7LFcYv3mU24+F2yVd3npmg== + dependencies: + "@octokit/types" "^4.1.6" + deprecation "^2.3.1" + +"@octokit/plugin-rest-endpoint-methods@4.12.2": + version "4.12.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.12.2.tgz#d2bd0b794d6c11a13113db6199baf44a39b06f50" + integrity sha512-5+MmGusB7wPw7OholtcGaMyjfrsFSpFqtJW8VsrbfU/TuaiQepY4wgVkS7P3TAObX257jrTbbGo/sJLcoGf16g== + dependencies: + "@octokit/types" "^6.10.1" + deprecation "^2.3.1" + "@octokit/request-error@^1.0.2": version "1.2.0" resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.0.tgz#a64d2a9d7a13555570cd79722de4a4d76371baaa" @@ -2191,6 +2227,20 @@ once "^1.4.0" universal-user-agent "^6.0.0" +"@octokit/request@^5.3.0", "@octokit/request@^5.4.0", "@octokit/request@^5.4.12": + version "5.4.14" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.14.tgz#ec5f96f78333bb2af390afa5ff66f114b063bc96" + integrity sha512-VkmtacOIQp9daSnBmDI92xNIeLuSRDOIuplp/CJomkvzt7M18NXgG044Cx/LFKLgjKt9T2tZR6AtJayba9GTSA== + dependencies: + "@octokit/endpoint" "^6.0.1" + "@octokit/request-error" "^2.0.0" + "@octokit/types" "^6.7.1" + deprecation "^2.0.0" + is-plain-object "^5.0.0" + node-fetch "^2.6.1" + once "^1.4.0" + universal-user-agent "^6.0.0" + "@octokit/rest@^16.28.4": version "16.38.1" resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.38.1.tgz#be24e0faa7d0bdb9459fbc089ec866ed11774b72" @@ -2210,6 +2260,26 @@ once "^1.4.0" universal-user-agent "^4.0.0" +"@octokit/rest@^17.1.3": + version "17.11.2" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-17.11.2.tgz#f3dbd46f9f06361c646230fd0ef8598e59183ead" + integrity sha512-4jTmn8WossTUaLfNDfXk4fVJgbz5JgZE8eCs4BvIb52lvIH8rpVMD1fgRCrHbSd6LRPE5JFZSfAEtszrOq3ZFQ== + dependencies: + "@octokit/core" "^2.4.3" + "@octokit/plugin-paginate-rest" "^2.2.0" + "@octokit/plugin-request-log" "^1.0.0" + "@octokit/plugin-rest-endpoint-methods" "3.17.0" + +"@octokit/rest@^18.0.12": + version "18.2.1" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.2.1.tgz#04835fe9ab0d90ca2a93898cde2aa944c78c70bc" + integrity sha512-DdQ1vps41JSyB2axyL1mBwJiXAPibgugIQPOmt0mL/yhwheQ6iuq2aKiJWgGWa9ldMfe3v9gIFYlrFgxQ5ThGQ== + dependencies: + "@octokit/core" "^3.2.3" + "@octokit/plugin-paginate-rest" "^2.6.2" + "@octokit/plugin-request-log" "^1.0.2" + "@octokit/plugin-rest-endpoint-methods" "4.12.2" + "@octokit/types@^2.0.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.1.1.tgz#77e80d1b663c5f1f829e5377b728fa3c4fe5a97d" @@ -2217,6 +2287,20 @@ dependencies: "@types/node" ">= 8" +"@octokit/types@^4.1.6": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-4.1.10.tgz#e4029c11e2cc1335051775bc1600e7e740e4aca4" + integrity sha512-/wbFy1cUIE5eICcg0wTKGXMlKSbaAxEr00qaBXzscLXpqhcwgXeS6P8O0pkysBhRfyjkKjJaYrvR1ExMO5eOXQ== + dependencies: + "@types/node" ">= 8" + +"@octokit/types@^5.0.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" + integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== + dependencies: + "@types/node" ">= 8" + "@octokit/types@^6.0.0": version "6.8.2" resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.8.2.tgz#ce4872e038d6df38b2d3c21bc12329af0b10facb" @@ -2233,10 +2317,12 @@ "@octokit/openapi-types" "^2.3.0" "@types/node" ">= 8" -"@parcel/fs-search@2.0.0-beta.1": - version "2.0.0-beta.1" - resolved "https://registry.yarnpkg.com/@parcel/fs-search/-/fs-search-2.0.0-beta.1.tgz#18491695f0f7bef27558019a2721f59426d0b418" - integrity sha512-n2dRDixuKfsV6qf/E0c6UoHNlEjourU3I4QnPlOPhJCSnC1ZGpvKNUIVFeZ1p4eMNzasf7YcJcGpivJkUOq8Eg== +"@octokit/types@^6.10.0", "@octokit/types@^6.10.1", "@octokit/types@^6.7.1": + version "6.10.1" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-6.10.1.tgz#5955dc0cf344bb82a46283a0c332651f5dd9f1ad" + integrity sha512-hgNC5jxKG8/RlqxU/6GThkGrvFpz25+cPzjQjyiXTNBvhyltn2Z4GhFY25+kbtXwZ4Co4zM0goW5jak1KLp1ug== + dependencies: + "@octokit/openapi-types" "^5.1.0" "@parcel/source-map@2.0.0-alpha.4.21": version "2.0.0-alpha.4.21" @@ -3179,13 +3265,6 @@ babel-plugin-apply-mdx-type-prop@1.6.22: "@babel/helper-plugin-utils" "7.10.4" "@mdx-js/util" "1.6.22" -babel-plugin-dynamic-import-node@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -3300,6 +3379,11 @@ before-after-hook@^2.0.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== +before-after-hook@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.1.tgz#99ae36992b5cfab4a83f6bee74ab27835f28f405" + integrity sha512-5ekuQOvO04MDj7kYZJaMab2S8SPjGJbotVNyv7QYFCOAwrGZs/YnoDNlh1U+m5hl7H2D/+n0taaAV/tfyd3KMA== + big.js@^5.2.2: version "5.2.2" resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" @@ -3322,16 +3406,7 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bl@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.2.tgz#52b71e9088515d0606d9dd9cc7aa48dc1f98e73a" - integrity sha512-j4OH8f6Qg2bGuWfRiltT2HYGx0e1QcBTrK9KAHNMwMZdQnDZFk0ZSYIpADjYCB3U12nicC5tVJwSIhwOWjb4RQ== - dependencies: - buffer "^5.5.0" - inherits "^2.0.4" - readable-stream "^3.4.0" - -bl@^4.0.3: +bl@^4.0.1, bl@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489" integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg== @@ -3465,16 +3540,7 @@ browserify-zlib@^0.2.0: dependencies: pako "~1.0.5" -browserslist@^4.0.0, browserslist@^4.6.6, browserslist@^4.9.1: - version "4.9.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.9.1.tgz#01ffb9ca31a1aef7678128fc6a2253316aa7287c" - integrity sha512-Q0DnKq20End3raFulq6Vfp1ecB9fh8yUNV55s8sekaDDeqBaCtWlRHCUdaWyUeSSBJM7IbM6HcsyaeYqgeDhnw== - dependencies: - caniuse-lite "^1.0.30001030" - electron-to-chromium "^1.3.363" - node-releases "^1.1.50" - -browserslist@^4.14.5, browserslist@^4.16.1: +browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.1, browserslist@^4.6.6: version "4.16.1" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.1.tgz#bf757a2da376b3447b800a16f0f1c96358138766" integrity sha512-UXhDrwqsNcpTYJBTZsbGATDxZbiVDsx6UjpmRUmtnP10pr8wAYr5LgFoEFw9ixriQH2mv/NX2SfGzE/o8GndLA== @@ -3673,12 +3739,7 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001030: - version "1.0.30001117" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001117.tgz#69a9fae5d480eaa9589f7641a83842ad396d17c4" - integrity sha512-4tY0Fatzdx59kYjQs+bNxUwZB03ZEBgVmJ1UkFPz/Q8OLiUUbjct2EdpnXj0fvFTPej2EkbPIG0w8BWsjAyk1Q== - -caniuse-lite@^1.0.30001173: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001173: version "1.0.30001181" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001181.tgz#4f0e5184e1ea7c3bf2727e735cbe7ca9a451d673" integrity sha512-m5ul/ARCX50JB8BSNM+oiPmQrR5UmngaQ3QThTTp5HcIIQGP/nPBs82BYLE+tigzm3VW+F4BJIhUyaVtEweelQ== @@ -3761,6 +3822,11 @@ charenc@~0.0.1: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= +checkup@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/checkup/-/checkup-1.3.0.tgz#d3800276fea5d0f247ffc951be78c8b02f8e0d76" + integrity sha1-04ACdv6l0PJH/8lRvnjIsC+ODXY= + chokidar@3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" @@ -3894,6 +3960,11 @@ cli-width@^3.0.0: resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== +clipanion@^2.6.2: + version "2.6.2" + resolved "https://registry.yarnpkg.com/clipanion/-/clipanion-2.6.2.tgz#820e7440812052442455b248f927b187ed732f71" + integrity sha512-0tOHJNMF9+4R3qcbBL+4IxLErpaYSYvzs10aXuECDbZdJOuJHdagJMAqvLdeaUQTI/o2uSCDRpet6ywDiKOAYw== + cliui@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-2.1.0.tgz#4b475760ff80264c762c3a1719032e91c7fea0d1" @@ -4838,7 +4909,7 @@ deasync@^0.1.14: bindings "^1.5.0" node-addon-api "^1.7.1" -debug@*, debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@*, debug@4.3.1, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -4981,7 +5052,7 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -deprecation@^2.0.0: +deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== @@ -5231,11 +5302,6 @@ ejs@^2.6.1: resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== -electron-to-chromium@^1.3.363: - version "1.3.368" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.368.tgz#d7597e04339f7ca70762031ec473d38eb2df6acb" - integrity sha512-fqzDipW3p+uDkHUHFPrdW3wINRKcJsbnJwBD7hgaQEQwcuLSvNLw6SeUp5gKDpTbmTl7zri7IZfhsdTUTnygJg== - electron-to-chromium@^1.3.634: version "1.3.649" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.649.tgz#3aa8be052d4d268ede45d8e98d0cd60ffefad607" @@ -6000,25 +6066,23 @@ fastq@^1.6.0: dependencies: reusify "^1.0.0" -fault@^1.0.0: +fault@^1.0.0, fault@^1.0.1: version "1.0.4" resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== dependencies: format "^0.2.0" -fault@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.3.tgz#4da88cf979b6b792b4e13c7ec836767725170b7e" - integrity sha512-sfFuP4X0hzrbGKjAUNXYvNqsZ5F6ohx/dZ9I0KQud/aiZNwg263r5L9yGB0clvXHCkzXh5W3t7RSHchggYIFmA== - dependencies: - format "^0.2.2" - fclone@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/fclone/-/fclone-1.0.11.tgz#10e85da38bfea7fc599341c296ee1d77266ee640" integrity sha1-EOhdo4v+p/xZk0HClu4ddyZu5kA= +fdir@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-4.1.0.tgz#f739ec79f61f69779a6430a622e5f54c57caf921" + integrity sha512-oOkohnPg4nUIkd6w22iGbFD7c7UvVnXB3a7/GHcPSsXDUGm6Jxp12bGI5O0gr0YuhDh5l/vDExdHOnrW/j9EqQ== + figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" @@ -6283,7 +6347,7 @@ form-data@~2.3.2: combined-stream "^1.0.6" mime-types "^2.1.12" -format@^0.2.0, format@^0.2.2: +format@^0.2.0: version "0.2.2" resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= @@ -6401,10 +6465,10 @@ genfun@^5.0.0: resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA== -gensync@^1.0.0-beta.1: - version "1.0.0-beta.1" - resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" - integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== +gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== get-caller-file@^1.0.1: version "1.0.3" @@ -7432,7 +7496,7 @@ inquirer@^6.2.0: strip-ansi "^5.1.0" through "^2.3.6" -inquirer@^7.0.0: +inquirer@^7.0.0, inquirer@^7.3.3: version "7.3.3" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003" integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA== @@ -7465,13 +7529,6 @@ interpret@^1.1.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== -invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - invert-kv@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" @@ -7981,6 +8038,11 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +jju@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/jju/-/jju-1.4.0.tgz#a3abe2718af241a2b2904f84a625970f389ae32a" + integrity sha1-o6vicYryQaKykE+EpiWXDzia4yo= + js-stringify@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" @@ -8127,13 +8189,20 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.0, json5@^2.1.2: +json5@^2.1.0: version "2.1.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== dependencies: minimist "^1.2.5" +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -8290,18 +8359,6 @@ less@^3.9.0: request "^2.83.0" source-map "~0.6.0" -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levenary@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" - integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== - dependencies: - leven "^3.1.0" - levn@^0.3.0, levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" @@ -8518,11 +8575,16 @@ lodash.uniq@4.5.0, lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1: +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lodash@^4.17.19: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + log-symbols@4.0.0, log-symbols@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" @@ -8557,7 +8619,7 @@ longest@^1.0.1: resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.1.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -8853,6 +8915,11 @@ mime-db@1.45.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== +mime-db@1.46.0: + version "1.46.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.46.0.tgz#6267748a7f799594de3cbc8cde91def349661cee" + integrity sha512-svXaP8UQRZ5K7or+ZmfNhg2xX3yKDMUzqadsSqi4NCH/KomcH75MAMYAGVlvXn4+b/xOPhS3I2uHKRUzvjY7BQ== + mime-db@~1.33.0: version "1.33.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" @@ -8872,6 +8939,13 @@ mime-types@^2.1.12, mime-types@~2.1.19: dependencies: mime-db "1.45.0" +mime-types@^2.1.21: + version "2.1.29" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.29.tgz#1d4ab77da64b91f5f72489df29236563754bb1b2" + integrity sha512-Y/jMt/S5sR9OaqteJtslsFZKWOIIqMACsJSiHghlCAyhf7jfVYjKBmLiX8OgpWeW+fjJ2b+Az69aPFPkUOY6xQ== + dependencies: + mime-db "1.46.0" + mime@^1.4.1: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" @@ -9279,13 +9353,6 @@ node-modules-regexp@^1.0.0: resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= -node-releases@^1.1.50: - version "1.1.50" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.50.tgz#803c40d2c45db172d0410e4efec83aa8c6ad0592" - integrity sha512-lgAmPv9eYZ0bGwUYAKlr8MG6K4CvWliWqnkcT2P8mMAgVrH3lqfBPorFlxiG1pHQnqmavJZ9vbMXUTNyMLbrgQ== - dependencies: - semver "^6.3.0" - node-releases@^1.1.69: version "1.1.70" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.70.tgz#66e0ed0273aa65666d7fe78febe7634875426a08" @@ -11004,6 +11071,19 @@ purgecss@^1.4.0: postcss-selector-parser "^6.0.0" yargs "^14.0.0" +putasset@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/putasset/-/putasset-5.0.3.tgz#2fa82a8fc5e2333869df8ffb0e1f8618b1c87b9b" + integrity sha512-LGRp0SLOC4PDP/BawMaG3/hw6iKgQPRXcBF7WIzx2XTYwHVk2sS3gpvZqz6bf9GhKMal2phs+DF7J6eIAXEL4w== + dependencies: + "@octokit/rest" "^17.1.3" + checkup "^1.3.0" + mime-types "^2.1.21" + readjson "^2.0.1" + try-catch "^3.0.0" + try-to-catch "^3.0.0" + yargs-parser "^18.1.1" + q@^1.1.2, q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -11287,6 +11367,14 @@ readdirp@~3.5.0: dependencies: picomatch "^2.2.1" +readjson@^2.0.1: + version "2.2.2" + resolved "https://registry.yarnpkg.com/readjson/-/readjson-2.2.2.tgz#ed940ebdd72b88b383e02db7117402f980158959" + integrity sha512-PdeC9tsmLWBiL8vMhJvocq+OezQ3HhsH2HrN7YkhfYcTjQSa/iraB15A7Qvt7Xpr0Yd2rDNt6GbFwVQDg3HcAw== + dependencies: + jju "^1.4.0" + try-catch "^3.0.0" + rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -11375,18 +11463,6 @@ regexpu-core@^1.0.0: regjsgen "^0.2.0" regjsparser "^0.1.4" -regexpu-core@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.0.tgz#fcbf458c50431b0bb7b45d6967b8192d91f3d938" - integrity sha512-TQ4KXRnIn6tz6tjnrXEkD/sshygKH/j5KzK86X8MkeHyZ8qst/LZ89j3X4/8HEIfHANTFIP/AbXakeRhWIl5YQ== - dependencies: - regenerate "^1.4.0" - regenerate-unicode-properties "^8.2.0" - regjsgen "^0.5.1" - regjsparser "^0.6.4" - unicode-match-property-ecmascript "^1.0.4" - unicode-match-property-value-ecmascript "^1.2.0" - regexpu-core@^4.7.1: version "4.7.1" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.7.1.tgz#2dea5a9a07233298fbf0db91fa9abc4c6e0f8ad6" @@ -11662,14 +11738,14 @@ resolve@^0.6.1: resolved "https://registry.yarnpkg.com/resolve/-/resolve-0.6.3.tgz#dd957982e7e736debdf53b58a4dd91754575dd46" integrity sha1-3ZV5gufnNt699TtYpN2RdUV13UY= -resolve@^1.0.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.3.2, resolve@^1.4.0, resolve@^1.8.1: +resolve@^1.0.0, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.4.0, resolve@^1.8.1: version "1.17.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== dependencies: path-parse "^1.0.6" -resolve@^1.17.0, resolve@^1.18.1: +resolve@^1.17.0, resolve@^1.18.1, resolve@^1.3.2: version "1.20.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== @@ -12978,6 +13054,11 @@ token-stream@0.0.1: resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-0.0.1.tgz#ceeefc717a76c4316f126d0b9dbaa55d7e7df01a" integrity sha1-zu78cXp2xDFvEm0LnbqlXX598Bo= +toml@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/toml/-/toml-3.0.0.tgz#342160f1af1904ec9d204d03a5d61222d762c5ee" + integrity sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w== + tough-cookie@^2.3.3, tough-cookie@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -13045,6 +13126,16 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.4.tgz#3b52b1f13924f460c3fbfd0df69b587dbcbc762e" integrity sha512-tdzBRDGWcI1OpPVmChbdSKhvSVurznZ8X36AYURAcl+0o2ldlCY2XPzyXNNxwJwwyIU+rIglTCG4kxtNKBQH7Q== +try-catch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/try-catch/-/try-catch-3.0.0.tgz#7996d8b89895e2e8ae62cbdbeb4fe17470f8131b" + integrity sha512-3uAqUnoemzca1ENvZ72EVimR+E8lqBbzwZ9v4CEbLjkaV3Q+FtdmPUt7jRtoSoTiYjyIMxEkf6YgUpe/voJ1ng== + +try-to-catch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/try-to-catch/-/try-to-catch-3.0.0.tgz#a1903b44d13d5124c54d14a461d22ec1f52ea14b" + integrity sha512-eIm6ZXwR35jVF8By/HdbbkcaCDTBI5PpCPkejRKrYp0jyf/DbCCcRhHD7/O9jtFI3ewsqo9WctFEiJTS6i+CQA== + tsconfig-paths@^3.9.0: version "3.9.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" @@ -13060,6 +13151,11 @@ tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" + integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== + tty-browserify@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.1.tgz#3f05251ee17904dfd0677546670db9651682b811" @@ -13419,6 +13515,13 @@ universal-user-agent@^4.0.0: dependencies: os-name "^3.1.0" +universal-user-agent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-5.0.0.tgz#a3182aa758069bf0e79952570ca757de3579c1d9" + integrity sha512-B5TPtzZleXyPrUMKCpEHFmVhMN6EhmJYjG5PQna9s7mXeSqGTLap4OpqLl5FCEFUI3UBmllkETwKf/db66Y54Q== + dependencies: + os-name "^3.1.0" + universal-user-agent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" @@ -14304,6 +14407,14 @@ yargs-parser@^15.0.0: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@^18.1.1: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"