From 7acff60a0e401b2b6eb8df9b354b902c7d65e70c Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 16 Sep 2021 14:53:40 -0400 Subject: [PATCH] Calculate a partial fence difference based on git changes since a provided oid (#101) * Add a file provider that avoids ts program walk Adds a faster file provider that discovers source and fence files with a fast asyncronous file walk rather than by relying on typescript to perform a syncronous walk + parse of the program. We still use typescript to parse compilerOptions, but since we no longer rely on the typescript program walk to identify files, we stub out file discovery so only the initial config partse happens. Also adds config options to support switching between the two providers, since it will only work when all source files you intend to check fences against fall under your rootDirs. This is the case for OWA, but I don't know what other consumers look like. Depends on u/mahuangh/faster-source-providers-2 * progress -> progressBar * progress -> progressBar * support definition files, simplify resolveImportsFromFile, exclude asset files in fdir source file provider * getScriptFileExtensions * add partial evaluation based on git checkout * remove FdirSourceFileProvider's dependencies * remove looseRootFileDiscovery * remove extra diff (fenceJobs -> normalizedFiles * add json to the moduleFileExtensions in jest * Added tests for getPartialCheck / getFenceDiff * add launch.json & debug current test * Prefer preProcessFile in getTsImportSetFromSourceString * consider tag diffs during partial evaluation * remove commented code from getTsImportSetFromSourceString * update to new getScriptFIleExtensions from u/mahuangh/faster-source-providers-3 * get diffcount of index properly * update log messages to replace -- with new sentences * remove errant \n in fenceless warnings * Update runner.ts * add new options to README * remove warning when skipping tag existence checks * avoid unecessary branch in runner.ts * null -> undefined in config.ts * remove empty else branch * moving diff utils to utils/diffing * remove leftover cruft in diffing from previous refactors * check partialCheckLimit 'number' not 'boolean' * clarify comment on why we need to evaluate source files with changed imports * move diffing tests to test/utils/diffing, and force a full recheck on tag removal * clarifying comments around fenceDiff * Update warning message: removed tags section -> removed tags Co-authored-by: Maxwell Huang-Hobbs Co-authored-by: Scott Mikula --- .vscode/launch.json | 30 + README.md | 70 +- jest.config.js | 9 +- package.json | 2 + src/core/cli.ts | 8 + src/core/result.ts | 4 +- src/core/runner.ts | 69 +- src/types/Options.ts | 2 + src/types/PartialCheck.ts | 6 + src/types/RawOptions.ts | 2 + src/types/config/Config.ts | 8 +- .../diffing/getFenceAndImportDiffsFromGit.ts | 210 +++++ src/utils/diffing/getFenceAndSourcePatches.ts | 28 + src/utils/diffing/getFenceDiff.ts | 114 +++ .../diffing/getPartialCheckFromImportDiffs.ts | 96 +++ src/utils/diffing/resolveHashOrRefToCommit.ts | 14 + src/utils/getOptions.ts | 6 + src/utils/getTsImportSetFromSourceString.ts | 6 + src/utils/loadConfig.ts | 10 +- test/utils/diffing/getFenceDiffTests.ts | 206 +++++ .../getPartialCheckFromImportDiffsTests.ts | 333 ++++++++ .../getTsImportSetFromSourceStringTests.ts | 64 ++ yarn.lock | 744 +++++++++++++++++- 23 files changed, 2016 insertions(+), 25 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 src/types/PartialCheck.ts create mode 100644 src/utils/diffing/getFenceAndImportDiffsFromGit.ts create mode 100644 src/utils/diffing/getFenceAndSourcePatches.ts create mode 100644 src/utils/diffing/getFenceDiff.ts create mode 100644 src/utils/diffing/getPartialCheckFromImportDiffs.ts create mode 100644 src/utils/diffing/resolveHashOrRefToCommit.ts create mode 100644 src/utils/getTsImportSetFromSourceString.ts create mode 100644 test/utils/diffing/getFenceDiffTests.ts create mode 100644 test/utils/diffing/getPartialCheckFromImportDiffsTests.ts create mode 100644 test/utils/getTsImportSetFromSourceStringTests.ts diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..b097f70 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,30 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "SingleTest", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/jest-cli/bin/jest.js", + "args": ["--testPathPattern", "${fileBasenameNoExtension}"], + "cwd": "${workspaceRoot}", + "preLaunchTask": null, + "runtimeExecutable": null, + "runtimeArgs": ["--nolazy"], + "env": { + "NODE_ENV": "development" + }, + "sourceMaps": true, + "outFiles": ["${workspaceRoot}/src/**"], + "console": "integratedTerminal", + "skipFiles": [ + "/**/*.js", + "${workspaceRoot}/node_modules/jest-*/**", + "${workspaceRoot}/node_modules/jsdom/**" + ] + } + ] +} diff --git a/README.md b/README.md index 0ba461e..d54bd1f 100644 --- a/README.md +++ b/README.md @@ -154,11 +154,77 @@ Default | CLI | API ### Root Directory -Specify the project root directory. +Specify the project root directory or directories. +These are the folders that will be scanned for fences, and if running with +`--looseRootFileDiscovery`, the directories that will be scanned for source files. Default | CLI | API ----------------|----------------------------------------|---- -`process.cwd()` | `--rootDir `
`-r ` | `rootDir: string` +`process.cwd()` | `--rootDir `
`-r ` | `rootDir: string | string[]` + + +### Ignore External Fences + +Ignore external fences (e.g. those in `node_modules`). + +Default | CLI | API +----------------|----------------------------------------|---- +`false` | `--ignoreExternalFences`
`-i` | `ignoreExternalFences: boolean` + + +### Loose Root File Discovery + +Discover sources from the root directories rather than discovering sources +from the project file. + +Default | CLI | API +----------------|----------------------------------------|---- +`false` | `--looseRootFileDiscovery`
`-x` | `looseRootFileDiscovery: boolean` + + +### Since Git Hash + +Only run on files changed between the current git index and the given commit hash +or reference name. If the git index is empty, good-fences will check against the +current HEAD instead. + +Default | CLI | API +----------------|---------------------------------------------|---- +`undefined` | `--sinceGitHash `
`-g ` | `sinceGitHash: string` + + +### Partial Check Limit + +When running in a partial check (e.g. with `--sinceGitHash`), the maximum number +of source files to check. If more than this number of files have changed in the +partial check (including fences and source files), good-fences will exit with +code 0. This is intended for using good-fences as a pre-commit check. + +Default | CLI | API +----------------|--------------------------------------------------|---- +`undefined` | `--partialCheckLimit `
`-l ` | `partialCheckLimit: number` + + +### Show Progress Bar + +Whether a progress bar should be displayed on the process stderr during fence +checking. Does not show while discovering files, only while actually running +fences, so it may take several minutes to show on large projects not running +with `--looseRootFileDiscovery`. + +Default | CLI | API +----------------|----------------------------------------------|---- +`false` | `--progressBar `
`-p ` | `maxConcurrentFenceJobs: boolean` + + +### Max Concurrent Fence Jobs + +The maximum number of fence jobs to run at the same time. Should be set below MFILE on your machine, as otherwise good-fences will hit EMFILE and crash out. + +Default | CLI | API +----------------|-------------------------------------------------------|---- +`6000` | `--maxConcurrentFenceJobs `
`-j ` | `maxConcurrentFenceJobs: number` + ## Return value diff --git a/jest.config.js b/jest.config.js index 9a2786d..dd2a996 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,7 +1,14 @@ module.exports = { testEnvironment: 'node', moduleDirectories: ['node_modules'], - moduleFileExtensions: ['ts', 'js'], + moduleFileExtensions: [ + 'ts', + 'js', + // nodegit parses its own package.json file, + // so we need this moduleFileExtension to be + // specified for tests. + 'json', + ], transform: { '.ts': '/jest.preprocessor.js', }, diff --git a/package.json b/package.json index afd2995..be0e6dd 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "commander": "^7.2.0", "fdir": "^5.1.0", "minimatch": "^3.0.4", + "nodegit": "^0.27.0", "picomatch": "^2.3.0", "tsconfig-paths": "^3.10.1", "typescript": "^4.0.3" @@ -28,6 +29,7 @@ "@types/commander": "^2.12.2", "@types/jest": "^26.0.15", "@types/node": "^12.7.8", + "@types/nodegit": "^0.27.2", "husky": "^4.3.8", "jest": "^26.6.0", "prettier": "^2.2.1", diff --git a/src/core/cli.ts b/src/core/cli.ts index 1672ab5..7d543b7 100644 --- a/src/core/cli.ts +++ b/src/core/cli.ts @@ -11,6 +11,14 @@ async function main() { .version(packageVersion) .option('-p, --project ', 'tsconfig.json file') .option('-r, --rootDir ', 'root directories of the project') + .option( + '-g, --sinceGitHash ', + 'Infer files and fences to check based on changes since the specified git hash' + ) + .option( + '-l, --partialCheckLimit ', + 'Maximum files to check during a partial check run. If more files than this limit are changed, the partial check will be aborted and good-fences will exit with code 0.' + ) .option( '-x, --looseRootFileDiscovery', '(UNSTABLE) Check source files under rootDirs instead of instantiating a full typescript program.' diff --git a/src/core/result.ts b/src/core/result.ts index a71645b..88f6da6 100644 --- a/src/core/result.ts +++ b/src/core/result.ts @@ -54,9 +54,9 @@ export function reportConfigError(message: string, configPath: string) { export function reportWarning(message: string, configPath?: string) { let fencePath = configPath + path.sep + 'fence.json'; - let detailedMessage = `Good-fences warning: ${message}\n`; + let detailedMessage = `Good-fences warning: ${message}`; if (configPath) { - detailedMessage += ` Fence: ${fencePath}`; + detailedMessage += `\n Fence: ${fencePath}`; } const warning: GoodFencesError = { diff --git a/src/core/runner.ts b/src/core/runner.ts index 1e33780..2d42389 100644 --- a/src/core/runner.ts +++ b/src/core/runner.ts @@ -3,12 +3,27 @@ import getOptions, { setOptions } from '../utils/getOptions'; import validateFile from '../validation/validateFile'; import TypeScriptProgram from './TypeScriptProgram'; import normalizePath from '../utils/normalizePath'; -import { getResult } from './result'; +import { getResult, reportWarning } from './result'; import { validateTagsExist } from '../validation/validateTagsExist'; import { SourceFileProvider } from './SourceFileProvider'; import { FDirSourceFileProvider } from './FdirSourceFileProvider'; import NormalizedPath from '../types/NormalizedPath'; import { runWithConcurrentLimit } from '../utils/runWithConcurrentLimit'; +import getConfigManager from '../utils/getConfigManager'; +import { getFenceAndImportDiffsFromGit } from '../utils/diffing/getFenceAndImportDiffsFromGit'; +import { getPartialCheckFromImportDiffs } from '../utils/diffing/getPartialCheckFromImportDiffs'; +import * as path from 'path'; +import { PartialCheck } from '../types/PartialCheck'; + +async function getPartialCheck(): Promise { + let options = getOptions(); + if (options.sinceGitHash) { + const diffs = await getFenceAndImportDiffsFromGit(options.sinceGitHash); + if (diffs) { + return getPartialCheckFromImportDiffs(diffs); + } + } +} async function getSourceFilesNormalized( sourceFileProvider: SourceFileProvider, @@ -19,24 +34,64 @@ async function getSourceFilesNormalized( return normalizedFiles; } +async function getSourceFilesFromPartialCheck( + sourceFileProvider: SourceFileProvider, + partialCheck: PartialCheck +) { + const fenceScopeFiles = await getSourceFilesNormalized( + sourceFileProvider, + partialCheck.fences.map((fencePath: NormalizedPath) => path.dirname(fencePath)) + ); + return Array.from(new Set([...partialCheck.sourceFiles, ...fenceScopeFiles])); +} + export async function run(rawOptions: RawOptions) { // Store options so they can be globally available setOptions(rawOptions); let options = getOptions(); + let partialCheck = await getPartialCheck(); + if (options.partialCheckLimit) { + if (!partialCheck) { + reportWarning( + `Skipping fence validation. Could not calculate a partial check, but partialCheckLimit was specified in options` + ); + return getResult(); + } + if ( + partialCheck.fences.length + partialCheck.sourceFiles.length > + options.partialCheckLimit + ) { + reportWarning( + `Skipping fence validation. The partial check had more than ${options.partialCheckLimit} changes` + ); + return getResult(); + } + } + let sourceFileProvider: SourceFileProvider = options.looseRootFileDiscovery ? new FDirSourceFileProvider(options.project, options.rootDir) : new TypeScriptProgram(options.project); - // Do some sanity checks on the fences - validateTagsExist(); + if (!partialCheck) { + // Validating tags exist requires a full load of all fences + // we can't do this in partial check mode. + // + // Prefetching the full config set here avoids the overhead + // of partial fence loading, since we know we are loading + // the full fence set. + getConfigManager().getAllConfigs(); + validateTagsExist(); + } - const normalizedFiles = await getSourceFilesNormalized(sourceFileProvider); + let normalizedFiles = await (partialCheck + ? getSourceFilesFromPartialCheck(sourceFileProvider, partialCheck) + : getSourceFilesNormalized(sourceFileProvider)); - // Limit the concurrent executed promises because - // otherwise we will open all the files at the same time and - // hit the MFILE error (when we hit rlimit) await runWithConcurrentLimit( + // we have to limit the concurrent executed promises because + // otherwise we will open all the files at the same time and + // hit the MFILE error (when we hit rlimit) options.maxConcurrentFenceJobs, normalizedFiles, (normalizedFile: NormalizedPath) => validateFile(normalizedFile, sourceFileProvider), diff --git a/src/types/Options.ts b/src/types/Options.ts index 798d6b1..b64322f 100644 --- a/src/types/Options.ts +++ b/src/types/Options.ts @@ -4,6 +4,8 @@ export default interface Options { project: NormalizedPath; rootDir: NormalizedPath[]; ignoreExternalFences: boolean; + partialCheckLimit: number; + sinceGitHash?: string; looseRootFileDiscovery: boolean; // Maximum number of fence validation jobs that can // be run at the same time. diff --git a/src/types/PartialCheck.ts b/src/types/PartialCheck.ts new file mode 100644 index 0000000..6548ba1 --- /dev/null +++ b/src/types/PartialCheck.ts @@ -0,0 +1,6 @@ +import NormalizedPath from './NormalizedPath'; + +export type PartialCheck = { + fences: NormalizedPath[]; + sourceFiles: NormalizedPath[]; +}; diff --git a/src/types/RawOptions.ts b/src/types/RawOptions.ts index 4f806d5..48c978a 100644 --- a/src/types/RawOptions.ts +++ b/src/types/RawOptions.ts @@ -2,6 +2,8 @@ export default interface RawOptions { project?: string; rootDir?: string | string[]; ignoreExternalFences?: boolean; + sinceGitHash?: string; + partialCheckLimit?: number; looseRootFileDiscovery?: boolean; maxConcurrentJobs?: number; progressBar?: boolean; diff --git a/src/types/config/Config.ts b/src/types/config/Config.ts index 8551eaa..6f476fa 100644 --- a/src/types/config/Config.ts +++ b/src/types/config/Config.ts @@ -4,8 +4,8 @@ import ExportRule from './ExportRule'; export default interface Config { path: NormalizedPath; - tags: string[]; - exports: ExportRule[]; - dependencies: DependencyRule[]; - imports: string[]; + tags: string[] | undefined; + exports: ExportRule[] | undefined; + dependencies: DependencyRule[] | undefined; + imports: string[] | undefined; } diff --git a/src/utils/diffing/getFenceAndImportDiffsFromGit.ts b/src/utils/diffing/getFenceAndImportDiffsFromGit.ts new file mode 100644 index 0000000..b2f8f14 --- /dev/null +++ b/src/utils/diffing/getFenceAndImportDiffsFromGit.ts @@ -0,0 +1,210 @@ +import * as Git from 'nodegit'; +import { loadConfigFromString } from '../loadConfig'; +import Config from '../../types/config/Config'; +import normalizePath from '../normalizePath'; +import NormalizedPath from '../../types/NormalizedPath'; +import { reportWarning } from '../../core/result'; +import { getScriptFileExtensions } from '../getScriptFileExtensions'; +import { FenceDiff, getFenceDiff } from './getFenceDiff'; +import { getTsImportSetFromSourceString } from '../getTsImportSetFromSourceString'; +import { resolveHashOrRefToCommit } from './resolveHashOrRefToCommit'; +import { getFenceAndSourcePatches } from './getFenceAndSourcePatches'; + +/** + * Creates an empty fence given a path. + * + * Used when diffing fences against a fence that did not or no longer exists. + */ +function emptyFence(path: NormalizedPath): Config { + return { + tags: [], + imports: null, + exports: null, + dependencies: null, + path: path, + }; +} + +export type SourceImportDiff = { + addedImports: string[]; + removedImports: string[]; +}; + +export type FenceAndImportDiffs = { + fenceDiffs: Map; + sourceImportDiffs: Map; +}; + +/** + * Given a git OID (commit hash) or ref name (refs/heads/master, HEAD~1), + * finds the difference in script file imports and fence changes + * between the current git index (e.g. staged set of files), + * and the specified oid/refname. + * + * @param compareOidOrRefName an oid or refname + * @returns The fence and import diffs + */ +export async function getFenceAndImportDiffsFromGit( + compareOidOrRefName: string +): Promise { + const repo = await Git.Repository.open(process.cwd()); + const [index, headCommitTree, compareTree] = await Promise.all([ + repo.index(), + repo.getHeadCommit().then(headCommit => headCommit?.getTree?.()), + resolveHashOrRefToCommit(repo, compareOidOrRefName).then(commit => commit.getTree()), + ]); + + let repoDiff: Git.Diff; + const indexToHead = await Git.Diff.treeToIndex(repo, headCommitTree, null); + const indexIsEmpty = indexToHead.numDeltas() === 0; + + // Permit all extensions in the extension set. If we are + // overly-permissive here, the script files we detect for + // checking should be filtered out while providing source + // files. + const mostPermissiveExtensionSet = getScriptFileExtensions({ + includeJson: true, + jsx: true, + allowJs: true, + // This is used as a glob of for *${dotExt}, so .d.ts files + // will be included in by the *.ts glob. Likewise for .d.tsx + includeDefinitions: false, + }); + + if (!indexIsEmpty) { + repoDiff = await Git.Diff.treeToIndex(repo, compareTree, index, { + contextLines: 0, + pathspec: mostPermissiveExtensionSet.map(dotExt => '*' + dotExt), + }); + } else { + repoDiff = await Git.Diff.treeToTree(repo, compareTree, headCommitTree, { + contextLines: 0, + pathspec: mostPermissiveExtensionSet.map(dotExt => '*' + dotExt), + }); + } + const [fencePatches, sourcePatches] = await getFenceAndSourcePatches( + repoDiff, + mostPermissiveExtensionSet + ); + + // TODO: track files across moves (Should just be a fence removal and addition) + for (let patch of [...fencePatches, ...sourcePatches]) { + // nodegit represents a file being created or deleted by + // setting the object hash of the old / new file as 0, + // and reports the oldFile and newFile's path as the same, + // so the below only triggers on moved files. + if (patch.oldFile().path() && patch.oldFile().path() !== patch.newFile().path()) { + reportWarning('Detected a moved fence or source file. Aborting partial check from git'); + return null; + } + } + + const fenceAndImportDiffs: FenceAndImportDiffs = { + fenceDiffs: new Map(), + sourceImportDiffs: new Map(), + }; + + const loadFencePatchesPromise = Promise.all( + fencePatches.map(async fencePatch => { + // an oid of zero means the object is not present in the + // git db (e.g. it was deleted or did not yet exist) + const newPath = !fencePatch.newFile().id().iszero() + ? fencePatch.newFile().path() + : null; + const oldPath = !fencePatch.oldFile().id().iszero() + ? fencePatch.oldFile().path() + : null; + + const newFenceContentPromise: Promise | Config = newPath + ? (async () => { + const indexEntry = await index.getByPath(newPath); + const newFenceBlob = await repo.getBlob(indexEntry.id); + return loadConfigFromString( + normalizePath(newPath), + newFenceBlob.content().toString('utf-8') + ); + })() + : emptyFence(normalizePath(oldPath)); + const oldFenceContentPromise: Promise | Config = oldPath + ? (async () => { + const oldFenceEntry = await compareTree.getEntry(oldPath); + const oldFenceBlob = await oldFenceEntry.getBlob(); + return loadConfigFromString( + normalizePath(oldPath), + oldFenceBlob.content().toString('utf-8') + ); + })() + : emptyFence(normalizePath(newPath)); + + const [newFence, oldFence] = await Promise.all([ + newFenceContentPromise, + oldFenceContentPromise, + ]); + + const fenceDiff = getFenceDiff(oldFence, newFence); + if (fenceDiff) { + fenceAndImportDiffs.fenceDiffs.set( + normalizePath(fencePatch.newFile().path()), + fenceDiff + ); + } + }) + ); + + const loadSourcePatchesPromise = Promise.all( + sourcePatches.map(async sourcePatch => { + // an oid of zero means the object is not present in the + // git db (e.g. it was deleted or did not yet exist) + const newPath = !sourcePatch.newFile().id().iszero() + ? sourcePatch.newFile().path() + : null; + const oldPath = !sourcePatch.oldFile().id().iszero() + ? sourcePatch.oldFile().path() + : null; + + if (!newPath) { + // only check files that actually exist now + return; + } + + const newSourceImportsPromise: Promise> = (async () => { + const indexEntry = await index.getByPath(newPath); + const newSourceBlob = await repo.getBlob(indexEntry.id); + return getTsImportSetFromSourceString(newSourceBlob.content().toString('utf-8')); + })(); + const oldSourceImportsPromise: Promise> | Set = oldPath + ? (async () => { + const oldSourceEntry = await compareTree.getEntry(oldPath); + const oldSourceBlob = await oldSourceEntry.getBlob(); + return getTsImportSetFromSourceString( + oldSourceBlob.content().toString('utf-8') + ); + })() + : new Set(); + + const [newSourceImports, oldSourceImports] = await Promise.all([ + newSourceImportsPromise, + oldSourceImportsPromise, + ]); + + const sourceImportDiff = { + removedImports: [...oldSourceImports].filter(x => !newSourceImports.has(x)), + addedImports: [...newSourceImports].filter(x => !oldSourceImports.has(x)), + }; + + if ( + sourceImportDiff.removedImports.length > 0 || + sourceImportDiff.addedImports.length > 0 + ) { + fenceAndImportDiffs.sourceImportDiffs.set( + normalizePath(sourcePatch.newFile().path()), + sourceImportDiff + ); + } + }) + ); + + await Promise.all([loadFencePatchesPromise, loadSourcePatchesPromise]); + + return fenceAndImportDiffs; +} diff --git a/src/utils/diffing/getFenceAndSourcePatches.ts b/src/utils/diffing/getFenceAndSourcePatches.ts new file mode 100644 index 0000000..4c39349 --- /dev/null +++ b/src/utils/diffing/getFenceAndSourcePatches.ts @@ -0,0 +1,28 @@ +import * as Git from 'nodegit'; + +/** + * Given a nodegit Diff object, partitions it by path + * into diffs between fences or script files. Ignores any paths + * that are neither fences nor script files + */ +export async function getFenceAndSourcePatches(diffSinceHash: Git.Diff, extensions: string[]) { + const patches = await diffSinceHash.patches(); + const fencePatches = []; + const sourcePatches = []; + for (let patch of patches) { + const oldFile = patch.oldFile(); + const newFile = patch.newFile(); + if (oldFile.path().endsWith('fence.json') || newFile.path().endsWith('fence.json')) { + fencePatches.push(patch); + } else if ( + extensions.some( + scriptFileExtension => + oldFile.path().endsWith(scriptFileExtension) || + newFile.path().endsWith(scriptFileExtension) + ) + ) { + sourcePatches.push(patch); + } + } + return [fencePatches, sourcePatches]; +} diff --git a/src/utils/diffing/getFenceDiff.ts b/src/utils/diffing/getFenceDiff.ts new file mode 100644 index 0000000..a299754 --- /dev/null +++ b/src/utils/diffing/getFenceDiff.ts @@ -0,0 +1,114 @@ +import type Config from '../../types/config/Config'; +import type DependencyRule from '../../types/config/DependencyRule'; +import type ExportRule from '../../types/config/ExportRule'; + +const isSameExport = (exportA: ExportRule, exportB: ExportRule) => { + return exportA.accessibleTo === exportB.accessibleTo && exportA.modules === exportB.modules; +}; + +const isSameDependencyRule = (dependencyA: DependencyRule, dependencyB: DependencyRule) => { + return ( + dependencyA.accessibleTo === dependencyB.accessibleTo && + dependencyA.dependency === dependencyB.dependency + ); +}; + +export type FenceDiff = { + tags: DiffList | null; + exports: DiffList | null; + imports: DiffList | null; + dependencies: DiffList | null; +}; + +type DiffList = { + /** + * The list of new entries in the new version of the list. + * + * If there is no new version of the list (e.g. the list was + * deleted in this change), this will be null. + */ + added: T[] | null; + /** + * The list of old entries in the old version of the list. + * + * If there was no old version of the list (e.g. the list was + * introduced in this change), this will be null. + */ + removed: T[] | null; +}; + +/** + * Gets a difference between the entries of the previous and new list. + * + * @param oldList - the old list, or null if the old list did not exist + * @param newList - the new list, or null if the old list did not exist + * @param checkIsSame - a method for comparing objects (e.g. for equivalent + * objects that are not referentially equal) + * @returns a DiffList + */ +export function diffList( + oldList: T[] | null, + newList: T[] | null, + checkIsSame: (a: T, b: T) => boolean +): DiffList | null { + if (newList && !oldList) { + return { + added: [...newList], + removed: null, + }; + } else if (oldList && !newList) { + return { + added: null, + removed: [...oldList], + }; + } else if (!oldList && !newList) { + // no diff (null -> null) + return null; + } else { + let listDiff: DiffList = { + added: [], + removed: [], + }; + + // both lists had content, diff them + for (let oldListEntry of oldList) { + if (!newList.some(checkIsSame.bind(null, oldListEntry))) { + listDiff.removed.push(oldListEntry); + } + } + + for (let newListEntry of newList) { + if (!oldList.some(checkIsSame.bind(null, newListEntry))) { + listDiff.added.push(newListEntry); + } + } + + return listDiff.added.length || listDiff.removed.length ? listDiff : null; + } +} + +/** + * Gets the difference between two fences, which can be used to calculate a partial + * set of fences and source files that need to be re-checked. + * + * Each entry of the resuting FenceDiff object will be a DiffList with an added: and removed: + * section that hold the added and removed list entries. If the list itself was added or + * removed the new list will be in the corresponding added: or removed: section, and the + * other entry will be null. + * + * @see DiffList + */ +export function getFenceDiff(oldFence: Config, newFence: Config): FenceDiff | null { + let diff: FenceDiff = { + tags: diffList(oldFence.tags, newFence.tags, (a: string, b: string) => a === b), + exports: diffList(oldFence.exports, newFence.exports, isSameExport), + imports: diffList(oldFence.imports, newFence.imports, (a: string, b: string) => a === b), + dependencies: diffList(oldFence.dependencies, newFence.dependencies, isSameDependencyRule), + }; + + if (diff.exports === null && diff.imports === null && diff.dependencies === null) { + return null; + } + + return diff; +} diff --git a/src/utils/diffing/getPartialCheckFromImportDiffs.ts b/src/utils/diffing/getPartialCheckFromImportDiffs.ts new file mode 100644 index 0000000..99d83be --- /dev/null +++ b/src/utils/diffing/getPartialCheckFromImportDiffs.ts @@ -0,0 +1,96 @@ +import { reportWarning } from '../../core/result'; +import NormalizedPath from '../../types/NormalizedPath'; +import { FenceAndImportDiffs } from './getFenceAndImportDiffsFromGit'; +import * as path from 'path'; +import { PartialCheck } from '../../types/PartialCheck'; + +export function getPartialCheckFromImportDiffs( + graphDiff: FenceAndImportDiffs +): PartialCheck | null { + let fences = new Set(); + let sourceFiles = new Set(); + + let canResolve = true; + + for (let [normalizedSourceFilePath, importDiff] of graphDiff.sourceImportDiffs.entries()) { + if (importDiff.addedImports?.length) { + // we need to re-check this file, since the new imports + // might violate a parent fence of the file, or might + // violate the exports rules of the fences of new modules + // it is importing. + sourceFiles.add(normalizedSourceFilePath); + } + } + + for (let [normalizedFencePath, fenceDiff] of graphDiff.fenceDiffs.entries()) { + if (fenceDiff.exports?.removed?.length) { + // if we removed an export, we have to re-evaluate all importers + // which mean we can't resolve from the repo diff + reportWarning( + `Cannot perform partial evaluation -- removed export(s) ${fenceDiff.exports.removed + .map(x => { + const v = { ...x }; + if (v.accessibleTo === null) { + delete v.accessibleTo; + } + return JSON.stringify(v); + }) + .join(', ')} from fence ${path.relative(process.cwd(), normalizedFencePath)}` + ); + canResolve = false; + } + + const fenceHadExportsSectionAdded = + fenceDiff.exports !== null && + fenceDiff.exports.removed === null && + fenceDiff.exports.added !== null; + if (fenceHadExportsSectionAdded) { + // if we added an exports section, we have to re-evaluate + // all importers, which means we can't resolve from the repo diff + reportWarning( + `Cannot perform partial evaluation -- added an exports section to fence ${normalizedFencePath}` + ); + canResolve = false; + } + + const fenceHadImportsSectionAdded = + fenceDiff.imports !== null && + fenceDiff.imports.removed === null && + fenceDiff.imports.added !== null; + const fenceHadImportsRemoved = fenceDiff.imports?.removed?.length; + if (fenceHadImportsRemoved || fenceHadImportsSectionAdded) { + // Forces a check on all fence children + fences.add(normalizedFencePath); + } + + const fenceHadDependenciesRemoved = fenceDiff.dependencies?.removed?.length; + const fenceHadDependenciesSectionAdded = + fenceDiff.dependencies !== null && + fenceDiff.dependencies.removed === null && + fenceDiff.dependencies.added !== null; + if (fenceHadDependenciesRemoved || fenceHadDependenciesSectionAdded) { + // Forces a check on all fence children + fences.add(normalizedFencePath); + } + + const fenceHadTagsRemoved = fenceDiff.tags?.removed?.length; + if (fenceHadTagsRemoved) { + // There might exist another fence that references the removed tag in + // an imports section, which would make imports that depend on that + // tag invalid. + reportWarning( + `Cannot perform partial evaluation -- removed tags from fence ${normalizedFencePath}` + ); + canResolve = false; + } + } + + if (!canResolve) { + return null; + } + + return { + fences: [...fences], + sourceFiles: [...sourceFiles], + }; +} diff --git a/src/utils/diffing/resolveHashOrRefToCommit.ts b/src/utils/diffing/resolveHashOrRefToCommit.ts new file mode 100644 index 0000000..06438c7 --- /dev/null +++ b/src/utils/diffing/resolveHashOrRefToCommit.ts @@ -0,0 +1,14 @@ +import * as Git from 'nodegit'; + +export async function resolveHashOrRefToCommit( + repo: Git.Repository, + compareOidOrRefName: string +): Promise { + let oid: Git.Oid; + try { + oid = Git.Oid.fromString(compareOidOrRefName); + } catch { + oid = await Git.Reference.nameToId(repo, compareOidOrRefName); + } + return await Git.Commit.lookup(repo, oid); +} diff --git a/src/utils/getOptions.ts b/src/utils/getOptions.ts index d74572d..0b69202 100644 --- a/src/utils/getOptions.ts +++ b/src/utils/getOptions.ts @@ -23,10 +23,16 @@ export function setOptions(rawOptions: RawOptions) { ? normalizePath(rawOptions.project) : normalizePath(rootDir[0], 'tsconfig.json'); + if (typeof rawOptions.partialCheckLimit === 'number' && !rawOptions.sinceGitHash) { + throw new Error('Cannot specify --partialCheckLimit without --sinceGitHash'); + } + options = { project, rootDir, ignoreExternalFences: rawOptions.ignoreExternalFences, + partialCheckLimit: rawOptions?.partialCheckLimit, + sinceGitHash: rawOptions.sinceGitHash, looseRootFileDiscovery: rawOptions.looseRootFileDiscovery || false, maxConcurrentFenceJobs: rawOptions.maxConcurrentJobs || 6000, progress: rawOptions.progressBar || false, diff --git a/src/utils/getTsImportSetFromSourceString.ts b/src/utils/getTsImportSetFromSourceString.ts new file mode 100644 index 0000000..f3cf5ec --- /dev/null +++ b/src/utils/getTsImportSetFromSourceString.ts @@ -0,0 +1,6 @@ +import { preProcessFile } from 'typescript'; + +export function getTsImportSetFromSourceString(tsSource: string): Set { + let fileInfo = preProcessFile(tsSource, true, true); + return new Set(fileInfo.importedFiles.map(importedFile => importedFile.fileName)); +} diff --git a/src/utils/loadConfig.ts b/src/utils/loadConfig.ts index 3eb7ef8..c117900 100644 --- a/src/utils/loadConfig.ts +++ b/src/utils/loadConfig.ts @@ -9,8 +9,12 @@ import ConfigSet from '../types/ConfigSet'; import ExportRule from '../types/config/ExportRule'; import validateRawConfig from '../validation/validateRawConfig'; import NormalizedPath from '../types/NormalizedPath'; +import DependencyRule from '../types/config/DependencyRule'; -function loadConfigFromString(configPath: NormalizedPath, fileContent: string): Config | null { +export function loadConfigFromString( + configPath: NormalizedPath, + fileContent: string +): Config | null { // Load the raw config let rawConfig: RawConfig = JSON.parse(fileContent); @@ -41,7 +45,7 @@ export default function loadConfig(file: string, configSet: ConfigSet) { } } -function normalizeDependencyRules(rules: RawDependencyRule[]) { +function normalizeDependencyRules(rules: RawDependencyRule[]): DependencyRule[] | null { if (!rules) { return null; } @@ -59,7 +63,7 @@ function normalizeDependencyRules(rules: RawDependencyRule[]) { }); } -export function normalizeExportRules(rules: RawExportRule[]): ExportRule[] { +export function normalizeExportRules(rules: RawExportRule[]): ExportRule[] | null { if (!rules) { return null; } diff --git a/test/utils/diffing/getFenceDiffTests.ts b/test/utils/diffing/getFenceDiffTests.ts new file mode 100644 index 0000000..5ab4444 --- /dev/null +++ b/test/utils/diffing/getFenceDiffTests.ts @@ -0,0 +1,206 @@ +import type NormalizedPath from '../../../src/types/NormalizedPath'; +import { diffList, getFenceDiff } from '../../../src/utils/diffing/getFenceDiff'; + +let strictCmp = (a: any, b: any): boolean => { + return a === b; +}; + +describe('diffList (internal)', () => { + describe('a null -> null transition', () => { + it('returns null (no change)', () => { + expect(diffList(null, null, strictCmp)).toBe(null); + }); + }); + + describe('a null -> array with content transition', () => { + it('returns the new list as added', () => { + expect(diffList(null, ['a'], strictCmp)).toEqual({ + added: ['a'], + removed: null, + }); + }); + + it('breaks referential equality between the added list and the a.added list', () => { + const a = ['a']; + const res = diffList(null, a, strictCmp); + expect(a).not.toBe(res.added); + }); + }); + + describe('a null -> empty array transition', () => { + it('returns the new list as added', () => { + expect(diffList(null, [], strictCmp)).toEqual({ + added: [], + removed: null, + }); + }); + }); + + describe('an array with content -> null transition', () => { + it('returns the old list content as removed', () => { + expect(diffList(['a'], null, strictCmp)).toEqual({ + added: null, + removed: ['a'], + }); + }); + }); + + describe('an empty array -> null transition', () => { + it('returns the old list content as removed', () => { + expect(diffList([], null, strictCmp)).toEqual({ + added: null, + removed: [], + }); + }); + }); + + describe('when an element is removed', () => { + it('returns the removed element in the removed array', () => { + expect(diffList(['a', 'b'], ['a'], strictCmp)).toEqual({ + added: [], + removed: ['b'], + }); + }); + }); + + describe('when an element is added', () => { + it('returns the added element in the added array', () => { + expect(diffList(['a'], ['a', 'b'], strictCmp)).toEqual({ + added: ['b'], + removed: [], + }); + }); + }); + + describe('when there is a mix of added and removed elements', () => { + it('returns the added element in the added array', () => { + expect(diffList(['a', 'c'], ['a', 'b'], strictCmp)).toEqual({ + added: ['b'], + removed: ['c'], + }); + }); + }); + + describe('when the input and output arrays have identical content in a different order', () => { + it('returns null (no change)', () => { + expect(diffList(['a', 'b'], ['b', 'a'], strictCmp)).toBe(null); + }); + }); +}); + +describe('getFenceDiff', () => { + describe('when diffing two fences that have all null entries', () => { + it('returns null (no fence-level change)', () => { + expect( + getFenceDiff( + { + imports: null, + exports: null, + tags: null, + dependencies: null, + path: '/mock/path1' as NormalizedPath, + }, + { + imports: null, + exports: null, + tags: null, + dependencies: null, + path: '/mock/path2' as NormalizedPath, + } + ) + ).toBe(null); + }); + }); + + describe('when diffing two fences that have identical content', () => { + it('returns null (no fence-level change)', () => { + expect( + getFenceDiff( + { + imports: ['a', 'b'], + exports: [ + { + modules: 'src/index', + accessibleTo: null, + }, + ], + tags: ['a', 'b'], + dependencies: [ + { + dependency: 'react-router', + accessibleTo: 'src/router/*', + }, + ], + path: '/mock/path1' as NormalizedPath, + }, + { + imports: ['a', 'b'], + exports: [ + { + modules: 'src/index', + accessibleTo: null, + }, + ], + tags: ['a', 'b'], + dependencies: [ + { + dependency: 'react-router', + accessibleTo: 'src/router/*', + }, + ], + path: '/mock/path2' as NormalizedPath, + } + ) + ).toBe(null); + }); + }); + + describe('when diffing two fences that have different imports, exports, dependencies, and tags', () => { + it('returns the diff of each list', () => { + expect( + getFenceDiff( + { + imports: ['a'], + exports: [ + { + modules: 'src/indexOld', + accessibleTo: null, + }, + ], + tags: ['tag-a', 'tag-b'], + dependencies: null, + path: '/mock/path1' as NormalizedPath, + }, + { + imports: ['a', 'b'], + exports: [ + { + modules: 'src/index', + accessibleTo: null, + }, + ], + tags: ['tag-b'], + dependencies: [ + { + dependency: 'react-router', + accessibleTo: 'src/router/*', + }, + ], + path: '/mock/path2' as NormalizedPath, + } + ) + ).toEqual({ + tags: { removed: ['tag-a'], added: [] }, + imports: { added: ['b'], removed: [] }, + dependencies: { + added: [{ accessibleTo: 'src/router/*', dependency: 'react-router' }], + removed: null, + }, + exports: { + added: [{ accessibleTo: null, modules: 'src/index' }], + removed: [{ accessibleTo: null, modules: 'src/indexOld' }], + }, + }); + }); + }); +}); diff --git a/test/utils/diffing/getPartialCheckFromImportDiffsTests.ts b/test/utils/diffing/getPartialCheckFromImportDiffsTests.ts new file mode 100644 index 0000000..83330cc --- /dev/null +++ b/test/utils/diffing/getPartialCheckFromImportDiffsTests.ts @@ -0,0 +1,333 @@ +import NormalizedPath from '../../../src/types/NormalizedPath'; +import { + FenceAndImportDiffs, + SourceImportDiff, +} from '../../../src/utils/diffing/getFenceAndImportDiffsFromGit'; +import { FenceDiff } from '../../../src/utils/diffing/getFenceDiff'; +import { getPartialCheckFromImportDiffs } from '../../../src/utils/diffing/getPartialCheckFromImportDiffs'; + +function testGraphDiff({ + fenceDiffs, + importDiffs, +}: { + fenceDiffs?: Record>; + importDiffs?: Record>; +}): FenceAndImportDiffs { + return { + fenceDiffs: new Map( + Object.entries(fenceDiffs || {}).map(([fencePath, partialFenceDiff]): [ + NormalizedPath, + FenceDiff + ] => [ + fencePath as NormalizedPath, + { + tags: null, + imports: null, + exports: null, + dependencies: null, + ...partialFenceDiff, + }, + ]) + ), + sourceImportDiffs: new Map( + Object.entries(importDiffs || {}).map(([importPath, partialSourceImportDiff]): [ + NormalizedPath, + SourceImportDiff + ] => [ + importPath as NormalizedPath, + { + addedImports: [], + removedImports: [], + ...partialSourceImportDiff, + }, + ]) + ), + }; +} + +describe('getPartialCheckFromImportDiffs', () => { + describe('editing fences', () => { + describe('in-place edits to existing fence sections', () => { + it('performs a full check when exports are removed from a fence', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + exports: { + added: [], + removed: [{ accessibleTo: null, modules: 'src/indexOld' }], + }, + }, + }, + }); + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + + // We fail to calculate a partial check, expect null here + expect(partialCheck).toBe(null); + }); + + it('performs no additional checks when exports are added to a fence', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + exports: { + added: [{ accessibleTo: 'test', modules: 'src/dir/file' }], + removed: [], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: [] }); + }); + + it('performs no additional checks when imports are added to a fence', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + imports: { + added: ['new-allowed-import'], + removed: [], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: [] }); + }); + + it("re-checks a fence's children when imports are removed from a fence", () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + imports: { + added: [], + removed: ['old-allowed-import'], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: ['/path/to/fence'], sourceFiles: [] }); + }); + + it('performs no additional checks when dependencies are added to a fence', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + dependencies: { + added: [ + { + dependency: 'react-dom', + accessibleTo: 'ui-mount-tag', + }, + ], + removed: [], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: [] }); + }); + + it("re-checks a fence's children when dependencies are removed from a fence", () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + dependencies: { + added: [], + removed: [ + { + dependency: 'react-dom', + accessibleTo: 'ui-mount-tag', + }, + ], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: ['/path/to/fence'], sourceFiles: [] }); + }); + }); + + describe('adding or removing fence sections', () => { + it('performs a full check when an exports section is added', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + exports: { + added: [], + removed: null, + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toBe(null); + }); + + it('performs no additional checks when the exports section is removed', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + exports: { + added: null, + removed: [], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: [] }); + }); + + it('checks the files under a fence when an imports section is added', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + imports: { + added: [], + removed: null, + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: ['/path/to/fence'], sourceFiles: [] }); + }); + + it('performs no additional checks when the imports section is removed', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + imports: { + added: null, + removed: [], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: [] }); + }); + + it('checks the files under a fence when an dependencies section is added', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + dependencies: { + added: [], + removed: null, + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: ['/path/to/fence'], sourceFiles: [] }); + }); + + it('performs no additional checks when the dependencies section is removed', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + dependencies: { + added: null, + removed: [], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: [] }); + }); + }); + + describe('when tags are added', () => { + it('performs no additional checks', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + tags: { + added: ['some-tag'], + removed: [], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: [] }); + }); + }); + + describe('when tags are removed', () => { + it('performs a full check', () => { + const graphDiff = testGraphDiff({ + fenceDiffs: { + '/path/to/fence': { + tags: { + added: [], + removed: ['some-tag'], + }, + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual(null); + }); + }); + }); + + describe('editing source files', () => { + describe('when imports are removed', () => { + it('performs no additional checks', () => { + const graphDiff = testGraphDiff({ + importDiffs: { + '/path/to/source/file': { + removedImports: [ + './path/to/foo', + 'package-bar/lib/util/someThing', + './styles.scss', + ], + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: [] }); + }); + }); + + describe('when imports are added', () => { + it('re-checks the file with the added imports', () => { + const graphDiff = testGraphDiff({ + importDiffs: { + '/path/to/source/file': { + addedImports: [ + './path/to/foo', + 'package-bar/lib/util/someThing', + './styles.scss', + ], + }, + }, + }); + + const partialCheck = getPartialCheckFromImportDiffs(graphDiff); + expect(partialCheck).toEqual({ fences: [], sourceFiles: ['/path/to/source/file'] }); + }); + }); + }); +}); diff --git a/test/utils/getTsImportSetFromSourceStringTests.ts b/test/utils/getTsImportSetFromSourceStringTests.ts new file mode 100644 index 0000000..d15c1cb --- /dev/null +++ b/test/utils/getTsImportSetFromSourceStringTests.ts @@ -0,0 +1,64 @@ +import { getTsImportSetFromSourceString } from '../../src/utils/getTsImportSetFromSourceString'; + +describe('getTsImportSetFromSourceString', () => { + it('handles root-level import statements', () => { + const parsedImports = getTsImportSetFromSourceString( + ` + import { foo } from 'import-specifier-from-root-level-import-statement'; + ` + ); + + expect(parsedImports).toEqual( + new Set(['import-specifier-from-root-level-import-statement']) + ); + }); + + it('handles static require statements in root-level assignemnts', () => { + const parsedImports = getTsImportSetFromSourceString( + ` + const foo = require('require-expression'); + ` + ); + + expect(parsedImports).toEqual(new Set(['require-expression'])); + }); + + it('handles static require expressions in non-root-level statements', () => { + const parsedImports = getTsImportSetFromSourceString( + ` + if (true) { + const foo = false ? require('require-expression-1') : require('require-expression-2'); + } + ` + ); + + expect(parsedImports).toEqual(new Set(['require-expression-1', 'require-expression-2'])); + }); + + it('handles import() expressions (webpack code splitting)', () => { + const parsedImports = getTsImportSetFromSourceString( + ` + const x = import('code-splitting-entrypoint' /* Webpack Chunk Name*/) + ` + ); + + expect(parsedImports).toEqual(new Set(['code-splitting-entrypoint'])); + }); + + describe('failure scenarios', () => { + // Exist as demonstrations of the limits of ts.preProcessFile, + // not as a strict part of the feature spec. + + it('does not handle dynamic require expressions', () => { + const parsedImports = getTsImportSetFromSourceString( + ` + if (true) { + const foo = require(false ? 'require-expression-1' : 'require-expression-2'; + } + ` + ); + + expect(parsedImports).toEqual(new Set([])); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index d2a3e7e..03c6cfd 100644 --- a/yarn.lock +++ b/yarn.lock @@ -581,6 +581,11 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" +"@sindresorhus/is@^2.0.0": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-2.1.1.tgz#ceff6a28a5b4867c2dd4a1ba513de278ccbe8bb1" + integrity sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg== + "@sinonjs/commons@^1.7.0": version "1.8.1" resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217" @@ -595,6 +600,13 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@szmarczak/http-timer@^4.0.0": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" + integrity sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w== + dependencies: + defer-to-connect "^2.0.0" + "@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": version "7.1.10" resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.10.tgz#ca58fc195dd9734e77e57c6f2df565623636ab40" @@ -635,6 +647,16 @@ dependencies: "@babel/types" "^7.3.0" +"@types/cacheable-request@^6.0.1": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.2.tgz#c324da0197de0a98a2312156536ae262429ff6b9" + integrity sha512-B3xVo+dlKM6nnKTcmm5ZtY/OL8bOAOd2Olee9M1zft65ox50OzjEHW91sDiU9j6cvW8Ejg1/Qkf4xd2kugApUA== + dependencies: + "@types/http-cache-semantics" "*" + "@types/keyv" "*" + "@types/node" "*" + "@types/responselike" "*" + "@types/cli-progress@^3.9.2": version "3.9.2" resolved "https://registry.yarnpkg.com/@types/cli-progress/-/cli-progress-3.9.2.tgz#6ca355f96268af39bee9f9307f0ac96145639c26" @@ -656,6 +678,11 @@ dependencies: "@types/node" "*" +"@types/http-cache-semantics@*": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" @@ -688,6 +715,13 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" +"@types/keyv@*", "@types/keyv@^3.1.1": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.2.tgz#5d97bb65526c20b6e0845f6b0d2ade4f28604ee5" + integrity sha512-/FvAK2p4jQOaJ6CGDHJTqZcUtbZe820qIeTg7o0Shg7drB4JHeL+V/dhSaly7NXx6u8eSee+r7coT+yuJEvDLg== + dependencies: + "@types/node" "*" + "@types/minimatch@^3.0.3": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.4.tgz#f0ec25dbf2f0e4b18647313ac031134ca5b24b21" @@ -703,6 +737,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.8.tgz#cb1bf6800238898bc2ff6ffa5702c3cadd350708" integrity sha512-FMdVn84tJJdV+xe+53sYiZS4R5yn1mAIxfj+DVoNiQjTYz1+OYmjwEZr1ev9nU0axXwda0QDbYl06QHanRVH3A== +"@types/nodegit@^0.27.2": + version "0.27.3" + resolved "https://registry.yarnpkg.com/@types/nodegit/-/nodegit-0.27.3.tgz#fee7d2c3b5e8d828cd59804d6525cb7e3cabdc1f" + integrity sha512-Bdu5zd62wcI2bwvxyZ1WPtANMLQKgXtZOMRtodN4kaUHm8DIK0fhrVNa6QPfkDUCf8hDdanP7cTLTp7Ts5VqZg== + dependencies: + "@types/node" "*" + "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" @@ -718,6 +759,13 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.1.5.tgz#b6ab3bba29e16b821d84e09ecfaded462b816b00" integrity sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ== +"@types/responselike@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" + integrity sha512-85Y2BjiufFzaMIlvJDvTTB8Fxl2xfLo4HgmHzVBz08w4wDePCTjYw66PdrolO0kzli3yam/YCgRufyo1DdQVTA== + dependencies: + "@types/node" "*" + "@types/stack-utils@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" @@ -740,6 +788,11 @@ abab@^2.0.3: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + acorn-globals@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" @@ -775,6 +828,16 @@ ansi-escapes@^4.2.1: dependencies: type-fest "^0.11.0" +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + ansi-regex@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" @@ -810,6 +873,19 @@ anymatch@^3.0.3: normalize-path "^3.0.0" picomatch "^2.0.4" +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -972,6 +1048,14 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +bl@^1.0.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.3.tgz#1e8dd80142eac80d7158c9dccc047fb620e035e7" + integrity sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww== + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + brace-expansion@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" @@ -1015,6 +1099,24 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== + +buffer-alloc@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -1035,6 +1137,27 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +cacheable-lookup@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz#87be64a18b925234875e10a9bb1ebca4adce6b38" + integrity sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg== + dependencies: + "@types/keyv" "^3.1.1" + keyv "^4.0.0" + +cacheable-request@^7.0.1: + version "7.0.2" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-7.0.2.tgz#ea0d0b889364a25854757301ca12b2da77f91d27" + integrity sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew== + dependencies: + clone-response "^1.0.2" + get-stream "^5.1.0" + http-cache-semantics "^4.0.0" + keyv "^4.0.0" + lowercase-keys "^2.0.0" + normalize-url "^6.0.1" + responselike "^2.0.0" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -1092,6 +1215,11 @@ char-regex@^1.0.2: resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== +chownr@^1.0.1, chownr@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -1124,11 +1252,23 @@ cliui@^6.0.0: strip-ansi "^6.0.0" wrap-ansi "^6.2.0" +clone-response@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" + integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= + dependencies: + mimic-response "^1.0.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + collect-v8-coverage@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" @@ -1198,6 +1338,11 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + convert-source-map@^1.1.0: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" @@ -1222,7 +1367,7 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -core-util-is@1.0.2: +core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= @@ -1298,6 +1443,13 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" +debug@^3.2.6: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + debug@^4.1.0, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -1320,6 +1472,18 @@ decode-uri-component@^0.2.0: resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +decompress-response@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-5.0.0.tgz#7849396e80e3d1eba8cb2f75ef4930f76461cb0f" + integrity sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw== + dependencies: + mimic-response "^2.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -1330,6 +1494,11 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +defer-to-connect@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== + define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" @@ -1357,6 +1526,16 @@ delayed-stream@~1.0.0: resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + detect-newline@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" @@ -1374,6 +1553,11 @@ domexception@^2.0.1: dependencies: webidl-conversions "^5.0.0" +duplexer3@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= + ecc-jsbn@~0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" @@ -1391,6 +1575,13 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +end-of-stream@^1.0.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + end-of-stream@^1.1.0: version "1.4.1" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" @@ -1637,6 +1828,27 @@ fragment-cache@^0.2.1: dependencies: map-cache "^0.2.2" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs-extra@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" + integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== + dependencies: + graceful-fs "^4.1.2" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1652,6 +1864,20 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + 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" @@ -1674,7 +1900,7 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" -get-stream@^5.0.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -1693,6 +1919,18 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +glob@^7.0.3: + version "7.1.7" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90" + integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.1.1, glob@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -1734,6 +1972,32 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +got@^10.7.0: + version "10.7.0" + resolved "https://registry.yarnpkg.com/got/-/got-10.7.0.tgz#62889dbcd6cca32cd6a154cc2d0c6895121d091f" + integrity sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg== + dependencies: + "@sindresorhus/is" "^2.0.0" + "@szmarczak/http-timer" "^4.0.0" + "@types/cacheable-request" "^6.0.1" + cacheable-lookup "^2.0.0" + cacheable-request "^7.0.1" + decompress-response "^5.0.0" + duplexer3 "^0.1.4" + get-stream "^5.0.0" + lowercase-keys "^2.0.0" + mimic-response "^2.1.0" + p-cancelable "^2.0.0" + p-event "^4.0.0" + responselike "^2.0.0" + to-readable-stream "^2.0.0" + type-fest "^0.10.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6: + version "4.2.8" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" + integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== + graceful-fs@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -1767,6 +2031,11 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -1822,6 +2091,11 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== +http-cache-semantics@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" + integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" @@ -1852,13 +2126,20 @@ husky@^4.3.8: slash "^3.0.0" which-pm-runs "^1.0.0" -iconv-lite@0.4.24: +iconv-lite@0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" +ignore-walk@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.4.tgz#c9a09f69b7c7b479a5d74ac1a3c0d4236d2a6335" + integrity sha512-PY6Ii8o1jMRA1z4F2hRkH/xN59ox43DavKvD3oDpfurRlOJyAHpifIwpbdv1n4jt4ov0jSpw3kQ4GhJnpBL6WQ== + dependencies: + minimatch "^3.0.4" + ignore@^5.1.4: version "5.1.8" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" @@ -1898,6 +2179,16 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= +inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + ip-regex@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" @@ -1990,6 +2281,18 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" @@ -2051,7 +2354,7 @@ is-wsl@^2.2.0: dependencies: is-docker "^2.0.0" -isarray@1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -2545,6 +2848,11 @@ jsesc@^2.5.1: resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== + json-parse-even-better-errors@^2.3.0: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" @@ -2586,6 +2894,13 @@ json5@^2.2.0: 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" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + jsprim@^1.2.2: version "1.4.1" resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" @@ -2596,6 +2911,13 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" +keyv@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.0.3.tgz#4f3aa98de254803cafcd2896734108daa35e4254" + integrity sha512-zdGa2TOpSZPq5mU6iowDARnMBZgtCqJ11dJROFi6tg6kTn4nuUdU09lFyLFSaHrWqpIJ+EBq4E8/Dc0Vx5vLdA== + dependencies: + json-buffer "3.0.1" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -2667,11 +2989,21 @@ lodash@^4.17.11: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +lodash@^4.17.14: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + lodash@^4.17.19: version "4.17.20" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== +lowercase-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" + integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== + make-dir@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -2759,6 +3091,16 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +mimic-response@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" + integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== + +mimic-response@^2.0.0, mimic-response@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA== + minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -2776,6 +3118,21 @@ minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minipass@^2.6.0, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -2784,6 +3141,13 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.5: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + mri@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.6.tgz#49952e1044db21dbf90f6cd92bc9c9a777d415a6" @@ -2810,6 +3174,11 @@ multimatch@^4.0.0: arrify "^2.0.1" minimatch "^3.0.4" +nan@^2.14.0: + version "2.15.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.15.0.tgz#3f34a473ff18e15c1b5626b62903b5ad6e665fee" + integrity sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -2832,11 +3201,37 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= +needle@^2.2.1: + version "2.8.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.8.0.tgz#1c8ef9c1a2c29dcc1e83d73809d7bc681c80a048" + integrity sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-gyp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-4.0.0.tgz#972654af4e5dd0cd2a19081b4b46fe0442ba6f45" + integrity sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA== + dependencies: + glob "^7.0.3" + graceful-fs "^4.1.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + osenv "0" + request "^2.87.0" + rimraf "2" + semver "~5.3.0" + tar "^4.4.8" + which "1" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -2859,6 +3254,52 @@ node-notifier@^8.0.0: uuid "^8.3.0" which "^2.0.2" +node-pre-gyp@^0.13.0: + version "0.13.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.13.0.tgz#df9ab7b68dd6498137717838e4f92a33fc9daa42" + integrity sha512-Md1D3xnEne8b/HGVQkZZwV27WUi1ZRuZBij24TNaZwUPU3ZAFtvT6xxJGaUVillfmMKnn5oD1HoGsp2Ftik7SQ== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4" + +nodegit@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/nodegit/-/nodegit-0.27.0.tgz#4e8cc236f60e1c97324a5acff99056fe116a6ebe" + integrity sha512-E9K4gPjWiA0b3Tx5lfWCzG7Cvodi2idl3V5UD2fZrOrHikIfrN7Fc2kWLtMUqqomyoToYJLeIC8IV7xb1CYRLA== + dependencies: + fs-extra "^7.0.0" + got "^10.7.0" + json5 "^2.1.0" + lodash "^4.17.14" + nan "^2.14.0" + node-gyp "^4.0.0" + node-pre-gyp "^0.13.0" + ramda "^0.25.0" + tar-fs "^1.16.3" + +"nopt@2 || 3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + +nopt@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== + dependencies: + abbrev "1" + osenv "^0.1.4" + normalize-package-data@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" @@ -2881,6 +3322,32 @@ normalize-path@^3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== +normalize-url@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" + integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== + +npm-bundled@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1" + integrity sha512-x5DHup0SuyQcmL3s7Rx/YQ8sbw/Hzg0rj48eN0dV7hf5cmQq5PXIeioroH3raV1QC1yh3uTYuMThvEQF3iKgGQ== + dependencies: + npm-normalize-package-bin "^1.0.1" + +npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +npm-packlist@^1.1.6: + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" + npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" @@ -2895,6 +3362,21 @@ npm-run-path@^4.0.0: dependencies: path-key "^3.0.0" +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + nwsapi@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" @@ -2905,6 +3387,11 @@ oauth-sign@~0.9.0: resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" @@ -2959,11 +3446,41 @@ optionator@^0.8.1: type-check "~0.3.2" wordwrap "~1.0.0" +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-tmpdir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@0, osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-cancelable@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf" + integrity sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg== + p-each-series@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== +p-event@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" + integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== + dependencies: + p-timeout "^3.1.0" + p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -2997,6 +3514,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-timeout@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" + integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== + dependencies: + p-finally "^1.0.0" + p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -3139,6 +3663,11 @@ pretty-quick@^3.1.0: mri "^1.1.5" multimatch "^4.0.0" +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + prompts@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.1.0.tgz#bf90bc71f6065d255ea2bdc0fe6520485c1b45db" @@ -3152,6 +3681,14 @@ psl@^1.1.28: resolved "https://registry.yarnpkg.com/psl/-/psl-1.2.0.tgz#df12b5b1b3a30f51c329eacbdef98f3a6e136dc6" integrity sha512-GEn74ZffufCmkDDLNcl3uuyF/aSD6exEyh1v/ZSdAomB82t6G9hzJVRx0jBmLDW+VfZqks3aScmMw9DszwUalA== +pump@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" + integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + pump@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" @@ -3170,6 +3707,21 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +ramda@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.25.0.tgz#8fdf68231cffa90bc2f9460390a0cb74a29b29a9" + integrity sha512-GXpfrYVPwx3K7RQ6aYT8KPS8XViSXUVJT1ONhoKPE9VAleW42YE+U+8VEyGWt41EnEQW7gwecYJriTI0pKoecQ== + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-is@^16.12.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -3194,6 +3746,19 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" +readable-stream@^2.0.6, readable-stream@^2.3.0, readable-stream@^2.3.5: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -3233,7 +3798,7 @@ request-promise-native@^1.0.8: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.88.2: +request@^2.87.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -3306,11 +3871,25 @@ resolve@^1.3.2: dependencies: path-parse "^1.0.6" +responselike@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-2.0.0.tgz#26391bcc3174f750f9a79eacc40a12a5c42d7723" + integrity sha512-xH48u3FTB9VsZw7R+vvgaKeLKzT6jOogbQhEe/jewwnZgzPcnyWui2Av6JpoYZF/91uueC+lqhWqeURw5/qhCw== + dependencies: + lowercase-keys "^2.0.0" + ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +rimraf@2, rimraf@^2.6.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + rimraf@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -3328,11 +3907,21 @@ safe-buffer@^5.0.1, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" integrity sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg== +safe-buffer@^5.1.1, safe-buffer@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-buffer@^5.1.2: version "5.2.0" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== +safe-buffer@~5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" @@ -3360,6 +3949,11 @@ sane@^4.0.3: minimist "^1.1.1" walker "~1.0.5" +sax@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + saxes@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" @@ -3382,6 +3976,11 @@ semver-regex@^3.1.2: resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== +semver@^5.3.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@^5.4.1, semver@^5.5.0: version "5.7.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" @@ -3402,7 +4001,12 @@ semver@^7.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== -set-blocking@^2.0.0: +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= + +set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= @@ -3602,6 +4206,23 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + string-width@^4.1.0, string-width@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" @@ -3611,6 +4232,27 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.0" +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -3638,6 +4280,11 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -3665,6 +4312,42 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tar-fs@^1.16.3: + version "1.16.3" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" + integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== + dependencies: + chownr "^1.0.1" + mkdirp "^0.5.1" + pump "^1.0.0" + tar-stream "^1.1.2" + +tar-stream@^1.1.2: + version "1.6.2" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" + integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== + dependencies: + bl "^1.0.0" + buffer-alloc "^1.2.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.1" + xtend "^4.0.0" + +tar@^4, tar@^4.4.8: + version "4.4.17" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.17.tgz#44be5e3fa8353ee1d11db3b1401561223a5c3985" + integrity sha512-q7OwXq6NTdcYIa+k58nEMV3j1euhDhGCs/VRw9ymx/PbH0jtIM2+VTgDE/BW3rbLkrBUXs5fzEKgic5oUciu7g== + dependencies: + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -3692,6 +4375,11 @@ tmpl@1.0.x: resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= +to-buffer@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -3704,6 +4392,11 @@ to-object-path@^0.3.0: dependencies: kind-of "^3.0.2" +to-readable-stream@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-2.1.0.tgz#82880316121bea662cdc226adb30addb50cb06e8" + integrity sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w== + to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" @@ -3791,6 +4484,11 @@ type-detect@4.0.8: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.10.0.tgz#7f06b2b9fbfc581068d1341ffabd0349ceafc642" + integrity sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw== + type-fest@^0.11.0: version "0.11.0" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1" @@ -3828,6 +4526,11 @@ union-value@^1.0.0: is-extendable "^0.1.1" set-value "^2.0.1" +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" @@ -3853,6 +4556,11 @@ use@^3.1.0: resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" @@ -3951,6 +4659,13 @@ which-pm-runs@^1.0.0: resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= +which@1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" @@ -3965,6 +4680,13 @@ which@^2.0.1, which@^2.0.2: dependencies: isexe "^2.0.0" +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" @@ -4009,11 +4731,21 @@ xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +yallist@^3.0.0, yallist@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + yaml@^1.10.0: version "1.10.2" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b"