diff --git a/.eslintrc.js b/.eslintrc.js index 788406f5..cef8c7ca 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -10,6 +10,7 @@ module.exports = { '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/no-use-before-define': 'off', '@typescript-eslint/camelcase': 'off', - '@typescript-eslint/explicit-member-accessibility': 'off' + '@typescript-eslint/explicit-member-accessibility': 'off', + '@typescript-eslint/no-explicit-any': 'off' } }; diff --git a/.gitignore b/.gitignore index cb560ea0..80213931 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ /dist /yarn-error.log .DS_Store +/test/integration/mock-environment diff --git a/.travis.yml b/.travis.yml index 46f77057..bda91886 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,16 @@ +os: + - linux + - osx +addons: + apt: + sources: + - ppa:git-core/ppa + packages: + - git language: node_js node_js: - - "8" - - "10" + - '8' + - '10' cache: yarn before_script: - yarn diff --git a/.vscode/launch.json b/.vscode/launch.json index ec5337a6..7277cd87 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -17,13 +17,18 @@ "name": "Jest", "type": "node", "request": "launch", - "args": ["--runInBand", "${file}"], + "args": [ + "--runInBand", + "${file}", + "--config", + "${workspaceRoot}/jest.unit.config.js" + ], "port": 9229, "address": "localhost", "stopOnEntry": false, "runtimeExecutable": null, "sourceMaps": true, - "program": "${workspaceRoot}/node_modules/jest/bin/jest.js", + "program": "${workspaceRoot}/node_modules/.bin/jest", "runtimeArgs": ["--inspect-brk"], "cwd": "${workspaceRoot}" } diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 42029ee3..3ba8b3e2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,6 +16,19 @@ yarn tsc node dist/index.js --branch 6.1 --upstream sqren/backport-demo --all ``` +**Run `backport` CLI globally** + +``` +yarn global remove backport +npm -g uninstall backport +yarn unlink backport +yarn link +sudo chmod +x dist/index.js +yarn tsc --watch +``` + +You can now use `backport` command anywhere, and it'll point to the development version. + ### Debug **Run tests** diff --git a/README.md b/README.md index 4bb8ad87..81428ee2 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,9 @@ The above commands will start an interactive prompt. You can use the `arrow keys | --accessToken | Github access token | | string | | --all | Show commits from other than me | false | boolean | | --apiHostname | Hostname for the Github API | api.github.com | string | +| --author | Filter commits by author | _Current user_ | string | | --branch | Branch to backport to | | string | +| --commitsCount | Number of commits to choose from | 10 | number | | --gitHostname | Hostname for Git remotes | github.com | string | | --labels | Pull request labels | | string | | --multiple | Select multiple branches and/or commits | false | boolean | diff --git a/__mocks__/child_process.js b/__mocks__/child_process.js deleted file mode 100644 index eef81ae4..00000000 --- a/__mocks__/child_process.js +++ /dev/null @@ -1,12 +0,0 @@ -const last = require('lodash.last'); - -const childProcess = jest.genMockFromModule('child_process'); -childProcess.exec = jest.fn((...args) => { - last(args)(); - return { - stderr: { - on: () => {} - } - }; -}); -module.exports = childProcess; diff --git a/__mocks__/find-up.js b/__mocks__/find-up.js deleted file mode 100644 index ce3daf54..00000000 --- a/__mocks__/find-up.js +++ /dev/null @@ -1,14 +0,0 @@ -const defaultReturnValue = '/path/to/project/config'; -let returnVal = defaultReturnValue; - -const findUp = jest.fn(() => { - const p = Promise.resolve(returnVal); - returnVal = defaultReturnValue; - return p; -}); - -findUp.__setMockPath = val => { - returnVal = val; -}; - -module.exports = findUp; diff --git a/__mocks__/fs.js b/__mocks__/fs.js deleted file mode 100644 index 94b60950..00000000 --- a/__mocks__/fs.js +++ /dev/null @@ -1,28 +0,0 @@ -const { callbackify } = require('util'); - -const fs = jest.genMockFromModule('fs'); - -fs.writeFile = callbackify((...args) => { - // console.log('Accessing directly writeFile', args); - return Promise.resolve('fs.writeFile mock value'); -}); - -fs.readFile = callbackify((...args) => { - // console.log('Accessing directly readFile', args); - return Promise.resolve('fs.readFile mock value'); -}); - -fs.stat = callbackify((...args) => { - // console.log('Accessing directly stat', args); - return Promise.resolve({ - isDirectory: () => {}, - __mock: 'fs.stat mock value' - }); -}); - -fs.chmod = callbackify((...args) => { - // console.log('Accessing directly chmod', args); - return Promise.resolve('fs.chmod mock value'); -}); - -module.exports = fs; diff --git a/__mocks__/mkdirp.js b/__mocks__/mkdirp.js deleted file mode 100644 index 14d14223..00000000 --- a/__mocks__/mkdirp.js +++ /dev/null @@ -1,5 +0,0 @@ -const { callbackify } = require('util'); - -module.exports = callbackify(() => { - return Promise.resolve('mkdirp mock value'); -}); diff --git a/__mocks__/ora.js b/__mocks__/ora.js deleted file mode 100644 index 2e0fe514..00000000 --- a/__mocks__/ora.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = () => { - return { - start: () => ({ - succeed: () => {}, - stop: () => {}, - fail: () => {}, - stopAndPersist: () => {} - }) - }; -}; diff --git a/__mocks__/os.js b/__mocks__/os.js deleted file mode 100644 index 7d311111..00000000 --- a/__mocks__/os.js +++ /dev/null @@ -1,5 +0,0 @@ -const os = jest.genMockFromModule('os'); - -os.homedir = () => '/myHomeDir'; - -module.exports = os; diff --git a/__mocks__/rimraf.js b/__mocks__/rimraf.js deleted file mode 100644 index d7247b94..00000000 --- a/__mocks__/rimraf.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = jest.fn((path, callback) => { - callback('Called from mock'); -}); diff --git a/docs/configuration.md b/docs/configuration.md index 07179b9c..bfee6f6e 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -118,6 +118,12 @@ CLI: `--prTitle "My PR Title"` Pull request description. Will be added to the end of the pull request description. +For people who often need to add the same description to PRs they can create a bash alias: + +```sh +alias backport-skip-ci='backport --prDescription "[skip-ci]"' +``` + CLI: `--prDescription "skip-ci"` #### `gitHostname` diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 00000000..d730ab55 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,13 @@ +module.exports = { + setupFiles: ['./test/unit/automatic-mocks.ts'], + transform: { + '^.+\\.tsx?$': 'ts-jest' + }, + testRegex: 'test/(unit|integration)/.*test.ts$', + moduleFileExtensions: ['ts', 'js', 'json'], + globals: { + 'ts-jest': { + diagnostics: false + } + } +}; diff --git a/package.json b/package.json index 02f3ef43..9df2418c 100644 --- a/package.json +++ b/package.json @@ -28,12 +28,12 @@ "license": "MIT", "scripts": { "cover": "jest --coverage", - "format": "prettier \"./src/**/*.ts\" --write", - "lint": "tsc -p ./test/tsconfig.json && eslint ./src/**/*.ts", + "format": "prettier \"./{src,test}/**/*.ts\" --write", + "lint": "tsc --project ./test/tsconfig.json && eslint ./src/**/*.ts ./test/**/*.ts", "postinstall": "test -f ./dist/scripts/runPostinstall.js && node ./dist/scripts/runPostinstall.js || echo 'Dist folder missing'", "prepublishOnly": "tsc", "publish-dry-run": "tar -tf $(npm pack)", - "test": "jest", + "test": "jest --config ./jest.config.js", "start": "ts-node --transpile-only ./src/index.ts" }, "lint-staged": { @@ -55,26 +55,6 @@ "type": "git", "url": "git+https://github.com/sqren/backport.git" }, - "jest": { - "testURL": "http://localhost/", - "setupFiles": [ - "./test/setup.js" - ], - "transform": { - "^.+\\.tsx?$": "ts-jest" - }, - "testRegex": "test.ts$", - "moduleFileExtensions": [ - "ts", - "js", - "json" - ], - "globals": { - "ts-jest": { - "diagnostics": false - } - } - }, "greenkeeper": { "ignore": [ "@types/node" @@ -84,49 +64,47 @@ "node": ">=8.0.0" }, "dependencies": { - "axios": "^0.18.0", - "find-up": "^3.0.0", - "inquirer": "^6.3.1", + "axios": "^0.19.0", + "del": "^5.0.0", + "find-up": "^4.1.0", + "inquirer": "^6.5.0", "lodash.flatten": "^4.4.0", "lodash.get": "^4.4.2", "lodash.isempty": "^4.4.0", "lodash.isstring": "^4.0.1", - "mkdirp": "^0.5.1", + "make-dir": "^3.0.0", "ora": "^3.4.0", - "rimraf": "^2.6.3", - "strip-json-comments": "^3.0.0", - "yargs": "^13.2.2" + "strip-json-comments": "^3.0.1", + "yargs": "^13.3.0" }, "devDependencies": { - "@types/core-js": "^2.5.0", - "@types/find-up": "^2.1.1", - "@types/inquirer": "^6.0.0", - "@types/jest": "^24.0.11", + "@types/core-js": "^2.5.2", + "@types/find-up": "^4.0.0", + "@types/inquirer": "^6.0.3", + "@types/jest": "^24.0.15", "@types/lodash.flatten": "^4.4.6", "@types/lodash.get": "^4.4.6", "@types/lodash.isempty": "^4.4.6", "@types/lodash.isstring": "^4.0.6", "@types/lodash.last": "^3.0.6", - "@types/mkdirp": "^0.5.2", - "@types/nock": "^10.0.0", + "@types/nock": "^10.0.3", "@types/node": "^10.14.4", - "@types/rimraf": "^2.0.2", - "@types/strip-json-comments": "^0.0.30", + "@types/strip-json-comments": "^3.0.0", "@types/yargs": "^13.0.0", - "@typescript-eslint/eslint-plugin": "^1.7.0", - "@typescript-eslint/parser": "^1.7.0", - "axios-mock-adapter": "^1.16.0", - "eslint": "^5.16.0", - "eslint-config-prettier": "^4.1.0", - "eslint-plugin-prettier": "^3.0.1", - "husky": "^2.0.0", - "jest": "^24.7.1", - "lint-staged": "^8.1.5", + "@typescript-eslint/eslint-plugin": "^1.12.0", + "@typescript-eslint/parser": "^1.12.0", + "eslint": "^6.0.1", + "eslint-config-prettier": "^6.0.0", + "eslint-plugin-import": "^2.18.0", + "eslint-plugin-prettier": "^3.1.0", + "husky": "^3.0.0", + "jest": "^24.8.0", + "lint-staged": "^9.2.0", "lodash.last": "^3.0.0", "nock": "^10.0.6", - "prettier": "^1.17.0", + "prettier": "^1.18.2", "ts-jest": "^24.0.2", - "ts-node": "^8.1.0", - "typescript": "^3.4.5" + "ts-node": "^8.3.0", + "typescript": "^3.5.3" } } diff --git a/src/__mocks__/logger.js b/src/__mocks__/logger.js deleted file mode 100644 index 635de812..00000000 --- a/src/__mocks__/logger.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - log: () => {}, - error: () => {} -}; diff --git a/src/index.ts b/src/index.ts index f5cebb4f..f861b359 100755 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,12 @@ #!/usr/bin/env node -import { initSteps } from './steps/steps'; import { getOptions } from './options/options'; +import { initSteps } from './steps/steps'; async function init() { try { - const options = await getOptions(process.argv); + const args = process.argv.slice(2); + const options = await getOptions(args); return await initSteps(options); } catch (e) { if (e.name === 'HandledError') { diff --git a/src/options/cliArgs.ts b/src/options/cliArgs.ts index 8dadb5e9..b3c68d22 100644 --- a/src/options/cliArgs.ts +++ b/src/options/cliArgs.ts @@ -4,7 +4,7 @@ import { OptionsFromConfigFiles } from './config/config'; export type OptionsFromCliArgs = ReturnType; export function getOptionsFromCliArgs( configOptions: OptionsFromConfigFiles, - argv: typeof process.argv + argv: string[] ) { const cliArgs = yargs(argv) .usage('$0 [args]') @@ -24,6 +24,11 @@ export function getOptionsFromCliArgs( description: 'Hostname for the Github API', type: 'string' }) + .option('author', { + default: configOptions.author, + description: 'Show commits by specific author', + type: 'string' + }) .option('branches', { default: [] as string[], description: 'Branch(es) to backport to', @@ -31,6 +36,11 @@ export function getOptionsFromCliArgs( alias: 'branch', string: true // ensure `6.0` is not coerced to `6` }) + .option('commitsCount', { + default: configOptions.commitsCount, + description: 'Number of commits to choose from', + type: 'number' + }) .option('gitHostname', { default: configOptions.gitHostname, description: 'Hostname for Github', @@ -89,6 +99,8 @@ export function getOptionsFromCliArgs( accessToken: cliArgs.accessToken, all: cliArgs.all, apiHostname: cliArgs.apiHostname, + author: cliArgs.author, + commitsCount: cliArgs.commitsCount, branchChoices: configOptions.branchChoices, branches: cliArgs.branches, gitHostname: cliArgs.gitHostname, diff --git a/src/options/config/config.ts b/src/options/config/config.ts index 3fc9a163..2778a807 100644 --- a/src/options/config/config.ts +++ b/src/options/config/config.ts @@ -1,8 +1,8 @@ +import isString from 'lodash.isstring'; +import { Config } from '../../types/Config'; +import { PromiseReturnType } from '../../types/commons'; import { getGlobalConfig } from './globalConfig'; import { getProjectConfig } from './projectConfig'; -import { PromiseReturnType } from '../../types/commons'; -import { Config } from '../../types/Config'; -import isString from 'lodash.isstring'; export type OptionsFromConfigFiles = PromiseReturnType< typeof getOptionsFromConfigFiles diff --git a/src/options/config/globalConfig.ts b/src/options/config/globalConfig.ts index fd679f32..e20014c7 100644 --- a/src/options/config/globalConfig.ts +++ b/src/options/config/globalConfig.ts @@ -1,6 +1,7 @@ -import { readConfigFile } from './readConfigFile'; -import { mkdirp, chmod, writeFile } from '../../services/rpc'; +import makeDir from 'make-dir'; +import { chmod, writeFile } from '../../services/fs-promisified'; import { getGlobalConfigPath, getReposPath } from '../../services/env'; +import { readConfigFile } from './readConfigFile'; export async function getGlobalConfig() { await maybeCreateGlobalConfigAndFolder(); @@ -12,7 +13,7 @@ export async function maybeCreateGlobalConfigAndFolder() { const reposPath = getReposPath(); const globalConfigPath = getGlobalConfigPath(); const configTemplate = await getConfigTemplate(); - await mkdirp(reposPath); + await makeDir(reposPath); const didCreate = await maybeCreateGlobalConfig( globalConfigPath, configTemplate diff --git a/src/options/config/readConfigFile.ts b/src/options/config/readConfigFile.ts index f8a7e19c..e29b1d56 100644 --- a/src/options/config/readConfigFile.ts +++ b/src/options/config/readConfigFile.ts @@ -1,7 +1,7 @@ import stripJsonComments from 'strip-json-comments'; -import { HandledError } from '../../services/HandledError'; -import { readFile } from '../../services/rpc'; import { Config } from '../../types/Config'; +import { HandledError } from '../../services/HandledError'; +import { readFile } from '../../services/fs-promisified'; export async function readConfigFile(filepath: string) { const fileContents = await readFile(filepath, 'utf8'); diff --git a/src/options/options.ts b/src/options/options.ts index e8e17588..5b529cb8 100644 --- a/src/options/options.ts +++ b/src/options/options.ts @@ -1,12 +1,12 @@ import isEmpty from 'lodash.isempty'; import { HandledError } from '../services/HandledError'; -import { OptionsFromCliArgs, getOptionsFromCliArgs } from './cliArgs'; -import { getOptionsFromConfigFiles } from './config/config'; import { PromiseReturnType } from '../types/commons'; import { getGlobalConfigPath } from '../services/env'; +import { OptionsFromCliArgs, getOptionsFromCliArgs } from './cliArgs'; +import { getOptionsFromConfigFiles } from './config/config'; export type BackportOptions = Readonly>; -export async function getOptions(argv: typeof process.argv) { +export async function getOptions(argv: string[]) { const optionsFromConfig = await getOptionsFromConfigFiles(); const optionsFromCli = getOptionsFromCliArgs(optionsFromConfig, argv); return validateRequiredOptions(optionsFromCli); @@ -72,6 +72,7 @@ export function validateRequiredOptions({ accessToken: options.accessToken, repoName, repoOwner, - username: options.username + username: options.username, + author: options.author || options.username }; } diff --git a/src/services/child-process-promisified.ts b/src/services/child-process-promisified.ts new file mode 100644 index 00000000..489eee51 --- /dev/null +++ b/src/services/child-process-promisified.ts @@ -0,0 +1,13 @@ +import child_process from 'child_process'; +import { promisify } from 'util'; + +export const exec = (cmd: string, options: child_process.ExecOptions = {}) => { + const execPromisified = promisify(child_process.exec); + return execPromisified(cmd, { maxBuffer: 100 * 1024 * 1024, ...options }); +}; + +export const execAsCallback = ( + ...args: Parameters +) => { + return child_process.exec(...args); +}; diff --git a/src/services/env.ts b/src/services/env.ts index 16042766..e5dab047 100644 --- a/src/services/env.ts +++ b/src/services/env.ts @@ -1,23 +1,19 @@ +import { homedir } from 'os'; import path from 'path'; -import os from 'os'; import { BackportOptions } from '../options/options'; export function getGlobalConfigPath() { - const homedir = os.homedir(); - return path.join(homedir, '.backport', 'config.json'); + return path.join(homedir(), '.backport', 'config.json'); } export function getReposPath() { - const homedir = os.homedir(); - return path.join(homedir, '.backport', 'repositories'); + return path.join(homedir(), '.backport', 'repositories'); } export function getRepoOwnerPath({ repoOwner }: BackportOptions) { - const homedir = os.homedir(); - return path.join(homedir, '.backport', 'repositories', repoOwner); + return path.join(homedir(), '.backport', 'repositories', repoOwner); } export function getRepoPath({ repoOwner, repoName }: BackportOptions) { - const homedir = os.homedir(); - return path.join(homedir, '.backport', 'repositories', repoOwner, repoName); + return path.join(homedir(), '.backport', 'repositories', repoOwner, repoName); } diff --git a/src/services/fs-promisified.ts b/src/services/fs-promisified.ts new file mode 100644 index 00000000..0af4e058 --- /dev/null +++ b/src/services/fs-promisified.ts @@ -0,0 +1,7 @@ +import { promisify } from 'util'; +import fs from 'fs'; + +export const writeFile = promisify(fs.writeFile); +export const readFile = promisify(fs.readFile); +export const stat = promisify(fs.stat); +export const chmod = promisify(fs.chmod); diff --git a/src/services/git.ts b/src/services/git.ts index 0a28c949..fe6849d6 100644 --- a/src/services/git.ts +++ b/src/services/git.ts @@ -1,13 +1,14 @@ -import childProcess from 'child_process'; -import rimraf from 'rimraf'; -import { exec, stat } from './rpc'; -import { HandledError } from './HandledError'; -import { getRepoPath, getRepoOwnerPath } from './env'; +import del from 'del'; import { BackportOptions } from '../options/options'; +import { HandledError } from './HandledError'; +import { stat } from './fs-promisified'; +import { getRepoOwnerPath, getRepoPath } from './env'; +import { execAsCallback, exec } from './child-process-promisified'; async function folderExists(path: string): Promise { try { - return (await stat(path)).isDirectory(); + const stats = await stat(path); + return stats.isDirectory(); } catch (e) { if (e.code === 'ENOENT') { return false; @@ -22,18 +23,14 @@ export function repoExists(options: BackportOptions): Promise { } export function deleteRepo(options: BackportOptions) { - return new Promise(resolve => { - const repoPath = getRepoPath(options); - rimraf(repoPath, resolve); - }); + const repoPath = getRepoPath(options); + return del(repoPath); } -function getRemoteUrl({ - repoOwner, - repoName, - accessToken, - gitHostname -}: BackportOptions) { +export function getRemoteUrl( + { repoName, accessToken, gitHostname }: BackportOptions, + repoOwner: string +) { return `https://${accessToken}@${gitHostname}/${repoOwner}/${repoName}.git`; } @@ -42,19 +39,18 @@ export function cloneRepo( callback: (progress: string) => void ) { return new Promise((resolve, reject) => { - const execProcess = childProcess.exec( - `git clone ${getRemoteUrl(options)} --progress`, - { - cwd: getRepoOwnerPath(options), - maxBuffer: 100 * 1024 * 1024 - }, - error => { - if (error) { - reject(error); - } else { - resolve(); - } + const cb = (error: any) => { + if (error) { + reject(error); + } else { + resolve(); } + }; + + const execProcess = execAsCallback( + `git clone ${getRemoteUrl(options, options.repoOwner)} --progress`, + { cwd: getRepoOwnerPath(options), maxBuffer: 100 * 1024 * 1024 }, + cb ); if (execProcess.stderr) { @@ -87,9 +83,7 @@ export async function deleteRemote( export async function addRemote(options: BackportOptions, remoteName: string) { try { await exec( - `git remote add ${remoteName} https://${options.accessToken}@${ - options.gitHostname - }/${remoteName}/${options.repoName}.git`, + `git remote add ${remoteName} ${getRemoteUrl(options, remoteName)}`, { cwd: getRepoPath(options) } @@ -101,9 +95,12 @@ export async function addRemote(options: BackportOptions, remoteName: string) { } export function cherrypick(options: BackportOptions, commitSha: string) { - return exec(`git cherry-pick ${commitSha}`, { - cwd: getRepoPath(options) - }); + return exec( + `git fetch ${options.repoOwner} master:master --force && git cherry-pick ${commitSha}`, + { + cwd: getRepoPath(options) + } + ); } export async function isIndexDirty(options: BackportOptions) { @@ -117,14 +114,14 @@ export async function isIndexDirty(options: BackportOptions) { } } -export async function createAndCheckoutBranch( +export async function createFeatureBranch( options: BackportOptions, baseBranch: string, featureBranch: string ) { try { return await exec( - `git fetch origin ${baseBranch} && git branch ${featureBranch} origin/${baseBranch} --force && git checkout ${featureBranch} `, + `git reset --hard && git clean -d --force && git fetch ${options.repoOwner} ${baseBranch} && git checkout -B ${featureBranch} ${options.repoOwner}/${baseBranch} --no-track`, { cwd: getRepoPath(options) } @@ -142,18 +139,21 @@ export async function createAndCheckoutBranch( } } -export function push(options: BackportOptions, featureBranch: string) { - return exec( - `git push ${options.username} ${featureBranch}:${featureBranch} --force`, - { - cwd: getRepoPath(options) - } - ); +export function deleteFeatureBranch( + options: BackportOptions, + featureBranch: string +) { + return exec(`git checkout master && git branch -D ${featureBranch}`, { + cwd: getRepoPath(options) + }); } -export async function resetAndPullMaster(options: BackportOptions) { +export function pushFeatureBranch( + options: BackportOptions, + featureBranch: string +) { return exec( - `git reset --hard && git clean -d --force && git checkout master && git pull origin master`, + `git push ${options.username} ${featureBranch}:${featureBranch} --force`, { cwd: getRepoPath(options) } diff --git a/src/services/github.ts b/src/services/github.ts deleted file mode 100644 index 11ce4148..00000000 --- a/src/services/github.ts +++ /dev/null @@ -1,199 +0,0 @@ -import { - GithubApiError, - GithubCommit, - GithubIssue, - GithubQuery, - GithubSearch -} from '../types/GithubApi'; -import axios, { AxiosResponse } from 'axios'; -import querystring from 'querystring'; -import get from 'lodash.get'; -import isEmpty from 'lodash.isempty'; -import { HandledError } from './HandledError'; -import { BackportOptions } from '../options/options'; -import { getPullRequestPayload } from '../steps/doBackportVersions'; - -export interface Commit { - sha: string; - message: string; - pullNumber?: number; -} - -export function getShortSha(sha: string) { - return sha.slice(0, 7); -} - -function getCommitMessage(message: string) { - return message.split('\n')[0].trim(); -} - -export async function fetchCommitsByAuthor( - options: BackportOptions -): Promise { - const { - accessToken, - all, - apiHostname, - repoName, - repoOwner, - username - } = options; - - const query: GithubQuery = { - access_token: accessToken, - per_page: 10 - }; - - if (!all) { - query.author = username; - query.per_page = 5; - } - - try { - const res: AxiosResponse = await axios( - `https://${apiHostname}/repos/${repoOwner}/${repoName}/commits?${querystring.stringify( - query - )}` - ); - - const promises = res.data.map(async commit => { - const sha = commit.sha; - const pullNumber = await fetchPullRequestNumberBySha(options, sha); - const message = getCommitMessage(commit.commit.message); - return { message, sha, pullNumber }; - }); - - return Promise.all(promises); - } catch (e) { - throw getError(e); - } -} - -export async function fetchCommitBySha( - options: BackportOptions & { sha: string } -): Promise { - const { apiHostname, repoName, repoOwner, sha, accessToken } = options; - try { - const res: AxiosResponse> = await axios( - `https://${apiHostname}/search/commits?q=hash:${sha}%20repo:${repoOwner}/${repoName}&per_page=1&access_token=${accessToken}`, - { - headers: { - Accept: 'application/vnd.github.cloak-preview' - } - } - ); - - if (isEmpty(res.data.items)) { - throw new HandledError(`No commit found for SHA: ${sha}`); - } - - const commitRes = res.data.items[0]; - const fullSha = commitRes.sha; - const pullNumber = await fetchPullRequestNumberBySha(options, fullSha); - - return { - message: getCommitMessage(commitRes.commit.message), - sha: fullSha, - pullNumber - }; - } catch (e) { - throw getError(e); - } -} - -async function fetchPullRequestNumberBySha( - { apiHostname, repoName, repoOwner, accessToken }: BackportOptions, - commitSha: string -): Promise { - try { - const res: AxiosResponse> = await axios( - `https://${apiHostname}/search/issues?q=repo:${repoOwner}/${repoName}+${commitSha}+base:master&access_token=${accessToken}` - ); - return get(res.data.items[0], 'number'); - } catch (e) { - throw getError(e); - } -} - -export async function createPullRequest( - { apiHostname, repoName, repoOwner, accessToken }: BackportOptions, - payload: ReturnType -) { - try { - const res: AxiosResponse = await axios.post( - `https://${apiHostname}/repos/${repoOwner}/${repoName}/pulls?access_token=${accessToken}`, - payload - ); - return { - html_url: res.data.html_url, - number: res.data.number - }; - } catch (e) { - throw getError(e); - } -} - -export async function addLabelsToPullRequest( - { apiHostname, repoName, repoOwner, labels, accessToken }: BackportOptions, - pullNumber: number -) { - try { - return await axios.post( - `https://${apiHostname}/repos/${repoOwner}/${repoName}/issues/${pullNumber}/labels?access_token=${accessToken}`, - labels - ); - } catch (e) { - throw getError(e); - } -} - -export async function verifyAccessToken({ - accessToken, - apiHostname, - repoName, - repoOwner -}: BackportOptions) { - try { - return await axios.head( - `https://${apiHostname}/repos/${repoOwner}/${repoName}?access_token=${accessToken}` - ); - } catch (e) { - const error = e as GithubApiError; - const statusCode = error.response && error.response.status; - - const grantedScopes = get(error, 'response.headers["x-oauth-scopes"]'); - const requiredScopes = get( - error, - 'response.headers["x-accepted-oauth-scopes"]' - ); - - switch (statusCode) { - case 401: - throw new HandledError( - `Please check your access token and make sure it is valid` - ); - case 404: - if (grantedScopes === requiredScopes) { - throw new HandledError( - `The repository "${repoOwner}/${repoName}" doesn't exist` - ); - } - - throw new HandledError( - `You do not have access to the repository "${repoOwner}/${repoName}". Please make sure your access token has the required scopes.\n\nRequired scopes: ${requiredScopes}\nAccess token scopes: ${grantedScopes}` - ); - default: - throw e.message; - } - } -} - -function getError(e: GithubApiError) { - if (e.response && e.response.data) { - return new HandledError( - JSON.stringify({ ...e.response.data, axiosUrl: e.config.url }, null, 4) - ); - } - - return e; -} diff --git a/src/services/github/Commit.d.ts b/src/services/github/Commit.d.ts new file mode 100644 index 00000000..589d7587 --- /dev/null +++ b/src/services/github/Commit.d.ts @@ -0,0 +1,14 @@ +// Commit object selected from list or via commit sha +export interface CommitSelected { + sha: string; + message: string; + pullNumber?: number; +} + +// commit object displayed in list of prompt choices +export interface CommitChoice extends CommitSelected { + existingBackports: { + branch: string; + state: 'OPEN' | 'CLOSED' | 'MERGED'; + }[]; +} diff --git a/src/types/GithubApi.d.ts b/src/services/github/GithubApiTypes.d.ts similarity index 84% rename from src/types/GithubApi.d.ts rename to src/services/github/GithubApiTypes.d.ts index 54315c97..a790a987 100644 --- a/src/types/GithubApi.d.ts +++ b/src/services/github/GithubApiTypes.d.ts @@ -1,11 +1,5 @@ import { AxiosError, AxiosResponse } from 'axios'; -export interface GithubQuery { - access_token: string; - per_page: number; - author?: string; -} - export interface GithubIssue { html_url: string; number: number; diff --git a/src/services/github/addLabelsToPullRequest.ts b/src/services/github/addLabelsToPullRequest.ts new file mode 100644 index 00000000..2353fb3d --- /dev/null +++ b/src/services/github/addLabelsToPullRequest.ts @@ -0,0 +1,17 @@ +import axios from 'axios'; +import { BackportOptions } from '../../options/options'; +import { handleGithubError } from './handleGithubError'; + +export async function addLabelsToPullRequest( + { apiHostname, repoName, repoOwner, labels, accessToken }: BackportOptions, + pullNumber: number +) { + try { + return await axios.post( + `https://${apiHostname}/repos/${repoOwner}/${repoName}/issues/${pullNumber}/labels?access_token=${accessToken}`, + labels + ); + } catch (e) { + throw handleGithubError(e); + } +} diff --git a/src/services/github/commitFormatters.ts b/src/services/github/commitFormatters.ts new file mode 100644 index 00000000..9b573beb --- /dev/null +++ b/src/services/github/commitFormatters.ts @@ -0,0 +1,23 @@ +import { CommitChoice, CommitSelected } from './Commit'; + +export function getHumanReadableReference(commit: CommitSelected) { + return commit.pullNumber ? `#${commit.pullNumber}` : getShortSha(commit.sha); +} + +export function getShortSha(sha: string) { + return sha.slice(0, 8); +} + +export function getFirstCommitMessageLine(message: string) { + return message.split('\n')[0].replace(/\s\(#\d+\)/g, ''); +} + +export function withFormattedCommitMessage< + T extends CommitSelected | CommitChoice +>(commit: T): T { + const firstMessageLine = getFirstCommitMessageLine(commit.message); + return { + ...commit, + message: `${firstMessageLine} (${getHumanReadableReference(commit)})` + }; +} diff --git a/src/services/github/createPullRequest.ts b/src/services/github/createPullRequest.ts new file mode 100644 index 00000000..e99d227e --- /dev/null +++ b/src/services/github/createPullRequest.ts @@ -0,0 +1,22 @@ +import axios, { AxiosResponse } from 'axios'; +import { BackportOptions } from '../../options/options'; +import { GithubIssue } from './GithubApiTypes'; +import { handleGithubError } from './handleGithubError'; + +export async function createPullRequest( + { apiHostname, repoName, repoOwner, accessToken }: BackportOptions, + payload: any +) { + try { + const res: AxiosResponse = await axios.post( + `https://${apiHostname}/repos/${repoOwner}/${repoName}/pulls?access_token=${accessToken}`, + payload + ); + return { + html_url: res.data.html_url, + number: res.data.number + }; + } catch (e) { + throw handleGithubError(e); + } +} diff --git a/src/services/github/fetchAuthorId.ts b/src/services/github/fetchAuthorId.ts new file mode 100644 index 00000000..5708f250 --- /dev/null +++ b/src/services/github/fetchAuthorId.ts @@ -0,0 +1,30 @@ +import { BackportOptions } from '../../options/options'; +import { gqlRequest } from './gqlRequest'; + +interface DataResponse { + user: { id: string }; +} + +export async function fetchAuthorId(options: BackportOptions) { + const { all, author, accessToken, apiHostname } = options; + if (all) { + return null; + } + + const query = /* GraphQL */ ` + query getIdByLogin($login: String!) { + user(login: $login) { + id + } + } + `; + + const res = await gqlRequest({ + apiHostname, + accessToken, + query, + variables: { login: author } + }); + + return res.user.id; +} diff --git a/src/services/github/fetchCommitBySha.ts b/src/services/github/fetchCommitBySha.ts new file mode 100644 index 00000000..dd4ae78c --- /dev/null +++ b/src/services/github/fetchCommitBySha.ts @@ -0,0 +1,51 @@ +import axios from 'axios'; +import get from 'lodash.get'; +import isEmpty from 'lodash.isempty'; +import { BackportOptions } from '../../options/options'; +import { HandledError } from '../HandledError'; +import { CommitSelected } from './Commit'; +import { GithubCommit, GithubIssue, GithubSearch } from './GithubApiTypes'; +import { handleGithubError } from './handleGithubError'; +import { withFormattedCommitMessage } from './commitFormatters'; + +export async function fetchCommitBySha( + options: BackportOptions & { sha: string } +): Promise { + const { apiHostname, repoName, repoOwner, sha, accessToken } = options; + try { + const res = await axios.get>( + `https://${apiHostname}/search/commits?q=hash:${sha}%20repo:${repoOwner}/${repoName}&per_page=1&access_token=${accessToken}`, + { + headers: { + Accept: 'application/vnd.github.cloak-preview' + } + } + ); + + if (isEmpty(res.data.items)) { + throw new HandledError(`No commit found on master with sha "${sha}"`); + } + + const commitRes = res.data.items[0]; + const fullSha = commitRes.sha; + const pullNumber = await fetchPullRequestNumberBySha(options, fullSha); + + return withFormattedCommitMessage({ + message: commitRes.commit.message, + sha: fullSha, + pullNumber + }); + } catch (e) { + throw handleGithubError(e); + } +} + +async function fetchPullRequestNumberBySha( + { apiHostname, repoName, repoOwner, accessToken }: BackportOptions, + commitSha: string +): Promise { + const res = await axios.get>( + `https://${apiHostname}/search/issues?q=repo:${repoOwner}/${repoName}+${commitSha}+base:master&access_token=${accessToken}` + ); + return get(res.data.items[0], 'number'); +} diff --git a/src/services/github/fetchCommitsByAuthor.ts b/src/services/github/fetchCommitsByAuthor.ts new file mode 100644 index 00000000..d358421d --- /dev/null +++ b/src/services/github/fetchCommitsByAuthor.ts @@ -0,0 +1,193 @@ +import get from 'lodash.get'; +import { BackportOptions } from '../../options/options'; +import { CommitChoice } from './Commit'; +import { fetchAuthorId } from './fetchAuthorId'; +import { + getFirstCommitMessageLine, + withFormattedCommitMessage +} from './commitFormatters'; +import { gqlRequest } from './gqlRequest'; + +export interface DataResponse { + repository: { + ref: { + target: { + history: { + edges: HistoryEdge[]; + }; + }; + }; + }; +} + +interface HistoryEdge { + node: { + oid: string; + message: string; + associatedPullRequests: { + edges: PullRequestEdge[]; + }; + }; +} + +export interface PullRequestEdge { + node: { + number: number; + timelineItems: { + edges: TimelineItemEdge[]; + }; + }; +} + +interface TimelineItemEdge { + node: { + source: { + __typename: string; + state: 'OPEN' | 'CLOSED' | 'MERGED'; + baseRefName: string; + commits: { + edges: CommitEdge[]; + }; + }; + }; +} + +interface CommitEdge { + node: { + commit: { + message: string; + }; + }; +} + +export async function fetchCommitsByAuthor( + options: BackportOptions +): Promise { + const { + accessToken, + apiHostname, + commitsCount, + repoName, + repoOwner + } = options; + + const query = /* GraphQL */ ` + query getCommitsByAuthorQuery( + $repoOwner: String! + $repoName: String! + $commitsCount: Int! + $authorId: ID + ) { + repository(owner: $repoOwner, name: $repoName) { + ref(qualifiedName: "master") { + target { + ... on Commit { + history(first: $commitsCount, author: { id: $authorId }) { + edges { + node { + oid + message + associatedPullRequests(first: 1) { + edges { + node { + number + timelineItems( + last: 20 + itemTypes: CROSS_REFERENCED_EVENT + ) { + edges { + node { + ... on CrossReferencedEvent { + source { + __typename + ... on PullRequest { + state + baseRefName + commits(first: 20) { + edges { + node { + commit { + message + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + `; + + const authorId = await fetchAuthorId(options); + const res = await gqlRequest({ + apiHostname, + accessToken, + query, + variables: { + repoOwner, + repoName, + commitsCount: commitsCount || 10, + authorId + } + }); + + return res.repository.ref.target.history.edges.map(edge => { + const historyNode = edge.node; + const firstPullRequest = historyNode.associatedPullRequests.edges[0]; + const pullNumber = get(firstPullRequest, 'node.number'); + const existingBackports = getExistingBackportPRs( + historyNode.message, + firstPullRequest + ); + + return withFormattedCommitMessage({ + sha: historyNode.oid, + message: historyNode.message, + pullNumber, + existingBackports + }); + }); +} + +export function getExistingBackportPRs( + message: string, + pullRequest?: PullRequestEdge +) { + if (!pullRequest) { + return []; + } + const firstMessageLine = getFirstCommitMessageLine(message); + return pullRequest.node.timelineItems.edges + .filter(item => { + const { source } = item.node; + return ( + source.__typename === 'PullRequest' && + (source.state === 'MERGED' || source.state === 'OPEN') && + source.commits.edges.some( + commit => + getFirstCommitMessageLine(commit.node.commit.message) === + firstMessageLine + ) + ); + }) + .map(item => { + const { source } = item.node; + return { + branch: source.baseRefName, + state: source.state + }; + }); +} diff --git a/src/services/github/gqlRequest.ts b/src/services/github/gqlRequest.ts new file mode 100644 index 00000000..6d2e1f4c --- /dev/null +++ b/src/services/github/gqlRequest.ts @@ -0,0 +1,62 @@ +import axios from 'axios'; +import get from 'lodash.get'; +import { HandledError } from '../HandledError'; + +interface GithubResponse { + data: DataResponse; + errors: { + type: string; + path: string[]; + locations: { + line: number; + column: number; + }[]; + message: string; + }[]; +} + +export async function gqlRequest({ + apiHostname, + query, + variables, + accessToken +}: { + apiHostname: string; + query: string; + variables?: { + [key: string]: string | number | null; + }; + accessToken: string; +}) { + try { + const { data } = await axios.post>( + `https://${apiHostname}/graphql`, + { query, variables }, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `bearer ${accessToken}` + } + } + ); + + if (data.errors) { + throw new HandledError( + data.errors.map(error => error.message).join(', ') + ); + } + + return data.data; + } catch (e) { + const responseError = get(e, 'response.data.errors') as { + message: string; + }[]; + if (responseError) { + throw new HandledError( + responseError.map(error => error.message).join(', ') + ); + } + + throw e; + } +} diff --git a/src/services/github/handleGithubError.ts b/src/services/github/handleGithubError.ts new file mode 100644 index 00000000..10103434 --- /dev/null +++ b/src/services/github/handleGithubError.ts @@ -0,0 +1,12 @@ +import { HandledError } from '../HandledError'; +import { GithubApiError } from './GithubApiTypes'; + +export function handleGithubError(e: GithubApiError) { + if (e.response && e.response.data) { + return new HandledError( + JSON.stringify({ ...e.response.data, axiosUrl: e.config.url }, null, 4) + ); + } + + return e; +} diff --git a/src/services/github/verifyAccessToken.ts b/src/services/github/verifyAccessToken.ts new file mode 100644 index 00000000..ebdd7c6a --- /dev/null +++ b/src/services/github/verifyAccessToken.ts @@ -0,0 +1,72 @@ +import axios from 'axios'; +import get from 'lodash.get'; +import { BackportOptions } from '../../options/options'; +import { HandledError } from '../HandledError'; +import { GithubApiError } from './GithubApiTypes'; + +function getSSOAuthUrl(error: GithubApiError) { + const githubSSO: string | undefined = get( + error, + 'response.headers["x-github-sso"]' + ); + if (githubSSO) { + return get(githubSSO.match(/url=(.*)/), '1'); + } +} + +export async function verifyAccessToken({ + accessToken, + apiHostname, + repoName, + repoOwner +}: BackportOptions) { + try { + return await axios.head( + `https://${apiHostname}/repos/${repoOwner}/${repoName}?access_token=${accessToken}` + ); + } catch (e) { + const error = e as GithubApiError; + const statusCode = error.response && error.response.status; + + const grantedScopes = get(error, 'response.headers["x-oauth-scopes"]'); + const requiredScopes = get( + error, + 'response.headers["x-accepted-oauth-scopes"]' + ); + + switch (statusCode) { + case 401: + throw new HandledError( + `Please check your access token and make sure it is valid` + ); + + case 403: { + const ssoAuthUrl = getSSOAuthUrl(error); + if (ssoAuthUrl) { + throw new HandledError( + `Please follow the link to authorize your personal access token with SSO:\n\n${ssoAuthUrl}` + ); + } + + throw new HandledError( + `Error while verifying access token: ${e.message}` + ); + } + + case 404: + if (grantedScopes === requiredScopes) { + throw new HandledError( + `The repository "${repoOwner}/${repoName}" doesn't exist` + ); + } + + throw new HandledError( + `You do not have access to the repository "${repoOwner}/${repoName}". Please make sure your access token has the required scopes.\n\nRequired scopes: ${requiredScopes}\nAccess token scopes: ${grantedScopes}` + ); + default: + throw new HandledError( + `Error while verifying access token: ${e.message}` + ); + } + } +} diff --git a/src/services/prompts.ts b/src/services/prompts.ts index a3ca04bb..8b6c9662 100644 --- a/src/services/prompts.ts +++ b/src/services/prompts.ts @@ -1,7 +1,9 @@ +import chalk from 'chalk'; import inquirer, { Question } from 'inquirer'; import isEmpty from 'lodash.isempty'; -import { Commit } from './github'; import { BranchChoice } from '../types/Config'; +import { CommitChoice } from './github/Commit'; +import { getHumanReadableReference } from './github/commitFormatters'; async function prompt(options: Question) { const { promptResult } = (await inquirer.prompt([ @@ -11,16 +13,27 @@ async function prompt(options: Question) { } export async function promptForCommits( - commits: Commit[], + commits: CommitChoice[], isMultipleChoice: boolean -): Promise { - const choices = commits.map((c, i) => ({ - name: `${i + 1}. ${c.message}`, - short: c.message, - value: c - })); - - const res = await prompt({ +): Promise { + const choices = commits.map((c, i) => { + const backportTags = c.existingBackports + .map(item => { + const styling = item.state === 'MERGED' ? chalk.green : chalk.gray; + return styling(item.branch); + }) + .join(', '); + + const position = chalk.gray(`${i + 1}.`); + + return { + name: `${position} ${c.message} ${backportTags}`, + short: getHumanReadableReference(c), + value: c + }; + }); + + const res = await prompt({ choices, message: 'Select commit to backport', pageSize: Math.min(10, commits.length), diff --git a/src/services/rpc.ts b/src/services/rpc.ts deleted file mode 100644 index 1e2b1698..00000000 --- a/src/services/rpc.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { promisify } from 'util'; -import { exec as execOriginal } from 'child_process'; -import fs from 'fs'; -import mkdirpOriginal from 'mkdirp'; - -const execAsPromised = promisify(execOriginal); -const mkdirpAsPromised = promisify(mkdirpOriginal); - -export function exec(cmd: string, options?: {}) { - return execAsPromised(cmd, { maxBuffer: 100 * 1024 * 1024, ...options }); -} -export const writeFile = promisify(fs.writeFile); -export const readFile = promisify(fs.readFile); -export const stat = promisify(fs.stat); -export const chmod = promisify(fs.chmod); -export const mkdirp = (path: string) => mkdirpAsPromised(path); diff --git a/src/steps/doBackportVersions.ts b/src/steps/doBackportVersions.ts index 9a631060..a2c3e89b 100644 --- a/src/steps/doBackportVersions.ts +++ b/src/steps/doBackportVersions.ts @@ -1,35 +1,30 @@ +import chalk from 'chalk'; import ora from 'ora'; -import { confirmPrompt } from '../services/prompts'; -import { - addLabelsToPullRequest, - createPullRequest, - Commit, - getShortSha -} from '../services/github'; +import { BackportOptions } from '../options/options'; +import { CommitSelected } from '../services/github/Commit'; import { HandledError } from '../services/HandledError'; -import { getRepoPath } from '../services/env'; -import { log } from '../services/logger'; +import { addLabelsToPullRequest } from '../services/github/addLabelsToPullRequest'; import { cherrypick, - createAndCheckoutBranch, + createFeatureBranch, + deleteFeatureBranch, isIndexDirty, - push, - resetAndPullMaster + pushFeatureBranch } from '../services/git'; -import { BackportOptions } from '../options/options'; +import { confirmPrompt } from '../services/prompts'; +import { createPullRequest } from '../services/github/createPullRequest'; +import { getRepoPath } from '../services/env'; +import { getShortSha } from '../services/github/commitFormatters'; +import { log } from '../services/logger'; export function doBackportVersions( options: BackportOptions, - commits: Commit[], + commits: CommitSelected[], branches: string[] ) { return sequentially(branches, async baseBranch => { try { - const pullRequest = await doBackportVersion(options, { - commits, - baseBranch - }); - log(`View pull request: ${pullRequest.html_url}`); + await doBackportVersion(options, { commits, baseBranch }); } catch (e) { if (e.name === 'HandledError') { console.error(e.message); @@ -47,18 +42,23 @@ export async function doBackportVersion( commits, baseBranch }: { - commits: Commit[]; + commits: CommitSelected[]; baseBranch: string; } ) { const featureBranch = getFeatureBranchName(baseBranch, commits); - const refValues = commits.map(commit => getReferenceLong(commit)).join(', '); - log(`Backporting ${refValues} to ${baseBranch}:`); + const commitMessages = commits + .map(commit => ` - ${commit.message}`) + .join('\n'); + log( + `\n${chalk.bold( + `Backporting the following commits to ${baseBranch}:` + )}\n${commitMessages}\n` + ); - await withSpinner({ text: 'Pulling latest changes' }, async () => { - await resetAndPullMaster(options); - await createAndCheckoutBranch(options, baseBranch, featureBranch); - }); + await withSpinner({ text: 'Pulling latest changes' }, () => + createFeatureBranch(options, baseBranch, featureBranch) + ); await sequentially(commits, commit => cherrypickAndConfirm(options, commit.sha) @@ -66,16 +66,18 @@ export async function doBackportVersion( await withSpinner( { text: `Pushing branch ${options.username}:${featureBranch}` }, - () => push(options, featureBranch) + () => pushFeatureBranch(options, featureBranch) ); - return withSpinner({ text: 'Creating pull request' }, async () => { + await deleteFeatureBranch(options, featureBranch); + + await withSpinner({ text: 'Creating pull request' }, async spinner => { const payload = getPullRequestPayload(options, baseBranch, commits); const pullRequest = await createPullRequest(options, payload); if (options.labels.length > 0) { await addLabelsToPullRequest(options, pullRequest.number); } - return pullRequest; + spinner.text = `Created pull request: ${pullRequest.html_url}`; }); } @@ -86,24 +88,18 @@ function sequentially(items: T[], handler: (item: T) => Promise) { }, Promise.resolve()); } -function getFeatureBranchName(baseBranch: string, commits: Commit[]) { +function getFeatureBranchName(baseBranch: string, commits: CommitSelected[]) { const refValues = commits - .map(commit => getReferenceShort(commit)) + .map(commit => + commit.pullNumber + ? `pr-${commit.pullNumber}` + : `commit-${getShortSha(commit.sha)}` + ) .join('_') .slice(0, 200); return `backport/${baseBranch}/${refValues}`; } -export function getReferenceLong(commit: Commit) { - return commit.pullNumber ? `#${commit.pullNumber}` : getShortSha(commit.sha); -} - -function getReferenceShort(commit: Commit) { - return commit.pullNumber - ? `pr-${commit.pullNumber}` - : `commit-${getShortSha(commit.sha)}`; -} - async function cherrypickAndConfirm(options: BackportOptions, sha: string) { const spinner = ora(`Cherry-picking commit ${getShortSha(sha)}`).start(); try { @@ -116,9 +112,7 @@ async function cherrypickAndConfirm(options: BackportOptions, sha: string) { options )} and when all conflicts have been resolved and staged run:` ); - log(` - git cherry-pick --continue - `); + log(`\ngit cherry-pick --continue\n`); const hasConflict = e.cmd.includes('git cherry-pick'); if (!hasConflict) { @@ -145,38 +139,30 @@ async function resolveConflictsOrAbort(options: BackportOptions) { function getPullRequestTitle( baseBranch: string, - commits: Commit[], + commits: CommitSelected[], prTitle: string ) { - const commitMessages = commits - .map(commit => commit.message) - .join(' | ') - .slice(0, 200); - - // prTitle could include baseBranch or commitMessages in template literal + const commitMessages = commits.map(commit => commit.message).join(' | '); return prTitle .replace('{baseBranch}', baseBranch) - .replace('{commitMessages}', commitMessages); + .replace('{commitMessages}', commitMessages) + .slice(0, 240); } -export function getPullRequestPayload( +function getPullRequestPayload( { prDescription, prTitle, username }: BackportOptions, baseBranch: string, - commits: Commit[] + commits: CommitSelected[] ) { const featureBranch = getFeatureBranchName(baseBranch, commits); - const commitRefs = commits - .map(commit => { - const ref = getReferenceLong(commit); - return ` - ${commit.message.replace(`(${ref})`, '')} (${ref})`; - }) + const commitMessages = commits + .map(commit => ` - ${commit.message}`) .join('\n'); - const bodySuffix = prDescription ? `\n\n${prDescription}` : ''; return { title: getPullRequestTitle(baseBranch, commits, prTitle), - body: `Backports the following commits to ${baseBranch}:\n${commitRefs}${bodySuffix}`, + body: `Backports the following commits to ${baseBranch}:\n${commitMessages}${bodySuffix}`, head: `${username}:${featureBranch}`, base: `${baseBranch}` }; @@ -184,12 +170,12 @@ export function getPullRequestPayload( async function withSpinner( { text }: { text: string }, - fn: () => Promise + fn: (spinner: ora.Ora) => Promise ): Promise { const spinner = ora(text).start(); try { - const res = await fn(); + const res = await fn(spinner); spinner.succeed(); return res; } catch (e) { diff --git a/src/steps/getBranches.ts b/src/steps/getBranches.ts index 4fe8e754..9fc3a2ad 100644 --- a/src/steps/getBranches.ts +++ b/src/steps/getBranches.ts @@ -1,7 +1,7 @@ -import { BackportOptions } from '../options/options'; -import { promptForBranches } from '../services/prompts'; import isEmpty from 'lodash.isempty'; +import { BackportOptions } from '../options/options'; import { BranchChoice } from '../types/Config'; +import { promptForBranches } from '../services/prompts'; export function getBranches(options: BackportOptions) { if (!isEmpty(options.branches)) { diff --git a/src/steps/getCommits.ts b/src/steps/getCommits.ts index d0051f0b..32c419df 100644 --- a/src/steps/getCommits.ts +++ b/src/steps/getCommits.ts @@ -1,12 +1,10 @@ +import isEmpty from 'lodash.isempty'; import { BackportOptions } from '../options/options'; -import { - fetchCommitBySha, - fetchCommitsByAuthor, - getShortSha -} from '../services/github'; import { promptForCommits } from '../services/prompts'; -import isEmpty from 'lodash.isempty'; import ora = require('ora'); +import { fetchCommitBySha } from '../services/github/fetchCommitBySha'; +import { fetchCommitsByAuthor } from '../services/github/fetchCommitsByAuthor'; +import { getShortSha } from '../services/github/commitFormatters'; export async function getCommits(options: BackportOptions) { if (options.sha) { @@ -37,7 +35,7 @@ async function getCommitsByPrompt(options: BackportOptions) { if (isEmpty(commits)) { const warningText = options.all ? 'There are no commits in this repository' - : 'There are no commits by you in this repository'; + : `There are no commits by "${options.author}" in this repository. Try with \`--all\` for commits by all users or \`--author=\` for commits from a specific user`; spinner.fail(warningText); process.exit(1); diff --git a/src/steps/maybeSetupRepo.ts b/src/steps/maybeSetupRepo.ts index 5296f3f4..7bb97e78 100644 --- a/src/steps/maybeSetupRepo.ts +++ b/src/steps/maybeSetupRepo.ts @@ -1,14 +1,14 @@ import { - repoExists, - deleteRepo, - cloneRepo, addRemote, - deleteRemote + cloneRepo, + deleteRemote, + deleteRepo, + repoExists } from '../services/git'; +import makeDir from 'make-dir'; import ora = require('ora'); -import { mkdirp } from '../services/rpc'; -import { getRepoOwnerPath } from '../services/env'; import { BackportOptions } from '../options/options'; +import { getRepoOwnerPath } from '../services/env'; export async function maybeSetupRepo(options: BackportOptions) { const isAlreadyCloned = await repoExists(options); @@ -19,11 +19,14 @@ export async function maybeSetupRepo(options: BackportOptions) { try { const spinnerCloneText = 'Cloning repository (one-time operation)'; spinner.text = `0% ${spinnerCloneText}`; - await mkdirp(getRepoOwnerPath(options)); + await makeDir(getRepoOwnerPath(options)); await cloneRepo(options, (progress: string) => { spinner.text = `${progress}% ${spinnerCloneText}`; }); + + // delete default "origin" remote to avoid confusion + await deleteRemote(options, 'origin'); spinner.succeed(`100% ${spinnerCloneText}`); } catch (e) { spinner.fail(); diff --git a/src/steps/steps.ts b/src/steps/steps.ts index 14a55c78..54526750 100755 --- a/src/steps/steps.ts +++ b/src/steps/steps.ts @@ -1,8 +1,8 @@ -import { verifyAccessToken } from '../services/github'; -import { doBackportVersions } from './doBackportVersions'; import { BackportOptions } from '../options/options'; -import { getCommits } from './getCommits'; +import { verifyAccessToken } from '../services/github/verifyAccessToken'; +import { doBackportVersions } from './doBackportVersions'; import { getBranches } from './getBranches'; +import { getCommits } from './getCommits'; import { maybeSetupRepo } from './maybeSetupRepo'; export async function initSteps(options: BackportOptions) { diff --git a/src/types/Config.ts b/src/types/Config.ts index 5fa0d912..4b81e41c 100644 --- a/src/types/Config.ts +++ b/src/types/Config.ts @@ -14,7 +14,9 @@ export interface Config { // both all?: boolean; + author?: string; apiHostname?: string; + commitsCount?: number; gitHostname?: string; labels?: string[]; multiple?: boolean; diff --git a/test/.eslintrc.json b/test/.eslintrc.json deleted file mode 100644 index f8cc8e47..00000000 --- a/test/.eslintrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rules": { - "@typescript-eslint/no-object-literal-type-assertion": "off", - "@typescript-eslint/no-explicit-any": "off" - } -} diff --git a/test/integration/__snapshots__/integration.test.ts.snap b/test/integration/__snapshots__/integration.test.ts.snap new file mode 100644 index 00000000..865f927d --- /dev/null +++ b/test/integration/__snapshots__/integration.test.ts.snap @@ -0,0 +1,192 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`when a multiple commits are backported should make correct API requests 1`] = ` +Object { + "query": " + query getIdByLogin($login: String!) { + user(login: $login) { + id + } + } + ", + "variables": Object { + "login": "sqren", + }, +} +`; + +exports[`when a multiple commits are backported should make correct API requests 2`] = ` +Object { + "query": " + query getCommitsByAuthorQuery( + $repoOwner: String! + $repoName: String! + $commitsCount: Int! + $authorId: ID + ) { + repository(owner: $repoOwner, name: $repoName) { + ref(qualifiedName: \\"master\\") { + target { + ... on Commit { + history(first: $commitsCount, author: { id: $authorId }) { + edges { + node { + oid + message + associatedPullRequests(first: 1) { + edges { + node { + number + timelineItems( + last: 20 + itemTypes: CROSS_REFERENCED_EVENT + ) { + edges { + node { + ... on CrossReferencedEvent { + source { + __typename + ... on PullRequest { + state + baseRefName + commits(first: 20) { + edges { + node { + commit { + message + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + ", + "variables": Object { + "authorId": "sqren_author_id", + "commitsCount": 10, + "repoName": "backport-demo", + "repoOwner": "elastic", + }, +} +`; + +exports[`when a multiple commits are backported should make correct API requests 3`] = ` +Object { + "base": "6.0", + "body": "Backports the following commits to 6.0: + - Add witch (#85) + - Add 👻 (2e63475c)", + "head": "sqren:backport/6.0/pr-85_commit-2e63475c", + "title": "[6.0] Add witch (#85) | Add 👻 (2e63475c)", +} +`; + +exports[`when a single commit is backported should make correct API requests 1`] = ` +Object { + "query": " + query getIdByLogin($login: String!) { + user(login: $login) { + id + } + } + ", + "variables": Object { + "login": "sqren", + }, +} +`; + +exports[`when a single commit is backported should make correct API requests 2`] = ` +Object { + "query": " + query getCommitsByAuthorQuery( + $repoOwner: String! + $repoName: String! + $commitsCount: Int! + $authorId: ID + ) { + repository(owner: $repoOwner, name: $repoName) { + ref(qualifiedName: \\"master\\") { + target { + ... on Commit { + history(first: $commitsCount, author: { id: $authorId }) { + edges { + node { + oid + message + associatedPullRequests(first: 1) { + edges { + node { + number + timelineItems( + last: 20 + itemTypes: CROSS_REFERENCED_EVENT + ) { + edges { + node { + ... on CrossReferencedEvent { + source { + __typename + ... on PullRequest { + state + baseRefName + commits(first: 20) { + edges { + node { + commit { + message + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + ", + "variables": Object { + "authorId": "sqren_author_id", + "commitsCount": 10, + "repoName": "backport-demo", + "repoOwner": "elastic", + }, +} +`; + +exports[`when a single commit is backported should make correct API requests 3`] = ` +Object { + "base": "6.0", + "body": "Backports the following commits to 6.0: + - Add witch (#85)", + "head": "sqren:backport/6.0/pr-85", + "title": "[6.0] Add witch (#85)", +} +`; diff --git a/test/integration/createSpies.ts b/test/integration/createSpies.ts new file mode 100644 index 00000000..d20ec67b --- /dev/null +++ b/test/integration/createSpies.ts @@ -0,0 +1,83 @@ +import axios from 'axios'; +import inquirer from 'inquirer'; +import { commitsWithPullRequestsMock } from '../unit/services/github/mocks/commitsByAuthorMock'; +import os from 'os'; +import childProcess = require('child_process'); +import { + HOMEDIR_PATH, + REMOTE_ORIGIN_REPO_PATH, + REMOTE_FORK_REPO_PATH +} from './envConstants'; + +const unmockedExec = childProcess.exec; + +export function createSpies({ commitCount }: { commitCount: number }) { + // set alternative homedir + jest.spyOn(os, 'homedir').mockReturnValue(HOMEDIR_PATH); + + // proxy exec calls and make a few modifications + jest.spyOn(childProcess, 'exec').mockImplementation((cmd, options, cb) => { + const nextCmd = cmd + .replace( + 'https://myAccessToken@github.com/elastic/backport-demo.git', + REMOTE_ORIGIN_REPO_PATH + ) + .replace( + 'https://myAccessToken@github.com/sqren/backport-demo.git', + REMOTE_FORK_REPO_PATH + ); + + return unmockedExec(nextCmd, options, cb); + }); + + // mock verifyAccessToken + jest.spyOn(axios, 'head').mockReturnValueOnce(true as any); + + // mock axios post request (graphql) + const axiosPostSpy = jest + .spyOn(axios, 'post') + + // mock author id + .mockReturnValueOnce({ + data: { + data: { + user: { + id: 'sqren_author_id' + } + } + } + } as any) + + // mock list of commits + .mockReturnValueOnce({ + data: { + data: commitsWithPullRequestsMock + } + } as any) + + // mock create pull request + .mockReturnValueOnce({ + data: { + html_url: 'pull request url', + number: 1337 + } + } as any); + + // mock prompt + jest + .spyOn(inquirer, 'prompt') + // @ts-ignore + .mockImplementationOnce(async (args: any) => { + return { + promptResult: + commitCount === 2 + ? [args[0].choices[0].value, args[0].choices[1].value] + : args[0].choices[1].value + }; + }) + .mockImplementationOnce(async (args: any) => { + return { promptResult: args[0].choices[0].name }; + }); + + return { axiosPostSpy }; +} diff --git a/test/integration/envConstants.ts b/test/integration/envConstants.ts new file mode 100644 index 00000000..9a697a92 --- /dev/null +++ b/test/integration/envConstants.ts @@ -0,0 +1,15 @@ +import { resolve } from 'path'; + +// paths +export const INTEGRATION_TEST_DATA_PATH = resolve( + './test/integration/mock-environment' +); +export const HOMEDIR_PATH = resolve( + './test/integration/mock-environment/homedir' +); +export const REMOTE_ORIGIN_REPO_PATH = resolve( + './test/integration/mock-environment/github.com/elastic/backport-demo/.git' +); +export const REMOTE_FORK_REPO_PATH = resolve( + './test/integration/mock-environment/github.com/sqren/backport-demo/.git' +); diff --git a/test/integration/helpers.ts b/test/integration/helpers.ts new file mode 100644 index 00000000..d34fcad9 --- /dev/null +++ b/test/integration/helpers.ts @@ -0,0 +1,40 @@ +import del = require('del'); +import childProcess = require('child_process'); +import { promisify } from 'util'; +import { INTEGRATION_TEST_DATA_PATH } from './envConstants'; + +type Exec = typeof childProcess.exec; +const unmockedExec = childProcess.exec; +const execPromisified = promisify(unmockedExec as Exec); + +export async function getBranches(cwd: string) { + const { stdout } = await execPromisified('git --no-pager branch', { cwd }); + + return stdout + .trim() + .split('\n') + .map(branch => branch.trim()); +} + +export async function getLatestCommit({ + branch, + commitCount, + cwd +}: { + branch: string; + commitCount: number; + cwd: string; +}) { + const cmd = `git --no-pager log ${branch} -n ${commitCount} --format="" --unified=0 --compact-summary`; + const { stdout } = await execPromisified(cmd, { cwd }); + + return stdout; +} + +// cleanup to delete previous files +export async function deleteAndSetupEnvironment() { + await del(INTEGRATION_TEST_DATA_PATH); + await execPromisified(`unzip mock-environment.zip`, { + cwd: './test/integration' + }); +} diff --git a/test/integration/integration.test.ts b/test/integration/integration.test.ts new file mode 100644 index 00000000..79b53a02 --- /dev/null +++ b/test/integration/integration.test.ts @@ -0,0 +1,142 @@ +import { getOptions } from '../../src/options/options'; +import { initSteps } from '../../src/steps/steps'; +import { REMOTE_ORIGIN_REPO_PATH, REMOTE_FORK_REPO_PATH } from './envConstants'; +import { createSpies } from './createSpies'; +import { + getBranches, + getLatestCommit, + deleteAndSetupEnvironment +} from './helpers'; + +jest.unmock('make-dir'); +jest.unmock('del'); +jest.unmock('../../src/services/child-process-promisified'); + +describe('when a single commit is backported', () => { + let axiosPostSpy: jest.SpyInstance; + + beforeAll(async () => { + const spies = createSpies({ commitCount: 1 }); + axiosPostSpy = spies.axiosPostSpy; + + await deleteAndSetupEnvironment(); + + const options = await getOptions([]); + await initSteps(options); + }); + + it('should make correct API requests', () => { + const [ + getAuthorPayload, + getCommitsPayload, + createPullRequestPayload + ] = axiosPostSpy.mock.calls.map(call => call[1]); + + expect(getAuthorPayload).toMatchSnapshot(); + expect(getCommitsPayload).toMatchSnapshot(); + expect(createPullRequestPayload).toMatchSnapshot(); + }); + + it('should not create new branches in origin (elastic/backport-demo)', async () => { + const branches = await getBranches(REMOTE_ORIGIN_REPO_PATH); + expect(branches).toEqual(['6.0', '* master']); + }); + + it('should create branch in the fork (sqren/backport-demo)', async () => { + const branches = await getBranches(REMOTE_FORK_REPO_PATH); + expect(branches).toEqual(['6.0', 'backport/6.0/pr-85', '* master']); + }); + + it('should have cherry picked the correct commit', async () => { + const commit = await getLatestCommit({ + branch: 'backport/6.0/pr-85', + commitCount: 1, + cwd: REMOTE_FORK_REPO_PATH + }); + expect(commit).toMatchInlineSnapshot(` + " romeo-and-juliet.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + + diff --git a/romeo-and-juliet.txt b/romeo-and-juliet.txt + index 87f1ac7..51e1e4b 100644 + --- a/romeo-and-juliet.txt + +++ b/romeo-and-juliet.txt + @@ -158 +158 @@ Thereto prick'd on by a most emulate pride, + -Dared to the combat; in which our valiant Hamlet-- + +Dared to the combat; in 🧙‍♀️ our valiant Hamlet-- + " + `); + }); +}); + +describe('when a multiple commits are backported', () => { + let axiosPostSpy: jest.SpyInstance; + + beforeAll(async () => { + jest.clearAllMocks(); + const spies = createSpies({ commitCount: 2 }); + axiosPostSpy = spies.axiosPostSpy; + + await deleteAndSetupEnvironment(); + + const options = await getOptions([]); + await initSteps(options); + }); + + it('should make correct API requests', () => { + const [ + getAuthorPayload, + getCommitsPayload, + createPullRequestPayload + ] = axiosPostSpy.mock.calls.map(call => call[1]); + + expect(getAuthorPayload).toMatchSnapshot(); + expect(getCommitsPayload).toMatchSnapshot(); + expect(createPullRequestPayload).toMatchSnapshot(); + }); + + it('should not create new branches in origin (elastic/backport-demo)', async () => { + const branches = await getBranches(REMOTE_ORIGIN_REPO_PATH); + expect(branches).toEqual(['6.0', '* master']); + }); + + it('should create branch in the fork (sqren/backport-demo)', async () => { + const branches = await getBranches(REMOTE_FORK_REPO_PATH); + expect(branches).toEqual([ + '6.0', + 'backport/6.0/pr-85_commit-2e63475c', + '* master' + ]); + }); + + it('should have cherry picked the correct commit', async () => { + const commit = await getLatestCommit({ + branch: 'backport/6.0/pr-85_commit-2e63475c', + commitCount: 2, + cwd: REMOTE_FORK_REPO_PATH + }); + expect(commit).toMatchInlineSnapshot(` + " romeo-and-juliet.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + + diff --git a/romeo-and-juliet.txt b/romeo-and-juliet.txt + index 51e1e4b..4814bb0 100644 + --- a/romeo-and-juliet.txt + +++ b/romeo-and-juliet.txt + @@ -203 +203 @@ But soft, behold! lo, where it comes again! + -Re-enter Ghost + +Re-enter 👻 + romeo-and-juliet.txt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + + diff --git a/romeo-and-juliet.txt b/romeo-and-juliet.txt + index 87f1ac7..51e1e4b 100644 + --- a/romeo-and-juliet.txt + +++ b/romeo-and-juliet.txt + @@ -158 +158 @@ Thereto prick'd on by a most emulate pride, + -Dared to the combat; in which our valiant Hamlet-- + +Dared to the combat; in 🧙‍♀️ our valiant Hamlet-- + " + `); + }); +}); diff --git a/test/integration/mock-environment.zip b/test/integration/mock-environment.zip new file mode 100644 index 00000000..2182242b Binary files /dev/null and b/test/integration/mock-environment.zip differ diff --git a/test/mocks/commits.ts b/test/mocks/commits.ts deleted file mode 100644 index 7a83bd23..00000000 --- a/test/mocks/commits.ts +++ /dev/null @@ -1,236 +0,0 @@ -export const commitsMock = [ - { - sha: 'commitSha', - commit: { - author: { - name: 'Søren Louv-Jansen', - email: 'sorenlouv@gmail.com', - date: '2017-09-05T08:48:42Z' - }, - committer: { - name: 'GitHub', - email: 'noreply@github.com', - date: '2017-09-05T08:48:42Z' - }, - message: 'Update readme: Make ui-framework url a link', - tree: { - sha: '10e994c1ad6c33e6fd1cdb3f51f03fe0217f9232', - url: - 'https://api.github.com/repos/elastic/kibana/git/trees/10e994c1ad6c33e6fd1cdb3f51f03fe0217f9232' - }, - url: 'https://api.github.com/repos/elastic/kibana/git/commits/commitSha', - comment_count: 0 - }, - url: 'https://api.github.com/repos/elastic/kibana/commits/commitSha', - html_url: 'https://github.com/elastic/kibana/commit/commitSha', - comments_url: - 'https://api.github.com/repos/elastic/kibana/commits/commitSha/comments', - author: { - login: 'sqren', - id: 209966, - avatar_url: 'https://avatars3.githubusercontent.com/u/209966?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/sqren', - html_url: 'https://github.com/sqren', - followers_url: 'https://api.github.com/users/sqren/followers', - following_url: - 'https://api.github.com/users/sqren/following{/other_user}', - gists_url: 'https://api.github.com/users/sqren/gists{/gist_id}', - starred_url: 'https://api.github.com/users/sqren/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/sqren/subscriptions', - organizations_url: 'https://api.github.com/users/sqren/orgs', - repos_url: 'https://api.github.com/users/sqren/repos', - events_url: 'https://api.github.com/users/sqren/events{/privacy}', - received_events_url: 'https://api.github.com/users/sqren/received_events', - type: 'User', - site_admin: false - }, - committer: { - login: 'web-flow', - id: 19864447, - avatar_url: 'https://avatars3.githubusercontent.com/u/19864447?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/web-flow', - html_url: 'https://github.com/web-flow', - followers_url: 'https://api.github.com/users/web-flow/followers', - following_url: - 'https://api.github.com/users/web-flow/following{/other_user}', - gists_url: 'https://api.github.com/users/web-flow/gists{/gist_id}', - starred_url: - 'https://api.github.com/users/web-flow/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/web-flow/subscriptions', - organizations_url: 'https://api.github.com/users/web-flow/orgs', - repos_url: 'https://api.github.com/users/web-flow/repos', - events_url: 'https://api.github.com/users/web-flow/events{/privacy}', - received_events_url: - 'https://api.github.com/users/web-flow/received_events', - type: 'User', - site_admin: false - }, - parents: [ - { - sha: 'dc9a2ee3ea34018c00d90496e55b2e3d1e5ae01c', - url: - 'https://api.github.com/repos/elastic/kibana/commits/dc9a2ee3ea34018c00d90496e55b2e3d1e5ae01c', - html_url: - 'https://github.com/elastic/kibana/commit/dc9a2ee3ea34018c00d90496e55b2e3d1e5ae01c' - } - ] - }, - { - sha: 'commitSha2', - commit: { - author: { - name: 'Søren Louv-Jansen', - email: 'sorenlouv@gmail.com', - date: '2017-08-28T08:27:51Z' - }, - committer: { - name: 'GitHub', - email: 'noreply@github.com', - date: '2017-08-28T08:27:51Z' - }, - message: 'Update react 15.6.1 (#13672)', - tree: { - sha: 'c1e9567c8172535ee7bb7b4db4de241921615f18', - url: - 'https://api.github.com/repos/elastic/kibana/git/trees/c1e9567c8172535ee7bb7b4db4de241921615f18' - }, - url: 'https://api.github.com/repos/elastic/kibana/git/commits/commitSha2', - comment_count: 0 - }, - url: 'https://api.github.com/repos/elastic/kibana/commits/commitSha2', - html_url: 'https://github.com/elastic/kibana/commit/commitSha2', - comments_url: - 'https://api.github.com/repos/elastic/kibana/commits/commitSha2/comments', - author: { - login: 'sqren', - id: 209966, - avatar_url: 'https://avatars3.githubusercontent.com/u/209966?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/sqren', - html_url: 'https://github.com/sqren', - followers_url: 'https://api.github.com/users/sqren/followers', - following_url: - 'https://api.github.com/users/sqren/following{/other_user}', - gists_url: 'https://api.github.com/users/sqren/gists{/gist_id}', - starred_url: 'https://api.github.com/users/sqren/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/sqren/subscriptions', - organizations_url: 'https://api.github.com/users/sqren/orgs', - repos_url: 'https://api.github.com/users/sqren/repos', - events_url: 'https://api.github.com/users/sqren/events{/privacy}', - received_events_url: 'https://api.github.com/users/sqren/received_events', - type: 'User', - site_admin: false - }, - committer: { - login: 'web-flow', - id: 19864447, - avatar_url: 'https://avatars3.githubusercontent.com/u/19864447?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/web-flow', - html_url: 'https://github.com/web-flow', - followers_url: 'https://api.github.com/users/web-flow/followers', - following_url: - 'https://api.github.com/users/web-flow/following{/other_user}', - gists_url: 'https://api.github.com/users/web-flow/gists{/gist_id}', - starred_url: - 'https://api.github.com/users/web-flow/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/web-flow/subscriptions', - organizations_url: 'https://api.github.com/users/web-flow/orgs', - repos_url: 'https://api.github.com/users/web-flow/repos', - events_url: 'https://api.github.com/users/web-flow/events{/privacy}', - received_events_url: - 'https://api.github.com/users/web-flow/received_events', - type: 'User', - site_admin: false - }, - parents: [ - { - sha: '19ac99a3883dbe3861986889d7006244471f6583', - url: - 'https://api.github.com/repos/elastic/kibana/commits/19ac99a3883dbe3861986889d7006244471f6583', - html_url: - 'https://github.com/elastic/kibana/commit/19ac99a3883dbe3861986889d7006244471f6583' - } - ] - }, - { - sha: 'commitSha3', - commit: { - author: { - name: 'Søren Louv-Jansen', - email: 'sorenlouv@gmail.com', - date: '2017-08-07T15:35:59Z' - }, - committer: { - name: 'GitHub', - email: 'noreply@github.com', - date: '2017-08-07T15:35:59Z' - }, - message: 'Mock out static files when running in Jest (#13315)', - tree: { - sha: 'cc828e040f43b4dd549c1d0bfc0cfde9cac908b8', - url: - 'https://api.github.com/repos/elastic/kibana/git/trees/cc828e040f43b4dd549c1d0bfc0cfde9cac908b8' - }, - url: 'https://api.github.com/repos/elastic/kibana/git/commits/commitSha3', - comment_count: 0 - }, - url: 'https://api.github.com/repos/elastic/kibana/commits/commitSha3', - html_url: 'https://github.com/elastic/kibana/commit/commitSha3', - comments_url: - 'https://api.github.com/repos/elastic/kibana/commits/commitSha3/comments', - author: { - login: 'sqren', - id: 209966, - avatar_url: 'https://avatars3.githubusercontent.com/u/209966?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/sqren', - html_url: 'https://github.com/sqren', - followers_url: 'https://api.github.com/users/sqren/followers', - following_url: - 'https://api.github.com/users/sqren/following{/other_user}', - gists_url: 'https://api.github.com/users/sqren/gists{/gist_id}', - starred_url: 'https://api.github.com/users/sqren/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/sqren/subscriptions', - organizations_url: 'https://api.github.com/users/sqren/orgs', - repos_url: 'https://api.github.com/users/sqren/repos', - events_url: 'https://api.github.com/users/sqren/events{/privacy}', - received_events_url: 'https://api.github.com/users/sqren/received_events', - type: 'User', - site_admin: false - }, - committer: { - login: 'web-flow', - id: 19864447, - avatar_url: 'https://avatars3.githubusercontent.com/u/19864447?v=4', - gravatar_id: '', - url: 'https://api.github.com/users/web-flow', - html_url: 'https://github.com/web-flow', - followers_url: 'https://api.github.com/users/web-flow/followers', - following_url: - 'https://api.github.com/users/web-flow/following{/other_user}', - gists_url: 'https://api.github.com/users/web-flow/gists{/gist_id}', - starred_url: - 'https://api.github.com/users/web-flow/starred{/owner}{/repo}', - subscriptions_url: 'https://api.github.com/users/web-flow/subscriptions', - organizations_url: 'https://api.github.com/users/web-flow/orgs', - repos_url: 'https://api.github.com/users/web-flow/repos', - events_url: 'https://api.github.com/users/web-flow/events{/privacy}', - received_events_url: - 'https://api.github.com/users/web-flow/received_events', - type: 'User', - site_admin: false - }, - parents: [ - { - sha: '161b07ab4a69b3664e5795304371fe9ee1bd1ab1', - url: - 'https://api.github.com/repos/elastic/kibana/commits/161b07ab4a69b3664e5795304371fe9ee1bd1ab1', - html_url: - 'https://github.com/elastic/kibana/commit/161b07ab4a69b3664e5795304371fe9ee1bd1ab1' - } - ] - } -]; diff --git a/test/options/config/config.test.ts b/test/options/config/config.test.ts deleted file mode 100644 index 2282a41c..00000000 --- a/test/options/config/config.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { getOptionsFromConfigFiles } from '../../../src/options/config/config'; -import { PromiseReturnType } from '../../../src/types/commons'; -import * as rpc from '../../../src/services/rpc'; - -describe('getOptionsFromConfigFiles', () => { - let res: PromiseReturnType; - - beforeEach(async () => { - jest.spyOn(rpc, 'readFile').mockImplementation(async filepath => { - switch (filepath) { - // mock project config - case '/path/to/project/config': - return JSON.stringify({ - upstream: 'elastic/kibana', - branches: ['6.x', '6.1'] - }); - - // mock global config - case '/myHomeDir/.backport/config.json': - return JSON.stringify({ - username: 'sqren', - accessToken: 'myAccessToken' - }); - default: - throw new Error(`Unknown filepath: "${filepath}"`); - } - }); - res = await getOptionsFromConfigFiles(); - }); - - it('should return correct config', () => { - expect(res).toEqual({ - accessToken: 'myAccessToken', - all: false, - apiHostname: 'api.github.com', - branchChoices: [ - { checked: false, name: '6.x' }, - { checked: false, name: '6.1' } - ], - gitHostname: 'github.com', - labels: [], - multiple: false, - multipleBranches: true, - multipleCommits: false, - prTitle: '[{baseBranch}] {commitMessages}', - upstream: 'elastic/kibana', - username: 'sqren' - }); - }); -}); diff --git a/test/services/github.test.ts b/test/services/github.test.ts deleted file mode 100644 index 361162df..00000000 --- a/test/services/github.test.ts +++ /dev/null @@ -1,132 +0,0 @@ -import { - fetchCommitsByAuthor, - fetchCommitBySha -} from '../../src/services/github'; -import axios from 'axios'; -import MockAdapter from 'axios-mock-adapter'; -import { BackportOptions } from '../../src/options/options'; - -function getDefaultOptions(options: Partial = {}) { - return { - repoOwner: 'elastic', - repoName: 'kibana', - accessToken: 'myAccessToken', - username: 'sqren', - apiHostname: 'api.github.com', - ...options - } as BackportOptions; -} - -describe('fetchCommitsByAuthor', () => { - it('should return commits with pull request', async () => { - const mock = new MockAdapter(axios); - const commitSha = 'myCommitSha'; - const options = getDefaultOptions(); - const { repoOwner, repoName, accessToken, username } = options; - - mock - .onGet( - `https://api.github.com/repos/${repoOwner}/${repoName}/commits?access_token=${accessToken}&per_page=5&author=${username}` - ) - .reply(200, [{ commit: { message: 'myMessage' }, sha: commitSha }]); - - mock - .onGet( - `https://api.github.com/search/issues?q=repo:${repoOwner}/${repoName}+${commitSha}+base:master&access_token=${accessToken}` - ) - .reply(200, { items: [{ number: 'myPullRequestNumber' }] }); - - expect(await fetchCommitsByAuthor(options)).toEqual([ - { - message: 'myMessage', - pullNumber: 'myPullRequestNumber', - sha: 'myCommitSha' - } - ]); - }); - - it('should return commits without pull request', async () => { - const mock = new MockAdapter(axios); - const commitSha = 'myCommitSha'; - const options = getDefaultOptions(); - const { repoOwner, repoName, accessToken, username } = options; - - mock - .onGet( - `https://api.github.com/repos/${repoOwner}/${repoName}/commits?access_token=${accessToken}&per_page=5&author=${username}` - ) - .reply(200, [{ commit: { message: 'myMessage' }, sha: commitSha }]); - - mock - .onGet( - `https://api.github.com/search/issues?q=repo:${repoOwner}/${repoName}+${commitSha}+base:master&access_token=${accessToken}` - ) - .reply(200, { items: [] }); - - expect(await fetchCommitsByAuthor(options)).toEqual([ - { - message: 'myMessage', - pullNumber: undefined, - sha: 'myCommitSha' - } - ]); - }); - - it('allows a custom github api hostname', async () => { - const mock = new MockAdapter(axios); - const options = getDefaultOptions({ - apiHostname: 'api.github.my-company.com' - }); - const { repoOwner, repoName, accessToken, username } = options; - const commitSha = 'myCommitSha'; - - mock - .onGet( - `https://api.github.my-company.com/repos/${repoOwner}/${repoName}/commits?access_token=${accessToken}&per_page=5&author=${username}` - ) - .reply(200, [{ commit: { message: 'myMessage' }, sha: commitSha }]); - - mock - .onGet( - `https://api.github.my-company.com/search/issues?q=repo:${repoOwner}/${repoName}+${commitSha}+base:master&access_token=${accessToken}` - ) - .reply(200, { items: [{ number: 'myPullRequestNumber' }] }); - - expect(await fetchCommitsByAuthor(options)).toEqual([ - { - message: 'myMessage', - pullNumber: 'myPullRequestNumber', - sha: 'myCommitSha' - } - ]); - }); -}); - -describe('fetchCommitBySha', () => { - it('should return single commit with pull request', async () => { - const mock = new MockAdapter(axios); - const commitSha = 'myCommitSha'; - const options = getDefaultOptions(); - const { repoOwner, repoName, accessToken } = options; - - mock - .onGet( - `https://api.github.com/search/commits?q=hash:${commitSha}%20repo:${repoOwner}/${repoName}&per_page=1&access_token=${accessToken}` - ) - .reply(200, { - items: [{ commit: { message: 'myMessage' }, sha: commitSha }] - }); - - mock - .onGet( - `https://api.github.com/search/issues?q=repo:${repoOwner}/${repoName}+${commitSha}+base:master&access_token=${accessToken}` - ) - .reply(200, { items: [{ number: 'myPullRequestNumber' }] }); - - expect(await fetchCommitBySha({ ...options, sha: commitSha })).toEqual({ - message: 'myMessage', - pullNumber: 'myPullRequestNumber', - sha: 'myCommitSha' - }); - }); -}); diff --git a/test/setup.js b/test/setup.js deleted file mode 100644 index 4883bedb..00000000 --- a/test/setup.js +++ /dev/null @@ -1,6 +0,0 @@ -// Mock the following dependencies automatically in all tests - -jest.mock('os'); -jest.mock('fs'); -jest.mock('child_process'); -jest.mock('../src/services/logger'); diff --git a/test/steps/__snapshots__/steps.test.ts.snap b/test/steps/__snapshots__/steps.test.ts.snap deleted file mode 100644 index e0f44aca..00000000 --- a/test/steps/__snapshots__/steps.test.ts.snap +++ /dev/null @@ -1,279 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`run through steps exec should be called with correct args 1`] = ` -Array [ - Array [ - "git clone https://myAccessToken@github.com/elastic/kibana.git --progress", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic", - "maxBuffer": 104857600, - }, - [Function], - ], - Array [ - "git remote rm sqren", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], - ], - Array [ - "git remote add sqren https://myAccessToken@github.com/sqren/kibana.git", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], - ], - Array [ - "git remote rm elastic", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], - ], - Array [ - "git remote add elastic https://myAccessToken@github.com/elastic/kibana.git", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], - ], - Array [ - "git reset --hard && git clean -d --force && git checkout master && git pull origin master", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], - ], - Array [ - "git fetch origin 6.2 && git branch backport/6.2/pr-myPullRequestNumber origin/6.2 --force && git checkout backport/6.2/pr-myPullRequestNumber ", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], - ], - Array [ - "git cherry-pick myCommitSha", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], - ], - Array [ - "git push sqren backport/6.2/pr-myPullRequestNumber:backport/6.2/pr-myPullRequestNumber --force", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], - ], -] -`; - -exports[`run through steps prompt calls should match snapshot 1`] = ` -Array [ - Array [ - Array [ - Object { - "choices": Array [ - Object { - "name": "1. Update readme: Make ui-framework url a link", - "short": "Update readme: Make ui-framework url a link", - "value": Object { - "message": "Update readme: Make ui-framework url a link", - "pullNumber": "Pull number for commitSha", - "sha": "commitSha", - }, - }, - Object { - "name": "2. Update react 15.6.1 (#13672)", - "short": "Update react 15.6.1 (#13672)", - "value": Object { - "message": "Update react 15.6.1 (#13672)", - "pullNumber": "Pull number for commitSha2", - "sha": "commitSha2", - }, - }, - Object { - "name": "3. Mock out static files when running in Jest (#13315)", - "short": "Mock out static files when running in Jest (#13315)", - "value": Object { - "message": "Mock out static files when running in Jest (#13315)", - "pullNumber": "Pull number for commitSha3", - "sha": "commitSha3", - }, - }, - ], - "message": "Select commit to backport", - "name": "promptResult", - "pageSize": 3, - "type": "list", - }, - ], - ], - Array [ - Array [ - Object { - "choices": Array [ - Object { - "name": "6.x", - }, - Object { - "name": "6.0", - }, - Object { - "name": "5.6", - }, - Object { - "name": "5.5", - }, - Object { - "name": "5.4", - }, - ], - "message": "Select branch to backport to", - "name": "promptResult", - "type": "list", - }, - ], - ], -] -`; - -exports[`run through steps should make correct requests 1`] = ` -Object { - "delete": Array [], - "get": Array [ - Object { - "data": undefined, - "headers": Object { - "Accept": "application/json, text/plain, */*", - }, - "maxContentLength": -1, - "method": "get", - "timeout": 0, - "transformRequest": Object { - "0": [Function], - }, - "transformResponse": Object { - "0": [Function], - }, - "url": "https://api.github.com/repos/elastic/kibana/commits?access_token=myAccessToken&per_page=5&author=sqren", - "validateStatus": [Function], - "xsrfCookieName": "XSRF-TOKEN", - "xsrfHeaderName": "X-XSRF-TOKEN", - }, - Object { - "data": undefined, - "headers": Object { - "Accept": "application/json, text/plain, */*", - }, - "maxContentLength": -1, - "method": "get", - "timeout": 0, - "transformRequest": Object { - "0": [Function], - }, - "transformResponse": Object { - "0": [Function], - }, - "url": "https://api.github.com/search/issues?q=repo:elastic/kibana+commitSha+base:master&access_token=myAccessToken", - "validateStatus": [Function], - "xsrfCookieName": "XSRF-TOKEN", - "xsrfHeaderName": "X-XSRF-TOKEN", - }, - Object { - "data": undefined, - "headers": Object { - "Accept": "application/json, text/plain, */*", - }, - "maxContentLength": -1, - "method": "get", - "timeout": 0, - "transformRequest": Object { - "0": [Function], - }, - "transformResponse": Object { - "0": [Function], - }, - "url": "https://api.github.com/search/issues?q=repo:elastic/kibana+commitSha2+base:master&access_token=myAccessToken", - "validateStatus": [Function], - "xsrfCookieName": "XSRF-TOKEN", - "xsrfHeaderName": "X-XSRF-TOKEN", - }, - Object { - "data": undefined, - "headers": Object { - "Accept": "application/json, text/plain, */*", - }, - "maxContentLength": -1, - "method": "get", - "timeout": 0, - "transformRequest": Object { - "0": [Function], - }, - "transformResponse": Object { - "0": [Function], - }, - "url": "https://api.github.com/search/issues?q=repo:elastic/kibana+commitSha3+base:master&access_token=myAccessToken", - "validateStatus": [Function], - "xsrfCookieName": "XSRF-TOKEN", - "xsrfHeaderName": "X-XSRF-TOKEN", - }, - ], - "head": Array [ - Object { - "data": undefined, - "headers": Object { - "Accept": "application/json, text/plain, */*", - }, - "maxContentLength": -1, - "method": "head", - "timeout": 0, - "transformRequest": Object { - "0": [Function], - }, - "transformResponse": Object { - "0": [Function], - }, - "url": "https://api.github.com/repos/elastic/kibana?access_token=myAccessToken", - "validateStatus": [Function], - "xsrfCookieName": "XSRF-TOKEN", - "xsrfHeaderName": "X-XSRF-TOKEN", - }, - ], - "list": Array [], - "options": Array [], - "patch": Array [], - "post": Array [ - Object { - "data": "{\\"title\\":\\"myPrTitle\\",\\"body\\":\\"Backports the following commits to 6.2:\\\\n - myCommitMessage (#myPullRequestNumber)\\\\n\\\\nmyPrDescription\\",\\"head\\":\\"sqren:backport/6.2/pr-myPullRequestNumber\\",\\"base\\":\\"6.2\\"}", - "headers": Object { - "Accept": "application/json, text/plain, */*", - "Content-Type": "application/json;charset=utf-8", - }, - "maxContentLength": -1, - "method": "post", - "timeout": 0, - "transformRequest": Object { - "0": [Function], - }, - "transformResponse": Object { - "0": [Function], - }, - "url": "https://api.github.com/repos/elastic/kibana/pulls?access_token=myAccessToken", - "validateStatus": [Function], - "xsrfCookieName": "XSRF-TOKEN", - "xsrfHeaderName": "X-XSRF-TOKEN", - }, - ], - "put": Array [], -} -`; diff --git a/test/steps/maybeSetupRepo.test.ts b/test/steps/maybeSetupRepo.test.ts deleted file mode 100644 index d3adae35..00000000 --- a/test/steps/maybeSetupRepo.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import rimraf from 'rimraf'; -import * as rpc from '../../src/services/rpc'; -import { maybeSetupRepo } from '../../src/steps/maybeSetupRepo'; -import { BackportOptions } from '../../src/options/options'; - -describe('maybeSetupRepo', () => { - it('should delete repo if an error occurs', async () => { - expect.assertions(1); - jest.spyOn(rpc, 'mkdirp').mockImplementationOnce(() => { - throw new Error(); - }); - - try { - await maybeSetupRepo({ - repoOwner: 'elastic', - repoName: 'kibana', - username: 'sqren', - accessToken: 'myAccessToken', - gitHostname: 'github.com' - } as BackportOptions); - } catch (e) { - expect(rimraf).toHaveBeenCalledWith( - '/myHomeDir/.backport/repositories/elastic/kibana', - expect.any(Function) - ); - } - }); -}); diff --git a/test/steps/steps.test.ts b/test/steps/steps.test.ts deleted file mode 100644 index 3929439a..00000000 --- a/test/steps/steps.test.ts +++ /dev/null @@ -1,166 +0,0 @@ -import axios from 'axios'; -import MockAdapter from 'axios-mock-adapter'; -import inquirer from 'inquirer'; -import * as childProcess from 'child_process'; -import { commitsMock } from '../mocks/commits'; -import { initSteps } from '../../src/steps/steps'; -import * as github from '../../src/services/github'; -import * as rpc from '../../src/services/rpc'; -import { BackportOptions } from '../../src/options/options'; - -function mockGetPullRequest( - axiosMock: MockAdapter, - { repoName, repoOwner, accessToken }: BackportOptions, - commitSha: string -) { - return axiosMock - .onGet( - `https://api.github.com/search/issues?q=repo:${repoOwner}/${repoName}+${commitSha}+base:master&access_token=${accessToken}` - ) - .reply(200, { items: [{ number: `Pull number for ${commitSha}` }] }); -} - -function mockVerifyAccessToken( - axiosMock: MockAdapter, - { repoName, repoOwner, accessToken }: BackportOptions -) { - return axiosMock - .onHead( - `https://api.github.com/repos/${repoOwner}/${repoName}?access_token=${accessToken}` - ) - .reply(200); -} - -function mockGetCommits( - axiosMock: MockAdapter, - { repoName, repoOwner, accessToken, username }: BackportOptions, - res: any -) { - return axiosMock - .onGet( - `https://api.github.com/repos/${repoOwner}/${repoName}/commits?access_token=${accessToken}&per_page=5&author=${username}` - ) - .reply(200, res); -} - -function mockCreatePullRequest( - axiosMock: MockAdapter, - { repoName, repoOwner, accessToken }: BackportOptions, - res: any -) { - return axiosMock - .onPost( - `https://api.github.com/repos/${repoOwner}/${repoName}/pulls?access_token=${accessToken}` - ) - .reply(200, res); -} - -describe('run through steps', () => { - let axiosMock: MockAdapter; - let execMock: jest.SpyInstance; - let inquirerPromptMock: jest.Mock; - - afterEach(() => { - inquirerPromptMock.mockClear(); - execMock.mockClear(); - }); - - beforeEach(async () => { - const options = { - accessToken: 'myAccessToken', - all: false, - apiHostname: 'api.github.com', - branches: [], - branchChoices: [ - { name: '6.x' }, - { name: '6.0' }, - { name: '5.6' }, - { name: '5.5' }, - { name: '5.4' } - ], - gitHostname: 'github.com', - labels: [], - multiple: false, - multipleBranches: false, - multipleCommits: false, - prDescription: 'myPrDescription', - prTitle: 'myPrTitle', - repoName: 'kibana', - repoOwner: 'elastic', - sha: undefined, - username: 'sqren' - }; - - execMock = jest.spyOn(childProcess, 'exec'); - - jest.spyOn(rpc, 'writeFile').mockResolvedValue(undefined); - jest.spyOn(rpc, 'mkdirp').mockResolvedValue(undefined); - - jest.spyOn(github, 'fetchCommitsByAuthor'); - jest.spyOn(github, 'createPullRequest'); - - inquirerPromptMock = jest - .spyOn(inquirer, 'prompt') - .mockResolvedValueOnce({ - promptResult: { - message: 'myCommitMessage', - sha: 'myCommitSha', - pullNumber: 'myPullRequestNumber' - } - }) - .mockResolvedValueOnce({ promptResult: '6.2' }); - - axiosMock = new MockAdapter(axios); - mockVerifyAccessToken(axiosMock, options); - mockGetCommits(axiosMock, options, commitsMock); - mockGetPullRequest(axiosMock, options, 'commitSha'); - mockGetPullRequest(axiosMock, options, 'commitSha2'); - mockGetPullRequest(axiosMock, options, 'commitSha3'); - mockCreatePullRequest(axiosMock, options, { - res: { html_url: 'myHtmlUrl' } - }); - - await initSteps(options); - }); - - it('should make correct requests', () => { - expect(axiosMock.history).toMatchSnapshot(); - }); - - it('getCommit should be called with correct args', () => { - expect(github.fetchCommitsByAuthor).toHaveBeenCalledWith( - expect.objectContaining({ - repoName: 'kibana', - repoOwner: 'elastic', - username: 'sqren', - apiHostname: 'api.github.com' - }) - ); - }); - - it('createPullRequest should be called with correct args', () => { - expect(github.createPullRequest).toHaveBeenCalledWith( - expect.objectContaining({ - repoName: 'kibana', - repoOwner: 'elastic', - apiHostname: 'api.github.com' - }), - { - base: '6.2', - body: `Backports the following commits to 6.2:\n - myCommitMessage (#myPullRequestNumber)\n\nmyPrDescription`, - head: 'sqren:backport/6.2/pr-myPullRequestNumber', - title: 'myPrTitle' - } - ); - }); - - it('prompt calls should match snapshot', () => { - expect(inquirer.prompt).toHaveBeenCalledTimes(2); - expect(inquirerPromptMock.mock.calls).toMatchSnapshot(); - }); - - it('exec should be called with correct args', () => { - expect(execMock).toHaveBeenCalledTimes(9); - expect(execMock.mock.calls).toMatchSnapshot(); - }); -}); diff --git a/test/tsconfig.json b/test/tsconfig.json index efebcbf0..8b5b03e4 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -1,13 +1,7 @@ { + "extends": "../tsconfig.json", "include": ["../src/types/*", "./**/*"], "compilerOptions": { - "target": "es2017", - "lib": ["es2017"], - "module": "commonjs", - "noEmit": true, - "forceConsistentCasingInFileNames": true, - "strict": true, - "noUnusedLocals": true, - "esModuleInterop": true + "noEmit": true } } diff --git a/test/unit/.eslintrc.js b/test/unit/.eslintrc.js new file mode 100644 index 00000000..e53d313a --- /dev/null +++ b/test/unit/.eslintrc.js @@ -0,0 +1,6 @@ +module.exports = { + extends: ['../../.eslintrc.js'], + rules: { + '@typescript-eslint/no-object-literal-type-assertion': 'off' + } +}; diff --git a/test/unit/automatic-mocks.ts b/test/unit/automatic-mocks.ts new file mode 100644 index 00000000..1da7d49a --- /dev/null +++ b/test/unit/automatic-mocks.ts @@ -0,0 +1,81 @@ +import last from 'lodash.last'; +import os from 'os'; + +jest.spyOn(os, 'homedir').mockReturnValue('/myHomeDir'); + +jest.mock('../../src/services/child-process-promisified', () => { + return { + exec: jest.fn(async () => 'success'), + + execAsCallback: jest.fn((...args) => { + last(args)(); + return { + stderr: { + on: () => {} + } + }; + }) + }; +}); + +jest.mock('../../src/services/fs-promisified', () => { + return { + writeFile: jest.fn(async () => 'fs.writeFile mock value'), + + readFile: jest.fn(async (filepath: string) => { + // mock project config + if (filepath === '/path/to/project/config') { + return JSON.stringify({ + upstream: 'elastic/backport-demo', + branches: ['6.0', '5.9'] + }); + } + + // mock global config + if (filepath.endsWith('/.backport/config.json')) { + return JSON.stringify({ + username: 'sqren', + accessToken: 'myAccessToken' + }); + } + + throw new Error(`Unknown filepath: "${filepath}"`); + }), + + stat: jest.fn(async () => { + return { + isDirectory: () => {} + }; + }), + + chmod: jest.fn(async () => 'fs.chmod mock value') + }; +}); + +jest.mock('find-up', () => { + return jest.fn(async () => '/path/to/project/config'); +}); + +jest.mock('make-dir', () => { + return jest.fn(() => Promise.resolve('/some/path')); +}); + +jest.mock('del', () => { + return jest.fn(async path => `Attempted to delete ${path}`); +}); + +jest.mock('ora', () => { + const ora = { + start: () => ({ + succeed: () => {}, + stop: () => {}, + fail: () => {}, + stopAndPersist: () => {} + }) + }; + + return () => ora; +}); + +// silence logger +jest.mock('../../src/services/logger'); diff --git a/test/options/__snapshots__/options.test.ts.snap b/test/unit/options/__snapshots__/options.test.ts.snap similarity index 100% rename from test/options/__snapshots__/options.test.ts.snap rename to test/unit/options/__snapshots__/options.test.ts.snap diff --git a/test/options/cliArgs.test.ts b/test/unit/options/cliArgs.test.ts similarity index 86% rename from test/options/cliArgs.test.ts rename to test/unit/options/cliArgs.test.ts index ea489b01..6034751e 100644 --- a/test/options/cliArgs.test.ts +++ b/test/unit/options/cliArgs.test.ts @@ -1,4 +1,4 @@ -import { getOptionsFromCliArgs } from '../../src/options/cliArgs'; +import { getOptionsFromCliArgs } from '../../../src/options/cliArgs'; describe('getOptionsFromCliArgs', () => { let res: ReturnType; @@ -20,8 +20,6 @@ describe('getOptionsFromCliArgs', () => { }; const argv = [ - '/Users/sqren/elastic/backport/node_modules/.bin/ts-node', - '/Users/sqren/elastic/backport/src/index.ts', '--branch', '6.0', '--branch', diff --git a/test/unit/options/config/config.test.ts b/test/unit/options/config/config.test.ts new file mode 100644 index 00000000..166c55e5 --- /dev/null +++ b/test/unit/options/config/config.test.ts @@ -0,0 +1,30 @@ +import { PromiseReturnType } from '../../../../src/types/commons'; +import { getOptionsFromConfigFiles } from '../../../../src/options/config/config'; + +describe('getOptionsFromConfigFiles', () => { + let res: PromiseReturnType; + + beforeEach(async () => { + res = await getOptionsFromConfigFiles(); + }); + + it('should return correct config', () => { + expect(res).toEqual({ + accessToken: 'myAccessToken', + all: false, + apiHostname: 'api.github.com', + branchChoices: [ + { checked: false, name: '6.0' }, + { checked: false, name: '5.9' } + ], + gitHostname: 'github.com', + labels: [], + multiple: false, + multipleBranches: true, + multipleCommits: false, + prTitle: '[{baseBranch}] {commitMessages}', + upstream: 'elastic/backport-demo', + username: 'sqren' + }); + }); +}); diff --git a/test/options/config/globalConfig.test.ts b/test/unit/options/config/globalConfig.test.ts similarity index 68% rename from test/options/config/globalConfig.test.ts rename to test/unit/options/config/globalConfig.test.ts index 89c1a5b3..ae4fdd00 100644 --- a/test/options/config/globalConfig.test.ts +++ b/test/unit/options/config/globalConfig.test.ts @@ -1,9 +1,10 @@ -import * as rpc from '../../../src/services/rpc'; +import * as fs from '../../../../src/services/fs-promisified'; +import { PromiseReturnType } from '../../../../src/types/commons'; import { getGlobalConfig, maybeCreateGlobalConfig -} from '../../../src/options/config/globalConfig'; -import { PromiseReturnType } from '../../../src/types/commons'; +} from '../../../../src/options/config/globalConfig'; +import makeDir from 'make-dir'; describe('config', () => { afterEach(() => jest.restoreAllMocks()); @@ -11,10 +12,9 @@ describe('config', () => { describe('getGlobalConfig', () => { let res: PromiseReturnType; beforeEach(async () => { - jest.spyOn(rpc, 'chmod').mockResolvedValue(); - jest.spyOn(rpc, 'mkdirp').mockResolvedValue(); - jest.spyOn(rpc, 'writeFile').mockResolvedValue(); - jest.spyOn(rpc, 'readFile').mockResolvedValue( + jest.spyOn(fs, 'chmod').mockResolvedValue(); + jest.spyOn(fs, 'writeFile').mockResolvedValue(); + jest.spyOn(fs, 'readFile').mockResolvedValue( JSON.stringify({ accessToken: 'myAccessToken', username: 'sqren' @@ -24,7 +24,7 @@ describe('config', () => { }); it("should create config if it doesn't exist", () => { - expect(rpc.writeFile).toHaveBeenCalledWith( + expect(fs.writeFile).toHaveBeenCalledWith( '/myHomeDir/.backport/config.json', expect.any(String), { flag: 'wx', mode: 384 } @@ -32,13 +32,11 @@ describe('config', () => { }); it("should create config folders if it they don't exist", () => { - expect(rpc.mkdirp).toHaveBeenCalledWith( - '/myHomeDir/.backport/repositories' - ); + expect(makeDir).toHaveBeenCalledWith('/myHomeDir/.backport/repositories'); }); it('should load config', () => { - expect(rpc.readFile).toHaveBeenCalledWith( + expect(fs.readFile).toHaveBeenCalledWith( '/myHomeDir/.backport/config.json', 'utf8' ); @@ -54,7 +52,7 @@ describe('config', () => { describe('maybeCreateGlobalConfig', () => { it('should create config and succeed', async () => { - jest.spyOn(rpc, 'writeFile').mockResolvedValue(undefined); + jest.spyOn(fs, 'writeFile').mockResolvedValue(undefined); const didCreate = await maybeCreateGlobalConfig( '/path/to/globalConfig', 'myConfigTemplate' @@ -62,7 +60,7 @@ describe('config', () => { expect(didCreate).toEqual(true); - expect(rpc.writeFile).toHaveBeenCalledWith( + expect(fs.writeFile).toHaveBeenCalledWith( '/path/to/globalConfig', expect.stringContaining('myConfigTemplate'), { flag: 'wx', mode: 384 } @@ -72,7 +70,7 @@ describe('config', () => { it('should not fail if config already exists', async () => { const err = new Error(); (err as any).code = 'EEXIST'; - jest.spyOn(rpc, 'writeFile').mockRejectedValueOnce(err); + jest.spyOn(fs, 'writeFile').mockRejectedValueOnce(err); const didCreate = await maybeCreateGlobalConfig( 'myPath', diff --git a/test/options/config/projectConfig.test.ts b/test/unit/options/config/projectConfig.test.ts similarity index 75% rename from test/options/config/projectConfig.test.ts rename to test/unit/options/config/projectConfig.test.ts index 692808db..5b7c2f3e 100644 --- a/test/options/config/projectConfig.test.ts +++ b/test/unit/options/config/projectConfig.test.ts @@ -1,7 +1,7 @@ import findUp from 'find-up'; -import * as rpc from '../../../src/services/rpc'; -import { getProjectConfig } from '../../../src/options/config/projectConfig'; -import { PromiseReturnType } from '../../../src/types/commons'; +import * as fs from '../../../../src/services/fs-promisified'; +import { PromiseReturnType } from '../../../../src/types/commons'; +import { getProjectConfig } from '../../../../src/options/config/projectConfig'; describe('getProjectConfig', () => { afterEach(() => jest.restoreAllMocks()); @@ -10,7 +10,7 @@ describe('getProjectConfig', () => { let projectConfig: PromiseReturnType; beforeEach(async () => { jest - .spyOn(rpc, 'readFile') + .spyOn(fs, 'readFile') .mockResolvedValue( JSON.stringify({ upstream: 'elastic/kibana', branches: ['6.x'] }) ); @@ -32,7 +32,7 @@ describe('getProjectConfig', () => { describe('when projectConfig is empty', () => { it('should return empty config', async () => { - jest.spyOn(rpc, 'readFile').mockResolvedValueOnce('{}'); + jest.spyOn(fs, 'readFile').mockResolvedValueOnce('{}'); const projectConfig = await getProjectConfig(); expect(projectConfig).toEqual({ branchChoices: undefined }); }); @@ -40,7 +40,7 @@ describe('getProjectConfig', () => { describe('when projectConfig is missing', () => { it('should return empty config', async () => { - (findUp as any).__setMockPath(); + ((findUp as any) as jest.SpyInstance).mockReturnValueOnce(undefined); const projectConfig = await getProjectConfig(); expect(projectConfig).toEqual({}); }); diff --git a/test/options/options.test.ts b/test/unit/options/options.test.ts similarity index 91% rename from test/options/options.test.ts rename to test/unit/options/options.test.ts index c358b5f1..4e046f23 100644 --- a/test/options/options.test.ts +++ b/test/unit/options/options.test.ts @@ -1,11 +1,14 @@ -import { validateRequiredOptions } from '../../src/options/options'; +import { OptionsFromCliArgs } from '../../../src/options/cliArgs'; +import { validateRequiredOptions } from '../../../src/options/options'; -const validOptions = { +const validOptions: OptionsFromCliArgs = { accessToken: 'myAccessToken', all: false, apiHostname: 'api.github.com', + author: undefined, branchChoices: [], branches: ['branchA'], + commitsCount: 10, gitHostname: 'github.com', labels: [], multiple: false, diff --git a/test/scripts/postinstall.test.ts b/test/unit/scripts/postinstall.test.ts similarity index 85% rename from test/scripts/postinstall.test.ts rename to test/unit/scripts/postinstall.test.ts index cfb35f41..744639f8 100644 --- a/test/scripts/postinstall.test.ts +++ b/test/unit/scripts/postinstall.test.ts @@ -1,5 +1,5 @@ -import { postinstall } from '../../src/scripts/postinstall'; -import * as globalConfig from '../../src/options/config/globalConfig'; +import * as globalConfig from '../../../src/options/config/globalConfig'; +import { postinstall } from '../../../src/scripts/postinstall'; describe('postinstall', () => { it("should create global config if it doesn't exist", async () => { diff --git a/test/services/env.test.ts b/test/unit/services/env.test.ts similarity index 81% rename from test/services/env.test.ts rename to test/unit/services/env.test.ts index ce76f928..1be977df 100644 --- a/test/services/env.test.ts +++ b/test/unit/services/env.test.ts @@ -1,12 +1,12 @@ +import { BackportOptions } from '../../../src/options/options'; import { getGlobalConfigPath, - getReposPath, getRepoOwnerPath, - getRepoPath -} from '../../src/services/env'; -import { BackportOptions } from '../../src/options/options'; + getRepoPath, + getReposPath +} from '../../../src/services/env'; -describe('env.js', () => { +describe('env', () => { test('getGlobalConfigPath', () => { expect(getGlobalConfigPath()).toBe('/myHomeDir/.backport/config.json'); }); diff --git a/test/services/git.test.ts b/test/unit/services/git.test.ts similarity index 76% rename from test/services/git.test.ts rename to test/unit/services/git.test.ts index 601f51c5..cc05f9f7 100644 --- a/test/services/git.test.ts +++ b/test/unit/services/git.test.ts @@ -1,10 +1,10 @@ -import { addRemote } from '../../src/services/git'; -import * as rpc from '../../src/services/rpc'; -import { BackportOptions } from '../../src/options/options'; +import { BackportOptions } from '../../../src/options/options'; +import { addRemote } from '../../../src/services/git'; +import * as childProcess from '../../../src/services/child-process-promisified'; describe('addRemote', () => { it('add correct origin remote', async () => { - const spy = jest.spyOn(rpc, 'exec').mockResolvedValue({} as any); + const spy = jest.spyOn(childProcess, 'exec').mockResolvedValue({} as any); await addRemote( { accessToken: 'myAccessToken', @@ -22,7 +22,7 @@ describe('addRemote', () => { }); it('add correct user remote', async () => { - const spy = jest.spyOn(rpc, 'exec').mockResolvedValue({} as any); + const spy = jest.spyOn(childProcess, 'exec').mockResolvedValue({} as any); await addRemote( { accessToken: 'myAccessToken', @@ -40,7 +40,7 @@ describe('addRemote', () => { }); it('allows custom github url', async () => { - const spy = jest.spyOn(rpc, 'exec').mockResolvedValue({} as any); + const spy = jest.spyOn(childProcess, 'exec').mockResolvedValue({} as any); await addRemote( { accessToken: 'myAccessToken', diff --git a/test/unit/services/github/__snapshots__/fetchCommitBySha.test.ts.snap b/test/unit/services/github/__snapshots__/fetchCommitBySha.test.ts.snap new file mode 100644 index 00000000..5b55338b --- /dev/null +++ b/test/unit/services/github/__snapshots__/fetchCommitBySha.test.ts.snap @@ -0,0 +1,17 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`fetchCommitBySha should return single commit with pull request 1`] = ` +Array [ + Array [ + "https://api.github.com/search/commits?q=hash:myCommitSha%20repo:elastic/kibana&per_page=1&access_token=myAccessToken", + Object { + "headers": Object { + "Accept": "application/vnd.github.cloak-preview", + }, + }, + ], + Array [ + "https://api.github.com/search/issues?q=repo:elastic/kibana+myCommitSha+base:master&access_token=myAccessToken", + ], +] +`; diff --git a/test/unit/services/github/__snapshots__/fetchCommitsByAuthor.test.ts.snap b/test/unit/services/github/__snapshots__/fetchCommitsByAuthor.test.ts.snap new file mode 100644 index 00000000..4d5a001e --- /dev/null +++ b/test/unit/services/github/__snapshots__/fetchCommitsByAuthor.test.ts.snap @@ -0,0 +1,94 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`fetchCommitsByAuthor when commit has an associated pull request should call with correct args to fetch author id 1`] = ` +Array [ + Object { + "accessToken": "myAccessToken", + "apiHostname": "api.github.com", + "query": " + query getIdByLogin($login: String!) { + user(login: $login) { + id + } + } + ", + "variables": Object { + "login": "sqren", + }, + }, +] +`; + +exports[`fetchCommitsByAuthor when commit has an associated pull request should call with correct args to fetch commits 1`] = ` +Array [ + Object { + "accessToken": "myAccessToken", + "apiHostname": "api.github.com", + "query": " + query getCommitsByAuthorQuery( + $repoOwner: String! + $repoName: String! + $commitsCount: Int! + $authorId: ID + ) { + repository(owner: $repoOwner, name: $repoName) { + ref(qualifiedName: \\"master\\") { + target { + ... on Commit { + history(first: $commitsCount, author: { id: $authorId }) { + edges { + node { + oid + message + associatedPullRequests(first: 1) { + edges { + node { + number + timelineItems( + last: 20 + itemTypes: CROSS_REFERENCED_EVENT + ) { + edges { + node { + ... on CrossReferencedEvent { + source { + __typename + ... on PullRequest { + state + baseRefName + commits(first: 20) { + edges { + node { + commit { + message + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + ", + "variables": Object { + "authorId": "myUserId", + "commitsCount": 10, + "repoName": "kibana", + "repoOwner": "elastic", + }, + }, +] +`; diff --git a/test/unit/services/github/commitFormatters.test.ts b/test/unit/services/github/commitFormatters.test.ts new file mode 100644 index 00000000..bdfd29a1 --- /dev/null +++ b/test/unit/services/github/commitFormatters.test.ts @@ -0,0 +1,58 @@ +import { + getFirstCommitMessageLine, + getHumanReadableReference, + withFormattedCommitMessage +} from '../../../../src/services/github/commitFormatters'; + +describe('getHumanReadableReference', () => { + it('should return a sha ref', () => { + expect( + getHumanReadableReference({ sha: 'mySha1234567', message: 'myMessage' }) + ).toEqual('mySha123'); + }); + + it('should return a pr ref', () => { + expect( + getHumanReadableReference({ + pullNumber: 1337, + sha: 'mySha1234567', + message: 'myMessage' + }) + ).toEqual('#1337'); + }); +}); + +describe('getFirstCommitMessageLine', () => { + it('should only return the first line of the message and omit the PR ref', () => { + expect( + getFirstCommitMessageLine( + 'My commit message (#1234)\n\n Additional commit message body' + ) + ).toEqual('My commit message'); + }); + + it('should return the commit message as-is', () => { + expect(getFirstCommitMessageLine('My commit message')).toEqual( + 'My commit message' + ); + }); +}); + +describe('withFormattedCommitMessage', () => { + it('should return a message with a sha ref', () => { + expect( + withFormattedCommitMessage({ sha: 'mySha1234567', message: 'myMessage' }) + .message + ).toEqual('myMessage (mySha123)'); + }); + + it('should return a message with a PR ref', () => { + expect( + withFormattedCommitMessage({ + sha: 'mySha1234567', + message: 'myMessage (#12)', + pullNumber: 1234 + }).message + ).toEqual('myMessage (#1234)'); + }); +}); diff --git a/test/unit/services/github/fetchCommitBySha.test.ts b/test/unit/services/github/fetchCommitBySha.test.ts new file mode 100644 index 00000000..280ed700 --- /dev/null +++ b/test/unit/services/github/fetchCommitBySha.test.ts @@ -0,0 +1,31 @@ +import axios from 'axios'; +import { fetchCommitBySha } from '../../../../src/services/github/fetchCommitBySha'; +import { getDefaultOptions } from './getDefaultOptions'; + +describe('fetchCommitBySha', () => { + it('should return single commit with pull request', async () => { + const commitSha = 'myCommitSha'; + const options = getDefaultOptions(); + + const axiosSpy = jest + .spyOn(axios, 'get') + + // mock commits + .mockResolvedValueOnce({ + data: { items: [{ commit: { message: 'myMessage' }, sha: commitSha }] } + }) + + // mock PRs + .mockResolvedValueOnce({ + data: { items: [{ number: 'myPullRequestNumber' }] } + }); + + expect(await fetchCommitBySha({ ...options, sha: commitSha })).toEqual({ + message: 'myMessage (#myPullRequestNumber)', + pullNumber: 'myPullRequestNumber', + sha: 'myCommitSha' + }); + + expect(axiosSpy.mock.calls).toMatchSnapshot(); + }); +}); diff --git a/test/unit/services/github/fetchCommitsByAuthor.test.ts b/test/unit/services/github/fetchCommitsByAuthor.test.ts new file mode 100644 index 00000000..a38fa082 --- /dev/null +++ b/test/unit/services/github/fetchCommitsByAuthor.test.ts @@ -0,0 +1,135 @@ +import * as gqlRequest from '../../../../src/services/github/gqlRequest'; +import { CommitSelected } from '../../../../src/services/github/Commit'; +import { + PullRequestEdge, + fetchCommitsByAuthor, + getExistingBackportPRs +} from '../../../../src/services/github/fetchCommitsByAuthor'; +import { commitsWithPullRequestsMock } from './mocks/commitsByAuthorMock'; +import { getDefaultOptions } from './getDefaultOptions'; + +describe('fetchCommitsByAuthor', () => { + describe('when commit has an associated pull request', () => { + let requestSpy: jasmine.Spy; + let res: CommitSelected[]; + beforeEach(async () => { + requestSpy = spyOn(gqlRequest, 'gqlRequest').and.returnValues( + { user: { id: 'myUserId' } }, + commitsWithPullRequestsMock + ); + + const options = getDefaultOptions(); + res = await fetchCommitsByAuthor(options); + }); + + it('Should return a list of commits with pullNumber and existing backports', () => { + expect(res).toEqual([ + { + sha: '2e63475c483f7844b0f2833bc57fdee32095bacb', + message: 'Add 👻 (2e63475c)', + existingBackports: [] + }, + { + sha: 'f3b618b9421fdecdb36862f907afbdd6344b361d', + message: 'Add witch (#85)', + pullNumber: 85, + existingBackports: [] + }, + { + sha: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', + message: 'Add SF mention (#80)', + pullNumber: 80, + existingBackports: [{ branch: '6.3', state: 'MERGED' }] + }, + { + sha: '3827bbbaf39914eda4f02f6940189844375fd097', + message: 'Add backport config (3827bbba)', + existingBackports: [] + }, + { + sha: '5ea0da550ac191029459289d67f99ad7d310812b', + message: 'Initial commit (5ea0da55)', + existingBackports: [] + } + ]); + }); + + it('should call with correct args to fetch author id', () => { + expect(requestSpy.calls.argsFor(0)).toMatchSnapshot(); + }); + + it('should call with correct args to fetch commits', () => { + expect(requestSpy.calls.argsFor(1)).toMatchSnapshot(); + }); + }); + + describe('when a custom github api hostname is supplied', () => { + it('should be used in gql requests', async () => { + const requestSpy = spyOn(gqlRequest, 'gqlRequest').and.returnValues( + { user: { id: 'myUserId' } }, + commitsWithPullRequestsMock + ); + + const options = getDefaultOptions({ + apiHostname: 'api.github.my-company.com' + }); + await fetchCommitsByAuthor(options); + + expect(requestSpy.calls.argsFor(0)[0].apiHostname).toBe( + 'api.github.my-company.com' + ); + expect(requestSpy.calls.argsFor(1)[0].apiHostname).toBe( + 'api.github.my-company.com' + ); + }); + }); +}); + +describe('getExistingBackportPRs', () => { + let pullRequest: PullRequestEdge; + beforeEach(() => { + pullRequest = { + node: { + number: 1234, + timelineItems: { + edges: [ + { + node: { + source: { + __typename: 'PullRequest', + state: 'MERGED' as const, + commits: { + edges: [ + { node: { commit: { message: 'my message (#1234)' } } } + ] + }, + baseRefName: '7.x' + } + } + } + ] + } + } + }; + }); + + it('should return a result when commit messages match', () => { + const existingPRs = getExistingBackportPRs( + 'my message (#1234)', + pullRequest + ); + + expect(existingPRs).toEqual([{ branch: '7.x', state: 'MERGED' }]); + }); + + it('should return a result when first line of commit message matches', () => { + pullRequest.node.timelineItems.edges[0].node.source.commits.edges[0].node.commit.message = + 'my message (#1234)\n\nsomething else'; + const existingPRs = getExistingBackportPRs( + 'my message (#1234)', + pullRequest + ); + + expect(existingPRs).toEqual([{ branch: '7.x', state: 'MERGED' }]); + }); +}); diff --git a/test/unit/services/github/getDefaultOptions.ts b/test/unit/services/github/getDefaultOptions.ts new file mode 100644 index 00000000..9a14468f --- /dev/null +++ b/test/unit/services/github/getDefaultOptions.ts @@ -0,0 +1,13 @@ +import { BackportOptions } from '../../../../src/options/options'; + +export function getDefaultOptions(options: Partial = {}) { + return { + repoOwner: 'elastic', + repoName: 'kibana', + accessToken: 'myAccessToken', + username: 'sqren', + author: 'sqren', + apiHostname: 'api.github.com', + ...options + } as BackportOptions; +} diff --git a/test/unit/services/github/gqlRequest.test.ts b/test/unit/services/github/gqlRequest.test.ts new file mode 100644 index 00000000..343a6da6 --- /dev/null +++ b/test/unit/services/github/gqlRequest.test.ts @@ -0,0 +1,70 @@ +import axios from 'axios'; +import { HandledError } from '../../../../src/services/HandledError'; +import { gqlRequest } from '../../../../src/services/github/gqlRequest'; + +describe('gqlRequest', () => { + describe('when request succeeds', () => { + let spy: jest.SpyInstance; + beforeEach(() => { + spy = jest.spyOn(axios, 'post').mockResolvedValue({ + data: { + data: 'some data' + } + } as any); + }); + + it('should return correct response', async () => { + expect( + await gqlRequest({ + accessToken: 'myAccessToken', + apiHostname: 'myApiHostname', + query: 'myQuery', + variables: { + foo: 'bar' + } + }) + ).toEqual('some data'); + }); + + it('should call with correct args', async () => { + expect(spy).toHaveBeenCalledWith( + 'https://myApiHostname/graphql', + { + query: 'myQuery', + variables: { foo: 'bar' } + }, + { + headers: { + Authorization: 'bearer myAccessToken', + 'Content-Type': 'application/json' + } + } + ); + }); + }); + + describe('when request fails', () => { + beforeEach(() => { + jest.spyOn(axios, 'post').mockRejectedValue({ + response: { + data: { + errors: [{ message: 'some error' }, { message: 'some other error' }] + } + } + } as any); + }); + + it('should return parsed github error', async () => { + return expect( + gqlRequest({ + accessToken: 'myAccessToken', + apiHostname: 'myApiHostname', + query: 'myQuery', + variables: { + foo: 'bar' + } + }) + ).rejects.toThrowError(new HandledError('some error, some other error')); + }); + }); +}); diff --git a/test/mocks/commit.ts b/test/unit/services/github/mocks/commitByShaMock.ts similarity index 97% rename from test/mocks/commit.ts rename to test/unit/services/github/mocks/commitByShaMock.ts index 0089ae65..2511f567 100644 --- a/test/mocks/commit.ts +++ b/test/unit/services/github/mocks/commitByShaMock.ts @@ -1,4 +1,4 @@ -export const commitMock = { +export const commitByShaMock = { sha: 'myCommitSha', commit: { author: { @@ -11,7 +11,7 @@ export const commitMock = { email: 'noreply@github.com', date: '2017-11-28T18:44:33Z' }, - message: '[Chrome] Bootstrap Angular into document.body (#15158)', + message: '[Chrome] Bootstrap Angular into document.body', tree: { sha: 'ce129055d52748ed4d931cbc1591d984d71ec04f', url: @@ -25,7 +25,7 @@ export const commitMock = { signature: '-----BEGIN PGP SIGNATURE-----\n\nwsBcBAABCAAQBQJaHa6RCRBK7hj4Ov3rIwAAdHIIAKCbJdxH0Rvxt7oY5hIHFbpI\nFLFKyvzssgIDULgWzqIcc839ChnQuJOtCvobSeGCS3OMcxG+D0DKfn0MAOVGMyfD\n3vWYfkwE7asq2wKPPAsJ8tXNFQ4QLdCh9M24VyZxZwL49si2tZlLwN7vbWAdLgrc\n8MP4YWw7s7Y3Bw0Sm13kDMw07jUWJJd/PgU+cYs3EU+nkjGuz5V85U6w6qavdhqM\n1tQ5iv3q6AyzUDBm4LRX0t89STrCZpt3lG6jhUsqQscGKGBCxhks3zra4DClJIeK\nWoZbSiLcuKgU81KJyF2Wq/i7XMvhv1UQdTu3gqZOHpZEwNjaMaqGoUVs8bu0w+Q=\n=EWOy\n-----END PGP SIGNATURE-----\n', payload: - 'tree ce129055d52748ed4d931cbc1591d984d71ec04f\nparent b81fd782c7a63bc231b4678aa4e685c2025fa302\nauthor Søren Louv-Jansen 1511894673 +0100\ncommitter GitHub 1511894673 +0100\n\n[Chrome] Bootstrap Angular into document.body (#15158)\n\n' + 'tree ce129055d52748ed4d931cbc1591d984d71ec04f\nparent b81fd782c7a63bc231b4678aa4e685c2025fa302\nauthor Søren Louv-Jansen 1511894673 +0100\ncommitter GitHub 1511894673 +0100\n\n[Chrome] Bootstrap Angular into document.body\n\n' } }, url: 'https://api.github.com/repos/elastic/kibana/commits/myCommitSha', diff --git a/test/unit/services/github/mocks/commitsByAuthorMock.ts b/test/unit/services/github/mocks/commitsByAuthorMock.ts new file mode 100644 index 00000000..fa27e28a --- /dev/null +++ b/test/unit/services/github/mocks/commitsByAuthorMock.ts @@ -0,0 +1,100 @@ +import { DataResponse } from '../../../../../src/services/github/fetchCommitsByAuthor'; + +export const commitsWithPullRequestsMock: DataResponse = { + repository: { + ref: { + target: { + history: { + edges: [ + { + node: { + oid: '2e63475c483f7844b0f2833bc57fdee32095bacb', + message: 'Add 👻', + associatedPullRequests: { + edges: [] + } + } + }, + { + node: { + oid: 'f3b618b9421fdecdb36862f907afbdd6344b361d', + message: 'Add witch (#85)', + associatedPullRequests: { + edges: [ + { + node: { + number: 85, + timelineItems: { + edges: [] + } + } + } + ] + } + } + }, + { + node: { + oid: '79cf18453ec32a4677009dcbab1c9c8c73fc14fe', + message: + 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!', + associatedPullRequests: { + edges: [ + { + node: { + number: 80, + timelineItems: { + edges: [ + { + node: { + source: { + __typename: 'PullRequest', + state: 'MERGED', + baseRefName: '6.3', + commits: { + edges: [ + { + node: { + commit: { + message: + 'Add SF mention (#80)\n\n* Add SF mention\r\n\r\n* Add several emojis!' + } + } + } + ] + } + } + } + } + ] + } + } + } + ] + } + } + }, + { + node: { + oid: '3827bbbaf39914eda4f02f6940189844375fd097', + message: 'Add backport config', + associatedPullRequests: { + edges: [] + } + } + }, + { + node: { + oid: '5ea0da550ac191029459289d67f99ad7d310812b', + message: 'Initial commit', + associatedPullRequests: { + edges: [] + } + } + } + ] + } + } + } + } +}; diff --git a/test/unit/services/github/verifyAccessToken.test.ts b/test/unit/services/github/verifyAccessToken.test.ts new file mode 100644 index 00000000..2180abf6 --- /dev/null +++ b/test/unit/services/github/verifyAccessToken.test.ts @@ -0,0 +1,117 @@ +import axios from 'axios'; +import { BackportOptions } from '../../../../src/options/options'; +import { verifyAccessToken } from '../../../../src/services/github/verifyAccessToken'; +import { getDefaultOptions } from './getDefaultOptions'; + +describe('verifyAccessToken', () => { + let options: BackportOptions; + beforeEach(() => { + options = { + accessToken: 'myAccessToken', + apiHostname: 'api.github.com', + repoName: 'kibana', + repoOwner: 'elastic' + } as BackportOptions; + }); + + it('should call verifyAccessToken with correct url', async () => { + const spy = jest.spyOn(axios, 'head').mockResolvedValue('hi' as any); + await verifyAccessToken(getDefaultOptions(options)); + + expect(spy).toHaveBeenCalledWith( + 'https://api.github.com/repos/elastic/kibana?access_token=myAccessToken' + ); + }); + + describe('when status code is', () => { + it('401', () => { + jest.spyOn(axios, 'head').mockRejectedValue({ + response: { + status: 401 + } + }); + + return expect(verifyAccessToken(options)).rejects.toThrowError( + 'Please check your access token and make sure it is valid' + ); + }); + + it('403 (unknown error)', () => { + jest.spyOn(axios, 'head').mockRejectedValue({ + message: 'unknown error', + response: { + status: 403 + } + }); + + return expect(verifyAccessToken(options)).rejects.toThrowError( + 'Error while verifying access token: unknown error' + ); + }); + + it('403 (SSO error)', () => { + jest.spyOn(axios, 'head').mockRejectedValue({ + response: { + headers: { + 'x-github-sso': 'required; url=https://ssourl.com' + }, + status: 403 + } + }); + + return expect(verifyAccessToken(options)).rejects.toMatchInlineSnapshot(` + [HandledError: Please follow the link to authorize your personal access token with SSO: + + https://ssourl.com] + `); + }); + + it('404 (repo does not exist)', () => { + jest.spyOn(axios, 'head').mockRejectedValue({ + response: { + headers: { + 'x-oauth-scopes': 'a,b,c', + 'x-accepted-oauth-scopes': 'a,b,c' + }, + status: 404 + } + }); + + return expect(verifyAccessToken(options)).rejects.toMatchInlineSnapshot( + `[HandledError: The repository "elastic/kibana" doesn't exist]` + ); + }); + + it('404 (insufficient permissions)', () => { + jest.spyOn(axios, 'head').mockRejectedValue({ + response: { + headers: { + 'x-oauth-scopes': 'a,b', + 'x-accepted-oauth-scopes': 'a,b,c' + }, + status: 404 + } + }); + + return expect(verifyAccessToken(options)).rejects.toMatchInlineSnapshot(` + [HandledError: You do not have access to the repository "elastic/kibana". Please make sure your access token has the required scopes. + + Required scopes: a,b,c + Access token scopes: a,b] + `); + }); + + it('any other status code', () => { + jest.spyOn(axios, 'head').mockRejectedValue({ + message: 'unknown error', + response: { + status: 500 + } + }); + + return expect(verifyAccessToken(options)).rejects.toThrowError( + 'Error while verifying access token: unknown error' + ); + }); + }); +}); diff --git a/test/steps/__snapshots__/doBackportVersions.test.ts.snap b/test/unit/steps/__snapshots__/doBackportVersions.test.ts.snap similarity index 54% rename from test/steps/__snapshots__/doBackportVersions.test.ts.snap rename to test/unit/steps/__snapshots__/doBackportVersions.test.ts.snap index 9138d4de..fa1d3f34 100644 --- a/test/steps/__snapshots__/doBackportVersions.test.ts.snap +++ b/test/unit/steps/__snapshots__/doBackportVersions.test.ts.snap @@ -3,28 +3,16 @@ exports[`doBackportVersion when cherry-picking fails and conflicts were not resolved 2`] = ` Array [ Array [ - "git reset --hard && git clean -d --force && git checkout master && git pull origin master", + "git reset --hard && git clean -d --force && git fetch elastic 6.x && git checkout -B backport/6.x/commit-mySha elastic/6.x --no-track", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git fetch origin 6.x && git branch backport/6.x/commit-mySha origin/6.x --force && git checkout backport/6.x/commit-mySha ", + "git fetch elastic master:master --force && git cherry-pick mySha", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], - ], - Array [ - "git cherry-pick mySha", - Object { - "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, - }, - [Function], ], ] `; @@ -32,44 +20,34 @@ Array [ exports[`doBackportVersion when cherry-picking fails and conflicts were resolved 1`] = ` Array [ Array [ - "git reset --hard && git clean -d --force && git checkout master && git pull origin master", + "git reset --hard && git clean -d --force && git fetch elastic 6.x && git checkout -B backport/6.x/commit-mySha elastic/6.x --no-track", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git fetch origin 6.x && git branch backport/6.x/commit-mySha origin/6.x --force && git checkout backport/6.x/commit-mySha ", + "git fetch elastic master:master --force && git cherry-pick mySha", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git cherry-pick mySha", + "git diff-index --quiet HEAD --", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git diff-index --quiet HEAD --", + "git push sqren backport/6.x/commit-mySha:backport/6.x/commit-mySha --force", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git push sqren backport/6.x/commit-mySha:backport/6.x/commit-mySha --force", + "git checkout master && git branch -D backport/6.x/commit-mySha", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], ] `; @@ -77,44 +55,34 @@ Array [ exports[`doBackportVersion when commit has a pull request reference should make correct git commands 1`] = ` Array [ Array [ - "git reset --hard && git clean -d --force && git checkout master && git pull origin master", + "git reset --hard && git clean -d --force && git fetch elastic 6.x && git checkout -B backport/6.x/pr-1000_pr-2000 elastic/6.x --no-track", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git fetch origin 6.x && git branch backport/6.x/pr-1000_pr-2000 origin/6.x --force && git checkout backport/6.x/pr-1000_pr-2000 ", + "git fetch elastic master:master --force && git cherry-pick mySha", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git cherry-pick mySha", + "git fetch elastic master:master --force && git cherry-pick mySha2", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git cherry-pick mySha2", + "git push sqren backport/6.x/pr-1000_pr-2000:backport/6.x/pr-1000_pr-2000 --force", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], Array [ - "git push sqren backport/6.x/pr-1000_pr-2000:backport/6.x/pr-1000_pr-2000 --force", + "git checkout master && git branch -D backport/6.x/pr-1000_pr-2000", Object { "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", - "maxBuffer": 104857600, }, - [Function], ], ] `; diff --git a/test/unit/steps/__snapshots__/steps.test.ts.snap b/test/unit/steps/__snapshots__/steps.test.ts.snap new file mode 100644 index 00000000..d939802c --- /dev/null +++ b/test/unit/steps/__snapshots__/steps.test.ts.snap @@ -0,0 +1,421 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`run through steps exec should be called with correct args 1`] = ` +Array [ + Array [ + "git remote rm origin", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], + Array [ + "git remote rm sqren", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], + Array [ + "git remote add sqren https://myAccessToken@github.com/sqren/kibana.git", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], + Array [ + "git remote rm elastic", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], + Array [ + "git remote add elastic https://myAccessToken@github.com/elastic/kibana.git", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], + Array [ + "git reset --hard && git clean -d --force && git fetch elastic 6.x && git checkout -B backport/6.x/commit-2e63475c elastic/6.x --no-track", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], + Array [ + "git fetch elastic master:master --force && git cherry-pick 2e63475c483f7844b0f2833bc57fdee32095bacb", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], + Array [ + "git push sqren backport/6.x/commit-2e63475c:backport/6.x/commit-2e63475c --force", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], + Array [ + "git checkout master && git branch -D backport/6.x/commit-2e63475c", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic/kibana", + }, + ], +] +`; + +exports[`run through steps git clone should be called with correct args 1`] = ` +Array [ + Array [ + "git clone https://myAccessToken@github.com/elastic/kibana.git --progress", + Object { + "cwd": "/myHomeDir/.backport/repositories/elastic", + "maxBuffer": 104857600, + }, + [Function], + ], +] +`; + +exports[`run through steps prompt calls should match snapshot 1`] = ` +Array [ + Array [ + Array [ + Object { + "choices": Array [ + Object { + "name": "1. Add 👻 (2e63475c) ", + "short": "2e63475c", + "value": Object { + "existingBackports": Array [], + "message": "Add 👻 (2e63475c)", + "pullNumber": undefined, + "sha": "2e63475c483f7844b0f2833bc57fdee32095bacb", + }, + }, + Object { + "name": "2. Add witch (#85) ", + "short": "#85", + "value": Object { + "existingBackports": Array [], + "message": "Add witch (#85)", + "pullNumber": 85, + "sha": "f3b618b9421fdecdb36862f907afbdd6344b361d", + }, + }, + Object { + "name": "3. Add SF mention (#80) 6.3", + "short": "#80", + "value": Object { + "existingBackports": Array [ + Object { + "branch": "6.3", + "state": "MERGED", + }, + ], + "message": "Add SF mention (#80)", + "pullNumber": 80, + "sha": "79cf18453ec32a4677009dcbab1c9c8c73fc14fe", + }, + }, + Object { + "name": "4. Add backport config (3827bbba) ", + "short": "3827bbba", + "value": Object { + "existingBackports": Array [], + "message": "Add backport config (3827bbba)", + "pullNumber": undefined, + "sha": "3827bbbaf39914eda4f02f6940189844375fd097", + }, + }, + Object { + "name": "5. Initial commit (5ea0da55) ", + "short": "5ea0da55", + "value": Object { + "existingBackports": Array [], + "message": "Initial commit (5ea0da55)", + "pullNumber": undefined, + "sha": "5ea0da550ac191029459289d67f99ad7d310812b", + }, + }, + ], + "message": "Select commit to backport", + "name": "promptResult", + "pageSize": 5, + "type": "list", + }, + ], + ], + Array [ + Array [ + Object { + "choices": Array [ + Object { + "name": "6.x", + }, + Object { + "name": "6.0", + }, + Object { + "name": "5.6", + }, + Object { + "name": "5.5", + }, + Object { + "name": "5.4", + }, + ], + "message": "Select branch to backport to", + "name": "promptResult", + "type": "list", + }, + ], + ], +] +`; + +exports[`run through steps should make correct POST requests 1`] = ` +[MockFunction] { + "calls": Array [ + Array [ + "https://api.github.com/graphql", + Object { + "query": " + query getIdByLogin($login: String!) { + user(login: $login) { + id + } + } + ", + "variables": Object { + "login": "sqren", + }, + }, + Object { + "headers": Object { + "Authorization": "bearer myAccessToken", + "Content-Type": "application/json", + }, + }, + ], + Array [ + "https://api.github.com/graphql", + Object { + "query": " + query getCommitsByAuthorQuery( + $repoOwner: String! + $repoName: String! + $commitsCount: Int! + $authorId: ID + ) { + repository(owner: $repoOwner, name: $repoName) { + ref(qualifiedName: \\"master\\") { + target { + ... on Commit { + history(first: $commitsCount, author: { id: $authorId }) { + edges { + node { + oid + message + associatedPullRequests(first: 1) { + edges { + node { + number + timelineItems( + last: 20 + itemTypes: CROSS_REFERENCED_EVENT + ) { + edges { + node { + ... on CrossReferencedEvent { + source { + __typename + ... on PullRequest { + state + baseRefName + commits(first: 20) { + edges { + node { + commit { + message + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + ", + "variables": Object { + "authorId": "sqren_author_id", + "commitsCount": 10, + "repoName": "kibana", + "repoOwner": "elastic", + }, + }, + Object { + "headers": Object { + "Authorization": "bearer myAccessToken", + "Content-Type": "application/json", + }, + }, + ], + Array [ + "https://api.github.com/repos/elastic/kibana/pulls?access_token=myAccessToken", + Object { + "base": "6.x", + "body": "Backports the following commits to 6.x: + - Add 👻 (2e63475c) + +myPrDescription", + "head": "sqren:backport/6.x/commit-2e63475c", + "title": "myPrTitle 6.x Add 👻 (2e63475c)", + }, + ], + ], + "results": Array [ + Object { + "type": "return", + "value": Object { + "data": Object { + "data": Object { + "user": Object { + "id": "sqren_author_id", + }, + }, + }, + }, + }, + Object { + "type": "return", + "value": Object { + "data": Object { + "data": Object { + "repository": Object { + "ref": Object { + "target": Object { + "history": Object { + "edges": Array [ + Object { + "node": Object { + "associatedPullRequests": Object { + "edges": Array [], + }, + "message": "Add 👻", + "oid": "2e63475c483f7844b0f2833bc57fdee32095bacb", + }, + }, + Object { + "node": Object { + "associatedPullRequests": Object { + "edges": Array [ + Object { + "node": Object { + "number": 85, + "timelineItems": Object { + "edges": Array [], + }, + }, + }, + ], + }, + "message": "Add witch (#85)", + "oid": "f3b618b9421fdecdb36862f907afbdd6344b361d", + }, + }, + Object { + "node": Object { + "associatedPullRequests": Object { + "edges": Array [ + Object { + "node": Object { + "number": 80, + "timelineItems": Object { + "edges": Array [ + Object { + "node": Object { + "source": Object { + "__typename": "PullRequest", + "baseRefName": "6.3", + "commits": Object { + "edges": Array [ + Object { + "node": Object { + "commit": Object { + "message": "Add SF mention (#80) + +* Add SF mention + +* Add several emojis!", + }, + }, + }, + ], + }, + "state": "MERGED", + }, + }, + }, + ], + }, + }, + }, + ], + }, + "message": "Add SF mention (#80) + +* Add SF mention + +* Add several emojis!", + "oid": "79cf18453ec32a4677009dcbab1c9c8c73fc14fe", + }, + }, + Object { + "node": Object { + "associatedPullRequests": Object { + "edges": Array [], + }, + "message": "Add backport config", + "oid": "3827bbbaf39914eda4f02f6940189844375fd097", + }, + }, + Object { + "node": Object { + "associatedPullRequests": Object { + "edges": Array [], + }, + "message": "Initial commit", + "oid": "5ea0da550ac191029459289d67f99ad7d310812b", + }, + }, + ], + }, + }, + }, + }, + }, + }, + }, + }, + Object { + "type": "return", + "value": Object { + "data": Object { + "html_url": "pull request url", + "number": 1337, + }, + }, + }, + ], +} +`; diff --git a/test/steps/doBackportVersions.test.ts b/test/unit/steps/doBackportVersions.test.ts similarity index 55% rename from test/steps/doBackportVersions.test.ts rename to test/unit/steps/doBackportVersions.test.ts index 3f682764..434fb48c 100644 --- a/test/steps/doBackportVersions.test.ts +++ b/test/unit/steps/doBackportVersions.test.ts @@ -1,29 +1,25 @@ import axios from 'axios'; -import * as childProcess from 'child_process'; -import { - doBackportVersion, - getReferenceLong -} from '../../src/steps/doBackportVersions'; -import { PromiseReturnType } from '../../src/types/commons'; -import last from 'lodash.last'; -import * as prompts from '../../src/services/prompts'; -import * as logger from '../../src/services/logger'; -import { BackportOptions } from '../../src/options/options'; +import * as logger from '../../../src/services/logger'; +import * as prompts from '../../../src/services/prompts'; +import { BackportOptions } from '../../../src/options/options'; +import { doBackportVersion } from '../../../src/steps/doBackportVersions'; +import { exec } from '../../../src/services/child-process-promisified'; describe('doBackportVersion', () => { - let axiosMockInstance: jest.Mock; + let axiosPostMock: jest.SpyInstance; beforeEach(() => { - axiosMockInstance = jest + axiosPostMock = jest .spyOn(axios, 'post') + // mock: createPullRequest - // @ts-ignore .mockResolvedValueOnce({ data: { number: 1337, html_url: 'myHtmlUrl' } }) + // mock: addLabelsToPullRequest .mockResolvedValueOnce(null); }); @@ -34,11 +30,10 @@ describe('doBackportVersion', () => { describe('when commit has a pull request reference', () => { let execSpy: jest.SpyInstance; - let res: PromiseReturnType; beforeEach(async () => { - execSpy = jest.spyOn(childProcess, 'exec'); + execSpy = (exec as any) as jest.SpyInstance; - res = await doBackportVersion( + await doBackportVersion( { repoOwner: 'elastic', repoName: 'kibana', @@ -52,12 +47,12 @@ describe('doBackportVersion', () => { commits: [ { sha: 'mySha', - message: 'myCommitMessage', + message: 'myCommitMessage (#1000)', pullNumber: 1000 }, { sha: 'mySha2', - message: 'myOtherCommitMessage', + message: 'myOtherCommitMessage (#2000)', pullNumber: 2000 } ], @@ -70,29 +65,33 @@ describe('doBackportVersion', () => { expect(execSpy.mock.calls).toMatchSnapshot(); }); - it('should return correct response', () => { - expect(res).toEqual({ html_url: 'myHtmlUrl', number: 1337 }); - }); + it('should create pull request', () => { + expect(axiosPostMock).toHaveBeenCalledTimes(2); + const [apiEndpoint, payload] = axiosPostMock.mock.calls[0]; + expect(apiEndpoint).toBe( + 'https://api.github.com/repos/elastic/kibana/pulls?access_token=undefined' + ); + expect(payload.title).toBe( + '[6.x] myCommitMessage (#1000) | myOtherCommitMessage (#2000)' + ); + expect(payload.body).toBe( + `Backports the following commits to 6.x: + - myCommitMessage (#1000) + - myOtherCommitMessage (#2000) - it('should create pull request and add labels', () => { - expect(axiosMockInstance).toHaveBeenCalledTimes(2); - expect(axiosMockInstance).toHaveBeenNthCalledWith( - 1, - 'https://api.github.com/repos/elastic/kibana/pulls?access_token=undefined', - { - title: '[6.x] myCommitMessage | myOtherCommitMessage', - body: - 'Backports the following commits to 6.x:\n - myCommitMessage (#1000)\n - myOtherCommitMessage (#2000)\n\nmyPrSuffix', - head: 'sqren:backport/6.x/pr-1000_pr-2000', - base: '6.x' - } +myPrSuffix` ); + expect(payload.head).toBe('sqren:backport/6.x/pr-1000_pr-2000'); + expect(payload.base).toBe('6.x'); + }); + + it('it should add labels', () => { + const [apiEndpoint, labels] = axiosPostMock.mock.calls[1]; - expect(axiosMockInstance).toHaveBeenNthCalledWith( - 2, - 'https://api.github.com/repos/elastic/kibana/issues/1337/labels?access_token=undefined', - ['backport'] + expect(apiEndpoint).toBe( + 'https://api.github.com/repos/elastic/kibana/issues/1337/labels?access_token=undefined' ); + expect(labels).toEqual(['backport']); }); }); @@ -108,31 +107,34 @@ describe('doBackportVersion', () => { apiHostname: 'api.github.com' } as BackportOptions, { - commits: [{ sha: 'mySha', message: 'myCommitMessage' }], + commits: [{ sha: 'mySha', message: 'myCommitMessage (mySha)' }], baseBranch: '6.x' } ); }); - it('should create pull request and add labels', () => { - expect(axiosMockInstance).toHaveBeenCalledTimes(2); - expect(axiosMockInstance).toHaveBeenNthCalledWith( - 1, - 'https://api.github.com/repos/elastic/kibana/pulls?access_token=undefined', - { - title: '[6.x] myCommitMessage', - body: - 'Backports the following commits to 6.x:\n - myCommitMessage (mySha)', - head: 'sqren:backport/6.x/commit-mySha', - base: '6.x' - } + it('should create pull request', () => { + expect(axiosPostMock).toHaveBeenCalledTimes(2); + const [apiEndpoint, payload] = axiosPostMock.mock.calls[0]; + expect(apiEndpoint).toBe( + 'https://api.github.com/repos/elastic/kibana/pulls?access_token=undefined' ); + expect(payload.title).toBe('[6.x] myCommitMessage (mySha)'); + expect(payload.body).toBe( + `Backports the following commits to 6.x: + - myCommitMessage (mySha)` + ); + expect(payload.head).toBe('sqren:backport/6.x/commit-mySha'); + expect(payload.base).toBe('6.x'); + }); + + it('it should add labels', () => { + const [apiEndpoint, labels] = axiosPostMock.mock.calls[1]; - expect(axiosMockInstance).toHaveBeenNthCalledWith( - 2, - 'https://api.github.com/repos/elastic/kibana/issues/1337/labels?access_token=undefined', - ['backport'] + expect(apiEndpoint).toBe( + 'https://api.github.com/repos/elastic/kibana/issues/1337/labels?access_token=undefined' ); + expect(labels).toEqual(['backport']); }); }); @@ -140,21 +142,18 @@ describe('doBackportVersion', () => { function didResolveConflict(didResolve: boolean) { const logSpy = jest.spyOn(logger, 'log'); - const execSpy = jest - .spyOn(childProcess, 'exec') - .mockImplementation((...args: any[]) => { - const [cmd] = args; + const execSpy = ((exec as any) as jest.SpyInstance).mockImplementation( + async (cmd: string) => { if (cmd.includes('git cherry-pick')) { - const e = new Error('as'); + const e = new Error('cherry pick error'); // @ts-ignore e.cmd = cmd; throw e; - } else { - last(args)(); } - return {} as any; - }); + return 'exec suceeded'; + } + ); spyOn(prompts, 'confirmPrompt').and.returnValue(didResolve); @@ -180,7 +179,7 @@ describe('doBackportVersion', () => { const { execSpy, promise } = didResolveConflict(true); await promise; expect(execSpy.mock.calls).toMatchSnapshot(); - expect(axiosMockInstance).toHaveBeenCalledTimes(2); + expect(axiosPostMock).toHaveBeenCalledTimes(2); }); it('and conflicts were not resolved', async () => { @@ -191,40 +190,25 @@ describe('doBackportVersion', () => { expect(logSpy.mock.calls).toMatchInlineSnapshot(` Array [ Array [ - "Backporting mySha to 6.x:", + " + Backporting the following commits to 6.x: + - myCommitMessage + ", ], Array [ "Please resolve conflicts in: /myHomeDir/.backport/repositories/elastic/kibana and when all conflicts have been resolved and staged run:", ], Array [ " - git cherry-pick --continue - ", + git cherry-pick --continue + ", ], ] `); expect(e.message).toEqual('Aborted'); expect(execSpy.mock.calls).toMatchSnapshot(); - expect(axiosMockInstance).toHaveBeenCalledTimes(0); + expect(axiosPostMock).toHaveBeenCalledTimes(0); }); }); }); }); - -describe('getReferenceLong', () => { - it('should return a sha', () => { - expect( - getReferenceLong({ sha: 'mySha1234567', message: 'myMessage' }) - ).toEqual('mySha12'); - }); - - it('should return a pr', () => { - expect( - getReferenceLong({ - pullNumber: 1337, - sha: 'mySha1234567', - message: 'myMessage' - }) - ).toEqual('#1337'); - }); -}); diff --git a/test/steps/getBranches.test.ts b/test/unit/steps/getBranches.test.ts similarity index 91% rename from test/steps/getBranches.test.ts rename to test/unit/steps/getBranches.test.ts index 2979cb33..64688ceb 100644 --- a/test/steps/getBranches.test.ts +++ b/test/unit/steps/getBranches.test.ts @@ -1,5 +1,5 @@ -import { getBranches } from '../../src/steps/getBranches'; -import * as prompts from '../../src/services/prompts'; +import * as prompts from '../../../src/services/prompts'; +import { getBranches } from '../../../src/steps/getBranches'; describe('getBranches', () => { let promptSpy: ReturnType; diff --git a/test/steps/getCommits.test.ts b/test/unit/steps/getCommitBySha.test.ts similarity index 75% rename from test/steps/getCommits.test.ts rename to test/unit/steps/getCommitBySha.test.ts index 38fbdded..77f1d953 100644 --- a/test/steps/getCommits.test.ts +++ b/test/unit/steps/getCommitBySha.test.ts @@ -1,19 +1,19 @@ -import { commitMock } from '../mocks/commit'; import axios from 'axios'; -import nock from 'nock'; import httpAdapter from 'axios/lib/adapters/http'; -import { getCommitBySha } from '../../src/steps/getCommits'; -import { BackportOptions } from '../../src/options/options'; +import nock from 'nock'; +import { getCommitBySha } from '../../../src/steps/getCommits'; +import { BackportOptions } from '../../../src/options/options'; +import { commitByShaMock } from '../services/github/mocks/commitByShaMock'; axios.defaults.adapter = httpAdapter; describe('getCommitBySha', () => { - it('should return a single commit', async () => { + it('should return a single commit without PR', async () => { nock('https://api.github.com') .get(`/search/commits`) .query(true) .reply(200, { - items: [commitMock] + items: [commitByShaMock] }); nock('https://api.github.com') @@ -23,14 +23,14 @@ describe('getCommitBySha', () => { items: [] }); - const commits = await getCommitBySha({ + const commit = await getCommitBySha({ repoOwner: 'elastic', repoName: 'kibana', sha: 'myCommitSha', apiHostname: 'api.github.com' } as BackportOptions & { sha: string }); - expect(commits).toEqual({ - message: '[Chrome] Bootstrap Angular into document.body (#15158)', + expect(commit).toEqual({ + message: '[Chrome] Bootstrap Angular into document.body (myCommit)', sha: 'myCommitSha', pullNumber: undefined }); @@ -51,7 +51,7 @@ describe('getCommitBySha', () => { sha: 'myCommitSha', apiHostname: 'api.github.com' } as BackportOptions & { sha: string }) - ).rejects.toThrowError('No commit found for SHA: myCommitSha'); + ).rejects.toThrowError('No commit found on master with sha "myCommitSha"'); }); it('should add PR number if available', async () => { @@ -59,7 +59,7 @@ describe('getCommitBySha', () => { .get(`/search/commits`) .query(true) .reply(200, { - items: [commitMock] + items: [commitByShaMock] }); nock('https://api.github.com') @@ -77,7 +77,7 @@ describe('getCommitBySha', () => { apiHostname: 'api.github.com' } as BackportOptions & { sha: string }) ).toEqual({ - message: '[Chrome] Bootstrap Angular into document.body (#15158)', + message: '[Chrome] Bootstrap Angular into document.body (#1338)', pullNumber: 1338, sha: 'myCommitSha' }); diff --git a/test/unit/steps/maybeSetupRepo.test.ts b/test/unit/steps/maybeSetupRepo.test.ts new file mode 100644 index 00000000..ca5d6bce --- /dev/null +++ b/test/unit/steps/maybeSetupRepo.test.ts @@ -0,0 +1,28 @@ +import del from 'del'; +import { BackportOptions } from '../../../src/options/options'; +import { maybeSetupRepo } from '../../../src/steps/maybeSetupRepo'; +import makeDir = require('make-dir'); + +describe('maybeSetupRepo', () => { + it('should delete repo if an error occurs', async () => { + expect.assertions(2); + ((makeDir as any) as jest.Mock).mockImplementationOnce(() => { + throw new Error('makeDir failed'); + }); + + try { + await maybeSetupRepo({ + repoOwner: 'elastic', + repoName: 'kibana', + username: 'sqren', + accessToken: 'myAccessToken', + gitHostname: 'github.com' + } as BackportOptions); + } catch (e) { + expect(e.message).toBe('makeDir failed'); + expect(del).toHaveBeenCalledWith( + '/myHomeDir/.backport/repositories/elastic/kibana' + ); + } + }); +}); diff --git a/test/unit/steps/steps.test.ts b/test/unit/steps/steps.test.ts new file mode 100644 index 00000000..cf448b42 --- /dev/null +++ b/test/unit/steps/steps.test.ts @@ -0,0 +1,155 @@ +import axios from 'axios'; +import inquirer from 'inquirer'; +import * as createPullRequest from '../../../src/services/github/createPullRequest'; +import * as fetchCommitsByAuthor from '../../../src/services/github/fetchCommitsByAuthor'; +import * as fs from '../../../src/services/fs-promisified'; +import { BackportOptions } from '../../../src/options/options'; +import { commitsWithPullRequestsMock } from '../services/github/mocks/commitsByAuthorMock'; +import { initSteps } from '../../../src/steps/steps'; +import * as childProcess from '../../../src/services/child-process-promisified'; + +describe('run through steps', () => { + let rpcExecMock: jest.SpyInstance; + let rpcExecOriginalMock: jest.SpyInstance; + let inquirerPromptMock: jest.SpyInstance; + let axiosHeadSpy: jest.SpyInstance; + let axiosPostSpy: jest.SpyInstance; + + afterEach(() => { + jest.clearAllMocks(); + }); + + beforeEach(async () => { + const options: BackportOptions = { + accessToken: 'myAccessToken', + all: false, + apiHostname: 'api.github.com', + author: 'sqren', + branches: [], + branchChoices: [ + { name: '6.x' }, + { name: '6.0' }, + { name: '5.6' }, + { name: '5.5' }, + { name: '5.4' } + ], + commitsCount: 10, + gitHostname: 'github.com', + labels: [], + multiple: false, + multipleBranches: false, + multipleCommits: false, + prDescription: 'myPrDescription', + prTitle: 'myPrTitle {baseBranch} {commitMessages}', + repoName: 'kibana', + repoOwner: 'elastic', + sha: undefined, + username: 'sqren' + }; + + rpcExecMock = (childProcess.exec as any) as jest.SpyInstance; + rpcExecOriginalMock = (childProcess.execAsCallback as any) as jest.SpyInstance; + + jest.spyOn(fs, 'writeFile').mockResolvedValue(undefined); + + jest.spyOn(fetchCommitsByAuthor, 'fetchCommitsByAuthor'); + jest.spyOn(createPullRequest, 'createPullRequest'); + + inquirerPromptMock = jest + .spyOn(inquirer, 'prompt') + // @ts-ignore + .mockImplementationOnce(async (args: any) => { + return { promptResult: args[0].choices[0].value }; + }) + .mockImplementationOnce(async (args: any) => { + return { promptResult: args[0].choices[0].name }; + }); + + // mock verifyAccessToken + axiosHeadSpy = jest.spyOn(axios, 'head').mockReturnValueOnce(true as any); + + // mock axios post request (graphql) + axiosPostSpy = jest + .spyOn(axios, 'post') + + // mock author id + .mockReturnValueOnce({ + data: { + data: { + user: { + id: 'sqren_author_id' + } + } + } + } as any) + + // mock list of commits + .mockReturnValueOnce({ + data: { + data: commitsWithPullRequestsMock + } + } as any) + + // mock create pull request + .mockReturnValueOnce({ + data: { + html_url: 'pull request url', + number: 1337 + } + } as any); + + await initSteps(options); + }); + + it('should check whether access token is valid', () => { + expect(axiosHeadSpy).toHaveBeenCalledWith( + 'https://api.github.com/repos/elastic/kibana?access_token=myAccessToken' + ); + }); + + it('should make correct POST requests', () => { + expect(axiosPostSpy).toMatchSnapshot(); + }); + + it('getCommit should be called with correct args', () => { + expect(fetchCommitsByAuthor.fetchCommitsByAuthor).toHaveBeenCalledWith( + expect.objectContaining({ + repoName: 'kibana', + repoOwner: 'elastic', + username: 'sqren', + apiHostname: 'api.github.com' + }) + ); + }); + + it('createPullRequest should be called with correct args', () => { + expect(createPullRequest.createPullRequest).toHaveBeenCalledWith( + expect.objectContaining({ + repoName: 'kibana', + repoOwner: 'elastic', + apiHostname: 'api.github.com' + }), + { + base: '6.x', + body: `Backports the following commits to 6.x:\n - Add 👻 (2e63475c)\n\nmyPrDescription`, + head: 'sqren:backport/6.x/commit-2e63475c', + title: 'myPrTitle 6.x Add 👻 (2e63475c)' + } + ); + }); + + it('prompt calls should match snapshot', () => { + expect(inquirer.prompt).toHaveBeenCalledTimes(2); + expect(inquirerPromptMock.mock.calls).toMatchSnapshot(); + }); + + it('exec should be called with correct args', () => { + expect(rpcExecMock).toHaveBeenCalledTimes(9); + expect(rpcExecMock.mock.calls).toMatchSnapshot(); + }); + + it('git clone should be called with correct args', () => { + expect(rpcExecOriginalMock).toHaveBeenCalledTimes(1); + expect(rpcExecOriginalMock.mock.calls).toMatchSnapshot(); + }); +}); diff --git a/yarn.lock b/yarn.lock index 91584725..2e3e6489 100644 --- a/yarn.lock +++ b/yarn.lock @@ -97,13 +97,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.0.0" -"@babel/runtime@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0.tgz#adeb78fedfc855aa05bc041640f3f6f98e85424c" - integrity sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA== - dependencies: - regenerator-runtime "^0.12.0" - "@babel/template@^7.0.0", "@babel/template@^7.1.0", "@babel/template@^7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.4.0.tgz#12474e9c077bae585c5d835a95c0b0b790c25c8b" @@ -154,32 +147,32 @@ chalk "^2.0.1" slash "^2.0.0" -"@jest/core@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.7.1.tgz#6707f50db238d0c5988860680e2e414df0032024" - integrity sha512-ivlZ8HX/FOASfHcb5DJpSPFps8ydfUYzLZfgFFqjkLijYysnIEOieg72YRhO4ZUB32xu40hsSMmaw+IGYeKONA== +"@jest/core@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.8.0.tgz#fbbdcd42a41d0d39cddbc9f520c8bab0c33eed5b" + integrity sha512-R9rhAJwCBQzaRnrRgAdVfnglUuATXdwTRsYqs6NMdVcAl5euG8LtWDe+fVkN27YfKVBW61IojVsXKaOmSnqd/A== dependencies: "@jest/console" "^24.7.1" - "@jest/reporters" "^24.7.1" - "@jest/test-result" "^24.7.1" - "@jest/transform" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/reporters" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" ansi-escapes "^3.0.0" chalk "^2.0.1" exit "^0.1.2" graceful-fs "^4.1.15" - jest-changed-files "^24.7.0" - jest-config "^24.7.1" - jest-haste-map "^24.7.1" - jest-message-util "^24.7.1" + jest-changed-files "^24.8.0" + jest-config "^24.8.0" + jest-haste-map "^24.8.0" + jest-message-util "^24.8.0" jest-regex-util "^24.3.0" - jest-resolve-dependencies "^24.7.1" - jest-runner "^24.7.1" - jest-runtime "^24.7.1" - jest-snapshot "^24.7.1" - jest-util "^24.7.1" - jest-validate "^24.7.0" - jest-watcher "^24.7.1" + jest-resolve-dependencies "^24.8.0" + jest-runner "^24.8.0" + jest-runtime "^24.8.0" + jest-snapshot "^24.8.0" + jest-util "^24.8.0" + jest-validate "^24.8.0" + jest-watcher "^24.8.0" micromatch "^3.1.10" p-each-series "^1.0.0" pirates "^4.0.1" @@ -187,45 +180,46 @@ rimraf "^2.5.4" strip-ansi "^5.0.0" -"@jest/environment@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.7.1.tgz#9b9196bc737561f67ac07817d4c5ece772e33135" - integrity sha512-wmcTTYc4/KqA+U5h1zQd5FXXynfa7VGP2NfF+c6QeGJ7c+2nStgh65RQWNX62SC716dTtqheTRrZl0j+54oGHw== - dependencies: - "@jest/fake-timers" "^24.7.1" - "@jest/transform" "^24.7.1" - "@jest/types" "^24.7.0" - jest-mock "^24.7.0" - -"@jest/fake-timers@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.7.1.tgz#56e5d09bdec09ee81050eaff2794b26c71d19db2" - integrity sha512-4vSQJDKfR2jScOe12L9282uiwuwQv9Lk7mgrCSZHA9evB9efB/qx8i0KJxsAKtp8fgJYBJdYY7ZU6u3F4/pyjA== - dependencies: - "@jest/types" "^24.7.0" - jest-message-util "^24.7.1" - jest-mock "^24.7.0" - -"@jest/reporters@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.7.1.tgz#38ac0b096cd691bbbe3051ddc25988d42e37773a" - integrity sha512-bO+WYNwHLNhrjB9EbPL4kX/mCCG4ZhhfWmO3m4FSpbgr7N83MFejayz30kKjgqr7smLyeaRFCBQMbXpUgnhAJw== - dependencies: - "@jest/environment" "^24.7.1" - "@jest/test-result" "^24.7.1" - "@jest/transform" "^24.7.1" - "@jest/types" "^24.7.0" +"@jest/environment@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.8.0.tgz#0342261383c776bdd652168f68065ef144af0eac" + integrity sha512-vlGt2HLg7qM+vtBrSkjDxk9K0YtRBi7HfRFaDxoRtyi+DyVChzhF20duvpdAnKVBV6W5tym8jm0U9EfXbDk1tw== + dependencies: + "@jest/fake-timers" "^24.8.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" + jest-mock "^24.8.0" + +"@jest/fake-timers@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.8.0.tgz#2e5b80a4f78f284bcb4bd5714b8e10dd36a8d3d1" + integrity sha512-2M4d5MufVXwi6VzZhJ9f5S/wU4ud2ck0kxPof1Iz3zWx6Y+V2eJrES9jEktB6O3o/oEyk+il/uNu9PvASjWXQw== + dependencies: + "@jest/types" "^24.8.0" + jest-message-util "^24.8.0" + jest-mock "^24.8.0" + +"@jest/reporters@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.8.0.tgz#075169cd029bddec54b8f2c0fc489fd0b9e05729" + integrity sha512-eZ9TyUYpyIIXfYCrw0UHUWUvE35vx5I92HGMgS93Pv7du+GHIzl+/vh8Qj9MCWFK/4TqyttVBPakWMOfZRIfxw== + dependencies: + "@jest/environment" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.2" - istanbul-api "^2.1.1" istanbul-lib-coverage "^2.0.2" istanbul-lib-instrument "^3.0.1" + istanbul-lib-report "^2.0.4" istanbul-lib-source-maps "^3.0.1" - jest-haste-map "^24.7.1" - jest-resolve "^24.7.1" - jest-runtime "^24.7.1" - jest-util "^24.7.1" + istanbul-reports "^2.1.1" + jest-haste-map "^24.8.0" + jest-resolve "^24.8.0" + jest-runtime "^24.8.0" + jest-util "^24.8.0" jest-worker "^24.6.0" node-notifier "^5.2.1" slash "^2.0.0" @@ -241,54 +235,76 @@ graceful-fs "^4.1.15" source-map "^0.6.0" -"@jest/test-result@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.7.1.tgz#19eacdb29a114300aed24db651e5d975f08b6bbe" - integrity sha512-3U7wITxstdEc2HMfBX7Yx3JZgiNBubwDqQMh+BXmZXHa3G13YWF3p6cK+5g0hGkN3iufg/vGPl3hLxQXD74Npg== +"@jest/test-result@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.8.0.tgz#7675d0aaf9d2484caa65e048d9b467d160f8e9d3" + integrity sha512-+YdLlxwizlfqkFDh7Mc7ONPQAhA4YylU1s529vVM1rsf67vGZH/2GGm5uO8QzPeVyaVMobCQ7FTxl38QrKRlng== dependencies: "@jest/console" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" "@types/istanbul-lib-coverage" "^2.0.0" -"@jest/test-sequencer@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.7.1.tgz#9c18e428e1ad945fa74f6233a9d35745ca0e63e0" - integrity sha512-84HQkCpVZI/G1zq53gHJvSmhUer4aMYp9tTaffW28Ih5OxfCg8hGr3nTSbL1OhVDRrFZwvF+/R9gY6JRkDUpUA== +"@jest/test-sequencer@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.8.0.tgz#2f993bcf6ef5eb4e65e8233a95a3320248cf994b" + integrity sha512-OzL/2yHyPdCHXEzhoBuq37CE99nkme15eHkAzXRVqthreWZamEMA0WoetwstsQBCXABhczpK03JNbc4L01vvLg== dependencies: - "@jest/test-result" "^24.7.1" - jest-haste-map "^24.7.1" - jest-runner "^24.7.1" - jest-runtime "^24.7.1" + "@jest/test-result" "^24.8.0" + jest-haste-map "^24.8.0" + jest-runner "^24.8.0" + jest-runtime "^24.8.0" -"@jest/transform@^24.7.1": - version "24.7.1" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.7.1.tgz#872318f125bcfab2de11f53b465ab1aa780789c2" - integrity sha512-EsOUqP9ULuJ66IkZQhI5LufCHlTbi7hrcllRMUEV/tOgqBVQi93+9qEvkX0n8mYpVXQ8VjwmICeRgg58mrtIEw== +"@jest/transform@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.8.0.tgz#628fb99dce4f9d254c6fd9341e3eea262e06fef5" + integrity sha512-xBMfFUP7TortCs0O+Xtez2W7Zu1PLH9bvJgtraN1CDST6LBM/eTOZ9SfwS/lvV8yOfcDpFmwf9bq5cYbXvqsvA== dependencies: "@babel/core" "^7.1.0" - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" babel-plugin-istanbul "^5.1.0" chalk "^2.0.1" convert-source-map "^1.4.0" fast-json-stable-stringify "^2.0.0" graceful-fs "^4.1.15" - jest-haste-map "^24.7.1" + jest-haste-map "^24.8.0" jest-regex-util "^24.3.0" - jest-util "^24.7.1" + jest-util "^24.8.0" micromatch "^3.1.10" realpath-native "^1.1.0" slash "^2.0.0" source-map "^0.6.1" write-file-atomic "2.4.1" -"@jest/types@^24.7.0": - version "24.7.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.7.0.tgz#c4ec8d1828cdf23234d9b4ee31f5482a3f04f48b" - integrity sha512-ipJUa2rFWiKoBqMKP63Myb6h9+iT3FHRTF2M8OR6irxWzItisa8i4dcSg14IbvmXUnBlHBlUQPYUHWyX3UPpYA== +"@jest/types@^24.8.0": + version "24.8.0" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.8.0.tgz#f31e25948c58f0abd8c845ae26fcea1491dea7ad" + integrity sha512-g17UxVr2YfBtaMUxn9u/4+siG1ptg9IGYAYwvpwn61nBg779RXnjE/m7CxYcIzEt0AbHZZAHSEZNhkE2WxURVg== dependencies: "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^1.1.1" "@types/yargs" "^12.0.9" +"@nodelib/fs.scandir@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.1.tgz#7fa8fed654939e1a39753d286b48b4836d00e0eb" + integrity sha512-NT/skIZjgotDSiXs0WqYhgcuBKhUMgfekCmCGtkUAiLqZdOnrdjmZr9wRl3ll64J9NF79uZ4fk16Dx0yMc/Xbg== + dependencies: + "@nodelib/fs.stat" "2.0.1" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.1", "@nodelib/fs.stat@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.1.tgz#814f71b1167390cfcb6a6b3d9cdeb0951a192c14" + integrity sha512-+RqhBlLn6YRBGOIoVYthsG0J9dfpO79eJyN7BYBkZJtfqrBwf2KK+rD/M/yjZR6WBmIhAgOV7S60eCgaSWtbFw== + +"@nodelib/fs.walk@^1.2.1": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.2.tgz#6a6450c5e17012abd81450eb74949a4d970d2807" + integrity sha512-J/DR3+W12uCzAJkw7niXDcqcKBg6+5G5Q/ZpThpGNzAUz70eOR6RV4XnnSN01qHZiVl0eavoxJsBypQoKsV2QQ== + dependencies: + "@nodelib/fs.scandir" "2.1.1" + fastq "^1.6.0" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" @@ -328,48 +344,78 @@ dependencies: "@babel/types" "^7.3.0" -"@types/core-js@^2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.0.tgz#35cc282488de6f10af1d92902899a3b8ca3fbc47" +"@types/core-js@^2.5.2": + version "2.5.2" + resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.2.tgz#d4c25420044d4a5b65e00a82fc04b7824b62691f" + integrity sha512-+NPqjXgyA02xTHKJDeDca9u8Zr42ts6jhdND4C3PrPeQ35RJa0dmfAedXW7a9K4N1QcBbuWI1nSfGK4r1eVFCQ== + +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== "@types/events@*": version "1.2.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" -"@types/find-up@^2.1.1": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@types/find-up/-/find-up-2.1.1.tgz#1cd2d240f1ad1f48d32346074724dc3107248a11" +"@types/find-up@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/find-up/-/find-up-4.0.0.tgz#6b74a76670477a23f0793cfaf2dafc86df59723a" + integrity sha512-QlRNKeOPFWKisbNtKVOOGXw3AeLbkw8UmT/EyEGM6brfqpYffKBcch7f1y40NYN9O90aK2+K0xBMDJfOAsg2qg== + dependencies: + find-up "*" -"@types/glob@*": - version "5.0.35" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-5.0.35.tgz#1ae151c802cece940443b5ac246925c85189f32a" +"@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== dependencies: "@types/events" "*" "@types/minimatch" "*" "@types/node" "*" -"@types/inquirer@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-6.0.0.tgz#bbf3c915f9266e30adf78fc2f3df72f205287aca" - integrity sha512-4evhNF+xgdnXNBKouwlZl4JW7uhv9t6JSCOOEg1s61T4QP+UbvyGWTSxj2SjAXz61ZvohJkepHU6p8KzHAClbg== +"@types/inquirer@^6.0.3": + version "6.0.3" + resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-6.0.3.tgz#597b3c1aa4a575899841ab99bb4f1774d0b8c090" + integrity sha512-lBsdZScFMaFYYIE3Y6CWX22B9VeY2NerT1kyU2heTc3u/W6a+Om6Au2q0rMzBrzynN0l4QoABhI0cbNdyz6fDg== dependencies: "@types/through" "*" - rxjs ">=6.4.0" + rxjs "^6.4.0" + +"@types/istanbul-lib-coverage@*": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" + integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== "@types/istanbul-lib-coverage@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.0.tgz#1eb8c033e98cf4e1a4cedcaf8bcafe8cb7591e85" integrity sha512-eAtOAFZefEnfJiRFQBGw1eYqa5GTLCZ1y86N0XSI/D6EB+E8z6VPV/UL7Gi5UEclFqoQk+6NRqEDsfmDLXn8sg== +"@types/istanbul-lib-report@*": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c" + integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" + integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA== + dependencies: + "@types/istanbul-lib-coverage" "*" + "@types/istanbul-lib-report" "*" + "@types/jest-diff@*": version "20.0.1" resolved "https://registry.yarnpkg.com/@types/jest-diff/-/jest-diff-20.0.1.tgz#35cc15b9c4f30a18ef21852e255fdb02f6d59b89" integrity sha512-yALhelO3i0hqZwhjtcr6dYyaLoCHbAMshwtj6cGxTvHZAKXHsYGdff6E8EPw3xLKY0ELUTQ69Q1rQiJENnccMA== -"@types/jest@^24.0.11": - version "24.0.11" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.11.tgz#1f099bea332c228ea6505a88159bfa86a5858340" - integrity sha512-2kLuPC5FDnWIDvaJBzsGTBQaBbnDweznicvK7UGYzlIJP4RJR2a4A/ByLUXEyEgag6jz8eHdlWExGDtH3EYUXQ== +"@types/jest@^24.0.15": + version "24.0.15" + resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.15.tgz#6c42d5af7fe3b44ffff7cc65de7bf741e8fa427f" + integrity sha512-MU1HIvWUme74stAoc3mgAi+aMlgKOudgEvQDIm1v4RkrDudBh1T+NFp5sftpBAdXdx1J0PbdpJ+M2EsSOi1djA== dependencies: "@types/jest-diff" "*" @@ -416,16 +462,10 @@ version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" -"@types/mkdirp@^0.5.2": - version "0.5.2" - resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" - dependencies: - "@types/node" "*" - -"@types/nock@^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/@types/nock/-/nock-10.0.0.tgz#08584a37447e61bfbe641a08c7d15310a08febd4" - integrity sha512-DJM4sOEUeGzqjDkMtCubuN8zQ9gUxzPC+WVMzK2X4q6Kc5pnRFWcm8gkk4JNsDs7Zs6jjVf+dNYbNOii8fzPLA== +"@types/nock@^10.0.3": + version "10.0.3" + resolved "https://registry.yarnpkg.com/@types/nock/-/nock-10.0.3.tgz#dab1d18ffbccfbf2db811dab9584304eeb6e1c4c" + integrity sha512-OthuN+2FuzfZO3yONJ/QVjKmLEuRagS9TV9lEId+WHL9KhftYG+/2z+pxlr0UgVVXSpVD8woie/3fzQn8ft/Ow== dependencies: "@types/node" "*" @@ -443,21 +483,17 @@ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== -"@types/rimraf@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-2.0.2.tgz#7f0fc3cf0ff0ad2a99bb723ae1764f30acaf8b6e" - dependencies: - "@types/glob" "*" - "@types/node" "*" - "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== -"@types/strip-json-comments@^0.0.30": - version "0.0.30" - resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" +"@types/strip-json-comments@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-3.0.0.tgz#b1101c0a14305b589b271535a6a5ed7a5c2ed180" + integrity sha512-+vSlZeCCGm/1Q3WwBJDUSGHvADTQjRl4Fve0AG9H+A4+xgJ7yAkWKoc4g7I9UoVqtwCzjv2g/GZn4xipokMYyQ== + dependencies: + strip-json-comments "*" "@types/through@*": version "0.0.29" @@ -482,31 +518,39 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.7.0.tgz#570e45dc84fb97852e363f1e00f47e604a0b8bcc" - integrity sha512-NUSz1aTlIzzTjFFVFyzrbo8oFjHg3K/M9MzYByqbMCxeFdErhLAcGITVfXzSz+Yvp5OOpMu3HkIttB0NyKl54Q== +"@typescript-eslint/eslint-plugin@^1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-1.12.0.tgz#96b4e08b5f998a198b8414508b1a289f9e8c549a" + integrity sha512-J/ZTZF+pLNqjXBGNfq5fahsoJ4vJOkYbitWPavA05IrZ7BXUaf4XWlhUB/ic1lpOGTRpLWF+PLAePjiHp6dz8g== dependencies: - "@typescript-eslint/parser" "1.7.0" - "@typescript-eslint/typescript-estree" "1.7.0" + "@typescript-eslint/experimental-utils" "1.12.0" eslint-utils "^1.3.1" + functional-red-black-tree "^1.0.1" regexpp "^2.0.1" - requireindex "^1.2.0" tsutils "^3.7.0" -"@typescript-eslint/parser@1.7.0", "@typescript-eslint/parser@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.7.0.tgz#c3ea0d158349ceefbb6da95b5b09924b75357851" - integrity sha512-1QFKxs2V940372srm12ovSE683afqc1jB6zF/f8iKhgLz1yoSjYeGHipasao33VXKI+0a/ob9okeogGdKGvvlg== +"@typescript-eslint/experimental-utils@1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-1.12.0.tgz#98417ee2e0c6fe8d1e50d934a6535d9c0f4277b6" + integrity sha512-s0soOTMJloytr9GbPteMLNiO2HvJ+qgQkRNplABXiVw6vq7uQRvidkby64Gqt/nA7pys74HksHwRULaB/QRVyw== dependencies: - "@typescript-eslint/typescript-estree" "1.7.0" + "@typescript-eslint/typescript-estree" "1.12.0" eslint-scope "^4.0.0" + +"@typescript-eslint/parser@^1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-1.12.0.tgz#9965895ec4745578185965d63f21510f93a3f35a" + integrity sha512-0uzbaa9ZLCA5yMWJywnJJ7YVENKGWVUhJDV5UrMoldC5HoI54W5kkdPhTfmtFKpPFp93MIwmJj0/61ztvmz5Dw== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "1.12.0" + "@typescript-eslint/typescript-estree" "1.12.0" eslint-visitor-keys "^1.0.0" -"@typescript-eslint/typescript-estree@1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.7.0.tgz#59ec02f5371964da1cc679dba7b878a417bc8c60" - integrity sha512-K5uedUxVmlYrVkFbyV3htDipvLqTE3QMOUQEHYJaKtgzxj6r7c5Ca/DG1tGgFxX+fsbi9nDIrf4arq7Ib7H/Yw== +"@typescript-eslint/typescript-estree@1.12.0": + version "1.12.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-1.12.0.tgz#d8dd0a7cffb5e3c0c3e98714042d83e316dfc9a9" + integrity sha512-nwN6yy//XcVhFs0ZyU+teJHB8tbCm7AIA8mu6E2r5hu6MajwYBY3Uwop7+rPZWUN/IUOHpL8C+iUPMDVYUU3og== dependencies: lodash.unescape "4.0.1" semver "5.5.0" @@ -557,7 +601,7 @@ ajv@^5.3.0: fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" -ajv@^6.9.1: +ajv@^6.10.0, ajv@^6.9.1: version "6.10.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1" integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg== @@ -610,13 +654,6 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" -append-transform@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-1.0.0.tgz#046a52ae582a228bd72f58acfbe2967c678759ab" - integrity sha512-P009oYkeHyU742iSZJzZZywj4QRJdnTWffaKuJQLablCZ1uz6/cW4yaRgcDaoQ+uwOxxnt0gRUcwfsNP2ri0gw== - dependencies: - default-require-extensions "^2.0.0" - aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -656,12 +693,25 @@ array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" +array-includes@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + array-union@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -700,13 +750,6 @@ async-limiter@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" -async@^2.6.1: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -723,27 +766,21 @@ aws4@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" -axios-mock-adapter@^1.16.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/axios-mock-adapter/-/axios-mock-adapter-1.16.0.tgz#cdd55bb60d8cb3fcd77fdb9cbb269e47b8b95180" - integrity sha512-m2D8ngMTQ5p4zZNBsPKoENgwz5rDfd0pZmXI/spdE2eeeKIcR3jquk+NRiBVFtb9UJlciBYplNzSUmgQ6X385Q== +axios@^0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.0.tgz#8e09bff3d9122e133f7b8101c8fbdd00ed3d2ab8" + integrity sha512-1uvKqKQta3KBxIz14F2v06AEHZ/dIoeKfbTRkK1E5oqjDnuEerLmYTgJB5AiQZHJcljpg1TuRzdjDR06qNk0DQ== dependencies: - deep-equal "^1.0.1" + follow-redirects "1.5.10" + is-buffer "^2.0.2" -axios@^0.18.0: - version "0.18.0" - resolved "http://registry.npmjs.org/axios/-/axios-0.18.0.tgz#32d53e4851efdc0a11993b6cd000789d70c05102" +babel-jest@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.8.0.tgz#5c15ff2b28e20b0f45df43fe6b7f2aae93dba589" + integrity sha512-+5/kaZt4I9efoXzPlZASyK/lN9qdRKmmUav9smVc0ruPQD7IsfucQ87gpOE8mn2jbDuS6M/YOW6n3v9ZoIfgnw== dependencies: - follow-redirects "^1.3.0" - is-buffer "^1.1.5" - -babel-jest@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.7.1.tgz#73902c9ff15a7dfbdc9994b0b17fcefd96042178" - integrity sha512-GPnLqfk8Mtt0i4OemjWkChi73A3ALs4w2/QbG64uAj8b5mmwzxc7jbJVRZt8NJkxi6FopVHog9S3xX6UJKb2qg== - dependencies: - "@jest/transform" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" "@types/babel__core" "^7.1.0" babel-plugin-istanbul "^5.1.0" babel-preset-jest "^24.6.0" @@ -818,6 +855,13 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" +braces@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + browser-process-hrtime@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.2.tgz#425d68a58d3447f02a04aa894187fce8af8b7b8e" @@ -927,7 +971,7 @@ chalk@^1.0.0, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.1: +chalk@^2.0.0, chalk@^2.0.1: version "2.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" dependencies: @@ -935,7 +979,7 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.1: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^2.1.0, chalk@^2.4.2: +chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -970,12 +1014,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -cli-cursor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - dependencies: - restore-cursor "^1.0.1" - cli-cursor@^2.0.0, cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -1006,6 +1044,15 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + clone@^1.0.2: version "1.0.4" resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" @@ -1041,20 +1088,11 @@ combined-stream@1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.14.1, commander@^2.9.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" - -commander@~2.20.0: +commander@^2.20.0, commander@~2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== -compare-versions@^3.2.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-3.4.0.tgz#e0747df5c9cb7f054d6d3dc3e1dbc444f9e92b26" - integrity sha512-tK69D7oNXXqUW3ZNo/z7NXTEz22TCF0pTE+YF9cxvaAM9XnkLo1fV621xCLrRR6aevJlKxExkss0vWqUCUpqdg== - component-emitter@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" @@ -1067,6 +1105,11 @@ 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" +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + convert-source-map@^1.1.0, convert-source-map@^1.4.0: version "1.6.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" @@ -1081,22 +1124,14 @@ 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" -cosmiconfig@^5.0.2: - version "5.0.6" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" - dependencies: - is-directory "^0.3.1" - js-yaml "^3.9.0" - parse-json "^4.0.0" - -cosmiconfig@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.0.tgz#45038e4d28a7fe787203aede9c25bca4a08b12c8" - integrity sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g== +cosmiconfig@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== dependencies: import-fresh "^2.0.0" is-directory "^0.3.1" - js-yaml "^3.13.0" + js-yaml "^3.13.1" parse-json "^4.0.0" cross-spawn@^6.0.0, cross-spawn@^6.0.5: @@ -1143,18 +1178,12 @@ debug@=3.1.0: dependencies: ms "2.0.0" -debug@^2.1.2, debug@^2.2.0, debug@^2.3.3: +debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" dependencies: ms "2.0.0" -debug@^3.1.0: - version "3.2.5" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.5.tgz#c2418fbfd7a29f4d4f70ff4cea604d4b64c46407" - dependencies: - ms "^2.1.1" - debug@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.0.tgz#373687bffa678b38b1cd91f861b63850035ddc87" @@ -1180,6 +1209,7 @@ decode-uri-component@^0.2.0: dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= deep-eql@^3.0.0: version "3.0.1" @@ -1187,7 +1217,7 @@ deep-eql@^3.0.0: dependencies: type-detect "^4.0.0" -deep-equal@^1.0.0, deep-equal@^1.0.1: +deep-equal@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" @@ -1199,13 +1229,6 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -default-require-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-2.0.0.tgz#f5f8fbb18a7d6d50b21f641f649ebb522cfe24f7" - integrity sha1-9fj7sYp9bVCyH2QfZJ67Uiz+JPc= - dependencies: - strip-bom "^3.0.0" - defaults@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" @@ -1237,16 +1260,29 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -del@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== dependencies: + "@types/glob" "^7.1.1" globby "^6.1.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - p-map "^1.1.1" - pify "^3.0.0" - rimraf "^2.2.8" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" + +del@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/del/-/del-5.0.0.tgz#4fa698b7a1ffb4e2ab3e8929ed699799654d6720" + integrity sha512-TfU3nUY0WDIhN18eq+pgpbLY9AfL5RfiE9czKaTSolc6aK7qASXfDErvYgjV1UqCR4sNXDoxO0/idPmhDUt2Sg== + dependencies: + globby "^10.0.0" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + rimraf "^2.6.3" delayed-stream@~1.0.0: version "1.0.0" @@ -1269,9 +1305,25 @@ diff-sequences@^24.3.0: resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.3.0.tgz#0f20e8a1df1abddaf4d9c226680952e64118b975" integrity sha512-xLqpez+Zj9GKSnPWS0WZw1igGocZ+uua8+y+5dDNTT934N3QuY1sp2LkHzwiaYQGz60hMq0pjAshdeXm5VUOEw== -diff@^3.1.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" +diff@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" + integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" doctrine@^3.0.0: version "3.0.0" @@ -1308,7 +1360,7 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" -error-ex@^1.3.1: +error-ex@^1.2.0, error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" dependencies: @@ -1324,6 +1376,18 @@ es-abstract@^1.5.1: is-callable "^1.1.3" is-regex "^1.0.4" +es-abstract@^1.7.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9" + integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-keys "^1.0.12" + es-to-primitive@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" @@ -1332,7 +1396,16 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.4, escape-string-regexp@^1.0.5: +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -1347,17 +1420,50 @@ escodegen@^1.9.1: optionalDependencies: source-map "~0.6.1" -eslint-config-prettier@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-4.1.0.tgz#181364895899fff9fd3605fecb5c4f20e7d5f395" - integrity sha512-zILwX9/Ocz4SV2vX7ox85AsrAgXV3f2o2gpIicdMIOra48WYqgUnWNH/cR/iHtmD2Vb3dLSC3LiEJnS05Gkw7w== +eslint-config-prettier@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.0.0.tgz#f429a53bde9fc7660e6353910fd996d6284d3c25" + integrity sha512-vDrcCFE3+2ixNT5H83g28bO/uYAwibJxerXPj+E7op4qzBCsAV36QfvdAyVOoNxKAH2Os/e01T/2x++V0LPukA== dependencies: get-stdin "^6.0.0" -eslint-plugin-prettier@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.0.1.tgz#19d521e3981f69dd6d14f64aec8c6a6ac6eb0b0d" - integrity sha512-/PMttrarPAY78PLvV3xfWibMOdMDl57hmlQ2XqFeA37wd+CJ7WSxV7txqjVPHi/AAFKd2lX0ZqfsOc/i5yFCSQ== +eslint-import-resolver-node@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== + dependencies: + debug "^2.6.9" + resolve "^1.5.0" + +eslint-module-utils@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz#8b93499e9b00eab80ccb6614e69f03678e84e09a" + integrity sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw== + dependencies: + debug "^2.6.8" + pkg-dir "^2.0.0" + +eslint-plugin-import@^2.18.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.18.0.tgz#7a5ba8d32622fb35eb9c8db195c2090bd18a3678" + integrity sha512-PZpAEC4gj/6DEMMoU2Df01C5c50r7zdGIN52Yfi7CvvWaYssG7Jt5R9nFG5gmqodxNOz9vQS87xk6Izdtpdrig== + dependencies: + array-includes "^3.0.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.4.0" + has "^1.0.3" + lodash "^4.17.11" + minimatch "^3.0.4" + read-pkg-up "^2.0.0" + resolve "^1.11.0" + +eslint-plugin-prettier@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.0.tgz#8695188f95daa93b0dc54b249347ca3b79c4686d" + integrity sha512-XWX2yVuwVNLOUhQijAkXz+rMPPoCr7WFiAl8ig6I7Xn+pPVhDhzg4DxHpmbeb0iqjO9UronEA3Tb09ChnFVHHA== dependencies: prettier-linter-helpers "^1.0.0" @@ -1379,13 +1485,13 @@ eslint-visitor-keys@^1.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== -eslint@^5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== +eslint@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.0.1.tgz#4a32181d72cb999d6f54151df7d337131f81cda7" + integrity sha512-DyQRaMmORQ+JsWShYsSg4OPTjY56u1nCjAmICrE8vLWqyLKxhFXOthwMj1SA8xwfrv0CofLNVnqbfyhwCkaO0w== dependencies: "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" + ajv "^6.10.0" chalk "^2.1.0" cross-spawn "^6.0.5" debug "^4.0.1" @@ -1393,18 +1499,19 @@ eslint@^5.16.0: eslint-scope "^4.0.3" eslint-utils "^1.3.1" eslint-visitor-keys "^1.0.0" - espree "^5.0.1" + espree "^6.0.0" esquery "^1.0.1" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" - glob "^7.1.2" + glob-parent "^3.1.0" globals "^11.7.0" ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" inquirer "^6.2.2" - js-yaml "^3.13.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" lodash "^4.17.11" @@ -1412,7 +1519,6 @@ eslint@^5.16.0: mkdirp "^0.5.1" natural-compare "^1.4.0" optionator "^0.8.2" - path-is-inside "^1.0.2" progress "^2.0.0" regexpp "^2.0.1" semver "^5.5.1" @@ -1421,10 +1527,10 @@ eslint@^5.16.0: table "^5.2.3" text-table "^0.2.0" -espree@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/espree/-/espree-5.0.1.tgz#5d6526fa4fc7f0788a5cf75b15f30323e2f81f7a" - integrity sha512-qWAZcWh4XE/RwzLJejfcofscgMc9CamR6Tn1+XRXNzrvUSSbiAjGOI/fggztjIi7y9VLPqnICMIPiGyr8JaZ0A== +espree@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.0.0.tgz#716fc1f5a245ef5b9a7fdb1d7b0d3f02322e75f6" + integrity sha512-lJvCS6YbCn3ImT3yKkPe0+tJ+mH6ljhGNjHQH9mRtiO6gjhVAOhVXW1yjnwqGwTkK3bGbye+hb00nFNmu0l/1Q== dependencies: acorn "^6.0.7" acorn-jsx "^5.0.0" @@ -1490,9 +1596,20 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" +execa@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/execa/-/execa-2.0.3.tgz#4b84301b33042cfb622771e886ed0b10e5634642" + integrity sha512-iM124nlyGSrXmuyZF1EMe83ESY2chIYVyDRZKgmcDynid2Q2v/+GuE7gNMl6Sy9Niwf4MC0DDxagOxeMPjuLsw== + dependencies: + cross-spawn "^6.0.5" + get-stream "^5.0.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^3.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" exit@^0.1.2: version "0.1.2" @@ -1510,16 +1627,16 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.7.1.tgz#d91defbab4e627470a152feaf35b3c31aa1c7c14" - integrity sha512-mGfvMTPduksV3xoI0xur56pQsg2vJjNf5+a+bXOjqCkiCBbmCayrBbHS/75y9K430cfqyocPr2ZjiNiRx4SRKw== +expect@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/expect/-/expect-24.8.0.tgz#471f8ec256b7b6129ca2524b2a62f030df38718d" + integrity sha512-/zYvP8iMDrzaaxHVa724eJBCKqSHmO0FA7EDkBiRHxg6OipmMn1fN+C8T9L9K8yr7UONkOifu6+LLH+z76CnaA== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" ansi-styles "^3.2.0" - jest-get-type "^24.3.0" - jest-matcher-utils "^24.7.0" - jest-message-util "^24.7.1" + jest-get-type "^24.8.0" + jest-matcher-utils "^24.8.0" + jest-message-util "^24.8.0" jest-regex-util "^24.3.0" extend-shallow@^2.0.1: @@ -1583,6 +1700,18 @@ fast-diff@^1.1.2: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== +fast-glob@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.0.4.tgz#d484a41005cb6faeb399b951fd1bd70ddaebb602" + integrity sha512-wkIbV6qg37xTJwqSsdnIphL1e+LaGz4AIQqr00mIubMaEhv1/HEmJ0uuCGZRNRUkZZmOB5mJKO0ZUTVq+SxMQg== + dependencies: + "@nodelib/fs.stat" "^2.0.1" + "@nodelib/fs.walk" "^1.2.1" + glob-parent "^5.0.0" + is-glob "^4.0.1" + merge2 "^1.2.3" + micromatch "^4.0.2" + fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" @@ -1591,6 +1720,13 @@ fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + fb-watchman@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.0.tgz#54e9abf7dfa2f26cd9b1636c588c1afc05de5d58" @@ -1617,14 +1753,6 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -fileset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fileset/-/fileset-2.0.3.tgz#8e7548a96d3cc2327ee5e674168723a333bba2a0" - integrity sha1-jnVIqW08wjJ+5eZ0FocjozO7oqA= - dependencies: - glob "^7.0.3" - minimatch "^3.0.3" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -1634,9 +1762,27 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" -find-parent-dir@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/find-parent-dir/-/find-parent-dir-0.3.0.tgz#33c44b429ab2b2f0646299c5f9f718f376ff8d54" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@*, find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" find-up@^3.0.0: version "3.0.0" @@ -1658,14 +1804,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== -fn-name@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-2.0.1.tgz#5214d7537a4d06a4a301c0cc262feb84188002e7" - integrity sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc= - -follow-redirects@^1.3.0: - version "1.5.8" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.8.tgz#1dbfe13e45ad969f813e86c00e5296f525c885a1" +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== dependencies: debug "=3.1.0" @@ -1718,14 +1860,6 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= -g-status@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/g-status/-/g-status-2.0.2.tgz#270fd32119e8fc9496f066fe5fe88e0a6bc78b97" - dependencies: - arrify "^1.0.1" - matcher "^1.0.0" - simple-git "^1.85.0" - gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1752,9 +1886,10 @@ get-func-name@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" -get-own-enumerable-property-symbols@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.0.tgz#b877b49a5c16aefac3655f2ed2ea5b684df8d203" + integrity sha512-CIJYJC4GGF06TakLg8z4GQKvDsx9EMspVxOYih7LerEL/WosUnFIww45CGfxfeKHqlg3twgUrYRT1O3WQqjGCg== get-stdin@^6.0.0: version "6.0.0" @@ -1775,6 +1910,13 @@ get-stream@^4.0.0: dependencies: pump "^3.0.0" +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -1785,6 +1927,21 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.0.0.tgz#1dc99f0f39b006d3e92c2c284068382f0c20e954" + integrity sha512-Z2RwiujPRGluePM6j699ktJYxmPpJKCfpGA13jz2hmFZC7gKetzrWvg5KN3+OsIFmydGyZ1AVwERCq1w/ZZwRg== + dependencies: + is-glob "^4.0.1" + glob@^7.0.3, glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" @@ -1802,6 +1959,20 @@ globals@^11.1.0, globals@^11.7.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" integrity sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw== +globby@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" + integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + globby@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" @@ -1857,6 +2028,11 @@ has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + has-unicode@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" @@ -1888,7 +2064,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1: +has@^1.0.1, has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" dependencies: @@ -1912,21 +2088,21 @@ http-signature@~1.2.0: jsprim "^1.2.2" sshpk "^1.7.0" -husky@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/husky/-/husky-2.0.0.tgz#fdc232f6e44af8257d86602c34105673ce532c79" - integrity sha512-YvSQ5UQHNfqm+g+P1sFTkPI23nEe0gbKXdv5ZTRStYSVdAYyH1iypFilAMVqXLXnjGtb6lBuR/2Sf5FkwCNY2Q== +husky@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/husky/-/husky-3.0.0.tgz#de63821a7049dc412b1afd753c259e2f6e227562" + integrity sha512-lKMEn7bRK+7f5eWPNGclDVciYNQt0GIkAQmhKl+uHP1qFzoN0h92kmH9HZ8PCwyVA2EQPD8KHf0FYWqnTxau+Q== dependencies: - cosmiconfig "^5.2.0" + cosmiconfig "^5.2.1" execa "^1.0.0" - find-up "^3.0.0" get-stdin "^7.0.0" is-ci "^2.0.0" - pkg-dir "^4.1.0" + opencollective-postinstall "^2.0.2" + pkg-dir "^4.2.0" please-upgrade-node "^3.1.1" - read-pkg "^5.0.0" + read-pkg "^5.1.1" run-node "^1.0.0" - slash "^2.0.0" + slash "^3.0.0" iconv-lite@0.4.23: version "0.4.23" @@ -1951,6 +2127,11 @@ ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== +ignore@^5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.2.tgz#e28e584d43ad7e92f96995019cc43b9e1ac49558" + integrity sha512-vdqWBp7MyzdmHkkRWV5nY+PfGRbYbahfuvsBCh277tq+w9zyNi7h5CYJCK0kmzti9kU+O/cB7sE8HvKv6aXAKQ== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" @@ -2017,10 +2198,10 @@ inquirer@^6.2.2: strip-ansi "^5.0.0" through "^2.3.6" -inquirer@^6.3.1: - version "6.3.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" - integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== +inquirer@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42" + integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA== dependencies: ansi-escapes "^3.2.0" chalk "^2.4.2" @@ -2028,7 +2209,7 @@ inquirer@^6.3.1: cli-width "^2.0.0" external-editor "^3.0.3" figures "^2.0.0" - lodash "^4.17.11" + lodash "^4.17.12" mute-stream "0.0.7" run-async "^2.2.0" rxjs "^6.4.0" @@ -2066,13 +2247,18 @@ is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" +is-buffer@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.3.tgz#4ecf3fcf749cbd1e472689e109ac66261a25e725" + integrity sha512-U15Q7MXTuZlrbymiz95PJpZxu8IlipAp4dtS3wOdgPXx3mqBnslrWU14kxfHB+Py/+2PVKSr37dMAgM2A4uArw== + is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" dependencies: builtin-modules "^1.0.0" -is-callable@^1.1.1, is-callable@^1.1.3: +is-callable@^1.1.1, is-callable@^1.1.3, is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" @@ -2129,7 +2315,7 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^2.1.1: +is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -2148,18 +2334,37 @@ is-generator-fn@^2.0.0: resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" dependencies: is-extglob "^2.1.1" +is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-obj@^1.0.1: version "1.0.1" resolved "http://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -2170,21 +2375,24 @@ is-observable@^1.1.0: dependencies: symbol-observable "^1.1.0" -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" +is-path-cwd@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== -is-path-in-cwd@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== dependencies: - is-path-inside "^1.0.0" + is-path-inside "^2.1.0" -is-path-inside@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== dependencies: - path-is-inside "^1.0.1" + path-is-inside "^1.0.2" is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" @@ -2210,10 +2418,22 @@ is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -2222,7 +2442,7 @@ is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" -isarray@1.0.0, isarray@~1.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" @@ -2244,38 +2464,12 @@ isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" -istanbul-api@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/istanbul-api/-/istanbul-api-2.1.1.tgz#194b773f6d9cbc99a9258446848b0f988951c4d0" - integrity sha512-kVmYrehiwyeBAk/wE71tW6emzLiHGjYIiDrc8sfyty4F8M02/lrgXSm+R1kXysmF20zArvmZXjlE/mg24TVPJw== - dependencies: - async "^2.6.1" - compare-versions "^3.2.1" - fileset "^2.0.3" - istanbul-lib-coverage "^2.0.3" - istanbul-lib-hook "^2.0.3" - istanbul-lib-instrument "^3.1.0" - istanbul-lib-report "^2.0.4" - istanbul-lib-source-maps "^3.0.2" - istanbul-reports "^2.1.1" - js-yaml "^3.12.0" - make-dir "^1.3.0" - minimatch "^3.0.4" - once "^1.4.0" - istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#0b891e5ad42312c2b9488554f603795f9a2211ba" integrity sha512-dKWuzRGCs4G+67VfW9pBFFz2Jpi4vSp/k7zBcJ888ofV5Mi1g5CUML5GvMvV6u9Cjybftu+E8Cgp+k0dI1E5lw== -istanbul-lib-hook@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-2.0.3.tgz#e0e581e461c611be5d0e5ef31c5f0109759916fb" - integrity sha512-CLmEqwEhuCYtGcpNVJjLV1DQyVnIqavMLFHV/DP+np/g3qvdxu3gsPqYoJMXm15sN84xOlckFB3VNvRbf5yEgA== - dependencies: - append-transform "^1.0.0" - -istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.1.0: +istanbul-lib-instrument@^3.0.0, istanbul-lib-instrument@^3.0.1: version "3.1.0" resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.1.0.tgz#a2b5484a7d445f1f311e93190813fa56dfb62971" integrity sha512-ooVllVGT38HIk8MxDj/OIHXSYvH+1tq/Vb38s8ixt9GoJadXska4WkGY+0wkmtYCZNYtaARniH/DixUGGLZ0uA== @@ -2297,7 +2491,7 @@ istanbul-lib-report@^2.0.4: make-dir "^1.3.0" supports-color "^6.0.0" -istanbul-lib-source-maps@^3.0.1, istanbul-lib-source-maps@^3.0.2: +istanbul-lib-source-maps@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.2.tgz#f1e817229a9146e8424a28e5d69ba220fda34156" integrity sha512-JX4v0CiKTGp9fZPmoxpu9YEkPbEqCqBbO3403VabKjH+NRXo72HafD5UgnjTEqHL2SAjaZK1XDuDOkn6I5QVfQ== @@ -2315,66 +2509,66 @@ istanbul-reports@^2.1.1: dependencies: handlebars "^4.1.0" -jest-changed-files@^24.7.0: - version "24.7.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.7.0.tgz#39d723a11b16ed7b373ac83adc76a69464b0c4fa" - integrity sha512-33BgewurnwSfJrW7T5/ZAXGE44o7swLslwh8aUckzq2e17/2Os1V0QU506ZNik3hjs8MgnEMKNkcud442NCDTw== +jest-changed-files@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.8.0.tgz#7e7eb21cf687587a85e50f3d249d1327e15b157b" + integrity sha512-qgANC1Yrivsq+UrLXsvJefBKVoCsKB0Hv+mBb6NMjjZ90wwxCDmU3hsCXBya30cH+LnPYjwgcU65i6yJ5Nfuug== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" execa "^1.0.0" throat "^4.0.0" -jest-cli@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.7.1.tgz#6093a539073b6f4953145abeeb9709cd621044f1" - integrity sha512-32OBoSCVPzcTslGFl6yVCMzB2SqX3IrWwZCY5mZYkb0D2WsogmU3eV2o8z7+gRQa4o4sZPX/k7GU+II7CxM6WQ== +jest-cli@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.8.0.tgz#b075ac914492ed114fa338ade7362a301693e989" + integrity sha512-+p6J00jSMPQ116ZLlHJJvdf8wbjNbZdeSX9ptfHX06/MSNaXmKihQzx5vQcw0q2G6JsdVkUIdWbOWtSnaYs3yA== dependencies: - "@jest/core" "^24.7.1" - "@jest/test-result" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/core" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" chalk "^2.0.1" exit "^0.1.2" import-local "^2.0.0" is-ci "^2.0.0" - jest-config "^24.7.1" - jest-util "^24.7.1" - jest-validate "^24.7.0" + jest-config "^24.8.0" + jest-util "^24.8.0" + jest-validate "^24.8.0" prompts "^2.0.1" realpath-native "^1.1.0" yargs "^12.0.2" -jest-config@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.7.1.tgz#6c1dd4db82a89710a3cf66bdba97827c9a1cf052" - integrity sha512-8FlJNLI+X+MU37j7j8RE4DnJkvAghXmBWdArVzypW6WxfGuxiL/CCkzBg0gHtXhD2rxla3IMOSUAHylSKYJ83g== +jest-config@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.8.0.tgz#77db3d265a6f726294687cbbccc36f8a76ee0f4f" + integrity sha512-Czl3Nn2uEzVGsOeaewGWoDPD8GStxCpAe0zOYs2x2l0fZAgPbCr3uwUkgNKV3LwE13VXythM946cd5rdGkkBZw== dependencies: "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^24.7.1" - "@jest/types" "^24.7.0" - babel-jest "^24.7.1" + "@jest/test-sequencer" "^24.8.0" + "@jest/types" "^24.8.0" + babel-jest "^24.8.0" chalk "^2.0.1" glob "^7.1.1" - jest-environment-jsdom "^24.7.1" - jest-environment-node "^24.7.1" - jest-get-type "^24.3.0" - jest-jasmine2 "^24.7.1" + jest-environment-jsdom "^24.8.0" + jest-environment-node "^24.8.0" + jest-get-type "^24.8.0" + jest-jasmine2 "^24.8.0" jest-regex-util "^24.3.0" - jest-resolve "^24.7.1" - jest-util "^24.7.1" - jest-validate "^24.7.0" + jest-resolve "^24.8.0" + jest-util "^24.8.0" + jest-validate "^24.8.0" micromatch "^3.1.10" - pretty-format "^24.7.0" + pretty-format "^24.8.0" realpath-native "^1.1.0" -jest-diff@^24.7.0: - version "24.7.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.7.0.tgz#5d862899be46249754806f66e5729c07fcb3580f" - integrity sha512-ULQZ5B1lWpH70O4xsANC4tf4Ko6RrpwhE3PtG6ERjMg1TiYTC2Wp4IntJVGro6a8HG9luYHhhmF4grF0Pltckg== +jest-diff@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.8.0.tgz#146435e7d1e3ffdf293d53ff97e193f1d1546172" + integrity sha512-wxetCEl49zUpJ/bvUmIFjd/o52J+yWcoc5ZyPq4/W1LUKGEhRYDIbP1KcF6t+PvqNrGAFk4/JhtxDq/Nnzs66g== dependencies: chalk "^2.0.1" diff-sequences "^24.3.0" - jest-get-type "^24.3.0" - pretty-format "^24.7.0" + jest-get-type "^24.8.0" + pretty-format "^24.8.0" jest-docblock@^24.3.0: version "24.3.0" @@ -2383,57 +2577,57 @@ jest-docblock@^24.3.0: dependencies: detect-newline "^2.1.0" -jest-each@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.7.1.tgz#fcc7dda4147c28430ad9fb6dc7211cd17ab54e74" - integrity sha512-4fsS8fEfLa3lfnI1Jw6NxjhyRTgfpuOVTeUZZFyVYqeTa4hPhr2YkToUhouuLTrL2eMGOfpbdMyRx0GQ/VooKA== +jest-each@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.8.0.tgz#a05fd2bf94ddc0b1da66c6d13ec2457f35e52775" + integrity sha512-NrwK9gaL5+XgrgoCsd9svsoWdVkK4gnvyhcpzd6m487tXHqIdYeykgq3MKI1u4I+5Zf0tofr70at9dWJDeb+BA== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" chalk "^2.0.1" - jest-get-type "^24.3.0" - jest-util "^24.7.1" - pretty-format "^24.7.0" - -jest-environment-jsdom@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.7.1.tgz#a40e004b4458ebeb8a98082df135fd501b9fbbd6" - integrity sha512-Gnhb+RqE2JuQGb3kJsLF8vfqjt3PHKSstq4Xc8ic+ax7QKo4Z0RWGucU3YV+DwKR3T9SYc+3YCUQEJs8r7+Jxg== - dependencies: - "@jest/environment" "^24.7.1" - "@jest/fake-timers" "^24.7.1" - "@jest/types" "^24.7.0" - jest-mock "^24.7.0" - jest-util "^24.7.1" + jest-get-type "^24.8.0" + jest-util "^24.8.0" + pretty-format "^24.8.0" + +jest-environment-jsdom@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.8.0.tgz#300f6949a146cabe1c9357ad9e9ecf9f43f38857" + integrity sha512-qbvgLmR7PpwjoFjM/sbuqHJt/NCkviuq9vus9NBn/76hhSidO+Z6Bn9tU8friecegbJL8gzZQEMZBQlFWDCwAQ== + dependencies: + "@jest/environment" "^24.8.0" + "@jest/fake-timers" "^24.8.0" + "@jest/types" "^24.8.0" + jest-mock "^24.8.0" + jest-util "^24.8.0" jsdom "^11.5.1" -jest-environment-node@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.7.1.tgz#fa2c047a31522a48038d26ee4f7c8fd9c1ecfe12" - integrity sha512-GJJQt1p9/C6aj6yNZMvovZuxTUd+BEJprETdvTKSb4kHcw4mFj8777USQV0FJoJ4V3djpOwA5eWyPwfq//PFBA== +jest-environment-node@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.8.0.tgz#d3f726ba8bc53087a60e7a84ca08883a4c892231" + integrity sha512-vIGUEScd1cdDgR6sqn2M08sJTRLQp6Dk/eIkCeO4PFHxZMOgy+uYLPMC4ix3PEfM5Au/x3uQ/5Tl0DpXXZsJ/Q== dependencies: - "@jest/environment" "^24.7.1" - "@jest/fake-timers" "^24.7.1" - "@jest/types" "^24.7.0" - jest-mock "^24.7.0" - jest-util "^24.7.1" + "@jest/environment" "^24.8.0" + "@jest/fake-timers" "^24.8.0" + "@jest/types" "^24.8.0" + jest-mock "^24.8.0" + jest-util "^24.8.0" -jest-get-type@^24.3.0: - version "24.3.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.3.0.tgz#582cfd1a4f91b5cdad1d43d2932f816d543c65da" - integrity sha512-HYF6pry72YUlVcvUx3sEpMRwXEWGEPlJ0bSPVnB3b3n++j4phUEoSPcS6GC0pPJ9rpyPSe4cb5muFo6D39cXow== +jest-get-type@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.8.0.tgz#a7440de30b651f5a70ea3ed7ff073a32dfe646fc" + integrity sha512-RR4fo8jEmMD9zSz2nLbs2j0zvPpk/KCEz3a62jJWbd2ayNo0cb+KFRxPHVhE4ZmgGJEQp0fosmNz84IfqM8cMQ== -jest-haste-map@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.7.1.tgz#772e215cd84080d4bbcb759cfb668ad649a21471" - integrity sha512-g0tWkzjpHD2qa03mTKhlydbmmYiA2KdcJe762SbfFo/7NIMgBWAA0XqQlApPwkWOF7Cxoi/gUqL0i6DIoLpMBw== +jest-haste-map@^24.8.0: + version "24.8.1" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.8.1.tgz#f39cc1d2b1d907e014165b4bd5a957afcb992982" + integrity sha512-SwaxMGVdAZk3ernAx2Uv2sorA7jm3Kx+lR0grp6rMmnY06Kn/urtKx1LPN2mGTea4fCT38impYT28FfcLUhX0g== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" anymatch "^2.0.0" fb-watchman "^2.0.0" graceful-fs "^4.1.15" invariant "^2.2.4" jest-serializer "^24.4.0" - jest-util "^24.7.1" + jest-util "^24.8.0" jest-worker "^24.6.0" micromatch "^3.1.10" sane "^4.0.3" @@ -2441,65 +2635,65 @@ jest-haste-map@^24.7.1: optionalDependencies: fsevents "^1.2.7" -jest-jasmine2@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.7.1.tgz#01398686dabe46553716303993f3be62e5d9d818" - integrity sha512-Y/9AOJDV1XS44wNwCaThq4Pw3gBPiOv/s6NcbOAkVRRUEPu+36L2xoPsqQXsDrxoBerqeyslpn2TpCI8Zr6J2w== +jest-jasmine2@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.8.0.tgz#a9c7e14c83dd77d8b15e820549ce8987cc8cd898" + integrity sha512-cEky88npEE5LKd5jPpTdDCLvKkdyklnaRycBXL6GNmpxe41F0WN44+i7lpQKa/hcbXaQ+rc9RMaM4dsebrYong== dependencies: "@babel/traverse" "^7.1.0" - "@jest/environment" "^24.7.1" - "@jest/test-result" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/environment" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" chalk "^2.0.1" co "^4.6.0" - expect "^24.7.1" + expect "^24.8.0" is-generator-fn "^2.0.0" - jest-each "^24.7.1" - jest-matcher-utils "^24.7.0" - jest-message-util "^24.7.1" - jest-runtime "^24.7.1" - jest-snapshot "^24.7.1" - jest-util "^24.7.1" - pretty-format "^24.7.0" + jest-each "^24.8.0" + jest-matcher-utils "^24.8.0" + jest-message-util "^24.8.0" + jest-runtime "^24.8.0" + jest-snapshot "^24.8.0" + jest-util "^24.8.0" + pretty-format "^24.8.0" throat "^4.0.0" -jest-leak-detector@^24.7.0: - version "24.7.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.7.0.tgz#323ff93ed69be12e898f5b040952f08a94288ff9" - integrity sha512-zV0qHKZGXtmPVVzT99CVEcHE9XDf+8LwiE0Ob7jjezERiGVljmqKFWpV2IkG+rkFIEUHFEkMiICu7wnoPM/RoQ== +jest-leak-detector@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.8.0.tgz#c0086384e1f650c2d8348095df769f29b48e6980" + integrity sha512-cG0yRSK8A831LN8lIHxI3AblB40uhv0z+SsQdW3GoMMVcK+sJwrIIyax5tu3eHHNJ8Fu6IMDpnLda2jhn2pD/g== dependencies: - pretty-format "^24.7.0" + pretty-format "^24.8.0" -jest-matcher-utils@^24.7.0: - version "24.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.7.0.tgz#bbee1ff37bc8b2e4afcaabc91617c1526af4bcd4" - integrity sha512-158ieSgk3LNXeUhbVJYRXyTPSCqNgVXOp/GT7O94mYd3pk/8+odKTyR1JLtNOQSPzNi8NFYVONtvSWA/e1RDXg== +jest-matcher-utils@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.8.0.tgz#2bce42204c9af12bde46f83dc839efe8be832495" + integrity sha512-lex1yASY51FvUuHgm0GOVj7DCYEouWSlIYmCW7APSqB9v8mXmKSn5+sWVF0MhuASG0bnYY106/49JU1FZNl5hw== dependencies: chalk "^2.0.1" - jest-diff "^24.7.0" - jest-get-type "^24.3.0" - pretty-format "^24.7.0" + jest-diff "^24.8.0" + jest-get-type "^24.8.0" + pretty-format "^24.8.0" -jest-message-util@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.7.1.tgz#f1dc3a6c195647096a99d0f1dadbc447ae547018" - integrity sha512-dk0gqVtyqezCHbcbk60CdIf+8UHgD+lmRHifeH3JRcnAqh4nEyPytSc9/L1+cQyxC+ceaeP696N4ATe7L+omcg== +jest-message-util@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.8.0.tgz#0d6891e72a4beacc0292b638685df42e28d6218b" + integrity sha512-p2k71rf/b6ns8btdB0uVdljWo9h0ovpnEe05ZKWceQGfXYr4KkzgKo3PBi8wdnd9OtNh46VpNIJynUn/3MKm1g== dependencies: "@babel/code-frame" "^7.0.0" - "@jest/test-result" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" "@types/stack-utils" "^1.0.1" chalk "^2.0.1" micromatch "^3.1.10" slash "^2.0.0" stack-utils "^1.0.1" -jest-mock@^24.7.0: - version "24.7.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.7.0.tgz#e49ce7262c12d7f5897b0d8af77f6db8e538023b" - integrity sha512-6taW4B4WUcEiT2V9BbOmwyGuwuAFT2G8yghF7nyNW1/2gq5+6aTqSPcS9lS6ArvEkX55vbPAS/Jarx5LSm4Fng== +jest-mock@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.8.0.tgz#2f9d14d37699e863f1febf4e4d5a33b7fdbbde56" + integrity sha512-6kWugwjGjJw+ZkK4mDa0Df3sDlUTsV47MSrT0nGQ0RBWJbpODDQ8MHDVtGtUYBne3IwZUhtB7elxHspU79WH3A== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" jest-pnp-resolver@^1.2.1: version "1.2.1" @@ -2511,75 +2705,75 @@ jest-regex-util@^24.3.0: resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.3.0.tgz#d5a65f60be1ae3e310d5214a0307581995227b36" integrity sha512-tXQR1NEOyGlfylyEjg1ImtScwMq8Oh3iJbGTjN7p0J23EuVX1MA8rwU69K4sLbCmwzgCUbVkm0FkSF9TdzOhtg== -jest-resolve-dependencies@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.7.1.tgz#cf93bbef26999488a96a2b2012f9fe7375aa378f" - integrity sha512-2Eyh5LJB2liNzfk4eo7bD1ZyBbqEJIyyrFtZG555cSWW9xVHxII2NuOkSl1yUYTAYCAmM2f2aIT5A7HzNmubyg== +jest-resolve-dependencies@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.8.0.tgz#19eec3241f2045d3f990dba331d0d7526acff8e0" + integrity sha512-hyK1qfIf/krV+fSNyhyJeq3elVMhK9Eijlwy+j5jqmZ9QsxwKBiP6qukQxaHtK8k6zql/KYWwCTQ+fDGTIJauw== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" jest-regex-util "^24.3.0" - jest-snapshot "^24.7.1" + jest-snapshot "^24.8.0" -jest-resolve@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.7.1.tgz#e4150198299298380a75a9fd55043fa3b9b17fde" - integrity sha512-Bgrc+/UUZpGJ4323sQyj85hV9d+ANyPNu6XfRDUcyFNX1QrZpSoM0kE4Mb2vZMAYTJZsBFzYe8X1UaOkOELSbw== +jest-resolve@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.8.0.tgz#84b8e5408c1f6a11539793e2b5feb1b6e722439f" + integrity sha512-+hjSzi1PoRvnuOICoYd5V/KpIQmkAsfjFO71458hQ2Whi/yf1GDeBOFj8Gxw4LrApHsVJvn5fmjcPdmoUHaVKw== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" browser-resolve "^1.11.3" chalk "^2.0.1" jest-pnp-resolver "^1.2.1" realpath-native "^1.1.0" -jest-runner@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.7.1.tgz#41c8a02a06aa23ea82d8bffd69d7fa98d32f85bf" - integrity sha512-aNFc9liWU/xt+G9pobdKZ4qTeG/wnJrJna3VqunziDNsWT3EBpmxXZRBMKCsNMyfy+A/XHiV+tsMLufdsNdgCw== +jest-runner@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.8.0.tgz#4f9ae07b767db27b740d7deffad0cf67ccb4c5bb" + integrity sha512-utFqC5BaA3JmznbissSs95X1ZF+d+4WuOWwpM9+Ak356YtMhHE/GXUondZdcyAAOTBEsRGAgH/0TwLzfI9h7ow== dependencies: "@jest/console" "^24.7.1" - "@jest/environment" "^24.7.1" - "@jest/test-result" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/environment" "^24.8.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" chalk "^2.4.2" exit "^0.1.2" graceful-fs "^4.1.15" - jest-config "^24.7.1" + jest-config "^24.8.0" jest-docblock "^24.3.0" - jest-haste-map "^24.7.1" - jest-jasmine2 "^24.7.1" - jest-leak-detector "^24.7.0" - jest-message-util "^24.7.1" - jest-resolve "^24.7.1" - jest-runtime "^24.7.1" - jest-util "^24.7.1" + jest-haste-map "^24.8.0" + jest-jasmine2 "^24.8.0" + jest-leak-detector "^24.8.0" + jest-message-util "^24.8.0" + jest-resolve "^24.8.0" + jest-runtime "^24.8.0" + jest-util "^24.8.0" jest-worker "^24.6.0" source-map-support "^0.5.6" throat "^4.0.0" -jest-runtime@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.7.1.tgz#2ffd70b22dd03a5988c0ab9465c85cdf5d25c597" - integrity sha512-0VAbyBy7tll3R+82IPJpf6QZkokzXPIS71aDeqh+WzPRXRCNz6StQ45otFariPdJ4FmXpDiArdhZrzNAC3sj6A== +jest-runtime@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.8.0.tgz#05f94d5b05c21f6dc54e427cd2e4980923350620" + integrity sha512-Mq0aIXhvO/3bX44ccT+czU1/57IgOMyy80oM0XR/nyD5zgBcesF84BPabZi39pJVA6UXw+fY2Q1N+4BiVUBWOA== dependencies: "@jest/console" "^24.7.1" - "@jest/environment" "^24.7.1" + "@jest/environment" "^24.8.0" "@jest/source-map" "^24.3.0" - "@jest/transform" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/transform" "^24.8.0" + "@jest/types" "^24.8.0" "@types/yargs" "^12.0.2" chalk "^2.0.1" exit "^0.1.2" glob "^7.1.3" graceful-fs "^4.1.15" - jest-config "^24.7.1" - jest-haste-map "^24.7.1" - jest-message-util "^24.7.1" - jest-mock "^24.7.0" + jest-config "^24.8.0" + jest-haste-map "^24.8.0" + jest-message-util "^24.8.0" + jest-mock "^24.8.0" jest-regex-util "^24.3.0" - jest-resolve "^24.7.1" - jest-snapshot "^24.7.1" - jest-util "^24.7.1" - jest-validate "^24.7.0" + jest-resolve "^24.8.0" + jest-snapshot "^24.8.0" + jest-util "^24.8.0" + jest-validate "^24.8.0" realpath-native "^1.1.0" slash "^2.0.0" strip-bom "^3.0.0" @@ -2590,34 +2784,34 @@ jest-serializer@^24.4.0: resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.4.0.tgz#f70c5918c8ea9235ccb1276d232e459080588db3" integrity sha512-k//0DtglVstc1fv+GY/VHDIjrtNjdYvYjMlbLUed4kxrE92sIUewOi5Hj3vrpB8CXfkJntRPDRjCrCvUhBdL8Q== -jest-snapshot@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.7.1.tgz#bd5a35f74aedff070975e9e9c90024f082099568" - integrity sha512-8Xk5O4p+JsZZn4RCNUS3pxA+ORKpEKepE+a5ejIKrId9CwrVN0NY+vkqEkXqlstA5NMBkNahXkR/4qEBy0t5yA== +jest-snapshot@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.8.0.tgz#3bec6a59da2ff7bc7d097a853fb67f9d415cb7c6" + integrity sha512-5ehtWoc8oU9/cAPe6fez6QofVJLBKyqkY2+TlKTOf0VllBB/mqUNdARdcjlZrs9F1Cv+/HKoCS/BknT0+tmfPg== dependencies: "@babel/types" "^7.0.0" - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" chalk "^2.0.1" - expect "^24.7.1" - jest-diff "^24.7.0" - jest-matcher-utils "^24.7.0" - jest-message-util "^24.7.1" - jest-resolve "^24.7.1" + expect "^24.8.0" + jest-diff "^24.8.0" + jest-matcher-utils "^24.8.0" + jest-message-util "^24.8.0" + jest-resolve "^24.8.0" mkdirp "^0.5.1" natural-compare "^1.4.0" - pretty-format "^24.7.0" + pretty-format "^24.8.0" semver "^5.5.0" -jest-util@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.7.1.tgz#b4043df57b32a23be27c75a2763d8faf242038ff" - integrity sha512-/KilOue2n2rZ5AnEBYoxOXkeTu6vi7cjgQ8MXEkih0oeAXT6JkS3fr7/j8+engCjciOU1Nq5loMSKe0A1oeX0A== +jest-util@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.8.0.tgz#41f0e945da11df44cc76d64ffb915d0716f46cd1" + integrity sha512-DYZeE+XyAnbNt0BG1OQqKy/4GVLPtzwGx5tsnDrFcax36rVE3lTA5fbvgmbVPUZf9w77AJ8otqR4VBbfFJkUZA== dependencies: "@jest/console" "^24.7.1" - "@jest/fake-timers" "^24.7.1" + "@jest/fake-timers" "^24.8.0" "@jest/source-map" "^24.3.0" - "@jest/test-result" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" callsites "^3.0.0" chalk "^2.0.1" graceful-fs "^4.1.15" @@ -2626,29 +2820,29 @@ jest-util@^24.7.1: slash "^2.0.0" source-map "^0.6.0" -jest-validate@^24.7.0: - version "24.7.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.7.0.tgz#70007076f338528ee1b1c8a8258b1b0bb982508d" - integrity sha512-cgai/gts9B2chz1rqVdmLhzYxQbgQurh1PEQSvSgPZ8KGa1AqXsqC45W5wKEwzxKrWqypuQrQxnF4+G9VejJJA== +jest-validate@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.8.0.tgz#624c41533e6dfe356ffadc6e2423a35c2d3b4849" + integrity sha512-+/N7VOEMW1Vzsrk3UWBDYTExTPwf68tavEPKDnJzrC6UlHtUDU/fuEdXqFoHzv9XnQ+zW6X3qMZhJ3YexfeLDA== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" camelcase "^5.0.0" chalk "^2.0.1" - jest-get-type "^24.3.0" + jest-get-type "^24.8.0" leven "^2.1.0" - pretty-format "^24.7.0" + pretty-format "^24.8.0" -jest-watcher@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.7.1.tgz#e161363d7f3f4e1ef3d389b7b3a0aad247b673f5" - integrity sha512-Wd6TepHLRHVKLNPacEsBwlp9raeBIO+01xrN24Dek4ggTS8HHnOzYSFnvp+6MtkkJ3KfMzy220KTi95e2rRkrw== +jest-watcher@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.8.0.tgz#58d49915ceddd2de85e238f6213cef1c93715de4" + integrity sha512-SBjwHt5NedQoVu54M5GEx7cl7IGEFFznvd/HNT8ier7cCAx/Qgu9ZMlaTQkvK22G1YOpcWBLQPFSImmxdn3DAw== dependencies: - "@jest/test-result" "^24.7.1" - "@jest/types" "^24.7.0" + "@jest/test-result" "^24.8.0" + "@jest/types" "^24.8.0" "@types/yargs" "^12.0.9" ansi-escapes "^3.0.0" chalk "^2.0.1" - jest-util "^24.7.1" + jest-util "^24.8.0" string-length "^2.0.0" jest-worker@^24.6.0: @@ -2659,19 +2853,19 @@ jest-worker@^24.6.0: merge-stream "^1.0.1" supports-color "^6.1.0" -jest@^24.7.1: - version "24.7.1" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.7.1.tgz#0d94331cf510c75893ee32f87d7321d5bf8f2501" - integrity sha512-AbvRar5r++izmqo5gdbAjTeA6uNRGoNRuj5vHB0OnDXo2DXWZJVuaObiGgtlvhKb+cWy2oYbQSfxv7Q7GjnAtA== +jest@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/jest/-/jest-24.8.0.tgz#d5dff1984d0d1002196e9b7f12f75af1b2809081" + integrity sha512-o0HM90RKFRNWmAWvlyV8i5jGZ97pFwkeVoGvPW1EtLTgJc2+jcuqcbbqcSZLE/3f2S5pt0y2ZBETuhpWNl1Reg== dependencies: import-local "^2.0.0" - jest-cli "^24.7.1" + jest-cli "^24.8.0" "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" -js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.9.0: +js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -2807,54 +3001,29 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -lint-staged@^8.1.5: - version "8.1.5" - resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-8.1.5.tgz#372476fe1a58b8834eb562ed4c99126bd60bdd79" - integrity sha512-e5ZavfnSLcBJE1BTzRTqw6ly8OkqVyO3GL2M6teSmTBYQ/2BuueD5GIt2RPsP31u/vjKdexUyDCxSyK75q4BDA== +lint-staged@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-9.2.0.tgz#155e5723dffdaa55d252c47bab05a2962c1e9781" + integrity sha512-K/CQWcxYunc8lGMNTFvtI4+ybJcHW3K4Ghudz2OrJhIWdW/i1WWu9rGiVj4yJ0+D/xh8a08kp5slt89VZC9Eqg== dependencies: - chalk "^2.3.1" - commander "^2.14.1" - cosmiconfig "^5.0.2" - debug "^3.1.0" + chalk "^2.4.2" + commander "^2.20.0" + cosmiconfig "^5.2.1" + debug "^4.1.1" dedent "^0.7.0" - del "^3.0.0" - execa "^1.0.0" - find-parent-dir "^0.3.0" - g-status "^2.0.2" - is-glob "^4.0.0" - is-windows "^1.0.2" - listr "^0.14.2" - listr-update-renderer "^0.5.0" - lodash "^4.17.11" - log-symbols "^2.2.0" - micromatch "^3.1.8" - npm-which "^3.0.1" - p-map "^1.1.1" - path-is-inside "^1.0.2" - pify "^3.0.0" - please-upgrade-node "^3.0.2" - staged-git-files "1.1.2" - string-argv "^0.0.2" - stringify-object "^3.2.2" - yup "^0.26.10" + del "^4.1.1" + execa "^2.0.1" + listr "^0.14.3" + log-symbols "^3.0.0" + micromatch "^4.0.2" + please-upgrade-node "^3.1.1" + string-argv "^0.3.0" + stringify-object "^3.3.0" listr-silent-renderer@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" -listr-update-renderer@^0.4.0: - version "0.4.0" - resolved "https://github.com/okonet/listr-update-renderer/tarball/upgrade-log-update#06073fa93166277607a7814f4e1f83960081414c" - dependencies: - chalk "^1.1.3" - cli-truncate "^0.2.1" - elegant-spinner "^1.0.1" - figures "^1.7.0" - indent-string "^3.0.0" - log-symbols "^1.0.2" - log-update "^2.3.0" - strip-ansi "^3.0.1" - listr-update-renderer@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.5.0.tgz#4ea8368548a7b8aecb7e06d8c95cb45ae2ede6a2" @@ -2869,28 +3038,40 @@ listr-update-renderer@^0.5.0: log-update "^2.3.0" strip-ansi "^3.0.1" -listr-verbose-renderer@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" +listr-verbose-renderer@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.5.0.tgz#f1132167535ea4c1261102b9f28dac7cba1e03db" + integrity sha512-04PDPqSlsqIOaaaGZ+41vq5FejI9auqTInicFRndCBgE3bXG8D6W1I+mWhk+1nqbHmyhla/6BUrd5OSiHwKRXw== dependencies: - chalk "^1.1.3" - cli-cursor "^1.0.2" + chalk "^2.4.1" + cli-cursor "^2.1.0" date-fns "^1.27.2" - figures "^1.7.0" + figures "^2.0.0" -listr@^0.14.2: - version "0.14.2" - resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.2.tgz#cbe44b021100a15376addfc2d79349ee430bfe14" +listr@^0.14.3: + version "0.14.3" + resolved "https://registry.yarnpkg.com/listr/-/listr-0.14.3.tgz#2fea909604e434be464c50bddba0d496928fa586" + integrity sha512-RmAl7su35BFd/xoMamRjpIE4j3v+L28o8CT5YhAXQJm1fD+1l9ngXY8JAQRJ+tFK2i5njvi0iRUKV09vPwA0iA== dependencies: "@samverschueren/stream-to-observable" "^0.3.0" is-observable "^1.1.0" is-promise "^2.1.0" is-stream "^1.1.0" listr-silent-renderer "^1.1.1" - listr-update-renderer "^0.4.0" - listr-verbose-renderer "^0.4.0" - p-map "^1.1.1" - rxjs "^6.1.0" + listr-update-renderer "^0.5.0" + listr-verbose-renderer "^0.5.0" + p-map "^2.0.0" + rxjs "^6.3.3" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" load-json-file@^4.0.0: version "4.0.0" @@ -2902,6 +3083,14 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -2909,6 +3098,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash.flatten@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" @@ -2938,7 +3134,7 @@ lodash.unescape@4.0.1: resolved "https://registry.yarnpkg.com/lodash.unescape/-/lodash.unescape-4.0.1.tgz#bf2249886ce514cda112fae9218cdc065211fc9c" integrity sha1-vyJJiGzlFM2hEvrpIYzcBlIR/Jw= -lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.5: +lodash@^4.13.1, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.5: version "4.17.14" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== @@ -2955,6 +3151,13 @@ log-symbols@^2.2.0: dependencies: chalk "^2.0.1" +log-symbols@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== + dependencies: + chalk "^2.4.2" + log-update@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/log-update/-/log-update-2.3.0.tgz#88328fd7d1ce7938b29283746f0b1bc126b24708" @@ -2976,6 +3179,13 @@ make-dir@^1.3.0: dependencies: pify "^3.0.0" +make-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801" + integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw== + dependencies: + semver "^6.0.0" + make-error@1.x, make-error@^1.1.1: version "1.3.5" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" @@ -3003,12 +3213,6 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" -matcher@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/matcher/-/matcher-1.1.1.tgz#51d8301e138f840982b338b116bb0c09af62c1c2" - dependencies: - escape-string-regexp "^1.0.4" - mem@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.0.0.tgz#6437690d9471678f6cc83659c00cbafcd6b0cdaf" @@ -3023,7 +3227,17 @@ merge-stream@^1.0.1: dependencies: readable-stream "^2.0.1" -micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.2.3.tgz#7ee99dbd69bb6481689253f018488a1b902b0ed5" + integrity sha512-gdUU1Fwj5ep4kplwcmftruWofEFt6lfpkkr3h860CXbAB9c3hGb55EOL2ali0Td5oebvW0E1+3Sr+Ur7XfKpRA== + +micromatch@^3.1.10, micromatch@^3.1.4: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== @@ -3042,6 +3256,14 @@ micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + mime-db@~1.36.0: version "1.36.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" @@ -3056,7 +3278,12 @@ mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" -minimatch@^3.0.3, minimatch@^3.0.4: +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -3245,25 +3472,18 @@ npm-packlist@^1.1.6: ignore-walk "^3.0.1" npm-bundled "^1.0.1" -npm-path@^2.0.2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-2.0.4.tgz#c641347a5ff9d6a09e4d9bce5580c4f505278e64" - dependencies: - which "^1.2.10" - 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" dependencies: path-key "^2.0.0" -npm-which@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-3.0.1.tgz#9225f26ec3a285c209cae67c3b11a6b4ab7140aa" +npm-run-path@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" + integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== dependencies: - commander "^2.9.0" - npm-path "^2.0.2" - which "^1.2.10" + path-key "^3.0.0" npmlog@^4.0.2: version "4.1.2" @@ -3327,16 +3547,24 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" -onetime@^1.0.0: - version "1.1.0" - resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" - onetime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +opencollective-postinstall@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.2.tgz#5657f1bede69b6e33a45939b061eb53d3c6c3a89" + integrity sha512-pVOEP16TrAO2/fjej1IdOyupJY8KDUM1CvsaScRbw6oddvpQoOfGk4ywha0HKKVAD6RkW4x6Q+tNBwhf3Bgpuw== + optimist@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" @@ -3380,15 +3608,6 @@ os-locale@^3.0.0: lcid "^2.0.0" mem "^4.0.0" -os-locale@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" - integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== - dependencies: - execa "^1.0.0" - lcid "^2.0.0" - mem "^4.0.0" - os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" @@ -3415,31 +3634,70 @@ p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + p-is-promise@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + p-limit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.0.0.tgz#e624ed54ee8c460a778b3c9f3670496ff8a57aec" dependencies: p-try "^2.0.0" +p-limit@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.0.tgz#417c9941e6027a9abcba5092dd2904e255b5fbc2" + integrity sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" dependencies: p-limit "^2.0.0" -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== p-reduce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + p-try@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" @@ -3451,6 +3709,13 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -3466,15 +3731,25 @@ pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" -path-is-inside@^1.0.1, path-is-inside@^1.0.2: +path-is-inside@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" @@ -3482,10 +3757,22 @@ path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" +path-key@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.0.tgz#99a10d870a803bdd5ee6f0470e58dfcd2f9a54d3" + integrity sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg== + path-parse@^1.0.5, path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -3493,6 +3780,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pathval@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" @@ -3501,6 +3793,11 @@ performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" +picomatch@^2.0.5: + version "2.0.7" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6" + integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA== + pify@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -3509,6 +3806,11 @@ pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + pinkie-promise@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" @@ -3526,20 +3828,27 @@ pirates@^4.0.1: dependencies: node-modules-regexp "^1.0.0" +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" dependencies: find-up "^3.0.0" -pkg-dir@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.1.0.tgz#aaeb91c0d3b9c4f74a44ad849f4de34781ae01de" - integrity sha512-55k9QN4saZ8q518lE6EFgYiu95u3BWkSajCifhdQjvLvmr8IpnRbhI+UGpWJQfa0KzDguHeeWT1ccO1PmkOi3A== +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== dependencies: - find-up "^3.0.0" + find-up "^4.0.0" -please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1: +please-upgrade-node@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.1.1.tgz#ed320051dfcc5024fae696712c8288993595e8ac" dependencies: @@ -3564,17 +3873,17 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^1.17.0: - version "1.17.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.17.0.tgz#53b303676eed22cc14a9f0cec09b477b3026c008" - integrity sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw== +prettier@^1.18.2: + version "1.18.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" + integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== -pretty-format@^24.7.0: - version "24.7.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.7.0.tgz#d23106bc2edcd776079c2daa5da02bcb12ed0c10" - integrity sha512-apen5cjf/U4dj7tHetpC7UEFCvtAgnNZnBDkfPv3fokzIqyOJckAG9OlAPC1BlFALnqT/lGB2tl9EJjlK6eCsA== +pretty-format@^24.8.0: + version "24.8.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.8.0.tgz#8dae7044f58db7cb8be245383b565a963e3c27f2" + integrity sha512-P952T7dkrDEplsR+TuY7q3VXDae5Sr7zmQb12JU/NDQa/3CH7/QW0yvqLcGN6jL+zQFKaoJcPc+yJxMTGmosqw== dependencies: - "@jest/types" "^24.7.0" + "@jest/types" "^24.8.0" ansi-regex "^4.0.0" ansi-styles "^3.2.0" react-is "^16.8.4" @@ -3600,11 +3909,6 @@ propagate@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/propagate/-/propagate-1.0.0.tgz#00c2daeedda20e87e3782b344adba1cddd6ad709" -property-expr@^1.5.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-1.5.1.tgz#22e8706894a0c8e28d58735804f6ba3a3673314f" - integrity sha512-CGuc0VUTGthpJXL36ydB6jnbyOf/rAHFvmVrJlH+Rg0DqqLFQGAP6hIaxD/G0OAmBJPhXDHuEJigrp0e0wFV6g== - psl@^1.1.24: version "1.1.29" resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" @@ -3642,6 +3946,14 @@ react-is@^16.8.4: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + read-pkg-up@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" @@ -3650,6 +3962,15 @@ read-pkg-up@^4.0.0: find-up "^3.0.0" read-pkg "^3.0.0" +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -3659,10 +3980,10 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" -read-pkg@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.1.0.tgz#62b924384c4525a1a7a96e2d456b80df142b4390" - integrity sha512-NjNkqf8hlMuSxh+p8h8x8sCIfEv/MoRs/nYDmSRSAk879F9C94ADq+kHUJ4LTy5Nn0PYSmMYsy1mD4+lcXiBKg== +read-pkg@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.1.1.tgz#5cf234dde7a405c90c88a519ab73c467e9cb83f5" + integrity sha512-dFcTLQi6BZ+aFUaICg7er+/usEoqFdQxiEBsEMNGoipenihtxxtdrQuBXvyANCEI8VuUIVYFgeHGx9sLLvim4w== dependencies: "@types/normalize-package-data" "^2.4.0" normalize-package-data "^2.5.0" @@ -3688,11 +4009,6 @@ realpath-native@^1.1.0: dependencies: util.promisify "^1.0.0" -regenerator-runtime@^0.12.0: - version "0.12.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" - integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== - 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" @@ -3769,11 +4085,6 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -requireindex@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" - integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -3811,19 +4122,19 @@ resolve@^1.10.0: dependencies: path-parse "^1.0.6" +resolve@^1.11.0, resolve@^1.5.0: + version "1.11.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" + integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== + dependencies: + path-parse "^1.0.6" + resolve@^1.3.2: version "1.8.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" dependencies: path-parse "^1.0.5" -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -3835,6 +4146,11 @@ ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rimraf@2.6.3, rimraf@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -3842,7 +4158,7 @@ rimraf@2.6.3, rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: @@ -3863,16 +4179,22 @@ run-node@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e" -rxjs@>=6.4.0, rxjs@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" - integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +rxjs@^6.3.3: + version "6.5.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.2.tgz#2e35ce815cd46d84d02a209fb4e5921e051dbec7" + integrity sha512-HUb7j3kvb7p7eCUHE3FqjoDsC1xfZQ4AHFWfTKSpZ+sAhhz5X1WX0ZuUqWbzB2QhSLp3DoLUG+hMdEDKqWo2Zg== dependencies: tslib "^1.9.0" -rxjs@^6.1.0: - version "6.3.2" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.3.2.tgz#6a688b16c4e6e980e62ea805ec30648e1c60907f" +rxjs@^6.4.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.4.0.tgz#f3bb0fe7bda7fb69deac0c16f17b50b0b8790504" + integrity sha512-Z9Yfa11F6B9Sg/BK9MnqnQ+aQYicPLtilXBp2yUtDt2JRCE0h26d33EnfO3ZxoNxG0T92OUucP3Ct7cpfkdFfw== dependencies: tslib "^1.9.0" @@ -3927,6 +4249,11 @@ semver@^5.5, semver@^5.5.1: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.0.tgz#790a7cf6fea5459bac96110b29b60412dc8ff96b" integrity sha512-Ya52jSX2u7QKghxeoFGpLwCtGlt7j0oY9DYb5apt9nPlJ42ID+ulTXESnt/qAQcoSERyZ5sl3LDIOw0nAn/5DA== +semver@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.2.0.tgz#4d813d9590aaf8a9192693d6c85b9344de5901db" + integrity sha512-jdFC1VdUGT/2Scgbimf7FSx9iJLXoqfglSF+gJeuNWVpiE37OIbc1jywR/GJyFdz3mnkz2/id0L0J/cr0izR5A== + 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" @@ -3967,12 +4294,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -simple-git@^1.85.0: - version "1.106.0" - resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-1.106.0.tgz#81024c7c22fafd0c386a2b338031cc60b3568b9c" - dependencies: - debug "^4.0.1" - sisteransi@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.0.tgz#77d9622ff909080f1c19e5f4a1df0c1b0a27b88c" @@ -3982,6 +4303,11 @@ slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + slice-ansi@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" @@ -4103,11 +4429,6 @@ stack-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.1.tgz#d4f33ab54e8e38778b0ca5cfd3b3afb12db68620" -staged-git-files@1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/staged-git-files/-/staged-git-files-1.1.2.tgz#4326d33886dc9ecfa29a6193bf511ba90a46454b" - integrity sha512-0Eyrk6uXW6tg9PYkhi/V/J4zHp33aNyi2hOCmhFLqLTIhbgqWn5jlSzI+IU0VqrZq6+DbHcabQl/WP6P3BG0QA== - static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -4119,9 +4440,10 @@ stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" -string-argv@^0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.0.2.tgz#dac30408690c21f3c3630a3ff3a05877bdcbd736" +string-argv@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.0.tgz#0ea99e7257fea5e97a1bfcdfc19cf12d68e6ec6a" + integrity sha512-NGZHq3nkSXVtGZXTBjFru3MNfoZyIzN25T7BmvdgnSC0LCJczAGLLMQLyjywSIaAoqSemgLzBRHOsnrHbt60+Q== string-length@^2.0.0: version "2.0.0" @@ -4145,7 +4467,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^3.0.0: +string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== @@ -4160,11 +4482,12 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -stringify-object@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.2.2.tgz#9853052e5a88fb605a44cd27445aa257ad7ffbcd" +stringify-object@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== dependencies: - get-own-enumerable-property-symbols "^2.0.1" + get-own-enumerable-property-symbols "^3.0.0" is-obj "^1.0.1" is-regexp "^1.0.0" @@ -4196,15 +4519,20 @@ strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" +strip-final-newline@^2.0.0: + version "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@*, strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + strip-json-comments@^2.0.1, 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" -strip-json-comments@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.0.tgz#86456f81e4bd10d314576c1adf7719ed0894ce3b" - integrity sha512-+yvKOYsd+oXGSoNMD0PgjwWn4MrgXTK/t/Fh54NXLf1cOOf3ceP/JvP5JRDP8jeKBsmtXS9PeoOr2eh1RKWSqg== - supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -4230,11 +4558,6 @@ symbol-tree@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.2.tgz#ae27db38f660a7ae2e1c3b7d1bc290819b8519e6" -synchronous-promise@^2.0.5: - version "2.0.7" - resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.7.tgz#3574b3d2fae86b145356a4b89103e1577f646fe3" - integrity sha512-16GbgwTmFMYFyQMLvtQjvNWh30dsFe1cAW5Fg1wm5+dg84L9Pe36mftsIRU95/W2YsISxsz/xq4VB23sqpgb/A== - table@^5.2.3: version "5.2.3" resolved "https://registry.yarnpkg.com/table/-/table-5.2.3.tgz#cde0cc6eb06751c009efab27e8c820ca5b67b7f2" @@ -4308,6 +4631,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -4317,11 +4647,6 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toposort@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" - integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= - tough-cookie@>=2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -4354,13 +4679,13 @@ ts-jest@^24.0.2: semver "^5.5" yargs-parser "10.x" -ts-node@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.1.0.tgz#8c4b37036abd448577db22a061fd7a67d47e658e" - integrity sha512-34jpuOrxDuf+O6iW1JpgTRDFynUZ1iEqtYruBqh35gICNjN8x+LpVcPAcwzLPi9VU6mdA3ym+x233nZmZp445A== +ts-node@^8.3.0: + version "8.3.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.3.0.tgz#e4059618411371924a1fb5f3b125915f324efb57" + integrity sha512-dyNS/RqyVTDcmNM4NIBAeDMpsAdaQ+ojdf0GOLqE6nwJOgzEkdRNzJywhDfwnuvB10oa6NLVG1rUJQCpRN7qoQ== dependencies: arg "^4.1.0" - diff "^3.1.0" + diff "^4.0.1" make-error "^1.1.1" source-map-support "^0.5.6" yn "^3.0.0" @@ -4401,10 +4726,10 @@ type-fest@^0.4.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.4.1.tgz#8bdf77743385d8a4f13ba95f610f5ccd68c728f8" integrity sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw== -typescript@^3.4.5: - version "3.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.5.tgz#2d2618d10bb566572b8d7aad5180d84257d70a99" - integrity sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw== +typescript@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.5.3.tgz#c830f657f93f1ea846819e929092f5fe5983e977" + integrity sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g== uglify-js@^3.1.4: version "3.6.0" @@ -4527,7 +4852,7 @@ which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" -which@^1.2.10, which@^1.2.9, which@^1.3.0: +which@^1.2.9, which@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" dependencies: @@ -4562,6 +4887,15 @@ wrap-ansi@^3.0.1: string-width "^2.1.1" strip-ansi "^4.0.0" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -4616,10 +4950,10 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^13.0.0: - version "13.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.0.0.tgz#3fc44f3e76a8bdb1cc3602e860108602e5ccde8b" - integrity sha512-w2LXjoL8oRdRQN+hOyppuXs+V/fVAYtpcrRxZuF7Kt/Oc+Jr2uAcVntaUTNT6w5ihoWfFDpNY8CPx1QskxZ/pw== +yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -4642,36 +4976,23 @@ yargs@^12.0.2: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" -yargs@^13.2.2: - version "13.2.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.2.tgz#0c101f580ae95cea7f39d927e7770e3fdc97f993" - integrity sha512-WyEoxgyTD3w5XRpAQNYUB9ycVH/PQrToaTXdYXRdOXvEy1l19br+VJsc0vcO8PTGg5ro/l/GY7F/JMEBmI0BxA== +yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== dependencies: - cliui "^4.0.0" + cliui "^5.0.0" find-up "^3.0.0" get-caller-file "^2.0.1" - os-locale "^3.1.0" require-directory "^2.1.1" require-main-filename "^2.0.0" set-blocking "^2.0.0" string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^13.0.0" + yargs-parser "^13.1.1" yn@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.0.tgz#fcbe2db63610361afcc5eb9e0ac91e976d046114" integrity sha512-kKfnnYkbTfrAdd0xICNFw7Atm8nKpLcLv9AZGEt+kczL/WQVai4e2V6ZN8U/O+iI6WrNuJjNNOyu4zfhl9D3Hg== - -yup@^0.26.10: - version "0.26.10" - resolved "https://registry.yarnpkg.com/yup/-/yup-0.26.10.tgz#3545839663289038faf25facfc07e11fd67c0cb1" - integrity sha512-keuNEbNSnsOTOuGCt3UJW69jDE3O4P+UHAakO7vSeFMnjaitcmlbij/a3oNb9g1Y1KvSKH/7O1R2PQ4m4TRylw== - dependencies: - "@babel/runtime" "7.0.0" - fn-name "~2.0.1" - lodash "^4.17.10" - property-expr "^1.5.0" - synchronous-promise "^2.0.5" - toposort "^2.0.2"