From b6551129382c333324e5ba1bf0583c5bec83533f Mon Sep 17 00:00:00 2001 From: DavidWells Date: Thu, 18 Jul 2019 16:17:56 -0700 Subject: [PATCH 1/6] =?UTF-8?q?add=20global=20flag=20support=20for=20?= =?UTF-8?q?=E2=80=94silent,=20=E2=80=94json,=20=E2=80=94auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/index.js b/src/index.js index f06c5a0..524b7c4 100644 --- a/src/index.js +++ b/src/index.js @@ -65,6 +65,43 @@ class BaseCommand extends Command { } } + parse(opts, argv = this.argv) { + /* enrich parse with global flags */ + const globalFlags = {} + if (opts.flags && !opts.flags.silent) { + globalFlags['silent'] = { + parse: (b, _) => b, + description: 'Silence CLI output', + allowNo: false, + type: 'boolean' + } + } + if (opts.flags && !opts.flags.json) { + globalFlags['json'] = { + parse: (b, _) => b, + description: 'Output return values as JSON', + allowNo: false, + type: 'boolean' + } + } + if (opts.flags && !opts.flags.auth) { + globalFlags['auth'] = { + parse: (b, _) => b, + description: 'Netlify auth token', + input: [], + multiple: false, + type: 'option' + } + } + + // enrich with flags here + opts.flags = Object.assign({}, opts.flags, globalFlags) + + return require('@oclif/parser').parse(argv, Object.assign({}, { + context: this, + }, opts)) + } + /** * Get user netlify API token * @param {string} - [tokenFromFlag] - value passed in by CLI flag From d308c4da351ca378a3335082d49eeb69f367dd74 Mon Sep 17 00:00:00 2001 From: DavidWells Date: Thu, 18 Jul 2019 16:20:23 -0700 Subject: [PATCH 2/6] add parser dep --- package-lock.json | 20 ++++++++++++++++---- package.json | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0c02f6c..34ed1a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -529,13 +529,25 @@ "integrity": "sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw==" }, "@oclif/parser": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.7.2.tgz", - "integrity": "sha512-ssYXztaf9TuOGCJQOYMg62L1Q4y2lB4wZORWng+Iy0ckP2A6IUnQy97V8YjAJkkohYZOu3Mga8LGfQcf+xdIIw==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/@oclif/parser/-/parser-3.8.3.tgz", + "integrity": "sha512-zN+3oGuv9Lg8NjFvxZTDKFEmhAMfAvd/JWeQp3Ri8pDezoyJQi4OSHHLM8sdHjBh8sePewfWI7+fDUXdrVbrqg==", "requires": { "@oclif/linewrap": "^1.0.0", - "chalk": "^2.4.1", + "chalk": "^2.4.2", "tslib": "^1.9.3" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } } }, "@oclif/plugin-help": { diff --git a/package.json b/package.json index 2b6ee8d..89d3c69 100644 --- a/package.json +++ b/package.json @@ -72,6 +72,7 @@ "dependencies": { "@iarna/toml": "^2.2.1", "@oclif/command": "^1.5.8", + "@oclif/parser": "^3.8.3", "chalk": "^2.4.1", "ci-info": "^2.0.0", "cli-ux": "^5.0.0", From 1af482ad006cdb9fd9d05ad04ee346cf0f9e911a Mon Sep 17 00:00:00 2001 From: DavidWells Date: Thu, 18 Jul 2019 16:25:44 -0700 Subject: [PATCH 3/6] =?UTF-8?q?suppress=20logs=20if=20=E2=80=94silent=20fl?= =?UTF-8?q?ag=20passed=20into=20command?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 524b7c4..18d546a 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ const { Command } = require('@oclif/command') const chalk = require('chalk') const API = require('netlify') +const { format, inspect } = require('util') const getConfigPath = require('./utils/get-config-path') const readConfig = require('./utils/read-config') const globalConfig = require('./global-config') @@ -65,6 +66,14 @@ class BaseCommand extends Command { } } + log(message = '', ...args) { + if (this.argv && this.argv.includes('--silent')) { + return + } + message = typeof message === 'string' ? message : inspect(message) + process.stdout.write(format(message, ...args) + '\n') + } + parse(opts, argv = this.argv) { /* enrich parse with global flags */ const globalFlags = {} @@ -197,4 +206,4 @@ class BaseCommand extends Command { } } -module.exports = BaseCommand \ No newline at end of file +module.exports = BaseCommand From 480590f966b7f807840d5bfbbb521c37f373ea98 Mon Sep 17 00:00:00 2001 From: DavidWells Date: Mon, 22 Jul 2019 12:31:32 -0700 Subject: [PATCH 4/6] =?UTF-8?q?Add=20`logJson`=20and=20ignore=20logs=20if?= =?UTF-8?q?=20=E2=80=94json=20passed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/index.js | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/index.js b/src/index.js index 18d546a..52e0c54 100644 --- a/src/index.js +++ b/src/index.js @@ -25,7 +25,8 @@ class BaseCommand extends Command { async init(err) { const projectRoot = findRoot(process.cwd()) // Grab netlify API token - const [ token ] = this.getConfigToken(argv.auth) + const authViaFlag = argv.auth || argv.a + const [ token ] = this.getConfigToken(authViaFlag) // Get site config from netlify.toml const configPath = getConfigPath(projectRoot) // TODO: https://github.com/request/caseless to handle key casing issues @@ -66,8 +67,15 @@ class BaseCommand extends Command { } } + logJson(message = '', ...args) { + if (!argv.json) { + return + } + process.stdout.write(JSON.stringify(message, null, 2)) + } + log(message = '', ...args) { - if (this.argv && this.argv.includes('--silent')) { + if (this.argv && this.argv.includes('--silent') || argv.silent || argv.json) { return } message = typeof message === 'string' ? message : inspect(message) @@ -75,9 +83,13 @@ class BaseCommand extends Command { } parse(opts, argv = this.argv) { + // Set flags object for commands without flags + if (!opts.flags) { + opts.flags = {} + } /* enrich parse with global flags */ const globalFlags = {} - if (opts.flags && !opts.flags.silent) { + if (!opts.flags.silent) { globalFlags['silent'] = { parse: (b, _) => b, description: 'Silence CLI output', @@ -85,7 +97,7 @@ class BaseCommand extends Command { type: 'boolean' } } - if (opts.flags && !opts.flags.json) { + if (!opts.flags.json) { globalFlags['json'] = { parse: (b, _) => b, description: 'Output return values as JSON', @@ -93,7 +105,7 @@ class BaseCommand extends Command { type: 'boolean' } } - if (opts.flags && !opts.flags.auth) { + if (!opts.flags.auth) { globalFlags['auth'] = { parse: (b, _) => b, description: 'Netlify auth token', From e77acca20672f8c98d548abede4044ba121d7f70 Mon Sep 17 00:00:00 2001 From: DavidWells Date: Mon, 22 Jul 2019 14:38:22 -0700 Subject: [PATCH 5/6] use global argv for logger --- src/index.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 52e0c54..6b7195e 100644 --- a/src/index.js +++ b/src/index.js @@ -25,7 +25,8 @@ class BaseCommand extends Command { async init(err) { const projectRoot = findRoot(process.cwd()) // Grab netlify API token - const authViaFlag = argv.auth || argv.a + const authViaFlag = getAuthArg(argv) + const [ token ] = this.getConfigToken(authViaFlag) // Get site config from netlify.toml const configPath = getConfigPath(projectRoot) @@ -68,6 +69,7 @@ class BaseCommand extends Command { } logJson(message = '', ...args) { + /* Only run json logger when --json flag present */ if (!argv.json) { return } @@ -75,15 +77,17 @@ class BaseCommand extends Command { } log(message = '', ...args) { - if (this.argv && this.argv.includes('--silent') || argv.silent || argv.json) { + /* If --silent or --json flag passed disable logger */ + if (argv.silent || argv.json) { return } message = typeof message === 'string' ? message : inspect(message) process.stdout.write(format(message, ...args) + '\n') } + /* Modified flag parser to support global --auth, --json, & --silent flags */ parse(opts, argv = this.argv) { - // Set flags object for commands without flags + /* Set flags object for commands without flags */ if (!opts.flags) { opts.flags = {} } @@ -218,4 +222,12 @@ class BaseCommand extends Command { } } +function getAuthArg(cliArgs) { + // If deploy command. Support shorthand 'a' flag + if (cliArgs && cliArgs._ && cliArgs._[0] === 'deploy') { + return cliArgs.auth || cliArgs.a + } + return cliArgs.auth +} + module.exports = BaseCommand From d1f89d6008dda14857c275582d49ee2906867009 Mon Sep 17 00:00:00 2001 From: DavidWells Date: Mon, 22 Jul 2019 17:11:40 -0700 Subject: [PATCH 6/6] add chalk API proxy --- src/index.js | 15 ++++++++++----- src/utils/chalk.js | 48 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 src/utils/chalk.js diff --git a/src/index.js b/src/index.js index 6b7195e..3916399 100644 --- a/src/index.js +++ b/src/index.js @@ -1,15 +1,16 @@ const { Command } = require('@oclif/command') -const chalk = require('chalk') const API = require('netlify') +const merge = require('lodash.merge') const { format, inspect } = require('util') const getConfigPath = require('./utils/get-config-path') const readConfig = require('./utils/read-config') const globalConfig = require('./global-config') const StateConfig = require('./state') +const chalkInstance = require('./utils/chalk') const openBrowser = require('./utils/open-browser') const findRoot = require('./utils/find-root') const { track, identify } = require('./utils/telemetry') -const merge = require('lodash.merge') + const argv = require('minimist')(process.argv.slice(2)) const { NETLIFY_AUTH_TOKEN } = process.env @@ -127,6 +128,10 @@ class BaseCommand extends Command { }, opts)) } + get chalk() { + // If --json flag disable chalk colors + return chalkInstance(argv.json) + } /** * Get user netlify API token * @param {string} - [tokenFromFlag] - value passed in by CLI flag @@ -212,11 +217,11 @@ class BaseCommand extends Command { // Log success this.log() - this.log(`${chalk.greenBright('You are now logged into your Netlify account!')}`) + this.log(`${this.chalk.greenBright('You are now logged into your Netlify account!')}`) this.log() - this.log(`Run ${chalk.cyanBright('netlify status')} for account details`) + this.log(`Run ${this.chalk.cyanBright('netlify status')} for account details`) this.log() - this.log(`To see all available commands run: ${chalk.cyanBright('netlify help')}`) + this.log(`To see all available commands run: ${this.chalk.cyanBright('netlify help')}`) this.log() return accessToken } diff --git a/src/utils/chalk.js b/src/utils/chalk.js new file mode 100644 index 0000000..358ef3b --- /dev/null +++ b/src/utils/chalk.js @@ -0,0 +1,48 @@ +const chalk = require('chalk') + +/** + * Chalk instance for CLI + * @param {boolean} noColors - disable chalk colors + * @return {object} - chalk instance or proxy noOp + */ +function safeChalk(noColors) { + /* if no colors return proxy to chalk API */ + if (noColors) { + return neverNull(chalk) + } + return chalk +} + +function noop() {} + +function neverNull(obj) { + function match(some, none = noop) { + return obj != null ? some(obj) : none() + } + return new Proxy((some, none) => { + if (some) { + // has value return it with no chalk wrapper + return some + } + if (!some && !none) return obj + return match(some, none) + }, { + get: (target, key) => { + const obj = target() + if (obj !== null && typeof obj === 'object') { + return neverNull(obj[key]) + } else { + return neverNull() + } + }, + set: (target, key, val) => { + const obj = target() + if (obj !== null && typeof obj === 'object') { + obj[key] = val + } + return true + } + }) +} + +module.exports = safeChalk \ No newline at end of file