Added CLI command structure (#14821)

Added CLI commands for REPL and timetravel functionality

- Added TimeTravel command for updating test data with a date offset
- Added REPL command for access to models and knex in development
- Added pattern for creating new CLI commands, including
  - User input
  - Output
  - Validation of `NODE_ENV`
- TimeTravel command is in the main Ghost repo because it requires the schema
This commit is contained in:
Matt Hanley 2022-05-17 15:40:12 +01:00 committed by GitHub
parent 8b973dcfaa
commit 236d07c90a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 421 additions and 7 deletions

126
core/cli/command.js Normal file
View File

@ -0,0 +1,126 @@
const cli = require('@tryghost/pretty-cli');
const logging = cli.ui.log;
const chalk = require('chalk');
const errors = {
ERR_INVALID_COMMAND: 1,
ERR_INVALID_ENV: 2
};
module.exports = class Command {
constructor() {
this.checkEnv();
this.init();
this.setup();
}
/**
* @private
*/
init() {
this.cli = cli;
this.cli.strict();
// this is always present but not used
this.cli.positional('<command>', {hidden: true});
}
setup() {
// init cli options
}
permittedEnvironments() {
return ['development', 'local'];
}
/**
* @private
*/
checkEnv() {
const env = process.env.NODE_ENV ?? 'development';
this.warn(`Node environment: ${chalk.bold(env)}`);
if (!this.permittedEnvironments().includes(env)) {
this.fatal(`Command ${this.constructor.name} is not permitted in ${env}`);
process.exit(errors.ERR_INVALID_ENV);
}
}
handle() {
this.warn(`Command ${this.constructor.name} has not been implemented.`);
}
async ask(message, opts = {type: 'input'}) {
const inquirer = require('inquirer');
const response = await inquirer.prompt([{
message,
...opts,
name: 'value'
}]);
return response.value;
}
async confirm(message) {
return this.ask(message, {type: 'confirm', default: false});
}
async secret(message) {
return this.ask(message, {type: 'password'});
}
progressBar(total, opts = {}) {
const progress = require('cli-progress');
const bar = new progress.Bar({
format: `|${chalk[opts.color ?? 'cyan']('{bar}')}| {percentage}% | {value}/{total} {status}`,
barCompleteChar: '\u2588',
barIncompleteChar: '\u2591',
hideCursor: true,
clearOnComplete: true,
stopOnComplete: true,
forceRedraw: true,
...opts
});
bar.start(total, 0, {status: ''});
return bar;
}
argument(key, opts = {}) {
this.cli[opts.type ?? 'positional'](key, opts);
}
help(message) {
this.cli.preface(`\n${message}`);
}
/* output aliases */
ok() {
logging.ok(...arguments);
}
info() {
logging.info(...arguments);
}
error() {
logging.error(...arguments);
}
fatal() {
logging.fatal(...arguments);
}
warn() {
logging.warn(...arguments);
}
debug() {
logging.debug(...arguments);
}
static async run(command) {
// attempt to load a cli command by name
if (typeof command === 'string') {
command = require(`./${command}`);
}
const cmd = new command();
if (cmd instanceof Command !== true) {
logging.fatal('Invalid command.');
process.exit(errors.ERR_INVALID_COMMAND);
}
const argv = await cmd.cli.parseAndExit();
return await cmd.handle(argv);
}
};

32
core/cli/repl.js Normal file
View File

@ -0,0 +1,32 @@
const Command = require('./command');
const chalk = require('chalk');
module.exports = class REPL extends Command {
setup() {
this.help('Launches a REPL environment with access to a configured db instance and models');
// this is only here to demo how to set a default value for an arg :)
this.argument('--color', {type: 'string', defaultValue: 'yellow', hidden: true});
}
initializeContext(context) {
const models = require('../server/models');
const knex = require('../server/data/db/connection');
models.init();
context.models = models;
context.m = models;
context.knex = knex;
context.k = knex;
}
async handle(argv = {}) {
this.debug(chalk[argv.color]('== Ghost development REPL =='));
this.info(`a knex database instance is available as ${chalk.magenta('knex')}`);
this.info(`bookshelf models are available as ${chalk.magenta('models')}`);
const repl = require('repl');
const cli = repl.start('> ');
this.initializeContext(cli.context);
cli.on('reset', this.initializeContext);
}
};

87
core/cli/timetravel.js Normal file
View File

@ -0,0 +1,87 @@
const Command = require('./command');
const chalk = require('chalk');
// we use logins as the basis for our offset
const datum = {
table: 'members_login_events',
column: 'created_at'
};
const helpText = `Updates the Ghost db and shifts all dates up to present day.
By default the offset is based on the date of the last member login.\n
${chalk.red('warning')} This is a destructive operation for testing purposes only. DO NOT run it against a database you care about.`;
module.exports = class TimeTravel extends Command {
setup() {
this.help(helpText);
this.argument('--offset', {type: 'number', desc: 'Specify a date offset (in days)'});
this.argument('--force', {type: 'boolean', desc: 'Continue without confirmation'});
}
async handle(argv = {}) {
const _ = require('lodash');
// knex has to be loaded _after_ the call to setup()
// the db connection requires nconf which passes argv to yargs,
// which intercepts --help and stops execution
const knex = require('../server/data/db/connection');
const schema = require('../server/data/schema');
const {DateTime} = require('luxon');
if (!argv.offset) {
const datumPoint = await knex(datum.table)
.max(datum.column, {as: datum.column})
.first();
if (!datumPoint[datum.column]) {
this.error('No data to use as baseline. Use --offset instead');
knex.destroy();
return;
}
argv.offset = Math.floor(
DateTime.utc()
.diff(DateTime.fromJSDate(datumPoint[datum.column]), 'days')
.toObject()
.days
);
}
const dateOffset = argv.offset;
this.info(`Timetravel will use an offset of +${dateOffset} days`);
this.warn('This is a destructive command that will modify your database.');
const confirm = argv.force || await this.confirm('Are you sure you want to continue?');
if (!confirm) {
this.warn('Aborting');
process.exit(1);
}
// map schema to {table: [dateTimeColumn,...]}
const dateTimeFields = _.pickBy(
_.mapValues(schema.tables, (table) => {
return _.keys(_.pickBy(table, (spec) => {
return spec.type === 'dateTime';
}));
}),
fields => fields.length > 0
);
const totalFields = _.reduce(dateTimeFields, (result, value) => {
return result + value.length;
}, 0);
const progressBar = this.progressBar(totalFields);
const db = await knex.transaction();
for (const table in dateTimeFields) {
for (const column of dateTimeFields[table]) {
progressBar.update({status: `Updating ${table}.${column}`});
await db(table)
.update(column, db.raw(`DATE_ADD(${column}, interval ${dateOffset} day)`));
progressBar.increment();
}
}
this.info(`Updated ${totalFields} fields`);
await db.commit();
knex.destroy();
}
};

View File

@ -12,8 +12,14 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development';
const argv = process.argv;
const mode = argv[2];
const command = require('./core/cli/command');
// Switch between boot modes
switch (mode) {
case 'repl':
case 'timetravel':
command.run(mode);
break;
default:
// New boot sequence
require('./core/boot')();

View File

@ -99,6 +99,7 @@
"@tryghost/nodemailer": "0.3.22",
"@tryghost/nql": "0.9.2",
"@tryghost/package-json": "1.0.21",
"@tryghost/pretty-cli": "1.2.27",
"@tryghost/promise": "0.1.18",
"@tryghost/request": "0.1.26",
"@tryghost/root-utils": "0.3.14",
@ -125,6 +126,7 @@
"brute-knex": "4.0.1",
"bson-objectid": "2.0.3",
"bthreads": "0.5.1",
"chalk": "4.1.2",
"cheerio": "0.22.0",
"compression": "1.7.4",
"connect-slashes": "1.4.0",
@ -192,6 +194,7 @@
"@playwright/test": "1.22.0",
"@tryghost/express-test": "0.10.0",
"c8": "7.11.3",
"cli-progress": "3.11.0",
"coffeescript": "2.7.0",
"cssnano": "5.1.8",
"eslint": "8.15.0",
@ -207,6 +210,7 @@
"grunt-shell": "4.0.0",
"grunt-subgrunt": "1.3.0",
"grunt-update-submodules": "0.4.1",
"inquirer": "8.2.4",
"jwks-rsa": "2.1.2",
"mocha": "10.0.0",
"mocha-slow-test-reporter": "0.1.2",

173
yarn.lock
View File

@ -2609,6 +2609,13 @@ ansi-colors@4.1.1, ansi-colors@^4.1.1:
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==
ansi-escapes@^4.2.1:
version "4.3.2"
resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==
dependencies:
type-fest "^0.21.3"
ansi-regex@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
@ -2974,7 +2981,7 @@ binary-extensions@^2.0.0:
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
bl@^4.0.3:
bl@^4.0.3, bl@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
@ -3384,7 +3391,7 @@ ccount@^1.0.0:
resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043"
integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg==
chalk@4.1.2, chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@~4.1.0:
chalk@4.1.2, chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@~4.1.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@ -3440,6 +3447,11 @@ character-reference-invalid@^1.0.0:
resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560"
integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
charenc@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
@ -3550,6 +3562,30 @@ clean-stack@^2.0.0, clean-stack@~2.2.0:
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
cli-cursor@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307"
integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==
dependencies:
restore-cursor "^3.1.0"
cli-progress@3.11.0:
version "3.11.0"
resolved "https://registry.yarnpkg.com/cli-progress/-/cli-progress-3.11.0.tgz#03651defd06182a5396ddc2a41da17c2f257ecdf"
integrity sha512-ug+V4/Qy3+0jX9XkWPV/AwHD98RxKXqDpL37vJBOxQhD90qQ3rDqDKoFpef9se91iTUuOXKlyg2HUyHBo5lHsQ==
dependencies:
string-width "^4.2.3"
cli-spinners@^2.5.0:
version "2.6.1"
resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d"
integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==
cli-width@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
cliui@^7.0.2:
version "7.0.4"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
@ -3566,6 +3602,11 @@ clone-response@^1.0.2:
dependencies:
mimic-response "^1.0.0"
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4=
co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
@ -4236,6 +4277,13 @@ deepmerge@^4.0.0, deepmerge@^4.2.2:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
defaults@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d"
integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=
dependencies:
clone "^1.0.2"
defer-to-connect@^1.0.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
@ -5223,6 +5271,15 @@ extend@^3.0.0, extend@^3.0.2, extend@~3.0.2:
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
external-editor@^3.0.3:
version "3.1.0"
resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495"
integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==
dependencies:
chardet "^0.7.0"
iconv-lite "^0.4.24"
tmp "^0.0.33"
extglob@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543"
@ -5311,7 +5368,7 @@ fd-slicer@~1.1.0:
dependencies:
pend "~1.2.0"
figures@^3.2.0:
figures@^3.0.0, figures@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
@ -6464,7 +6521,7 @@ humanize-ms@^1.2.1:
dependencies:
ms "^2.0.0"
iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==
@ -6578,6 +6635,27 @@ ini@^2.0.0:
resolved "https://registry.yarnpkg.com/ini/-/ini-2.0.0.tgz#e5fd556ecdd5726be978fa1001862eacb0a94bc5"
integrity sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==
inquirer@8.2.4:
version "8.2.4"
resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.4.tgz#ddbfe86ca2f67649a67daa6f1051c128f684f0b4"
integrity sha512-nn4F01dxU8VeKfq192IjLsxu0/OmMZ4Lg3xKAns148rCaXP6ntAoEkVYZThWjwON8AlzdZZi6oqnhNbxUG9hVg==
dependencies:
ansi-escapes "^4.2.1"
chalk "^4.1.1"
cli-cursor "^3.1.0"
cli-width "^3.0.0"
external-editor "^3.0.3"
figures "^3.0.0"
lodash "^4.17.21"
mute-stream "0.0.8"
ora "^5.4.1"
run-async "^2.4.0"
rxjs "^7.5.5"
string-width "^4.1.0"
strip-ansi "^6.0.0"
through "^2.3.6"
wrap-ansi "^7.0.0"
install-artifact-from-github@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/install-artifact-from-github/-/install-artifact-from-github-1.3.0.tgz#cab6ff821976b8a35b0c079da19a727c90381a40"
@ -6851,6 +6929,11 @@ is-hexadecimal@^1.0.0:
resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7"
integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==
is-interactive@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
is-invalid-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/is-invalid-path/-/is-invalid-path-0.1.0.tgz#307a855b3cf1a938b44ea70d2c61106053714f34"
@ -7965,7 +8048,7 @@ lodash@4.17.21, lodash@^4.14.2, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.1
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@4.1.0:
log-symbols@4.1.0, log-symbols@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
@ -8404,6 +8487,11 @@ mime@^2.4.6, mime@^2.5.0:
resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367"
integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==
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==
mimic-fn@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-3.0.0.tgz#76044cfa8818bbf6999c5c9acadf2d3649b14b4b"
@ -8641,6 +8729,11 @@ multer@1.4.4:
type-is "^1.6.4"
xtend "^4.0.0"
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==
mv@~2:
version "2.1.1"
resolved "https://registry.yarnpkg.com/mv/-/mv-2.1.1.tgz#ae6ce0d6f6d5e0a4f7d893798d03c1ea9559b6a2"
@ -9130,6 +9223,13 @@ once@1.4.0, once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
onetime@^5.1.0:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
dependencies:
mimic-fn "^2.1.0"
optimist@>=0.3.0:
version "0.6.1"
resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686"
@ -9162,12 +9262,27 @@ optionator@^0.9.1:
type-check "^0.4.0"
word-wrap "^1.2.3"
ora@^5.4.1:
version "5.4.1"
resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
dependencies:
bl "^4.1.0"
chalk "^4.1.0"
cli-cursor "^3.1.0"
cli-spinners "^2.5.0"
is-interactive "^1.0.0"
is-unicode-supported "^0.1.0"
log-symbols "^4.1.0"
strip-ansi "^6.0.0"
wcwidth "^1.0.1"
os-homedir@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3"
integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M=
os-tmpdir@^1.0.0:
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"
integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=
@ -10360,6 +10475,14 @@ responselike@^2.0.0:
dependencies:
lowercase-keys "^2.0.0"
restore-cursor@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e"
integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==
dependencies:
onetime "^5.1.0"
signal-exit "^3.0.2"
ret@~0.1.10:
version "0.1.15"
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
@ -10411,6 +10534,18 @@ rss@1.2.2:
mime-types "2.1.13"
xml "1.0.1"
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==
rxjs@^7.5.5:
version "7.5.5"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f"
integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw==
dependencies:
tslib "^2.1.0"
safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
@ -11300,6 +11435,11 @@ text-table@^0.2.0:
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=
through@^2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
thunkify@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/thunkify/-/thunkify-2.1.2.tgz#faa0e9d230c51acc95ca13a361ac05ca7e04553d"
@ -11354,6 +11494,13 @@ tmp@0.2.1:
dependencies:
rimraf "^3.0.0"
tmp@^0.0.33:
version "0.0.33"
resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9"
integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==
dependencies:
os-tmpdir "~1.0.2"
tmpl@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
@ -11472,7 +11619,7 @@ tslib@^1.11.1, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.0.1, tslib@^2.0.3, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1:
tslib@^2.0.1, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@^2.3.1:
version "2.4.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3"
integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==
@ -11518,6 +11665,11 @@ type-fest@^0.20.2:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
type-fest@^0.21.3:
version "0.21.3"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37"
integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==
type-fest@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
@ -11999,6 +12151,13 @@ walker@^1.0.7:
dependencies:
makeerror "1.0.12"
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=
dependencies:
defaults "^1.0.3"
web-resource-inliner@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/web-resource-inliner/-/web-resource-inliner-5.0.0.tgz#ac30db8096931f20a7c1b3ade54ff444e2e20f7b"