From 5e62c930b151f9d6d491b7a9d97159d8f069206e Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Wed, 27 May 2020 13:07:25 +0300 Subject: [PATCH] Cleanup the crowdin integration script, completely migrate it to API v2 --- @types/cwordin-api.d.ts | 98 ----------- @types/multi-progress.d.ts | 10 -- @types/prompt.d.ts | 56 ------ babel.config.js | 12 +- config.js | 12 +- packages/scripts/i18n-crowdin.ts | 291 +++++++++---------------------- packages/scripts/package.json | 11 +- yarn.lock | 160 +++++------------ 8 files changed, 161 insertions(+), 489 deletions(-) delete mode 100644 @types/cwordin-api.d.ts delete mode 100644 @types/multi-progress.d.ts delete mode 100644 @types/prompt.d.ts diff --git a/@types/cwordin-api.d.ts b/@types/cwordin-api.d.ts deleted file mode 100644 index 9ca2289..0000000 --- a/@types/cwordin-api.d.ts +++ /dev/null @@ -1,98 +0,0 @@ -declare module 'crowdin-api' { - export interface ProjectInfoFile { - node_type: 'file'; - id: number; - name: string; - created: string; - last_updated: string; - last_accessed: string; - last_revision: string; - } - - export interface ProjectInfoDirectory { - node_type: 'directory'; - id: number; - name: string; - files: Array; - } - - export interface ProjectInfoResponse { - details: { - source_language: { - name: string; - code: string; - }; - name: string; - identifier: string; - created: string; - description: string; - join_policy: string; - last_build: string | null; - last_activity: string; - participants_count: string; // it's number, but string in the response - logo_url: string | null; - total_strings_count: string; // it's number, but string in the response - total_words_count: string; // it's number, but string in the response - duplicate_strings_count: number; - duplicate_words_count: number; - invite_url: { - translator: string; - proofreader: string; - }; - }; - languages: Array<{ - name: string; // English language name - code: string; - can_translate: 0 | 1; - can_approve: 0 | 1; - }>; - files: Array; - } - - export interface LanguageStatusNode { - node_type: 'directory' | 'file'; - id: number; - name: string; - phrases: number; - translated: number; - approved: number; - words: number; - words_translated: number; - words_approved: number; - files: Array; - } - - export interface LanguageStatusResponse { - files: Array; - } - - type FilesList = Record; - - export default class CrowdinApi { - constructor(params: { apiKey: string; projectName: string; baseUrl?: string }); - projectInfo(): Promise; - languageStatus(language: string): Promise; - exportFile( - file: string, - language: string, - params?: { - branch?: string; - format?: 'xliff'; - export_translated_only?: boolean; - export_approved_only?: boolean; - }, - ): Promise; // TODO: not sure about Promise return type - updateFile( - files: FilesList, - params: { - titles?: Record; - export_patterns?: Record; - new_names?: Record; - first_line_contains_header?: string; - scheme?: string; - update_option?: 'update_as_unapproved' | 'update_without_changes'; - branch?: string; - }, - ): Promise; - } -} diff --git a/@types/multi-progress.d.ts b/@types/multi-progress.d.ts deleted file mode 100644 index 67df384..0000000 --- a/@types/multi-progress.d.ts +++ /dev/null @@ -1,10 +0,0 @@ -declare module 'multi-progress' { - export default class MultiProgress { - constructor(stream?: string); - newBar(schema: string, options: ProgressBar.ProgressBarOptions): ProgressBar; - terminate(): void; - move(index: number): void; - tick(index: number, value?: number, options?: any): void; - update(index: number, value?: number, options?: any): void; - } -} diff --git a/@types/prompt.d.ts b/@types/prompt.d.ts deleted file mode 100644 index 14a2e70..0000000 --- a/@types/prompt.d.ts +++ /dev/null @@ -1,56 +0,0 @@ -// Type definitions for Prompt.js 1.0.0 -// Project: https://github.com/flatiron/prompt - -declare module 'prompt' { - type PropertiesType = Array | prompt.PromptSchema | Array; - - namespace prompt { - interface PromptSchema { - properties: PromptProperties; - } - - interface PromptProperties { - [propName: string]: PromptPropertyOptions; - } - - interface PromptPropertyOptions { - name?: string; - pattern?: RegExp; - message?: string; - required?: boolean; - hidden?: boolean; - description?: string; - type?: string; - default?: string; - before?: (value: any) => any; - conform?: (result: any) => boolean; - } - - export function start(): void; - - export function get( - properties: T, - callback: ( - err: Error, - result: T extends Array - ? Record - : T extends PromptSchema - ? Record - : T extends Array - ? Record - : never, - ) => void, - ): void; - - export function addProperties(obj: any, properties: PropertiesType, callback: (err: Error) => void): void; - - export function history(propertyName: string): any; - - export let override: any; - export let colors: boolean; - export let message: string; - export let delimiter: string; - } - - export = prompt; -} diff --git a/babel.config.js b/babel.config.js index 028a217..c95ccf7 100644 --- a/babel.config.js +++ b/babel.config.js @@ -8,7 +8,16 @@ module.exports = { }, ], '@babel/preset-react', - '@babel/preset-env', + [ + '@babel/preset-env', + { + ignoreBrowserslistConfig: true, + targets: { + node: true, + }, + modules: 'commonjs', + }, + ], ], plugins: [ '@babel/plugin-syntax-dynamic-import', @@ -29,6 +38,7 @@ module.exports = { [ '@babel/preset-env', { + ignoreBrowserslistConfig: false, modules: false, useBuiltIns: 'usage', // or "entry" corejs: 3, diff --git a/config.js b/config.js index fe65a79..e6b90a2 100644 --- a/config.js +++ b/config.js @@ -1,4 +1,7 @@ /* eslint-env node */ +/* eslint-disable @typescript-eslint/no-var-requires */ + +const path = require('path'); require('dotenv').config(); @@ -9,5 +12,12 @@ module.exports = { apiHost: env.API_HOST || 'https://dev.account.ely.by', ga: env.GA_ID && { id: env.GA_ID }, sentryDSN: env.SENTRY_DSN, - crowdinApiKey: env.CROWDIN_API_KEY, + crowdin: { + apiKey: env.CROWDIN_API_KEY, + projectId: 350687, + filePath: 'accounts/site.json', + sourceLang: 'en', + basePath: path.resolve(`${__dirname}/packages/app/i18n`), + minApproved: 80, // Minimal ready percent before translation can be published + }, }; diff --git a/packages/scripts/i18n-crowdin.ts b/packages/scripts/i18n-crowdin.ts index 8341449..f852567 100644 --- a/packages/scripts/i18n-crowdin.ts +++ b/packages/scripts/i18n-crowdin.ts @@ -3,53 +3,40 @@ import fs from 'fs'; import path from 'path'; + import axios from 'axios'; import JSON5 from 'json5'; -import CrowdinApi, { LanguageStatusNode, LanguageStatusResponse, ProjectInfoResponse } from 'crowdin-api'; -import { TranslationStatus, Translations, Credentials } from '@crowdin/crowdin-api-client'; -import MultiProgress from 'multi-progress'; +import Crowdin, { SourceFilesModel } from '@crowdin/crowdin-api-client'; +import ProgressBar from 'progress'; import ch from 'chalk'; import iso639 from 'iso-639-1'; -import prompt from 'prompt'; +import { prompt } from 'inquirer'; -import { ValuesType } from 'utility-types'; +import config from './../../config'; -import config from '../../config'; - -if (!config.crowdinApiKey) { +if (!config.crowdin.apiKey) { console.error(ch.red`crowdinApiKey is required`); process.exit(126); } -const ORGANIZATION_ID = 'elyby'; -const PROJECT_ID = 350687; -const FILE_ID = 6; -const PROJECT_KEY = config.crowdinApiKey; -const CROWDIN_FILE_PATH = 'accounts/site.json'; -const SOURCE_LANG = 'en'; -const LANG_DIR = path.resolve(`${__dirname}/../app/i18n`); +const PROJECT_ID = config.crowdin.projectId; +const CROWDIN_FILE_PATH = config.crowdin.filePath; +const SOURCE_LANG = config.crowdin.sourceLang; +const LANG_DIR = config.crowdin.basePath; const INDEX_FILE_NAME = 'index.js'; -const MIN_RELEASE_PROGRESS = 80; // Minimal ready percent before translation can be published +const MIN_RELEASE_PROGRESS = config.crowdin.minApproved; -const credentials: Credentials = { - token: config.crowdinApiKey, -}; -const translationStatusApi = new TranslationStatus(credentials); -const translationsApi = new Translations(credentials); - -const crowdin = new CrowdinApi({ - apiKey: PROJECT_KEY, - projectName: ORGANIZATION_ID, +const crowdin = new Crowdin({ + token: config.crowdin.apiKey, }); -const progressBar = new MultiProgress(); /** * Locales that has been verified by core team members */ -const releasedLocales: Array = ['be', 'fr', 'id', 'pt', 'ru', 'uk', 'vi', 'zh']; +const releasedLocales: ReadonlyArray = ['be', 'fr', 'id', 'pt', 'ru', 'uk', 'vi', 'zh']; /** - * Array of Crowdin locales to our internal locales representation + * Map Crowdin locales into our internal locales representation */ const LOCALES_MAP: Record = { 'pt-BR': 'pt', @@ -57,7 +44,8 @@ const LOCALES_MAP: Record = { }; /** - * This array allows us to customise native languages names, because ISO-639-1 sometimes is strange + * This array allows us to customise native languages names, + * because ISO-639-1 sometimes is strange */ const NATIVE_NAMES_MAP: Record = { be: 'Беларуская', @@ -108,30 +96,6 @@ function sortByKeys>(object: T): T { }, {} as T); } -async function pullLocales(): Promise { - const { languages } = await crowdin.projectInfo(); - - return languages; -} - -function findFile(root: LanguageStatusResponse['files'], path: string): LanguageStatusNode | null { - const [nodeToSearch, ...rest] = path.split('/'); - - for (const node of root) { - if (node.name !== nodeToSearch) { - continue; - } - - if (rest.length === 0) { - return node; - } - - return findFile(node.files, rest.join('/')); - } - - return null; -} - interface IndexFileEntry { code: string; name: string; @@ -140,9 +104,48 @@ interface IndexFileEntry { isReleased: boolean; } -async function pullNew(): Promise { +function getLocaleFilePath(languageId: string): string { + return path.join(LANG_DIR, `${toInternalLocale(languageId)}.json`); +} + +let directoriesList: Array; +let filesList: Array; + +async function findFileId(path: string, parentDir: number|null = null): Promise { + const [nodeToSearch, ...rest] = path.split('/'); + if (rest.length === 0) { + if (!filesList) { + const { data: filesResponse } = await crowdin.sourceFilesApi.listProjectFiles(PROJECT_ID); + filesList = filesResponse.map((fileData) => fileData.data); + } + + const file = filesList.find((file) => file.directoryId === parentDir && file.name === nodeToSearch); + if (file === undefined) { + throw new Error('Cannot find file by provided path'); + } + + return file.id; + } + + if (!directoriesList) { + const { data: dirsResponse } = await crowdin.sourceFilesApi.listProjectDirectories(PROJECT_ID); + directoriesList = dirsResponse.map((dirData) => dirData.data); + } + + const dir = directoriesList.find((dir) => dir.directoryId === parentDir && dir.name === nodeToSearch); + if (dir === undefined) { + throw new Error('Cannot find directory by provided path'); + } + + return findFileId(rest.join('/'), dir.id); +} + +async function pull(): Promise { + console.log('Loading file info...'); + const fileId = await findFileId(CROWDIN_FILE_PATH); + console.log('Pulling translation progress...'); - const { data: translationProgress } = await translationStatusApi.getFileProgress(PROJECT_ID, FILE_ID, 100); + const { data: translationProgress } = await crowdin.translationStatusApi.getFileProgress(PROJECT_ID, fileId, 100); const localesToPull: Array = []; const indexFileEntries: Record = { @@ -170,7 +173,7 @@ async function pullNew(): Promise { }); // Add prefix 'c' to current and total to prevent filling thees placeholders with real values - const downloadingProgressBar = progressBar.newBar('Downloading translates :bar :percent | :cCurrent/:total', { + const downloadingProgressBar = new ProgressBar('Downloading translates :bar :percent | :cCurrent/:total', { total: localesToPull.length, incomplete: '\u2591', complete: '\u2588', @@ -179,18 +182,18 @@ async function pullNew(): Promise { let downloadingReady = 0; const promises = localesToPull.map(async (languageId): Promise => { - const { data: { url } } = await translationsApi.buildProjectFileTranslation(PROJECT_ID, FILE_ID, { + const { data: { url } } = await crowdin.translationsApi.buildProjectFileTranslation(PROJECT_ID, fileId, { targetLanguageId: languageId, exportApprovedOnly: true, }); - const fileResponse = await axios.get(url, { + const { data: fileContents } = await axios.get(url, { // Disable response parsing transformResponse: [], }); - fs.writeFileSync(path.join(LANG_DIR, `${toInternalLocale(languageId)}.json`), fileResponse.data); + fs.writeFileSync(getLocaleFilePath(languageId), fileContents); - downloadingProgressBar.update(++downloadingReady / localesToPull, { + downloadingProgressBar.update(++downloadingReady / localesToPull.length, { cCurrent: downloadingReady, }); }); @@ -204,156 +207,32 @@ async function pullNew(): Promise { console.log(ch.green('The index file was successfully written')); } -async function pull() { - console.log('Pulling locales list...'); - const locales = await pullLocales(); - const checkingProgressBar = progressBar.newBar('| Pulling locales info :bar :percent | :current/:total', { - total: locales.length, - incomplete: '\u2591', - complete: '\u2588', - width: locales.length, - }); - // Add prefix 'c' to current and total to prevent filling thees placeholders with real values - const downloadingProgressBar = progressBar.newBar('| Downloading translates :bar :percent | :cCurrent/:cTotal', { - total: 100, - incomplete: '\u2591', - complete: '\u2588', - width: locales.length, - }); - let downloadingTotal = 0; - let downloadingReady = 0; +async function push(): Promise { + const { disapproveTranslates } = await prompt([{ + name: 'disapproveTranslates', + type: 'confirm', + default: true, + message: 'Disapprove changed lines?', + }]); - interface Result { - locale: ValuesType; - progress: number; - translatesFilePath: string; - } + console.log('Loading file info...'); + const fileId = await findFileId(CROWDIN_FILE_PATH); - const results = await Promise.all( - // TODO: there is should be some way to reimplement this - // with reduce to avoid null values - locales.map( - async (locale): Promise => { - const { files } = await crowdin.languageStatus(locale.code); - checkingProgressBar.tick(); - const fileInfo = findFile(files, CROWDIN_FILE_PATH); - - if (fileInfo === null) { - throw new Error('Unable to find translation file. Please check the CROWDIN_FILE_PATH param.'); - } - - const progress = (fileInfo.words_approved / fileInfo.words) * 100; - - if (!releasedLocales.includes(toInternalLocale(locale.code)) && progress < MIN_RELEASE_PROGRESS) { - return null; - } - - downloadingProgressBar.update(downloadingReady / ++downloadingTotal, { - cCurrent: downloadingReady, - cTotal: downloadingTotal, - }); - - const translatesFilePath = await crowdin.exportFile(CROWDIN_FILE_PATH, locale.code); - - downloadingProgressBar.update(++downloadingReady / downloadingTotal, { - cCurrent: downloadingReady, - cTotal: downloadingTotal, - }); - - return { - locale, - progress, - translatesFilePath, - }; - }, - ), + console.log('Uploading the source file to the storage...') + const { data: { id: storageId } } = await crowdin.uploadStorageApi.addStorage( + path.basename(CROWDIN_FILE_PATH), + fs.readFileSync(getLocaleFilePath(SOURCE_LANG)), ); - console.log('Locales are downloaded. Writing them to file system.'); - - const indexFileEntries: Record = { - en: { - code: 'en', - name: 'English', - englishName: 'English', - progress: 100, - isReleased: true, - }, - }; - await Promise.all( - results - .filter((result): result is Result => result !== null) - .map( - (result) => - new Promise((resolve, reject) => { - const { - locale: { code, name }, - progress, - translatesFilePath, - } = result; - const ourCode = toInternalLocale(code); - - indexFileEntries[ourCode] = { - code: ourCode, - name: NATIVE_NAMES_MAP[ourCode] || iso639.getNativeName(ourCode), - englishName: ENGLISH_NAMES_MAP[ourCode] || name, - progress: parseFloat(progress.toFixed(1)), - isReleased: releasedLocales.includes(ourCode), - }; - - fs.copyFile(translatesFilePath, path.join(LANG_DIR, `${ourCode}.json`), 0, (err) => { - err ? reject(err) : resolve(); - }); - }), - ), - ); - - console.log('Writing an index file.'); - - fs.writeFileSync(path.join(LANG_DIR, INDEX_FILE_NAME), serializeToModule(indexFileEntries)); - - console.log(ch.green('The index file was successfully written')); -} - -function push() { - return new Promise((resolve, reject) => { - prompt.start(); - prompt.get( - { - properties: { - disapprove: { - description: 'Disapprove changed lines? [Y/n]', - pattern: /^y|n$/i, - message: 'Please enter "y" or "n"', - default: 'y', - before: (value) => value.toLowerCase() === 'y', - }, - }, - }, - async (err, { disapprove }) => { - if (err) { - reject(err); - - return; - } - - console.log(`Publishing ${ch.bold(SOURCE_LANG)} translates file...`); - - await crowdin.updateFile( - { - [CROWDIN_FILE_PATH]: path.join(LANG_DIR, `${SOURCE_LANG}.json`), - }, - { - update_option: disapprove ? 'update_as_unapproved' : 'update_without_changes', - }, - ); - - console.log(ch.green('Success')); - - resolve(); - }, - ); + console.log(`Applying the new revision...`); + await crowdin.sourceFilesApi.updateOrRestoreFile(PROJECT_ID, fileId, { + storageId, + updateOption: disapproveTranslates + ? SourceFilesModel.UpdateOption.CLEAR_TRANSLATIONS_AND_APPROVALS + : SourceFilesModel.UpdateOption.KEEP_TRANSLATIONS_AND_APPROVALS, }); + + console.log(ch.green('Success')); } try { @@ -361,7 +240,7 @@ try { switch (action) { case 'pull': - pullNew(); + pull(); break; case 'push': push(); diff --git a/packages/scripts/package.json b/packages/scripts/package.json index 14c3251..3db2cb0 100644 --- a/packages/scripts/package.json +++ b/packages/scripts/package.json @@ -12,20 +12,21 @@ "dependencies": { "@babel/node": "^7.8.3", "@crowdin/crowdin-api-client": "^1.8.0", - "@types/mkdirp": "^1.0.0", - "@types/progress": "^2.0.3", "axios": "^0.19.2", "chalk": "^4.0.0", "crowdin-api": "^4.0.0", "glob": "^7.1.6", + "inquirer": "^7.1.0", "iso-639-1": "^2.1.3", "json5": "^2.1.3", "mkdirp": "^1.0.4", - "multi-progress": "^2.0.0", - "prompt": "https://github.com/flatiron/prompt.git#master", - "utility-types": "^3.10.0" + "progress": "^2.0.3" }, "devDependencies": { + "@types/inquirer": "^6.5.0", + "@types/json5": "^0.0.30", + "@types/mkdirp": "^1.0.0", + "@types/progress": "^2.0.3", "@types/webpack": "^4.41.13" } } diff --git a/yarn.lock b/yarn.lock index dcbfd8b..5b25a2c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3040,6 +3040,14 @@ resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880" integrity sha512-iYCgjm1dGPRuo12+BStjd1HiVQqhlRhWDOQigNxn023HcjnhsiFz9pc6CzJj4HwDCSQca9bxTL4PxJDbkdm3PA== +"@types/inquirer@^6.5.0": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@types/inquirer/-/inquirer-6.5.0.tgz#b83b0bf30b88b8be7246d40e51d32fe9d10e09be" + integrity sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw== + dependencies: + "@types/through" "*" + rxjs "^6.4.0" + "@types/intl@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@types/intl/-/intl-1.2.0.tgz#1245511f13064402087979f498764611a3c758fc" @@ -3093,6 +3101,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== +"@types/json5@^0.0.30": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.30.tgz#44cb52f32a809734ca562e685c6473b5754a7818" + integrity sha512-sqm9g7mHlPY/43fcSNrCYfOeX9zkTTK+euO5E6+CVijSMm5tTjkVdwdqRkY3ljjIAf8679vps5jKUoJBCLsMDA== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -3332,6 +3345,13 @@ "@types/testing-library__dom" "*" pretty-format "^25.1.0" +"@types/through@*": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/through/-/through-0.0.30.tgz#e0e42ce77e897bd6aead6f6ea62aeb135b8a3895" + integrity sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg== + dependencies: + "@types/node" "*" + "@types/uglify-js@*": version "3.9.0" resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.9.0.tgz#4490a140ca82aa855ad68093829e7fd6ae94ea87" @@ -4244,16 +4264,6 @@ async@~0.2.6: resolved "https://registry.yarnpkg.com/async/-/async-0.2.10.tgz#b6bbe0b0674b9d719708ca38de8c237cb526c3d1" integrity sha1-trvgsGdLnXGXCMo43owjfLUmw9E= -async@~0.9.0: - version "0.9.2" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" - integrity sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0= - -async@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async/-/async-1.0.0.tgz#f8fc04ca3a13784ade9e1641af98578cfbd647a9" - integrity sha1-+PwEyjoTeErenhZBr5hXjPvWR6k= - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -5576,11 +5586,6 @@ color@^3.0.0: color-convert "^1.9.1" color-string "^1.5.2" -colors@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" - integrity sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs= - colors@^1.1.2: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" @@ -6201,11 +6206,6 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" -cycle@1.0.x: - version "1.0.3" - resolved "https://registry.yarnpkg.com/cycle/-/cycle-1.0.3.tgz#21e80b2be8580f98b468f379430662b046c34ad2" - integrity sha1-IegLK+hYD5i0aPN5QwZisEbDStI= - cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" @@ -6349,11 +6349,6 @@ deep-equal@^1.0.1, deep-equal@^1.1.1: object-keys "^1.1.1" regexp.prototype.flags "^1.2.0" -deep-equal@~0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" - integrity sha1-hLdFiW80xoTpjyzg5Cq69Du6AX0= - deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -7402,11 +7397,6 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -eyes@0.1.x: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A= - fake-tag@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/fake-tag/-/fake-tag-1.0.1.tgz#1d59da482240a02bd83500ca98976530ed154b0d" @@ -8613,11 +8603,6 @@ human-signals@^1.1.1: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -i@0.3.x: - version "0.3.6" - resolved "https://registry.yarnpkg.com/i/-/i-0.3.6.tgz#d96c92732076f072711b6b10fd7d4f65ad8ee23d" - integrity sha1-2WyScyB28HJxG2sQ/X1PZa2O4j0= - iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -8821,6 +8806,25 @@ inquirer@^7.0.0: strip-ansi "^5.1.0" through "^2.3.6" +inquirer@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.1.0.tgz#1298a01859883e17c7264b82870ae1034f92dd29" + integrity sha512-5fJMWEmikSYu0nv/flMc475MhGbB7TSPd/2IpFV4I4rMklboCH2rQjYY5kKiYGHqUF9gvaambupcJFFG9dvReg== + dependencies: + ansi-escapes "^4.2.1" + chalk "^3.0.0" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.4.0" + rxjs "^6.5.3" + string-width "^4.1.0" + strip-ansi "^6.0.0" + through "^2.3.6" + internal-ip@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" @@ -9387,7 +9391,7 @@ isomorphic-fetch@^2.1.1: node-fetch "^1.0.1" whatwg-fetch ">=0.10.0" -isstream@0.1.x, isstream@~0.1.2: +isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= @@ -10924,7 +10928,7 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp@0.x.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@~0.5.1: +"mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= @@ -10975,13 +10979,6 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -multi-progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/multi-progress/-/multi-progress-2.0.0.tgz#29ccb42cf24874b1c6384f03127ce5dff7b22f2c" - integrity sha1-Kcy0LPJIdLHGOE8DEnzl3/eyLyw= - dependencies: - progress "^1.1.8" - multicast-dns-service-types@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" @@ -11000,7 +10997,7 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -mute-stream@0.0.8, mute-stream@~0.0.4: +mute-stream@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== @@ -11037,11 +11034,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -ncp@1.0.x: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ncp/-/ncp-1.0.1.tgz#d15367e5cb87432ba117d2bf80fdf45aecfb4246" - integrity sha1-0VNn5cuHQyuhF9K/gP30Wuz7QkY= - neatequal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/neatequal/-/neatequal-1.0.0.tgz#2ee1211bc9fa6e4c55715fd210bb05602eb1ae3b" @@ -12563,11 +12555,6 @@ progress-stream@^2.0.0: speedometer "~1.0.0" through2 "~2.0.3" -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= - progress@^2.0.0, progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" @@ -12605,16 +12592,6 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -"prompt@https://github.com/flatiron/prompt.git#master": - version "1.0.0" - resolved "https://github.com/flatiron/prompt.git#8d5495c84c3f433b8f26ea2798f8ba68c3656459" - dependencies: - colors "^1.1.2" - read "1.0.x" - revalidator "0.1.x" - utile "0.3.x" - winston "2.x" - prompts@^2.0.1: version "2.3.0" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.0.tgz#a444e968fa4cc7e86689a74050685ac8006c4cc4" @@ -13203,13 +13180,6 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -read@1.0.x: - version "1.0.7" - resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" - integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= - dependencies: - mute-stream "~0.0.4" - "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" @@ -13694,11 +13664,6 @@ retry@0.12.0, retry@^0.12.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= -revalidator@0.1.x: - version "0.1.8" - resolved "https://registry.yarnpkg.com/revalidator/-/revalidator-0.1.8.tgz#fece61bfa0c1b52a206bd6b18198184bdd523a3b" - integrity sha1-/s5hv6DBtSoga9axgZgYS91SOjs= - rgb-regex@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" @@ -13709,7 +13674,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2, rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1: +rimraf@2, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3, rimraf@^2.7.1: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -13750,6 +13715,11 @@ run-async@^2.2.0: dependencies: is-promise "^2.1.0" +run-async@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" @@ -14501,11 +14471,6 @@ stable@^0.1.8: resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== -stack-trace@0.0.x: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= - stack-utils@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.2.tgz#5cf48b4557becb4638d0bc4f21d23f5d19586593" @@ -15687,23 +15652,6 @@ utila@^0.4.0, utila@~0.4: resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= -utile@0.3.x: - version "0.3.0" - resolved "https://registry.yarnpkg.com/utile/-/utile-0.3.0.tgz#1352c340eb820e4d8ddba039a4fbfaa32ed4ef3a" - integrity sha1-E1LDQOuCDk2N26A5pPv6oy7U7zo= - dependencies: - async "~0.9.0" - deep-equal "~0.2.1" - i "0.3.x" - mkdirp "0.x.x" - ncp "1.0.x" - rimraf "2.x.x" - -utility-types@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.10.0.tgz#ea4148f9a741015f05ed74fd615e1d20e6bed82b" - integrity sha512-O11mqxmi7wMKCo6HKFt5AhO4BwY3VV68YU07tgxfz8zJTIxr4BpsezN49Ffwy9j3ZpwwJp4fkRwjRzq3uWE6Rg== - utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" @@ -16203,18 +16151,6 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -winston@2.x: - version "2.4.4" - resolved "https://registry.yarnpkg.com/winston/-/winston-2.4.4.tgz#a01e4d1d0a103cf4eada6fc1f886b3110d71c34b" - integrity sha512-NBo2Pepn4hK4V01UfcWcDlmiVTs7VTB1h7bgnB0rgP146bYhMxX0ypCz3lBOfNxCO4Zuek7yeT+y/zM1OfMw4Q== - dependencies: - async "~1.0.0" - colors "1.0.x" - cycle "1.0.x" - eyes "0.1.x" - isstream "0.1.x" - stack-trace "0.0.x" - word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"