diff --git a/bin/now-alias.js b/bin/now-alias.js index 0c02d69..00d2e78 100755 --- a/bin/now-alias.js +++ b/bin/now-alias.js @@ -1,18 +1,18 @@ #!/usr/bin/env node // Packages -import chalk from 'chalk'; -import minimist from 'minimist'; -import table from 'text-table'; -import ms from 'ms'; +import chalk from 'chalk' +import minimist from 'minimist' +import table from 'text-table' +import ms from 'ms' // Ours -import strlen from '../lib/strlen'; -import NowAlias from '../lib/alias'; -import login from '../lib/login'; -import * as cfg from '../lib/cfg'; -import { error } from '../lib/error'; -import toHost from '../lib/to-host'; +import strlen from '../lib/strlen' +import NowAlias from '../lib/alias' +import login from '../lib/login' +import * as cfg from '../lib/cfg' +import {error} from '../lib/error' +import toHost from '../lib/to-host' const argv = minimist(process.argv.slice(2), { string: ['config', 'token'], @@ -23,8 +23,8 @@ const argv = minimist(process.argv.slice(2), { debug: 'd', token: 't' } -}); -const subcommand = argv._[0]; +}) +const subcommand = argv._[0] // options const help = () => { @@ -70,209 +70,218 @@ const help = () => { To get the list of alias ids, use ${chalk.dim('`now alias ls`')}. ${chalk.dim('Alias:')} ln -`); -}; +`) +} // options -const debug = argv.debug; -const apiUrl = argv.url || 'https://api.zeit.co'; -if (argv.config) cfg.setConfigFile(argv.config); +const debug = argv.debug +const apiUrl = argv.url || 'https://api.zeit.co' + +if (argv.config) { + cfg.setConfigFile(argv.config) +} -const exit = (code) => { +const exit = code => { // we give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 - setTimeout(() => process.exit(code || 0), 100); -}; + setTimeout(() => process.exit(code || 0), 100) +} if (argv.help || !subcommand) { - help(); - exit(0); + help() + exit(0) } else { - const config = cfg.read(); + const config = cfg.read() Promise.resolve(argv.token || config.token || login(apiUrl)) - .then(async (token) => { + .then(async token => { try { - await run(token); + await run(token) } catch (err) { if (err.userError) { - error(err.message); + error(err.message) } else { - error(`Unknown error: ${err.stack}`); + error(`Unknown error: ${err.stack}`) } - exit(1); + exit(1) } }) - .catch((e) => { - error(`Authentication error – ${e.message}`); - exit(1); - }); + .catch(e => { + error(`Authentication error – ${e.message}`) + exit(1) + }) } -async function run (token) { - const alias = new NowAlias(apiUrl, token, { debug }); - const args = argv._.slice(1); +async function run(token) { + const alias = new NowAlias(apiUrl, token, {debug}) + const args = argv._.slice(1) switch (subcommand) { case 'list': case 'ls': - if (0 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now alias ls`')}`); - return exit(1); + if (args.length !== 0) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now alias ls`')}`) + return exit(1) } - const start_ = new Date(); - const list = await alias.list(); - const urls = new Map(list.map(l => [l.uid, l.url])); - const aliases = await alias.ls(); - aliases.sort((a, b) => new Date(b.created) - new Date(a.created)); - const current = new Date(); - - const header = [['', 'id', 'source', 'url', 'created'].map(s => chalk.dim(s))]; - const text = 0 === list.length ? null : table(header.concat(aliases.map((_alias) => { - const _url = chalk.underline(`https://${_alias.alias}`); - const target = _alias.deploymentId; - const _sourceUrl = urls.get(target) - ? chalk.underline(`https://${urls.get(target)}`) - : chalk.gray(''); - - const time = chalk.gray(ms(current - new Date(_alias.created)) + ' ago'); + const start_ = new Date() + const list = await alias.list() + const urls = new Map(list.map(l => [l.uid, l.url])) + const aliases = await alias.ls() + aliases.sort((a, b) => new Date(b.created) - new Date(a.created)) + const current = new Date() + + const header = [['', 'id', 'source', 'url', 'created'].map(s => chalk.dim(s))] + const text = list.length === 0 ? null : table(header.concat(aliases.map(_alias => { + const _url = chalk.underline(`https://${_alias.alias}`) + const target = _alias.deploymentId + const _sourceUrl = urls.get(target) ? chalk.underline(`https://${urls.get(target)}`) : chalk.gray('') + + const time = chalk.gray(ms(current - new Date(_alias.created)) + ' ago') return [ '', // we default to `''` because some early aliases didn't // have an uid associated - null == _alias.uid ? '' : _alias.uid, + _alias.uid === null ? '' : _alias.uid, _sourceUrl, _url, time - ]; - })), { align: ['l', 'r', 'l', 'l'], hsep: ' '.repeat(2), stringLength: strlen }); + ] + })), {align: ['l', 'r', 'l', 'l'], hsep: ' '.repeat(2), stringLength: strlen}) + + const elapsed_ = ms(new Date() - start_) + console.log(`> ${aliases.length} alias${aliases.length === 1 ? '' : 'es'} found ${chalk.gray(`[${elapsed_}]`)}`) - const elapsed_ = ms(new Date() - start_); - console.log(`> ${aliases.length} alias${aliases.length !== 1 ? 'es' : ''} found ${chalk.gray(`[${elapsed_}]`)}`); - if (text) console.log('\n' + text + '\n'); - break; + if (text) { + console.log('\n' + text + '\n') + } + + break case 'remove': case 'rm': - const _target = String(args[0]); + const _target = String(args[0]) if (!_target) { - const err = new Error('No alias id specified'); - err.userError = true; - throw err; + const err = new Error('No alias id specified') + err.userError = true + throw err } - if (1 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now alias rm `')}`); - return exit(1); + if (args.length !== 1) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now alias rm `')}`) + return exit(1) } - const _aliases = await alias.ls(); - const _alias = findAlias(_target, _aliases); + const _aliases = await alias.ls() + const _alias = findAlias(_target, _aliases) if (!_alias) { - const err = new Error(`Alias not found by "${_target}". Run ${chalk.dim('`now alias ls`')} to see your aliases.`); - err.userError = true; - throw err; + const err = new Error(`Alias not found by "${_target}". Run ${chalk.dim('`now alias ls`')} to see your aliases.`) + err.userError = true + throw err } try { - const confirmation = (await readConfirmation(alias, _alias, _aliases)).toLowerCase(); - if ('y' !== confirmation && 'yes' !== confirmation) { - console.log('\n> Aborted'); - process.exit(0); + const confirmation = (await readConfirmation(alias, _alias, _aliases)).toLowerCase() + if (confirmation !== 'y' && confirmation !== 'yes') { + console.log('\n> Aborted') + process.exit(0) } - const start = new Date(); - await alias.rm(_alias); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Alias ${chalk.bold(_alias.uid)} removed [${elapsed}]`); + const start = new Date() + await alias.rm(_alias) + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} Alias ${chalk.bold(_alias.uid)} removed [${elapsed}]`) } catch (err) { - error(err); - exit(1); + error(err) + exit(1) } - break; + break case 'add': case 'set': - if (2 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now alias set `')}`); - return exit(1); + if (args.length !== 2) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now alias set `')}`) + return exit(1) } - await alias.set(String(args[0]), String(args[1])); - break; + await alias.set(String(args[0]), String(args[1])) + break default: - if (2 === argv._.length) { - await alias.set(String(argv._[0]), String(argv._[1])); + if (argv._.length === 2) { + await alias.set(String(argv._[0]), String(argv._[1])) } else if (argv._.length >= 3) { - error('Invalid number of arguments'); - help(); - exit(1); + error('Invalid number of arguments') + help() + exit(1) } else { - error('Please specify a valid subcommand: ls | set | rm'); - help(); - exit(1); + error('Please specify a valid subcommand: ls | set | rm') + help() + exit(1) } } - alias.close(); + alias.close() } -function indent (text, n) { - return text.split('\n').map((l) => ' '.repeat(n) + l).join('\n'); -} +async function readConfirmation(alias, _alias) { + const deploymentsList = await alias.list() + const urls = new Map(deploymentsList.map(l => [l.uid, l.url])) -async function readConfirmation (alias, _alias, list) { - const deploymentsList = await alias.list(); - const urls = new Map(deploymentsList.map(l => [l.uid, l.url])); - - return new Promise((resolve, reject) => { - const time = chalk.gray(ms(new Date() - new Date(_alias.created)) + ' ago'); - const _sourceUrl = chalk.underline(`https://${urls.get(_alias.deploymentId)}`); + return new Promise(resolve => { + const time = chalk.gray(ms(new Date() - new Date(_alias.created)) + ' ago') + const _sourceUrl = chalk.underline(`https://${urls.get(_alias.deploymentId)}`) const tbl = table( [[_alias.uid, _sourceUrl, chalk.underline(`https://${_alias.alias}`), time]], - { align: ['l', 'r', 'l'], hsep: ' '.repeat(6) } - ); - - process.stdout.write('> The following alias will be removed permanently\n'); - process.stdout.write(' ' + tbl + '\n'); - process.stdout.write(` ${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`); - - process.stdin.on('data', (d) => { - process.stdin.pause(); - resolve(d.toString().trim()); - }).resume(); - }); + {align: ['l', 'r', 'l'], hsep: ' '.repeat(6)} + ) + + process.stdout.write('> The following alias will be removed permanently\n') + process.stdout.write(' ' + tbl + '\n') + process.stdout.write(` ${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`) + + process.stdin.on('data', d => { + process.stdin.pause() + resolve(d.toString().trim()) + }).resume() + }) } -function findAlias (alias, list) { - let key, val; +function findAlias(alias, list) { + let key + let val + if (/\./.test(alias)) { - val = toHost(alias); - key = 'alias'; + val = toHost(alias) + key = 'alias' } else { - val = alias; - key = 'uid'; + val = alias + key = 'uid' } - const _alias = list.find((d) => { + const _alias = list.find(d => { if (d[key] === val) { - if (debug) console.log(`> [debug] matched alias ${d.uid} by ${key} ${val}`); - return true; + if (debug) { + console.log(`> [debug] matched alias ${d.uid} by ${key} ${val}`) + } + + return true } // match prefix if (`${val}.now.sh` === d.alias) { - if (debug) console.log(`> [debug] matched alias ${d.uid} by url ${d.host}`); - return true; + if (debug) { + console.log(`> [debug] matched alias ${d.uid} by url ${d.host}`) + } + + return true } - return false; - }); + return false + }) - return _alias; + return _alias } diff --git a/bin/now-certs.js b/bin/now-certs.js index 51f3c3a..c3425c9 100755 --- a/bin/now-certs.js +++ b/bin/now-certs.js @@ -1,20 +1,21 @@ #!/usr/bin/env node // Native -import path from 'path'; +import path from 'path' // Packages -import chalk from 'chalk'; -import table from 'text-table'; -import minimist from 'minimist'; -import fs from 'fs-promise'; -import ms from 'ms'; +import chalk from 'chalk' +import table from 'text-table' +import minimist from 'minimist' +import fs from 'fs-promise' +import ms from 'ms' // Ours -import strlen from '../lib/strlen'; -import * as cfg from '../lib/cfg'; -import {handleError, error} from '../lib/error'; -import NowCerts from '../lib/certs'; +import strlen from '../lib/strlen' +import * as cfg from '../lib/cfg' +import {handleError, error} from '../lib/error' +import NowCerts from '../lib/certs' +import login from '../lib/login' const argv = minimist(process.argv.slice(2), { string: ['config', 'token', 'crt', 'key', 'ca'], @@ -25,8 +26,9 @@ const argv = minimist(process.argv.slice(2), { debug: 'd', token: 't' } -}); -const subcommand = argv._[0]; +}) + +const subcommand = argv._[0] // options const help = () => { @@ -64,190 +66,199 @@ const help = () => { ${chalk.gray('–')} Replacing an existing certificate with a user-supplied certificate: ${chalk.cyan('$ now certs replace --crt domain.crt --key domain.key --ca ca_chain.crt domain.com')} -`); -}; +`) +} // options -const debug = argv.debug; -const apiUrl = argv.url || 'https://api.zeit.co'; -if (argv.config) cfg.setConfigFile(argv.config); +const debug = argv.debug +const apiUrl = argv.url || 'https://api.zeit.co' + +if (argv.config) { + cfg.setConfigFile(argv.config) +} -const exit = (code) => { +const exit = code => { // we give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 - setTimeout(() => process.exit(code || 0), 100); -}; + setTimeout(() => process.exit(code || 0), 100) +} if (argv.help || !subcommand) { - help(); - exit(0); + help() + exit(0) } else { - const config = cfg.read(); + const config = cfg.read() Promise.resolve(argv.token || config.token || login(apiUrl)) - .then(async (token) => { + .then(async token => { try { - await run(token); + await run(token) } catch (err) { - handleError(err); - exit(1); + handleError(err) + exit(1) } }) - .catch((e) => { - error(`Authentication error – ${e.message}`); - exit(1); - }); + .catch(e => { + error(`Authentication error – ${e.message}`) + exit(1) + }) } -function formatExpirationDate (date) { - const diff = date - Date.now(); - return diff < 0 ? chalk.gray(ms(new Date(-diff)) + ' ago') : chalk.gray('in ' + ms(new Date(diff))); +function formatExpirationDate(date) { + const diff = date - Date.now() + return diff < 0 ? chalk.gray(ms(new Date(-diff)) + ' ago') : chalk.gray('in ' + ms(new Date(diff))) } -async function run (token) { - const certs = new NowCerts(apiUrl, token, { debug }); - const args = argv._.slice(1); - const start = Date.now(); +async function run(token) { + const certs = new NowCerts(apiUrl, token, {debug}) + const args = argv._.slice(1) + const start = Date.now() - if ('ls' === subcommand || 'list' === subcommand) { - if (0 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs ls`')}`); - return exit(1); + if (subcommand === 'ls' || subcommand === 'list') { + if (args.length !== 0) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs ls`')}`) + return exit(1) } - const list = await certs.ls(); - const elapsed = ms(new Date() - start); - console.log(`> ${list.length} certificate${list.length !== 1 ? 's' : ''} found ${chalk.gray(`[${elapsed}]`)}`); - if (0 < list.length) { - const cur = Date.now(); + const list = await certs.ls() + const elapsed = ms(new Date() - start) + + console.log(`> ${list.length} certificate${list.length === 1 ? '' : 's'} found ${chalk.gray(`[${elapsed}]`)}`) + + if (list.length > 0) { + const cur = Date.now() list.sort((a, b) => { - return a.cn.localeCompare(b.cn); - }); - const header = [['', 'id', 'cn', 'created', 'expiration'].map(s => chalk.dim(s))]; - const out = table(header.concat(list.map((cert) => { - const cn = chalk.bold(cert.cn); - const time = chalk.gray(ms(cur - new Date(cert.created)) + ' ago'); - const expiration = formatExpirationDate(new Date(cert.expiration)); + return a.cn.localeCompare(b.cn) + }) + const header = [['', 'id', 'cn', 'created', 'expiration'].map(s => chalk.dim(s))] + const out = table(header.concat(list.map(cert => { + const cn = chalk.bold(cert.cn) + const time = chalk.gray(ms(cur - new Date(cert.created)) + ' ago') + const expiration = formatExpirationDate(new Date(cert.expiration)) return [ '', cert.uid ? cert.uid : 'unknown', cn, time, expiration - ]; - })), { align: ['l', 'r', 'l', 'l', 'l'], hsep: ' '.repeat(2), stringLength: strlen }); - if (out) console.log('\n' + out + '\n'); + ] + })), {align: ['l', 'r', 'l', 'l', 'l'], hsep: ' '.repeat(2), stringLength: strlen}) + + if (out) { + console.log('\n' + out + '\n') + } } - } else if ('create' === subcommand) { - if (1 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs create `')}`); - return exit(1); + } else if (subcommand === 'create') { + if (args.length !== 1) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs create `')}`) + return exit(1) } - const cn = args[0]; - const cert = await certs.create(cn); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Certificate ${chalk.bold(cn)} ${chalk.gray(`(${cert.uid})`)} issued ${chalk.gray(`[${elapsed}]`)}`); - } else if ('renew' === subcommand) { - if (1 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs renew `')}`); - return exit(1); + const cn = args[0] + const cert = await certs.create(cn) + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} Certificate ${chalk.bold(cn)} ${chalk.gray(`(${cert.uid})`)} issued ${chalk.gray(`[${elapsed}]`)}`) + } else if (subcommand === 'renew') { + if (args.length !== 1) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs renew `')}`) + return exit(1) } - const cert = await getCertIdCn(certs, args[0]); - const yes = await readConfirmation(cert, 'The following certificate will be renewed\n'); + const cert = await getCertIdCn(certs, args[0]) + const yes = await readConfirmation(cert, 'The following certificate will be renewed\n') + if (!yes) { - error('User abort'); - return exit(0); + error('User abort') + return exit(0) } - await certs.renew(cert.cn); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Certificate ${chalk.bold(cert.cn)} ${chalk.gray(`(${cert.uid})`)} renewed ${chalk.gray(`[${elapsed}]`)}`); - } else if ('replace' === subcommand) { + await certs.renew(cert.cn) + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} Certificate ${chalk.bold(cert.cn)} ${chalk.gray(`(${cert.uid})`)} renewed ${chalk.gray(`[${elapsed}]`)}`) + } else if (subcommand === 'replace') { if (!argv.crt || !argv.key) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs replace --crt DOMAIN.CRT --key DOMAIN.KEY [--ca CA.CRT] `')}`); - return exit(1); + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs replace --crt DOMAIN.CRT --key DOMAIN.KEY [--ca CA.CRT] `')}`) + return exit(1) } - const crt = readX509File(argv.crt); - const key = readX509File(argv.key); - const ca = argv.ca ? readX509File(argv.ca) : ''; + const crt = readX509File(argv.crt) + const key = readX509File(argv.key) + const ca = argv.ca ? readX509File(argv.ca) : '' - const cert = await getCertIdCn(certs, args[0]); - const yes = await readConfirmation(cert, 'The following certificate will be replaced permanently\n'); + const cert = await getCertIdCn(certs, args[0]) + const yes = await readConfirmation(cert, 'The following certificate will be replaced permanently\n') if (!yes) { - error('User abort'); - return exit(0); + error('User abort') + return exit(0) } - await certs.replace(cert.cn, crt, key, ca); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Certificate ${chalk.bold(cert.cn)} ${chalk.gray(`(${cert.uid})`)} replaced ${chalk.gray(`[${elapsed}]`)}`); - } else if ('rm' === subcommand || 'remove' === subcommand) { - if (1 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs rm `')}`); - return exit(1); + await certs.replace(cert.cn, crt, key, ca) + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} Certificate ${chalk.bold(cert.cn)} ${chalk.gray(`(${cert.uid})`)} replaced ${chalk.gray(`[${elapsed}]`)}`) + } else if (subcommand === 'rm' || subcommand === 'remove') { + if (args.length !== 1) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now certs rm `')}`) + return exit(1) } - const cert = await getCertIdCn(certs, args[0]); - const yes = await readConfirmation(cert, 'The following certificate will be removed permanently\n'); + const cert = await getCertIdCn(certs, args[0]) + const yes = await readConfirmation(cert, 'The following certificate will be removed permanently\n') if (!yes) { - error('User abort'); - return exit(0); + error('User abort') + return exit(0) } - await certs.delete(cert.cn); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Certificate ${chalk.bold(cert.cn)} ${chalk.gray(`(${cert.uid})`)} removed ${chalk.gray(`[${elapsed}]`)}`); + await certs.delete(cert.cn) + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} Certificate ${chalk.bold(cert.cn)} ${chalk.gray(`(${cert.uid})`)} removed ${chalk.gray(`[${elapsed}]`)}`) } else { - error('Please specify a valid subcommand: ls | create | renew | replace | rm'); - help(); - exit(1); + error('Please specify a valid subcommand: ls | create | renew | replace | rm') + help() + exit(1) } - return certs.close(); + return certs.close() } -process.on('uncaughtException', (err) => { - handleError(err); - exit(1); -}); +process.on('uncaughtException', err => { + handleError(err) + exit(1) +}) -function readConfirmation (cert, msg) { - return new Promise((resolve, reject) => { - const time = chalk.gray(ms(new Date() - new Date(cert.created)) + ' ago'); +function readConfirmation(cert, msg) { + return new Promise(resolve => { + const time = chalk.gray(ms(new Date() - new Date(cert.created)) + ' ago') const tbl = table( [[cert.uid, chalk.bold(cert.cn), time]], - { align: ['l', 'r', 'l'], hsep: ' '.repeat(6) } - ); + {align: ['l', 'r', 'l'], hsep: ' '.repeat(6)} + ) - process.stdout.write(`> ${msg}`); - process.stdout.write(' ' + tbl + '\n'); + process.stdout.write(`> ${msg}`) + process.stdout.write(' ' + tbl + '\n') - process.stdout.write(`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`); + process.stdout.write(`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`) - process.stdin.on('data', (d) => { - process.stdin.pause(); - resolve('y' === d.toString().trim().toLowerCase()); - }).resume(); - }); + process.stdin.on('data', d => { + process.stdin.pause() + resolve(d.toString().trim().toLowerCase() === 'y') + }).resume() + }) } -function readX509File (file) { - return fs.readFileSync(path.resolve(file), 'utf8'); +function readX509File(file) { + return fs.readFileSync(path.resolve(file), 'utf8') } -async function getCertIdCn (certs, idOrCn) { - const list = await certs.ls(); - const thecert = list.filter((cert) => { - return cert.uid === idOrCn || cert.cn === idOrCn; - })[0]; +async function getCertIdCn(certs, idOrCn) { + const list = await certs.ls() + const thecert = list.filter(cert => { + return cert.uid === idOrCn || cert.cn === idOrCn + })[0] if (!thecert) { - error(`No certificate found by id or cn "${idOrCn}"`); - return exit(1); + error(`No certificate found by id or cn "${idOrCn}"`) + return exit(1) } - return thecert; + return thecert } diff --git a/bin/now-deploy.js b/bin/now-deploy.js index d21c5cf..d6cf171 100755 --- a/bin/now-deploy.js +++ b/bin/now-deploy.js @@ -1,26 +1,26 @@ #!/usr/bin/env node // Native -import {resolve} from 'path'; +import {resolve} from 'path' // Packages -import Progress from 'progress'; -import {stat} from 'fs-promise'; -import bytes from 'bytes'; -import chalk from 'chalk'; -import minimist from 'minimist'; -import ms from 'ms'; +import Progress from 'progress' +import {stat} from 'fs-promise' +import bytes from 'bytes' +import chalk from 'chalk' +import minimist from 'minimist' +import ms from 'ms' // Ours -import copy from '../lib/copy'; -import login from '../lib/login'; -import * as cfg from '../lib/cfg'; -import {version} from '../../package'; -import Logger from '../lib/build-logger'; -import Now from '../lib'; -import toHumanPath from '../lib/utils/to-human-path'; -import promptOptions from '../lib/utils/prompt-options'; -import {handleError, error} from '../lib/error'; +import copy from '../lib/copy' +import login from '../lib/login' +import * as cfg from '../lib/cfg' +import {version} from '../../package' +import Logger from '../lib/build-logger' +import Now from '../lib' +import toHumanPath from '../lib/utils/to-human-path' +import promptOptions from '../lib/utils/prompt-options' +import {handleError, error} from '../lib/error' const argv = minimist(process.argv.slice(2), { string: [ @@ -52,7 +52,7 @@ const argv = minimist(process.argv.slice(2), { 'no-clipboard': 'C', 'forward-npm': 'N' } -}); +}) const help = () => { console.log(` @@ -115,227 +115,243 @@ const help = () => { ${chalk.gray('–')} Displays comprehensive help for the subcommand ${chalk.dim('`list`')} ${chalk.cyan('$ now help list')} -`); -}; +`) +} -let path = argv._[0]; +let path = argv._[0] -if (null != path) { +if (path === null) { + path = process.cwd() +} else { // if path is relative: resolve // if path is absolute: clear up strange `/` etc - path = resolve(process.cwd(), path); -} else { - path = process.cwd(); + path = resolve(process.cwd(), path) } -const exit = (code) => { +const exit = code => { // we give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 - setTimeout(() => process.exit(code || 0), 100); -}; + setTimeout(() => process.exit(code || 0), 100) +} // options -const debug = argv.debug; -const clipboard = !argv['no-clipboard']; -const forwardNpm = argv['forward-npm']; -const forceNew = argv.force; -const forceSync = argv.forceSync; -const shouldLogin = argv.login; -const wantsPublic = argv.public; -const apiUrl = argv.url || 'https://api.zeit.co'; -const isTTY = process.stdout.isTTY; -const quiet = !isTTY; -if (argv.config) cfg.setConfigFile(argv.config); -const config = cfg.read(); -const alwaysForwardNpm = config.forwardNpm; +const debug = argv.debug +const clipboard = !argv['no-clipboard'] +const forwardNpm = argv['forward-npm'] +const forceNew = argv.force +const forceSync = argv.forceSync +const shouldLogin = argv.login +const wantsPublic = argv.public +const apiUrl = argv.url || 'https://api.zeit.co' +const isTTY = process.stdout.isTTY +const quiet = !isTTY + +if (argv.config) { + cfg.setConfigFile(argv.config) +} + +const config = cfg.read() +const alwaysForwardNpm = config.forwardNpm if (argv.h || argv.help) { - help(); - exit(0); + help() + exit(0) } else if (argv.v || argv.version) { - console.log(chalk.bold('𝚫 now'), version); - process.exit(0); + console.log(chalk.bold('𝚫 now'), version) + process.exit(0) } else if (!(argv.token || config.token) || shouldLogin) { login(apiUrl) - .then((token) => { + .then(token => { if (shouldLogin) { - console.log('> Logged in successfully. Token saved in ~/.now.json'); - process.exit(0); + console.log('> Logged in successfully. Token saved in ~/.now.json') + process.exit(0) } else { - sync(token).catch((err) => { - error(`Unknown error: ${err.stack}`); - process.exit(1); - }); + sync(token).catch(err => { + error(`Unknown error: ${err.stack}`) + process.exit(1) + }) } }) - .catch((e) => { - error(`Authentication error – ${e.message}`); - process.exit(1); - }); + .catch(e => { + error(`Authentication error – ${e.message}`) + process.exit(1) + }) } else { - sync(argv.token || config.token).catch((err) => { - error(`Unknown error: ${err.stack}`); - process.exit(1); - }); + sync(argv.token || config.token).catch(err => { + error(`Unknown error: ${err.stack}`) + process.exit(1) + }) } -async function sync (token) { - const start = Date.now(); +async function sync(token) { + const start = Date.now() if (!quiet) { - console.log(`> Deploying ${chalk.bold(toHumanPath(path))}`); + console.log(`> Deploying ${chalk.bold(toHumanPath(path))}`) } try { - await stat(path); + await stat(path) } catch (err) { - error(`Could not read directory ${chalk.bold(path)}`); - process.exit(1); + error(`Could not read directory ${chalk.bold(path)}`) + process.exit(1) } - let deploymentType, hasPackage, hasDockerfile; + let deploymentType + let hasPackage + let hasDockerfile if (argv.docker) { if (debug) { - console.log(`> [debug] Forcing \`deploymentType\` = \`docker\``); + console.log(`> [debug] Forcing \`deploymentType\` = \`docker\``) } - deploymentType = 'docker'; + deploymentType = 'docker' + } else if (argv.npm) { + deploymentType = 'npm' } else { - if (argv.npm) { - deploymentType = 'npm'; - } else { - try { - await stat(resolve(path, 'package.json')); - } catch (err) { - hasPackage = true; + try { + await stat(resolve(path, 'package.json')) + } catch (err) { + hasPackage = true + } + + [hasPackage, hasDockerfile] = await Promise.all([ + await (async () => { + try { + await stat(resolve(path, 'package.json')) + } catch (err) { + return false + } + return true + })(), + await (async () => { + try { + await stat(resolve(path, 'Dockerfile')) + } catch (err) { + return false + } + return true + })() + ]) + + if (hasPackage && hasDockerfile) { + if (debug) { + console.log('[debug] multiple manifests found, disambiguating') } - [hasPackage, hasDockerfile] = await Promise.all([ - await (async () => { - try { - await stat(resolve(path, 'package.json')); - } catch (err) { - return false; - } - return true; - })(), - await (async () => { - try { - await stat(resolve(path, 'Dockerfile')); - } catch (err) { - return false; - } - return true; - })() - ]); - - if (hasPackage && hasDockerfile) { - if (debug) console.log('[debug] multiple manifests found, disambiguating'); - if (isTTY) { - try { - console.log(`> Two manifests found. Press [${chalk.bold('n')}] to deploy or re-run with --flag`); - deploymentType = await promptOptions([ + if (isTTY) { + try { + console.log(`> Two manifests found. Press [${chalk.bold('n')}] to deploy or re-run with --flag`) + deploymentType = await promptOptions([ ['npm', `${chalk.bold('package.json')}\t${chalk.gray(' --npm')} `], ['docker', `${chalk.bold('Dockerfile')}\t${chalk.gray('--docker')} `] - ]); - } catch (err) { - error(err.message); - process.exit(1); - } - } else { - error('Ambiguous deployment (`package.json` and `Dockerfile` found). ' + - 'Please supply `--npm` or `--docker` to disambiguate.'); + ]) + } catch (err) { + error(err.message) + process.exit(1) } - } else if (hasPackage) { - if (debug) console.log('[debug] `package.json` found, assuming `deploymentType` = `npm`'); - deploymentType = 'npm'; - } else if (hasDockerfile) { - if (debug) console.log('[debug] `Dockerfile` found, assuming `deploymentType` = `docker`'); - deploymentType = 'docker'; } else { - error(`Could not access a ${chalk.dim('`package.json`')} or ${chalk.dim('`Dockerfile`')} in ${chalk.bold(path)}`); - console.log(`> To deploy statically, try: ${chalk.dim(chalk.underline('https://zeit.co/blog/serve-it-now'))}.`); - process.exit(1); + error('Ambiguous deployment (`package.json` and `Dockerfile` found). ' + + 'Please supply `--npm` or `--docker` to disambiguate.') + } + } else if (hasPackage) { + if (debug) { + console.log('[debug] `package.json` found, assuming `deploymentType` = `npm`') + } + + deploymentType = 'npm' + } else if (hasDockerfile) { + if (debug) { + console.log('[debug] `Dockerfile` found, assuming `deploymentType` = `docker`') } + + deploymentType = 'docker' + } else { + error(`Could not access a ${chalk.dim('`package.json`')} or ${chalk.dim('`Dockerfile`')} in ${chalk.bold(path)}`) + console.log(`> To deploy statically, try: ${chalk.dim(chalk.underline('https://zeit.co/blog/serve-it-now'))}.`) + process.exit(1) } } - const now = new Now(apiUrl, token, { debug }); - const envs = [].concat(argv.env || []); + const now = new Now(apiUrl, token, {debug}) + const envs = [].concat(argv.env || []) - let secrets; - const findSecret = async (uidOrName) => { - if (!secrets) secrets = await now.listSecrets(); - return secrets.filter((secret) => { - return secret.name === uidOrName || secret.uid === uidOrName; - }); - }; + let secrets + const findSecret = async uidOrName => { + if (!secrets) { + secrets = await now.listSecrets() + } - const env_ = await Promise.all(envs.map(async (kv) => { - const [key, ...rest] = kv.split('='); - let val; + return secrets.filter(secret => { + return secret.name === uidOrName || secret.uid === uidOrName + }) + } - if (rest.length) { - val = rest.join('='); + const env_ = await Promise.all(envs.map(async kv => { + const [key, ...rest] = kv.split('=') + let val + + if (rest.length > 0) { + val = rest.join('=') } if (/[^A-z0-9_]/i.test(key)) { - error(`Invalid ${chalk.dim('-e')} key ${chalk.bold(`"${chalk.bold(key)}"`)}. Only letters, digits and underscores are allowed.`); - return process.exit(1); + error(`Invalid ${chalk.dim('-e')} key ${chalk.bold(`"${chalk.bold(key)}"`)}. Only letters, digits and underscores are allowed.`) + return process.exit(1) } - if ('' === key || null == key) { - error(`Invalid env option ${chalk.bold(`"${kv}"`)}`); - return process.exit(1); + if (key === '' || key === null) { + error(`Invalid env option ${chalk.bold(`"${kv}"`)}`) + return process.exit(1) } - if (val == null) { - if (!(key in process.env)) { - error(`No value specified for env ${chalk.bold(`"${chalk.bold(key)}"`)} and it was not found in your env.`); - return process.exit(1); - } else { - console.log(`> Reading ${chalk.bold(`"${chalk.bold(key)}"`)} from your env (as no value was specified)`); + if (val === null) { + if ((key in process.env)) { + console.log(`> Reading ${chalk.bold(`"${chalk.bold(key)}"`)} from your env (as no value was specified)`) // escape value if it begins with @ - val = process.env[key].replace(/^\@/, '\\@'); + val = process.env[key].replace(/^\@/, '\\@') + } else { + error(`No value specified for env ${chalk.bold(`"${chalk.bold(key)}"`)} and it was not found in your env.`) + return process.exit(1) } } - if ('@' === val[0]) { - const uidOrName = val.substr(1); - const secrets = await findSecret(uidOrName); + if (val[0] === '@') { + const uidOrName = val.substr(1) + const secrets = await findSecret(uidOrName) if (secrets.length === 0) { - if ('' === uidOrName) { - error(`Empty reference provided for env key ${chalk.bold(`"${chalk.bold(key)}"`)}`); + if (uidOrName === '') { + error(`Empty reference provided for env key ${chalk.bold(`"${chalk.bold(key)}"`)}`) } else { - error(`No secret found by uid or name ${chalk.bold(`"${uidOrName}"`)}`); + error(`No secret found by uid or name ${chalk.bold(`"${uidOrName}"`)}`) } - return process.exit(1); + return process.exit(1) } else if (secrets.length > 1) { - error(`Ambiguous secret ${chalk.bold(`"${uidOrName}"`)} (matches ${chalk.bold(secrets.length)} secrets)`); - return process.exit(1); - } else { - val = { uid: secrets[0].uid }; + error(`Ambiguous secret ${chalk.bold(`"${uidOrName}"`)} (matches ${chalk.bold(secrets.length)} secrets)`) + return process.exit(1) } + + val = {uid: secrets[0].uid} } return [ key, - typeof val === 'string' - // add support for escaping the @ as \@ - ? val.replace(/^\\@/, '@') - : val - ]; - })); - - let env = {}; + typeof val === 'string' ? val.replace(/^\\@/, '@') : val + ] + })) + + const env = {} env_ - .filter(v => !!v) + .filter(v => Boolean(v)) .forEach(([key, val]) => { - if (key in env) console.log(`> ${chalk.yellow('NOTE:')} Overriding duplicate env key ${chalk.bold(`"${key}"`)}`); + if (key in env) { + console.log(`> ${chalk.yellow('NOTE:')} Overriding duplicate env key ${chalk.bold(`"${key}"`)}`) + } + env[key] = val - }); + }) try { await now.create(path, { @@ -346,45 +362,49 @@ async function sync (token) { forwardNpm: alwaysForwardNpm || forwardNpm, quiet, wantsPublic - }); + }) } catch (err) { - if (debug) console.log(`> [debug] error: ${err.stack}`); - handleError(err); - process.exit(1); + if (debug) { + console.log(`> [debug] error: ${err.stack}`) + } + + handleError(err) + process.exit(1) } - const { url } = now; - const elapsed = ms(new Date() - start); + const {url} = now + const elapsed = ms(new Date() - start) if (isTTY) { if (clipboard) { try { - await copy(url); - console.log(`${chalk.cyan('> Ready!')} ${chalk.bold(url)} (copied to clipboard) [${elapsed}]`); + await copy(url) + console.log(`${chalk.cyan('> Ready!')} ${chalk.bold(url)} (copied to clipboard) [${elapsed}]`) } catch (err) { - console.log(`${chalk.cyan('> Ready!')} ${chalk.bold(url)} [${elapsed}]`); + console.log(`${chalk.cyan('> Ready!')} ${chalk.bold(url)} [${elapsed}]`) } } else { - console.log(`> ${url} [${elapsed}]`); + console.log(`> ${url} [${elapsed}]`) } } else { - process.stdout.write(url); + process.stdout.write(url) } - const start_u = new Date(); + const startU = new Date() + const complete = () => { if (!quiet) { - const elapsed_u = ms(new Date() - start_u); - console.log(`> Sync complete (${bytes(now.syncAmount)}) [${elapsed_u}] `); - console.log('> Initializing…'); + const elapsedU = ms(new Date() - startU) + console.log(`> Sync complete (${bytes(now.syncAmount)}) [${elapsedU}] `) + console.log('> Initializing…') } // close http2 agent - now.close(); + now.close() // show build logs - printLogs(now.host); - }; + printLogs(now.host) + } if (now.syncAmount) { const bar = new Progress('> Upload [:bar] :percent :etas', { @@ -392,45 +412,45 @@ async function sync (token) { complete: '=', incomplete: '', total: now.syncAmount - }); + }) - now.upload(); + now.upload() - now.on('upload', ({ names, data }) => { - const amount = data.length; + now.on('upload', ({names, data}) => { + const amount = data.length if (debug) { - console.log(`> [debug] Uploaded: ${names.join(' ')} (${bytes(data.length)})`); + console.log(`> [debug] Uploaded: ${names.join(' ')} (${bytes(data.length)})`) } - bar.tick(amount); - }); + bar.tick(amount) + }) - now.on('complete', complete); + now.on('complete', complete) - now.on('error', (err) => { - error('Upload failed'); - handleError(err); - process.exit(1); - }); + now.on('error', err => { + error('Upload failed') + handleError(err) + process.exit(1) + }) } else { if (!quiet) { - console.log(`> Initializing…`); + console.log(`> Initializing…`) } // close http2 agent - now.close(); + now.close() // show build logs - printLogs(now.host); + printLogs(now.host) } } -function printLogs (host) { +function printLogs(host) { // log build - const logger = new Logger(host, { debug, quiet }); + const logger = new Logger(host, {debug, quiet}) logger.on('close', () => { if (!quiet) { - console.log(`${chalk.cyan('> Deployment complete!')}`); + console.log(`${chalk.cyan('> Deployment complete!')}`) } - process.exit(0); - }); + process.exit(0) + }) } diff --git a/bin/now-domains.js b/bin/now-domains.js index e8c624e..011cd46 100755 --- a/bin/now-domains.js +++ b/bin/now-domains.js @@ -1,18 +1,18 @@ #!/usr/bin/env node // Packages -import chalk from 'chalk'; -import minimist from 'minimist'; -import table from 'text-table'; -import ms from 'ms'; +import chalk from 'chalk' +import minimist from 'minimist' +import table from 'text-table' +import ms from 'ms' // Ours -import login from '../lib/login'; -import * as cfg from '../lib/cfg'; -import { error } from '../lib/error'; -import toHost from '../lib/to-host'; -import strlen from '../lib/strlen'; -import NowDomains from '../lib/domains'; +import login from '../lib/login' +import * as cfg from '../lib/cfg' +import {error} from '../lib/error' +import toHost from '../lib/to-host' +import strlen from '../lib/strlen' +import NowDomains from '../lib/domains' const argv = minimist(process.argv.slice(2), { string: ['config', 'token'], @@ -23,8 +23,8 @@ const argv = minimist(process.argv.slice(2), { debug: 'd', token: 't' } -}); -const subcommand = argv._[0]; +}) +const subcommand = argv._[0] // options const help = () => { @@ -75,192 +75,201 @@ const help = () => { ${chalk.cyan('$ now domain rm domainId')} To get the list of domain ids, use ${chalk.dim('`now domains ls`')}. -`); -}; +`) +} // options -const debug = argv.debug; -const apiUrl = argv.url || 'https://api.zeit.co'; -if (argv.config) cfg.setConfigFile(argv.config); +const debug = argv.debug +const apiUrl = argv.url || 'https://api.zeit.co' + +if (argv.config) { + cfg.setConfigFile(argv.config) +} -const exit = (code) => { +const exit = code => { // we give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 - setTimeout(() => process.exit(code || 0), 100); -}; + setTimeout(() => process.exit(code || 0), 100) +} if (argv.help || !subcommand) { - help(); - exit(0); + help() + exit(0) } else { - const config = cfg.read(); + const config = cfg.read() Promise.resolve(argv.token || config.token || login(apiUrl)) - .then(async (token) => { + .then(async token => { try { - await run(token); + await run(token) } catch (err) { if (err.userError) { - error(err.message); + error(err.message) } else { - error(`Unknown error: ${err.stack}`); + error(`Unknown error: ${err.stack}`) } - exit(1); + exit(1) } }) - .catch((e) => { - error(`Authentication error – ${e.message}`); - exit(1); - }); + .catch(e => { + error(`Authentication error – ${e.message}`) + exit(1) + }) } -async function run (token) { - const domain = new NowDomains(apiUrl, token, { debug }); - const args = argv._.slice(1); +async function run(token) { + const domain = new NowDomains(apiUrl, token, {debug}) + const args = argv._.slice(1) switch (subcommand) { case 'ls': case 'list': - if (0 !== args.length) { - error('Invalid number of arguments'); - return exit(1); + if (args.length !== 0) { + error('Invalid number of arguments') + return exit(1) } - const start_ = new Date(); - const domains = await domain.ls(); - domains.sort((a, b) => new Date(b.created) - new Date(a.created)); - const current = new Date(); - const header = [['', 'id', 'dns', 'url', 'created'].map(s => chalk.dim(s))]; - const out = domains.length === 0 ? null : table(header.concat(domains.map((domain) => { - const ns = domain.isExternal ? 'external' : 'zeit.world'; - const url = chalk.underline(`https://${domain.name}`); - const time = chalk.gray(ms(current - new Date(domain.created)) + ' ago'); + const start_ = new Date() + const domains = await domain.ls() + domains.sort((a, b) => new Date(b.created) - new Date(a.created)) + const current = new Date() + const header = [['', 'id', 'dns', 'url', 'created'].map(s => chalk.dim(s))] + const out = domains.length === 0 ? null : table(header.concat(domains.map(domain => { + const ns = domain.isExternal ? 'external' : 'zeit.world' + const url = chalk.underline(`https://${domain.name}`) + const time = chalk.gray(ms(current - new Date(domain.created)) + ' ago') return [ '', domain.uid, ns, url, time - ]; - })), { align: ['l', 'r', 'l', 'l', 'l'], hsep: ' '.repeat(2), stringLength: strlen }); + ] + })), {align: ['l', 'r', 'l', 'l', 'l'], hsep: ' '.repeat(2), stringLength: strlen}) - const elapsed_ = ms(new Date() - start_); - console.log(`> ${domains.length} domain${domains.length !== 1 ? 's' : ''} found ${chalk.gray(`[${elapsed_}]`)}`); - if (out) console.log('\n' + out + '\n'); - break; + const elapsed_ = ms(new Date() - start_) + console.log(`> ${domains.length} domain${domains.length === 1 ? '' : 's'} found ${chalk.gray(`[${elapsed_}]`)}`) + + if (out) { + console.log('\n' + out + '\n') + } + + break case 'rm': case 'remove': - if (1 !== args.length) { - error('Invalid number of arguments'); - return exit(1); + if (args.length !== 1) { + error('Invalid number of arguments') + return exit(1) } - const _target = String(args[0]); + const _target = String(args[0]) if (!_target) { - const err = new Error('No domain specified'); - err.userError = true; - throw err; + const err = new Error('No domain specified') + err.userError = true + throw err } - const _domains = await domain.ls(); - const _domain = findDomain(_target, _domains); + const _domains = await domain.ls() + const _domain = findDomain(_target, _domains) if (!_domain) { - const err = new Error(`Domain not found by "${_target}". Run ${chalk.dim('`now domains ls`')} to see your domains.`); - err.userError = true; - throw err; + const err = new Error(`Domain not found by "${_target}". Run ${chalk.dim('`now domains ls`')} to see your domains.`) + err.userError = true + throw err } try { - const confirmation = (await readConfirmation(domain, _domain, _domains)).toLowerCase(); - if ('y' !== confirmation && 'yes' !== confirmation) { - console.log('\n> Aborted'); - process.exit(0); + const confirmation = (await readConfirmation(domain, _domain, _domains)).toLowerCase() + if (confirmation !== 'y' && confirmation !== 'yes') { + console.log('\n> Aborted') + process.exit(0) } - const start = new Date(); - await domain.rm(_domain.name); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Domain ${chalk.bold(_domain.uid)} removed [${elapsed}]`); + const start = new Date() + await domain.rm(_domain.name) + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} Domain ${chalk.bold(_domain.uid)} removed [${elapsed}]`) } catch (err) { - error(err); - exit(1); + error(err) + exit(1) } - break; + break case 'add': case 'set': - if (1 !== args.length) { - error('Invalid number of arguments'); - return exit(1); + if (args.length !== 1) { + error('Invalid number of arguments') + return exit(1) } - const start = new Date(); - const name = String(args[0]); - const { uid, created } = await domain.add(name); - const elapsed = ms(new Date() - start); + const start = new Date() + const name = String(args[0]) + const {uid, created} = await domain.add(name) + const elapsed = ms(new Date() - start) if (created) { - console.log(`${chalk.cyan('> Success!')} Domain ${chalk.bold(chalk.underline(name))} ${chalk.dim(`(${uid})`)} added [${elapsed}]`); + console.log(`${chalk.cyan('> Success!')} Domain ${chalk.bold(chalk.underline(name))} ${chalk.dim(`(${uid})`)} added [${elapsed}]`) } else { - console.log(`${chalk.cyan('> Success!')} Domain ${chalk.bold(chalk.underline(name))} ${chalk.dim(`(${uid})`)} already exists [${elapsed}]`); + console.log(`${chalk.cyan('> Success!')} Domain ${chalk.bold(chalk.underline(name))} ${chalk.dim(`(${uid})`)} already exists [${elapsed}]`) } - break; + break default: - error('Please specify a valid subcommand: ls | add | rm'); - help(); - exit(1); + error('Please specify a valid subcommand: ls | add | rm') + help() + exit(1) } - domain.close(); -} - -function indent (text, n) { - return text.split('\n').map((l) => ' '.repeat(n) + l).join('\n'); + domain.close() } -async function readConfirmation (domain, _domain, list) { - const urls = new Map(list.map(l => [l.uid, l.url])); - - return new Promise((resolve, reject) => { - const time = chalk.gray(ms(new Date() - new Date(_domain.created)) + ' ago'); +async function readConfirmation(domain, _domain) { + return new Promise(resolve => { + const time = chalk.gray(ms(new Date() - new Date(_domain.created)) + ' ago') const tbl = table( [[_domain.uid, chalk.underline(`https://${_domain.name}`), time]], - { align: ['l', 'r', 'l'], hsep: ' '.repeat(6) } - ); - - process.stdout.write('> The following domain will be removed permanently\n'); - process.stdout.write(' ' + tbl + '\n'); - if (_domain.aliases.length) { - process.stdout.write(`> ${chalk.yellow('Warning!')} This domain's ` - + `${chalk.bold(_domain.aliases.length + ' alias' + (_domain.aliases.length !== 1 ? 'es': ''))} ` - + `will be removed. Run ${chalk.dim('`now alias ls`')} to list.\n`); + {align: ['l', 'r', 'l'], hsep: ' '.repeat(6)} + ) + + process.stdout.write('> The following domain will be removed permanently\n') + process.stdout.write(' ' + tbl + '\n') + + if (_domain.aliases.length > 0) { + process.stdout.write(`> ${chalk.yellow('Warning!')} This domain's ` + + `${chalk.bold(_domain.aliases.length + ' alias' + (_domain.aliases.length === 1 ? '' : 'es'))} ` + + `will be removed. Run ${chalk.dim('`now alias ls`')} to list.\n`) } - process.stdout.write(` ${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`); - process.stdin.on('data', (d) => { - process.stdin.pause(); - resolve(d.toString().trim()); - }).resume(); - }); + process.stdout.write(` ${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`) + + process.stdin.on('data', d => { + process.stdin.pause() + resolve(d.toString().trim()) + }).resume() + }) } -function findDomain (val, list) { - return list.find((d) => { +function findDomain(val, list) { + return list.find(d => { if (d.uid === val) { - if (debug) console.log(`> [debug] matched domain ${d.uid} by uid`); - return true; + if (debug) { + console.log(`> [debug] matched domain ${d.uid} by uid`) + } + + return true } // match prefix if (d.name === toHost(val)) { - if (debug) console.log(`> [debug] matched domain ${d.uid} by name ${d.name}`); - return true; + if (debug) { + console.log(`> [debug] matched domain ${d.uid} by name ${d.name}`) + } + + return true } - return false; - }); + return false + }) } diff --git a/bin/now-list.js b/bin/now-list.js index b6fd058..266010f 100755 --- a/bin/now-list.js +++ b/bin/now-list.js @@ -1,18 +1,18 @@ #!/usr/bin/env node // Packages -import fs from 'fs-promise'; -import minimist from 'minimist'; -import chalk from 'chalk'; -import table from 'text-table'; -import ms from 'ms'; +import fs from 'fs-promise' +import minimist from 'minimist' +import chalk from 'chalk' +import table from 'text-table' +import ms from 'ms' // Ours -import strlen from '../lib/strlen'; -import Now from '../lib'; -import login from '../lib/login'; -import * as cfg from '../lib/cfg'; -import {handleError, error} from '../lib/error'; +import strlen from '../lib/strlen' +import Now from '../lib' +import login from '../lib/login' +import * as cfg from '../lib/cfg' +import {handleError, error} from '../lib/error' const argv = minimist(process.argv.slice(2), { string: ['config', 'token'], @@ -23,7 +23,7 @@ const argv = minimist(process.argv.slice(2), { debug: 'd', token: 't' } -}); +}) const help = () => { console.log(` @@ -47,95 +47,110 @@ const help = () => { ${chalk.cyan('$ now ls my-app')} ${chalk.dim('Alias:')} ls -`); -}; +`) +} if (argv.help) { - help(); - process.exit(0); + help() + process.exit(0) } -const app = argv._[0]; +const app = argv._[0] // options -const debug = argv.debug; -const apiUrl = argv.url || 'https://api.zeit.co'; -if (argv.config) cfg.setConfigFile(argv.config); -const config = cfg.read(); +const debug = argv.debug +const apiUrl = argv.url || 'https://api.zeit.co' + +if (argv.config) { + cfg.setConfigFile(argv.config) +} + +const config = cfg.read() Promise.resolve(argv.token || config.token || login(apiUrl)) -.then(async (token) => { +.then(async token => { try { - await list(token); + await list(token) } catch (err) { - error(`Unknown error: ${err.stack}`); - process.exit(1); + error(`Unknown error: ${err.stack}`) + process.exit(1) } }) -.catch((e) => { - error(`Authentication error – ${e.message}`); - process.exit(1); -}); +.catch(e => { + error(`Authentication error – ${e.message}`) + process.exit(1) +}) -async function list (token) { - const now = new Now(apiUrl, token, { debug }); - const start = new Date(); +async function list(token) { + const now = new Now(apiUrl, token, {debug}) + const start = new Date() - let deployments; + let deployments try { - deployments = await now.list(app); + deployments = await now.list(app) } catch (err) { - handleError(err); - process.exit(1); + handleError(err) + process.exit(1) } - now.close(); + now.close() + + const apps = new Map() - const apps = new Map(); for (const dep of deployments) { - const deps = apps.get(dep.name) || []; - apps.set(dep.name, deps.concat(dep)); + const deps = apps.get(dep.name) || [] + apps.set(dep.name, deps.concat(dep)) } - const sorted = await sort([...apps]); + const sorted = await sort([...apps]) + const current = Date.now() - const current = Date.now(); const text = sorted.map(([name, deps]) => { - const t = table(deps.map(({ uid, url, created }) => { - const _url = chalk.underline(`https://${url}`); - const time = chalk.gray(ms(current - created) + ' ago'); - return [uid, _url, time]; - }), { align: ['l', 'r', 'l'], hsep: ' '.repeat(6), stringLength: strlen }); - return chalk.bold(name) + '\n\n' + indent(t, 2); - }).join('\n\n'); - const elapsed = ms(new Date() - start); - console.log(`> ${deployments.length} deployment${deployments.length !== 1 ? 's' : ''} found ${chalk.gray(`[${elapsed}]`)}`); - if (text) console.log('\n' + text + '\n'); + const t = table(deps.map(({uid, url, created}) => { + const _url = chalk.underline(`https://${url}`) + const time = chalk.gray(ms(current - created) + ' ago') + return [uid, _url, time] + }), {align: ['l', 'r', 'l'], hsep: ' '.repeat(6), stringLength: strlen}) + return chalk.bold(name) + '\n\n' + indent(t, 2) + }).join('\n\n') + + const elapsed = ms(new Date() - start) + console.log(`> ${deployments.length} deployment${deployments.length === 1 ? '' : 's'} found ${chalk.gray(`[${elapsed}]`)}`) + + if (text) { + console.log('\n' + text + '\n') + } } -async function sort (apps) { - let pkg; +async function sort(apps) { + let pkg try { - const json = await fs.readFile('package.json'); - pkg = JSON.parse(json); + const json = await fs.readFile('package.json') + pkg = JSON.parse(json) } catch (err) { - pkg = {}; + pkg = {} } return apps .map(([name, deps]) => { deps = deps.slice().sort((a, b) => { - return b.created - a.created; - }); - return [name, deps]; + return b.created - a.created + }) + return [name, deps] }) .sort(([nameA, depsA], [nameB, depsB]) => { - if (pkg.name === nameA) return -1; - if (pkg.name === nameB) return 1; - return depsB[0].created - depsA[0].created; - }); + if (pkg.name === nameA) { + return -1 + } + + if (pkg.name === nameB) { + return 1 + } + + return depsB[0].created - depsA[0].created + }) } -function indent (text, n) { - return text.split('\n').map((l) => ' '.repeat(n) + l).join('\n'); +function indent(text, n) { + return text.split('\n').map(l => ' '.repeat(n) + l).join('\n') } diff --git a/bin/now-remove.js b/bin/now-remove.js index d110ed1..e9537eb 100755 --- a/bin/now-remove.js +++ b/bin/now-remove.js @@ -1,16 +1,16 @@ #!/usr/bin/env node // Packages -import minimist from 'minimist'; -import chalk from 'chalk'; -import ms from 'ms'; -import table from 'text-table'; +import minimist from 'minimist' +import chalk from 'chalk' +import ms from 'ms' +import table from 'text-table' // Ours -import Now from '../lib'; -import login from '../lib/login'; -import * as cfg from '../lib/cfg'; -import {handleError, error} from '../lib/error'; +import Now from '../lib' +import login from '../lib/login' +import * as cfg from '../lib/cfg' +import {handleError, error} from '../lib/error' const argv = minimist(process.argv.slice(2), { string: ['config', 'token'], @@ -21,9 +21,9 @@ const argv = minimist(process.argv.slice(2), { debug: 'd', token: 't' } -}); +}) -const ids = argv._; +const ids = argv._ // options const help = () => { @@ -52,118 +52,120 @@ const help = () => { ${chalk.cyan('$ now rm eyWt6zuSdeus uWHoA9RQ1d1o')} ${chalk.dim('Alias:')} rm -`); -}; +`) +} -if (argv.help || 0 === ids.length) { - help(); - process.exit(0); +if (argv.help || ids.length === 0) { + help() + process.exit(0) } // options -const debug = argv.debug; -const apiUrl = argv.url || 'https://api.zeit.co'; -const hard = argv.hard || false; -if (argv.config) cfg.setConfigFile(argv.config); -const config = cfg.read(); +const debug = argv.debug +const apiUrl = argv.url || 'https://api.zeit.co' +const hard = argv.hard || false + +if (argv.config) { + cfg.setConfigFile(argv.config) +} -function readConfirmation (matches) { - return new Promise((resolve, reject) => { +const config = cfg.read() - process.stdout.write(`> The following deployment${matches.length === 1 ? '' : 's'} will be removed permanently:\n`); +function readConfirmation(matches) { + return new Promise(resolve => { + process.stdout.write(`> The following deployment${matches.length === 1 ? '' : 's'} will be removed permanently:\n`) const tbl = table( - matches.map((depl) => { - const time = chalk.gray(ms(new Date() - depl.created) + ' ago'); - const url = chalk.underline(`https://${depl.url}`); - return [depl.uid, url, time]; + matches.map(depl => { + const time = chalk.gray(ms(new Date() - depl.created) + ' ago') + const url = chalk.underline(`https://${depl.url}`) + return [depl.uid, url, time] }), - { align: ['l', 'r', 'l'], hsep: ' '.repeat(6) } - ); - process.stdout.write(tbl + '\n'); + {align: ['l', 'r', 'l'], hsep: ' '.repeat(6)} + ) + process.stdout.write(tbl + '\n') - for (let depl of matches) { - for (let alias of depl.aliases) { + for (const depl of matches) { + for (const alias of depl.aliases) { process.stdout.write( `> ${chalk.yellow('Warning!')} Deployment ${chalk.bold(depl.uid)} ` + `is an alias for ${chalk.underline(`https://${alias.alias}`)} and will be removed.\n` - ); + ) } } - process.stdout.write(`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`); + process.stdout.write(`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`) - process.stdin.on('data', (d) => { - process.stdin.pause(); - resolve(d.toString().trim()); - }).resume(); - }); + process.stdin.on('data', d => { + process.stdin.pause() + resolve(d.toString().trim()) + }).resume() + }) } Promise.resolve(argv.token || config.token || login(apiUrl)) -.then(async (token) => { +.then(async token => { try { - await remove(token); + await remove(token) } catch (err) { - error(`Unknown error: ${err.stack}`); - process.exit(1); + error(`Unknown error: ${err.stack}`) + process.exit(1) } }) -.catch((e) => { - error(`Authentication error – ${e.message}`); - process.exit(1); -}); +.catch(e => { + error(`Authentication error – ${e.message}`) + process.exit(1) +}) -async function remove (token) { - const now = new Now(apiUrl, token, { debug }); +async function remove(token) { + const now = new Now(apiUrl, token, {debug}) - const deployments = await now.list(); + const deployments = await now.list() - const matches = deployments.filter((d) => { - return ids.find((id) => { + const matches = deployments.filter(d => { + return ids.find(id => { // `url` should match the hostname of the deployment - let u = id.replace(/^https\:\/\//i, ''); - if (-1 === u.indexOf('.')) { + let u = id.replace(/^https\:\/\//i, '') + + if (u.indexOf('.') === -1) { // `.now.sh` domain is implied if just the subdomain is given - u += '.now.sh'; + u += '.now.sh' } - return d.uid === id - || d.name === id - || d.url === u; - }); - }); + return d.uid === id || d.name === id || d.url === u + }) + }) - if (0 === matches.length) { - error(`Could not find any deployments matching ${ids.map((id) => chalk.bold(`"${id}"`)).join(', ')}. Run ${chalk.dim(`\`now ls\``)} to list.`); - return process.exit(1); + if (matches.length === 0) { + error(`Could not find any deployments matching ${ids.map(id => chalk.bold(`"${id}"`)).join(', ')}. Run ${chalk.dim(`\`now ls\``)} to list.`) + return process.exit(1) } - const aliases = await Promise.all(matches.map((depl) => now.listAliases(depl.uid))); + const aliases = await Promise.all(matches.map(depl => now.listAliases(depl.uid))) for (let i = 0; i < matches.length; i++) { - matches[i].aliases = aliases[i]; + matches[i].aliases = aliases[i] } try { - const confirmation = (await readConfirmation(matches)).toLowerCase(); - if ('y' !== confirmation && 'yes' !== confirmation) { - console.log('\n> Aborted'); - process.exit(0); + const confirmation = (await readConfirmation(matches)).toLowerCase() + if (confirmation !== 'y' && confirmation !== 'yes') { + console.log('\n> Aborted') + process.exit(0) } - const start = new Date(); + const start = new Date() - await Promise.all(matches.map((depl) => now.remove(depl.uid, { hard }))); + await Promise.all(matches.map(depl => now.remove(depl.uid, {hard}))) - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} [${elapsed}]`); - console.log(table(matches.map((depl) => { - return [ `Deployment ${chalk.bold(depl.uid)} removed` ]; - }))); + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} [${elapsed}]`) + console.log(table(matches.map(depl => { + return [`Deployment ${chalk.bold(depl.uid)} removed`] + }))) } catch (err) { - handleError(err); - process.exit(1); + handleError(err) + process.exit(1) } - now.close(); + now.close() } diff --git a/bin/now-secrets.js b/bin/now-secrets.js index 8b4d04d..1388164 100755 --- a/bin/now-secrets.js +++ b/bin/now-secrets.js @@ -1,17 +1,17 @@ #!/usr/bin/env node // Packages -import chalk from 'chalk'; -import table from 'text-table'; -import minimist from 'minimist'; -import ms from 'ms'; +import chalk from 'chalk' +import table from 'text-table' +import minimist from 'minimist' +import ms from 'ms' // Ours -import strlen from '../lib/strlen'; -import * as cfg from '../lib/cfg'; -import {handleError, error} from '../lib/error'; -import NowSecrets from '../lib/secrets'; -import login from '../lib/login'; +import strlen from '../lib/strlen' +import * as cfg from '../lib/cfg' +import {handleError, error} from '../lib/error' +import NowSecrets from '../lib/secrets' +import login from '../lib/login' const argv = minimist(process.argv.slice(2), { string: ['config', 'token'], @@ -23,8 +23,9 @@ const argv = minimist(process.argv.slice(2), { base64: 'b', token: 't' } -}); -const subcommand = argv._[0]; +}) + +const subcommand = argv._[0] // options const help = () => { @@ -66,160 +67,173 @@ const help = () => { ${chalk.gray('–')} Removes a secret: ${chalk.cyan(`$ now secrets rm my-secret`)} -`); -}; +`) +} // options -const debug = argv.debug; -const apiUrl = argv.url || 'https://api.zeit.co'; -if (argv.config) cfg.setConfigFile(argv.config); +const debug = argv.debug +const apiUrl = argv.url || 'https://api.zeit.co' -const exit = (code) => { +if (argv.config) { + cfg.setConfigFile(argv.config) +} + +const exit = code => { // we give stdout some time to flush out // because there's a node bug where // stdout writes are asynchronous // https://github.com/nodejs/node/issues/6456 - setTimeout(() => process.exit(code || 0), 100); -}; + setTimeout(() => process.exit(code || 0), 100) +} if (argv.help || !subcommand) { - help(); - exit(0); + help() + exit(0) } else { - const config = cfg.read(); + const config = cfg.read() Promise.resolve(argv.token || config.token || login(apiUrl)) - .then(async (token) => { + .then(async token => { try { - await run(token); + await run(token) } catch (err) { - handleError(err); - exit(1); + handleError(err) + exit(1) } }) - .catch((e) => { - error(`Authentication error – ${e.message}`); - exit(1); - }); + .catch(e => { + error(`Authentication error – ${e.message}`) + exit(1) + }) } -async function run (token) { - const secrets = new NowSecrets(apiUrl, token, { debug }); - const args = argv._.slice(1); - const start = Date.now(); +async function run(token) { + const secrets = new NowSecrets(apiUrl, token, {debug}) + const args = argv._.slice(1) + const start = Date.now() - if ('ls' === subcommand || 'list' === subcommand) { - if (0 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret ls`')}`); - return exit(1); + if (subcommand === 'ls' || subcommand === 'list') { + if (args.length !== 0) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret ls`')}`) + return exit(1) } - const list = await secrets.ls(); - const elapsed = ms(new Date() - start); - console.log(`> ${list.length} secret${list.length !== 1 ? 's' : ''} found ${chalk.gray(`[${elapsed}]`)}`); - if (0 < list.length) { - const cur = Date.now(); - const header = [['', 'id', 'name', 'created'].map(s => chalk.dim(s))]; - const out = table(header.concat(list.map((secret) => { + + const list = await secrets.ls() + const elapsed = ms(new Date() - start) + + console.log(`> ${list.length} secret${list.length === 1 ? '' : 's'} found ${chalk.gray(`[${elapsed}]`)}`) + + if (list.length > 0) { + const cur = Date.now() + const header = [['', 'id', 'name', 'created'].map(s => chalk.dim(s))] + const out = table(header.concat(list.map(secret => { return [ '', secret.uid, chalk.bold(secret.name), chalk.gray(ms(cur - new Date(secret.created)) + ' ago') - ]; - })), { align: ['l', 'r', 'l', 'l'], hsep: ' '.repeat(2), stringLength: strlen }); - if (out) console.log('\n' + out + '\n'); + ] + })), {align: ['l', 'r', 'l', 'l'], hsep: ' '.repeat(2), stringLength: strlen}) + + if (out) { + console.log('\n' + out + '\n') + } } - return secrets.close(); + return secrets.close() } - if ('rm' === subcommand || 'remove' === subcommand) { - if (1 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret rm `')}`); - return exit(1); + if (subcommand === 'rm' || subcommand === 'remove') { + if (args.length !== 1) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret rm `')}`) + return exit(1) } - const list = await secrets.ls(); - const theSecret = list.filter((secret) => { - return secret.uid === args[0] - || secret.name === args[0]; - })[0]; + const list = await secrets.ls() + const theSecret = list.filter(secret => { + return secret.uid === args[0] || secret.name === args[0] + })[0] if (theSecret) { - const yes = await readConfirmation(theSecret); + const yes = await readConfirmation(theSecret) if (!yes) { - error('User abort'); - return exit(0); + error('User abort') + return exit(0) } } else { - error(`No secret found by id or name "${args[0]}"`); - return exit(1); + error(`No secret found by id or name "${args[0]}"`) + return exit(1) } - const secret = await secrets.rm(args[0]); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(secret.name)} ${chalk.gray(`(${secret.uid})`)} removed ${chalk.gray(`[${elapsed}]`)}`); - return secrets.close(); + const secret = await secrets.rm(args[0]) + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(secret.name)} ${chalk.gray(`(${secret.uid})`)} removed ${chalk.gray(`[${elapsed}]`)}`) + return secrets.close() } - if ('rename' === subcommand) { - if (2 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret rename `')}`); - return exit(1); + if (subcommand === 'rename') { + if (args.length !== 2) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret rename `')}`) + return exit(1) } - const secret = await secrets.rename(args[0], args[1]); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(secret.oldName)} ${chalk.gray(`(${secret.uid})`)} renamed to ${chalk.bold(args[1])} ${chalk.gray(`[${elapsed}]`)}`); - return secrets.close(); + const secret = await secrets.rename(args[0], args[1]) + const elapsed = ms(new Date() - start) + console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(secret.oldName)} ${chalk.gray(`(${secret.uid})`)} renamed to ${chalk.bold(args[1])} ${chalk.gray(`[${elapsed}]`)}`) + return secrets.close() } - if ('add' === subcommand || 'set' === subcommand) { - if (2 !== args.length) { - error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret add `')}`); + if (subcommand === 'add' || subcommand === 'set') { + if (args.length !== 2) { + error(`Invalid number of arguments. Usage: ${chalk.cyan('`now secret add `')}`) + if (args.length > 2) { - const [, ...rest] = args; - console.log('> If your secret has spaces, make sure to wrap it in quotes. Example: \n' - + ` ${chalk.cyan('$ now secret add ${args[0]} "${escaped}"')} `); + const example = chalk.cyan(`$ now secret add ${args[0]}`) + console.log(`> If your secret has spaces, make sure to wrap it in quotes. Example: \n ${example} `) } - return exit(1); + + return exit(1) } - const [name, value_] = args; - let value; + + const [name, value_] = args + let value + if (argv.base64) { - value = { base64: value_ }; + value = {base64: value_} } else { - value = value_; + value = value_ } - const secret = await secrets.add(name, value); - const elapsed = ms(new Date() - start); - console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(name.toLowerCase())} ${chalk.gray(`(${secret.uid})`)} added ${chalk.gray(`[${elapsed}]`)}`); - return secrets.close(); + + const secret = await secrets.add(name, value) + const elapsed = ms(new Date() - start) + + console.log(`${chalk.cyan('> Success!')} Secret ${chalk.bold(name.toLowerCase())} ${chalk.gray(`(${secret.uid})`)} added ${chalk.gray(`[${elapsed}]`)}`) + return secrets.close() } - error('Please specify a valid subcommand: ls | add | rename | rm'); - help(); - exit(1); + error('Please specify a valid subcommand: ls | add | rename | rm') + help() + exit(1) } -process.on('uncaughtException', (err) => { - handleError(err); - exit(1); -}); +process.on('uncaughtException', err => { + handleError(err) + exit(1) +}) -function readConfirmation (secret) { - return new Promise((resolve, reject) => { - const time = chalk.gray(ms(new Date() - new Date(secret.created)) + ' ago'); +function readConfirmation(secret) { + return new Promise(resolve => { + const time = chalk.gray(ms(new Date() - new Date(secret.created)) + ' ago') const tbl = table( [[secret.uid, chalk.bold(secret.name), time]], - { align: ['l', 'r', 'l'], hsep: ' '.repeat(6) } - ); + {align: ['l', 'r', 'l'], hsep: ' '.repeat(6)} + ) - process.stdout.write('> The following secret will be removed permanently\n'); - process.stdout.write(' ' + tbl + '\n'); + process.stdout.write('> The following secret will be removed permanently\n') + process.stdout.write(' ' + tbl + '\n') - process.stdout.write(`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`); + process.stdout.write(`${chalk.bold.red('> Are you sure?')} ${chalk.gray('[yN] ')}`) - process.stdin.on('data', (d) => { - process.stdin.pause(); - resolve('y' === d.toString().trim().toLowerCase()); - }).resume(); - }); + process.stdin.on('data', d => { + process.stdin.pause() + resolve(d.toString().trim().toLowerCase() === 'y') + }).resume() + }) } diff --git a/package.json b/package.json index 35058f1..9a5b704 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,9 @@ "no-use-before-define": 0, "complexity": 0, "unicorn/no-process-exit": 0, - "no-control-regex": 0 + "no-control-regex": 0, + "no-case-declarations": 0, + "no-useless-escape": 0 } }, "bin": {