heroku-cli-util
Advanced tools
Comparing version 6.0.1 to 6.0.2
71
index.js
@@ -1,37 +0,36 @@ | ||
'use strict'; | ||
var console = require('./lib/console'); | ||
var errors = require('./lib/errors'); | ||
var prompt = require('./lib/prompt'); | ||
var styled = require('./lib/styled'); | ||
'use strict' | ||
var console = require('./lib/console') | ||
var errors = require('./lib/errors') | ||
var prompt = require('./lib/prompt') | ||
var styled = require('./lib/styled') | ||
exports.hush = console.hush; | ||
exports.log = console.log.bind(console); | ||
exports.formatDate = require('./lib/date').formatDate; | ||
exports.error = errors.error; | ||
exports.action = require('./lib/action'); | ||
exports.warn = exports.action.warn; | ||
exports.errorHandler = errors.errorHandler; | ||
exports.console = console; | ||
exports.yubikey = require('./lib/yubikey'); | ||
exports.prompt = prompt.prompt; | ||
exports.confirmApp = prompt.confirmApp; | ||
exports.preauth = require('./lib/preauth'); | ||
exports.command = require('./lib/command'); | ||
exports.color = require('./lib/color'); | ||
exports.extend = require('./lib/extend'); | ||
exports.debug = console.debug; | ||
exports.mockConsole = console.mock; | ||
exports.table = require('./lib/table'); | ||
exports.stdout = ''; | ||
exports.stderr = ''; | ||
exports.styledHeader = styled.styledHeader; | ||
exports.styledObject = styled.styledObject; | ||
exports.styledHash = styled.styledObject; | ||
exports.styledNameValues = styled.styledNameValues; | ||
exports.styledJSON = styled.styledJSON; | ||
exports.rollbar = require('./lib/rollbar'); | ||
exports.open = require('./lib/open'); | ||
exports.got = require('./lib/got'); | ||
exports.linewrap = require('./lib/linewrap'); | ||
exports.Spinner = require('./lib/spinner'); | ||
exports.exit = require('./lib/exit').exit; | ||
exports.hush = console.hush | ||
exports.log = console.log.bind(console) | ||
exports.formatDate = require('./lib/date').formatDate | ||
exports.error = errors.error | ||
exports.action = require('./lib/action') | ||
exports.warn = exports.action.warn | ||
exports.errorHandler = errors.errorHandler | ||
exports.console = console | ||
exports.yubikey = require('./lib/yubikey') | ||
exports.prompt = prompt.prompt | ||
exports.confirmApp = prompt.confirmApp | ||
exports.preauth = require('./lib/preauth') | ||
exports.command = require('./lib/command') | ||
exports.color = require('./lib/color') | ||
exports.debug = console.debug | ||
exports.mockConsole = console.mock | ||
exports.table = require('./lib/table') | ||
exports.stdout = '' | ||
exports.stderr = '' | ||
exports.styledHeader = styled.styledHeader | ||
exports.styledObject = styled.styledObject | ||
exports.styledHash = styled.styledObject | ||
exports.styledNameValues = styled.styledNameValues | ||
exports.styledJSON = styled.styledJSON | ||
exports.rollbar = require('./lib/rollbar') | ||
exports.open = require('./lib/open') | ||
exports.got = require('./lib/got') | ||
exports.linewrap = require('./lib/linewrap') | ||
exports.Spinner = require('./lib/spinner') | ||
exports.exit = require('./lib/exit').exit |
@@ -1,50 +0,50 @@ | ||
'use strict'; | ||
'use strict' | ||
let cli = require('..'); | ||
let errors = require('./errors'); | ||
let cli = require('..') | ||
let errors = require('./errors') | ||
function action (message, options, promise) { | ||
if (options.then) { | ||
let swap = promise; | ||
promise = options; | ||
options = swap; | ||
let swap = promise | ||
promise = options | ||
options = swap | ||
} | ||
options = options || {}; | ||
options = options || {} | ||
module.exports.task = { | ||
promise: promise, | ||
spinner: new cli.Spinner({spinner: options.spinner, text: `${message}... `}), | ||
}; | ||
spinner: new cli.Spinner({spinner: options.spinner, text: `${message}... `}) | ||
} | ||
module.exports.task.spinner.start(); | ||
module.exports.task.spinner.start() | ||
return promise.then(function (result) { | ||
module.exports.task.spinner.stop(); | ||
module.exports.task = null; | ||
module.exports.task.spinner.stop() | ||
module.exports.task = null | ||
if (options.success !== false) { | ||
cli.console.error(options.success || 'done'); | ||
cli.console.error(options.success || 'done') | ||
} | ||
return result; | ||
return result | ||
}).catch(function (err) { | ||
module.exports.task.spinner.stop(); | ||
module.exports.task = null; | ||
module.exports.task.spinner.stop() | ||
module.exports.task = null | ||
if (err.body && err.body.id === 'two_factor') { | ||
cli.console.error(cli.color.yellow.bold('!')); | ||
cli.console.error(cli.color.yellow.bold('!')) | ||
} else { | ||
cli.console.error(cli.color.red.bold('!!!')); | ||
cli.console.error(cli.color.red.bold('!!!')) | ||
} | ||
throw err; | ||
}); | ||
throw err | ||
}) | ||
} | ||
function warn (msg) { | ||
if (module.exports.task) module.exports.task.spinner.warn(msg); | ||
else errors.warn(msg); | ||
if (module.exports.task) module.exports.task.spinner.warn(msg) | ||
else errors.warn(msg) | ||
} | ||
function update (msg) { | ||
if (module.exports.task) module.exports.task.spinner.update(msg); | ||
if (module.exports.task) module.exports.task.spinner.update(msg) | ||
} | ||
module.exports = action; | ||
module.exports.warn = warn; | ||
module.exports.update = update; | ||
module.exports = action | ||
module.exports.warn = warn | ||
module.exports.update = update |
@@ -1,6 +0,4 @@ | ||
'use strict'; | ||
'use strict' | ||
const chalk = require('chalk'); | ||
const pickBy = require('lodash.pickby'); | ||
const mapValues = require('lodash.mapvalues'); | ||
const chalk = require('chalk') | ||
@@ -11,24 +9,22 @@ let colors = { | ||
configVar: 'green' | ||
}; | ||
} | ||
let definedColors = pickBy(colors, function(value) { | ||
return typeof(chalk[value]) === 'function'; | ||
}); | ||
for (let color of Object.keys(colors)) { | ||
let c = chalk[colors[color]] | ||
colors[color] = s => c(s) | ||
} | ||
let boundColors = mapValues(definedColors, v => s => chalk[v](s)); | ||
colors.release = s => chalk.blue.bold(s) | ||
colors.cmd = s => chalk.cyan.bold(s) | ||
boundColors.release = s => chalk.blue.bold(s); | ||
boundColors.cmd = s => chalk.cyan.bold(s); | ||
colors.heroku = s => { | ||
if (!chalk.enabled) return s | ||
let supports = require('supports-color') | ||
if (!supports) return s | ||
supports.has256 = supports.has256 || (process.env.TERM || '').indexOf('256') !== -1 | ||
return supports.has256 ? '\u001b[38;5;104m' + s + chalk.styles.modifiers.reset.open : chalk.magenta(s) | ||
} | ||
boundColors.heroku = s => { | ||
if (!chalk.enabled) return s; | ||
let supports = require('supports-color'); | ||
if (!supports) return s; | ||
supports.has256 = supports.has256 || (process.env.TERM || '').indexOf('256') !== -1; | ||
return supports.has256 ? '\u001b[38;5;104m'+s+chalk.styles.modifiers.reset.open : chalk.magenta(s); | ||
}; | ||
colors.app = s => chalk.enabled && process.platform !== 'win32' ? colors.heroku(`⬢ ${s}`) : colors.heroku(s) | ||
boundColors.app = s => chalk.enabled && process.platform !== 'win32' ? boundColors.heroku(`⬢ ${s}`) : boundColors.heroku(s); | ||
module.exports = Object.assign(chalk, boundColors); | ||
module.exports = Object.assign(chalk, colors) |
@@ -1,82 +0,82 @@ | ||
'use strict'; | ||
'use strict' | ||
let co = require('co'); | ||
let Heroku = require('heroku-client'); | ||
let cli = require('..'); | ||
let co = require('co') | ||
let Heroku = require('heroku-client') | ||
let cli = require('..') | ||
function apiMiddleware (response, cb) { | ||
let warning = response.headers['x-heroku-warning'] || response.headers['warning-message']; | ||
if (warning) cli.action.warn(warning); | ||
cb(); | ||
let warning = response.headers['x-heroku-warning'] || response.headers['warning-message'] | ||
if (warning) cli.action.warn(warning) | ||
cb() | ||
} | ||
function heroku (context) { | ||
let host = context.apiUrl || 'https://api.heroku.com'; | ||
let host = context.apiUrl || 'https://api.heroku.com' | ||
let opts = { | ||
userAgent: context.version, | ||
debug: context.debug, | ||
debugHeaders: context.debugHeaders, | ||
token: context.auth ? context.auth.password : null, | ||
host: host, | ||
headers: {}, | ||
rejectUnauthorized: !(process.env.HEROKU_SSL_VERIFY === 'disable' || host.endsWith('herokudev.com')), | ||
middleware: apiMiddleware, | ||
}; | ||
userAgent: context.version, | ||
debug: context.debug, | ||
debugHeaders: context.debugHeaders, | ||
token: context.auth ? context.auth.password : null, | ||
host: host, | ||
headers: {}, | ||
rejectUnauthorized: !(process.env.HEROKU_SSL_VERIFY === 'disable' || host.endsWith('herokudev.com')), | ||
middleware: apiMiddleware | ||
} | ||
if (process.env.HEROKU_HEADERS) { | ||
opts.headers = cli.extend(opts.headers, JSON.parse(process.env.HEROKU_HEADERS)); | ||
Object.assign(opts.headers, JSON.parse(process.env.HEROKU_HEADERS)) | ||
} | ||
if (context.secondFactor) { | ||
opts.headers = cli.extend(opts.headers, {'Heroku-Two-Factor-Code': context.secondFactor}); | ||
Object.assign(opts.headers, {'Heroku-Two-Factor-Code': context.secondFactor}) | ||
} | ||
if (context.reason) { | ||
opts.headers = cli.extend(opts.headers, {'X-Heroku-Sudo-Reason': context.reason}); | ||
Object.assign(opts.headers, {'X-Heroku-Sudo-Reason': context.reason}) | ||
} | ||
return new Heroku(opts); | ||
return new Heroku(opts) | ||
} | ||
let httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy; | ||
let httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy || process.env.HTTP_PROXY || process.env.http_proxy | ||
function setupHttpProxy() { | ||
const url = require('url'); | ||
cli.hush(`proxy set to ${httpsProxy}`); | ||
let proxy = url.parse(httpsProxy); | ||
process.env.HEROKU_HTTP_PROXY_HOST = proxy.hostname; | ||
process.env.HEROKU_HTTP_PROXY_PORT = proxy.port; | ||
process.env.HEROKU_HTTP_PROXY_AUTH = proxy.auth; | ||
function setupHttpProxy () { | ||
const url = require('url') | ||
cli.hush(`proxy set to ${httpsProxy}`) | ||
let proxy = url.parse(httpsProxy) | ||
process.env.HEROKU_HTTP_PROXY_HOST = proxy.hostname | ||
process.env.HEROKU_HTTP_PROXY_PORT = proxy.port | ||
process.env.HEROKU_HTTP_PROXY_AUTH = proxy.auth | ||
} | ||
function errHandlerOpts (rollbar, context) { | ||
rollbar = rollbar || {}; | ||
let cmd = null; | ||
if (context.command) cmd = context.command.command ? `${context.command.topic}:${context.command.command}` : context.command.topic; | ||
rollbar = rollbar || {} | ||
let cmd = null | ||
if (context.command) cmd = context.command.command ? `${context.command.topic}:${context.command.command}` : context.command.topic | ||
return { | ||
debug: context.debug, | ||
dev: context.dev, | ||
debug: context.debug, | ||
dev: context.dev, | ||
rollbar: cli.rollbar(rollbar.cred, { | ||
version: context.version, | ||
context: cmd, | ||
context: cmd | ||
}) | ||
}; | ||
} | ||
} | ||
function login () { | ||
const spawn = require('child_process').spawn; | ||
return new Promise(function (fulfill, error) { | ||
const spawn = require('child_process').spawn | ||
return new Promise(function (resolve, reject) { | ||
spawn('heroku', ['login'], {stdio: 'inherit'}) | ||
.on('close', function (e) { | ||
if (e === 0) fulfill(); | ||
else error(new Error('Authorization failed.')); | ||
}); | ||
}); | ||
.on('close', function (e) { | ||
if (e === 0) resolve() | ||
else reject(new Error('Authorization failed.')) | ||
}) | ||
}) | ||
} | ||
function getNewAPIKey () { | ||
const exec = require('child_process').exec; | ||
return new Promise(function (fulfill, reject) { | ||
const exec = require('child_process').exec | ||
return new Promise(function (resolve, reject) { | ||
exec('heroku auth:token', function (error, stdout, stderr) { | ||
if (stderr) console.error(stderr); | ||
if (error) reject(error); | ||
fulfill(stdout.trim()); | ||
}); | ||
}); | ||
if (stderr) console.error(stderr) | ||
if (error) reject(error) | ||
resolve(stdout.trim()) | ||
}) | ||
}) | ||
} | ||
@@ -87,29 +87,29 @@ | ||
cli.error(`API key is currently set by the HEROKU_API_KEY environment variable. | ||
Ensure this is set to a correct value or unset it to use the netrc file.`); | ||
process.exit(1); | ||
Ensure this is set to a correct value or unset it to use the netrc file.`) | ||
process.exit(1) | ||
} | ||
return login().then(getNewAPIKey); | ||
return login().then(getNewAPIKey) | ||
} | ||
function twoFactorPrompt(options, context) { | ||
cli.yubikey.enable(); | ||
function twoFactorPrompt (options, context) { | ||
cli.yubikey.enable() | ||
return cli.prompt('Two-factor code', {mask: true}) | ||
.then(function (secondFactor) { | ||
cli.yubikey.disable(); | ||
return secondFactor; | ||
}) | ||
.then(function (secondFactor) { | ||
if (options.preauth) { | ||
return cli.preauth(context.app, heroku(context), secondFactor); | ||
} else { | ||
context.secondFactor = secondFactor; | ||
} | ||
}); | ||
.then(function (secondFactor) { | ||
cli.yubikey.disable() | ||
return secondFactor | ||
}) | ||
.then(function (secondFactor) { | ||
if (options.preauth) { | ||
return cli.preauth(context.app, heroku(context), secondFactor) | ||
} else { | ||
context.secondFactor = secondFactor | ||
} | ||
}) | ||
} | ||
function reasonPrompt(context) { | ||
function reasonPrompt (context) { | ||
return cli.prompt('Reason') | ||
.then(function (reason) { | ||
context.reason = reason; | ||
}); | ||
.then(function (reason) { | ||
context.reason = reason | ||
}) | ||
} | ||
@@ -120,29 +120,27 @@ | ||
if (typeof options === 'function') { | ||
fn = options; | ||
options = {}; | ||
fn = options | ||
options = {} | ||
} | ||
if (httpsProxy) { setupHttpProxy(); } | ||
cli.color.enabled = context.supportsColor; | ||
let handleErr = cli.errorHandler(errHandlerOpts(options.rollbar, context)); | ||
if (httpsProxy) setupHttpProxy() | ||
cli.color.enabled = context.supportsColor | ||
let handleErr = cli.errorHandler(errHandlerOpts(options.rollbar, context)) | ||
let run = function () { | ||
return co.wrap(fn)(context, heroku(context)) | ||
.catch(function (err) { | ||
if (err && err.body && err.body.id === 'unauthorized') { | ||
cli.error(err.body.message || 'Unauthorized'); | ||
relogin() | ||
.then(apiKey => context.auth = {password: apiKey}) | ||
.then(run) | ||
.catch(handleErr); | ||
} | ||
else if (err && err.body && err.body.id === 'sudo_reason_required') { | ||
cli.warn(err.body.message); | ||
reasonPrompt(context).then(run).catch(handleErr); | ||
} | ||
else if (err && err.body && err.body.id === 'two_factor') { | ||
twoFactorPrompt(options, context).then(run).catch(handleErr); | ||
} else throw err; | ||
}).catch(handleErr); | ||
}; | ||
return run(); | ||
}; | ||
}; | ||
.catch(function (err) { | ||
if (err && err.body && err.body.id === 'unauthorized') { | ||
cli.error(err.body.message || 'Unauthorized') | ||
relogin() | ||
.then(apiKey => { context.auth = {password: apiKey} }) | ||
.then(run) | ||
.catch(handleErr) | ||
} else if (err && err.body && err.body.id === 'sudo_reason_required') { | ||
cli.warn(err.body.message) | ||
reasonPrompt(context).then(run).catch(handleErr) | ||
} else if (err && err.body && err.body.id === 'two_factor') { | ||
twoFactorPrompt(options, context).then(run).catch(handleErr) | ||
} else throw err | ||
}).catch(handleErr) | ||
} | ||
return run() | ||
} | ||
} |
@@ -1,11 +0,11 @@ | ||
'use strict'; | ||
'use strict' | ||
var cli = require('..'); | ||
var cli = require('..') | ||
var mocking; | ||
var mocking | ||
function concatArguments(args) { | ||
return Array.prototype.map.call(args, function(arg) { | ||
return arg + ''; | ||
}).join(' '); | ||
function concatArguments (args) { | ||
return Array.prototype.map.call(args, function (arg) { | ||
return arg + '' | ||
}).join(' ') | ||
} | ||
@@ -20,5 +20,5 @@ | ||
if (mocking) { | ||
cli.stdout += cli.color.stripColor(concatArguments(arguments) + '\n'); | ||
cli.stdout += cli.color.stripColor(concatArguments(arguments) + '\n') | ||
} else { | ||
console.log.apply(null, arguments); | ||
console.log.apply(null, arguments) | ||
} | ||
@@ -34,5 +34,5 @@ } | ||
if (mocking) { | ||
cli.stdout += cli.color.stripColor(concatArguments(arguments)); | ||
cli.stdout += cli.color.stripColor(concatArguments(arguments)) | ||
} else { | ||
process.stdout.write.apply(process.stdout, arguments); | ||
process.stdout.write.apply(process.stdout, arguments) | ||
} | ||
@@ -42,5 +42,5 @@ } | ||
function hush () { | ||
let debug = process.env.HEROKU_DEBUG; | ||
let debug = process.env.HEROKU_DEBUG | ||
if (debug && (debug === '1' || debug.toUpperCase() === 'TRUE')) { | ||
console.error.apply(null, arguments); | ||
console.error.apply(null, arguments) | ||
} | ||
@@ -56,5 +56,5 @@ } | ||
if (mocking) { | ||
cli.stderr += cli.color.stripColor(concatArguments(arguments) + '\n'); | ||
cli.stderr += cli.color.stripColor(concatArguments(arguments) + '\n') | ||
} else { | ||
console.error.apply(null, arguments); | ||
console.error.apply(null, arguments) | ||
} | ||
@@ -70,5 +70,5 @@ } | ||
if (mocking) { | ||
cli.stderr += cli.color.stripColor(concatArguments(arguments)); | ||
cli.stderr += cli.color.stripColor(concatArguments(arguments)) | ||
} else { | ||
process.stderr.write.apply(process.stderr, arguments); | ||
process.stderr.write.apply(process.stderr, arguments) | ||
} | ||
@@ -83,7 +83,8 @@ } | ||
function mock (mock) { | ||
if (mock === false) mocking = false; | ||
else { | ||
mocking = true; | ||
cli.stderr = ''; | ||
cli.stdout = ''; | ||
if (mock === false) { | ||
mocking = false | ||
} else { | ||
mocking = true | ||
cli.stderr = '' | ||
cli.stdout = '' | ||
} | ||
@@ -99,12 +100,12 @@ } | ||
function debug (obj) { | ||
console.dir(obj, {colors: true}); | ||
console.dir(obj, {colors: true}) | ||
} | ||
exports.hush = hush; | ||
exports.log = log; | ||
exports.writeLog = writeLog; | ||
exports.error = error; | ||
exports.writeError = writeError; | ||
exports.mock = mock; | ||
exports.mocking = () => mocking; | ||
exports.debug = debug; | ||
exports.hush = hush | ||
exports.log = log | ||
exports.writeLog = writeLog | ||
exports.error = error | ||
exports.writeError = writeError | ||
exports.mock = mock | ||
exports.mocking = () => mocking | ||
exports.debug = debug |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
'use strict' | ||
@@ -7,4 +7,4 @@ /** | ||
* @example | ||
* let cli = require('heroku-cli-util'); | ||
* var d = new Date(); | ||
* let cli = require('heroku-cli-util') | ||
* var d = new Date() | ||
* cli.formatDate(d); // '2015-05-14T18:03:10.034Z' | ||
@@ -16,5 +16,5 @@ * | ||
function formatDate (date) { | ||
return date.toISOString(); | ||
return date.toISOString() | ||
} | ||
exports.formatDate = formatDate; | ||
exports.formatDate = formatDate |
@@ -1,12 +0,12 @@ | ||
'use strict'; | ||
'use strict' | ||
let cli = require('..'); | ||
let console = require('./console'); | ||
let linewrap = require('./linewrap'); | ||
let path = require('path'); | ||
let os = require('os'); | ||
let cli = require('..') | ||
let console = require('./console') | ||
let linewrap = require('./linewrap') | ||
let path = require('path') | ||
let os = require('os') | ||
function errtermwidth() { | ||
if (!process.stderr.isTTY) return 80; | ||
return process.stderr.getWindowSize()[0]; | ||
function errtermwidth () { | ||
if (!process.stderr.isTTY) return 80 | ||
return process.stderr.getWindowSize()[0] | ||
} | ||
@@ -17,14 +17,14 @@ | ||
errtermwidth(), { | ||
skipScheme: 'ansi-color', | ||
skip: /^\$ .*$/, | ||
})(msg || ''); | ||
skipScheme: 'ansi-color', | ||
skip: /^\$ .*$/ | ||
})(msg || '') | ||
} | ||
function bangify (msg, c) { | ||
let lines = msg.split('\n'); | ||
for(let i=0; i<lines.length; i++) { | ||
let line = lines[i]; | ||
lines[i] = ' ' + c + line.substr(2,line.length); | ||
let lines = msg.split('\n') | ||
for (let i = 0; i < lines.length; i++) { | ||
let line = lines[i] | ||
lines[i] = ' ' + c + line.substr(2, line.length) | ||
} | ||
return lines.join('\n'); | ||
return lines.join('\n') | ||
} | ||
@@ -36,5 +36,5 @@ | ||
if (err.body.message) { | ||
return err.body.message; | ||
return err.body.message | ||
} else if (err.body.error) { | ||
return err.body.error; | ||
return err.body.error | ||
} | ||
@@ -44,77 +44,77 @@ } | ||
if (err.message && err.code) { | ||
return `${err.code}: ${err.message}`; | ||
return `${err.code}: ${err.message}` | ||
} else if (err.message) { | ||
return err.message; | ||
return err.message | ||
} | ||
return err; | ||
return err | ||
} | ||
let arrow = process.platform === 'win32' ? '!' : '▸'; | ||
let arrow = process.platform === 'win32' ? '!' : '▸' | ||
function error (err) { | ||
console.error(bangify(wrap(getErrorMessage(err)), cli.color.red(arrow))); | ||
console.error(bangify(wrap(getErrorMessage(err)), cli.color.red(arrow))) | ||
} | ||
function warn (msg) { | ||
console.error(bangify(wrap(msg), cli.color.yellow(arrow))); | ||
console.error(bangify(wrap(msg), cli.color.yellow(arrow))) | ||
} | ||
function logtimestamp() { | ||
function logtimestamp () { | ||
return new Date().toISOString() | ||
.replace(/T/, ' ') | ||
.replace(/-/g, '/') | ||
.replace(/\..+/, ''); | ||
.replace(/T/, ' ') | ||
.replace(/-/g, '/') | ||
.replace(/\..+/, '') | ||
} | ||
function cacheHome() { | ||
let base; | ||
if (process.env.XDG_CACHE_HOME) base = process.env.XDG_CACHE_HOME; | ||
function cacheHome () { | ||
let base | ||
if (process.env.XDG_CACHE_HOME) base = process.env.XDG_CACHE_HOME | ||
if (!base) { | ||
if (process.platform === "win32" && process.env.LOCALAPPDATA) { | ||
base = process.env.LOCALAPPDATA; | ||
} else { | ||
base = path.join(os.homedir(), ".cache"); | ||
} | ||
} | ||
return path.join(base, "heroku"); | ||
if (process.platform === 'win32' && process.env.LOCALAPPDATA) { | ||
base = process.env.LOCALAPPDATA | ||
} else { | ||
base = path.join(os.homedir(), '.cache') | ||
} | ||
} | ||
return path.join(base, 'heroku') | ||
} | ||
function log(msg) { | ||
let fs = require('fs'); | ||
let logPath = path.join(cacheHome(), 'error.log'); | ||
fs.appendFileSync(logPath, logtimestamp() + ' ' + cli.color.stripColor(msg) + '\n'); | ||
function log (msg) { | ||
let fs = require('fs') | ||
let logPath = path.join(cacheHome(), 'error.log') | ||
fs.appendFileSync(logPath, logtimestamp() + ' ' + cli.color.stripColor(msg) + '\n') | ||
} | ||
function errorHandler(options) { | ||
options = options || {}; | ||
function errorHandler (options) { | ||
options = options || {} | ||
function exit () { | ||
if (options.exit !== false) { | ||
process.exit(1); | ||
process.exit(1) | ||
} | ||
} | ||
return function handleErr(err) { | ||
if (cli.raiseErrors) { throw err; } | ||
return function handleErr (err) { | ||
if (cli.raiseErrors) throw err | ||
try { | ||
if (err !== '') { error(err); } | ||
if (err !== '') error(err) | ||
if (err.stack) { | ||
log(err.stack); | ||
log(err.stack) | ||
if (options.debug) { | ||
console.error(err.stack); | ||
console.error(err.stack) | ||
} | ||
} | ||
if (err.body) { | ||
log(JSON.stringify(err.body)); | ||
log(JSON.stringify(err.body)) | ||
} | ||
if (options.dev) exit(); | ||
else if (options.rollbar) options.rollbar.error(err).then(exit, exit); | ||
else exit(); | ||
if (options.dev) exit() | ||
else if (options.rollbar) options.rollbar.error(err).then(exit, exit) | ||
else exit() | ||
} catch (err) { | ||
console.error(err.stack); | ||
process.exit(-1); | ||
console.error(err.stack) | ||
process.exit(-1) | ||
} | ||
}; | ||
} | ||
} | ||
module.exports.error = error; | ||
module.exports.warn = warn; | ||
module.exports.errorHandler = errorHandler; | ||
module.exports.error = error | ||
module.exports.warn = warn | ||
module.exports.errorHandler = errorHandler |
@@ -1,37 +0,37 @@ | ||
'use strict'; | ||
'use strict' | ||
var util = require('util'); | ||
var cli = require('./errors'); | ||
var util = require('util') | ||
var cli = require('./errors') | ||
function ErrorExit(code) { | ||
Error.call(this); | ||
Error.captureStackTrace(this, this.constructor); | ||
this.name = this.constructor.name; | ||
function ErrorExit (code) { | ||
Error.call(this) | ||
Error.captureStackTrace(this, this.constructor) | ||
this.name = this.constructor.name | ||
this.code = code; | ||
this.code = code | ||
} | ||
util.inherits(ErrorExit, Error); | ||
util.inherits(ErrorExit, Error) | ||
var mocking; | ||
var mocking | ||
function exit(code, message) { | ||
function exit (code, message) { | ||
if (message) { | ||
cli.error(message); | ||
cli.error(message) | ||
} | ||
if (mocking) { | ||
throw new ErrorExit(code); | ||
throw new ErrorExit(code) | ||
} else { | ||
process.exit(code); | ||
process.exit(code) | ||
} | ||
} | ||
exit.mock = function() { | ||
mocking = true; | ||
}; | ||
exit.mock = function () { | ||
mocking = true | ||
} | ||
exit.ErrorExit = ErrorExit; | ||
exit.ErrorExit = ErrorExit | ||
module.exports = { | ||
exit | ||
}; | ||
} |
144
lib/got.js
@@ -1,29 +0,29 @@ | ||
'use strict'; | ||
'use strict' | ||
let hush = require('./console').hush; | ||
let hush = require('./console').hush | ||
function findProxy(urlParsed) { | ||
let httpProxy = process.env.HTTP_PROXY || process.env.http_proxy; | ||
let httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy; | ||
function findProxy (urlParsed) { | ||
let httpProxy = process.env.HTTP_PROXY || process.env.http_proxy | ||
let httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy | ||
if (urlParsed.protocol === 'https:') { | ||
return httpsProxy || httpProxy; | ||
return httpsProxy || httpProxy | ||
} else { | ||
return httpProxy; | ||
return httpProxy | ||
} | ||
} | ||
function findTunnel(urlParsed) { | ||
let tunnel = require('tunnel-agent'); | ||
function findTunnel (urlParsed) { | ||
let tunnel = require('tunnel-agent') | ||
if (urlParsed.protocol === 'https:') { | ||
return tunnel.httpsOverHttp; | ||
return tunnel.httpsOverHttp | ||
} else { | ||
return tunnel.httpOverHttp; | ||
return tunnel.httpOverHttp | ||
} | ||
} | ||
function agent(urlParsed, proxyParsed, certs) { | ||
let tunnelMethod = findTunnel(urlParsed); | ||
let opts = { | ||
function agent (urlParsed, proxyParsed, certs) { | ||
let tunnelMethod = findTunnel(urlParsed) | ||
let opts = { | ||
proxy: { | ||
@@ -33,81 +33,81 @@ host: proxyParsed.hostname, | ||
} | ||
}; | ||
} | ||
if (proxyParsed.auth) { | ||
opts.proxy.proxyAuth = proxyParsed.auth; | ||
opts.proxy.proxyAuth = proxyParsed.auth | ||
} | ||
if (certs.length > 0) { | ||
opts.ca = certs; | ||
opts.ca = certs | ||
} | ||
let tunnelAgent = tunnelMethod(opts); | ||
let tunnelAgent = tunnelMethod(opts) | ||
if (urlParsed.protocol === 'https:') { | ||
tunnelAgent.defaultPort = 443; | ||
tunnelAgent.defaultPort = 443 | ||
} | ||
return tunnelAgent; | ||
return tunnelAgent | ||
} | ||
function sslCertFile() { | ||
return process.env.SSL_CERT_FILE ? [process.env.SSL_CERT_FILE] : []; | ||
function sslCertFile () { | ||
return process.env.SSL_CERT_FILE ? [process.env.SSL_CERT_FILE] : [] | ||
} | ||
function sslCertDir() { | ||
let cert_dir = process.env.SSL_CERT_DIR; | ||
if (cert_dir) { | ||
const fs = require('fs'); | ||
const path = require('path'); | ||
return fs.readdirSync(cert_dir).map(f => path.join(cert_dir, f)); | ||
function sslCertDir () { | ||
let certDir = process.env.SSL_CERT_DIR | ||
if (certDir) { | ||
const fs = require('fs') | ||
const path = require('path') | ||
return fs.readdirSync(certDir).map(f => path.join(certDir, f)) | ||
} else { | ||
return []; | ||
return [] | ||
} | ||
} | ||
function getCerts() { | ||
let filenames = sslCertFile().concat(sslCertDir()); | ||
function getCerts () { | ||
let filenames = sslCertFile().concat(sslCertDir()) | ||
if (filenames.length > 0) { | ||
hush('Adding the following trusted certificate authorities'); | ||
hush('Adding the following trusted certificate authorities') | ||
} | ||
return filenames.map(function(filename) { | ||
const fs = require('fs'); | ||
hush(' ' + filename); | ||
return fs.readFileSync(filename); | ||
}); | ||
return filenames.map(function (filename) { | ||
const fs = require('fs') | ||
hush(' ' + filename) | ||
return fs.readFileSync(filename) | ||
}) | ||
} | ||
function addToOpts(url, opts) { | ||
const urlLib = require('url'); | ||
function addToOpts (url, opts) { | ||
const urlLib = require('url') | ||
let urlParsed = urlLib.parse(url); | ||
let proxy = findProxy(urlParsed); | ||
let urlParsed = urlLib.parse(url) | ||
let proxy = findProxy(urlParsed) | ||
let certs = getCerts(); | ||
let certs = getCerts() | ||
if (proxy) { | ||
let proxyParsed = urlLib.parse(proxy); | ||
opts = Object.assign({}, opts, {agent: agent(urlParsed, proxyParsed, certs)}); | ||
let proxyParsed = urlLib.parse(proxy) | ||
opts = Object.assign({}, opts, {agent: agent(urlParsed, proxyParsed, certs)}) | ||
} | ||
if (certs.length > 0) { | ||
opts = Object.assign({}, opts, {ca: certs}); | ||
opts = Object.assign({}, opts, {ca: certs}) | ||
} | ||
return opts; | ||
return opts | ||
} | ||
let loadErrors; | ||
let loadErrors | ||
function got(url, opts) { | ||
const gotDelegate = require('got'); | ||
loadErrors(); | ||
return gotDelegate(url, addToOpts(url, opts)); | ||
function got (url, opts) { | ||
const gotDelegate = require('got') | ||
loadErrors() | ||
return gotDelegate(url, addToOpts(url, opts)) | ||
} | ||
got.stream = function (url, opts) { | ||
const gotDelegate = require('got'); | ||
loadErrors(); | ||
return gotDelegate.stream(url, addToOpts(url, opts)); | ||
}; | ||
const gotDelegate = require('got') | ||
loadErrors() | ||
return gotDelegate.stream(url, addToOpts(url, opts)) | ||
} | ||
@@ -121,30 +121,30 @@ const helpers = [ | ||
'delete' | ||
]; | ||
] | ||
helpers.forEach(el => { | ||
got[el] = (url, opts) => got(url, Object.assign({}, opts, {method: el})); | ||
}); | ||
got[el] = (url, opts) => got(url, Object.assign({}, opts, {method: el})) | ||
}) | ||
helpers.forEach(el => { | ||
got.stream[el] = function (url, opts) { | ||
return got.stream(url, Object.assign({}, opts, {method: el})); | ||
}; | ||
}); | ||
return got.stream(url, Object.assign({}, opts, {method: el})) | ||
} | ||
}) | ||
loadErrors = () => { | ||
const gotDelegate = require('got'); | ||
const gotDelegate = require('got') | ||
const errors = [ | ||
"HTTPError", | ||
"MaxRedirectsError", | ||
"ParseError", | ||
"ReadError", | ||
"RequestError" | ||
]; | ||
'HTTPError', | ||
'MaxRedirectsError', | ||
'ParseError', | ||
'ReadError', | ||
'RequestError' | ||
] | ||
errors.forEach(el => { | ||
got[el] = gotDelegate[el]; | ||
}); | ||
}; | ||
got[el] = gotDelegate[el] | ||
}) | ||
} | ||
module.exports = got; | ||
module.exports = got |
1359
lib/linewrap.js
@@ -5,783 +5,780 @@ // code is from https://github.com/AnAppAMonth/linewrap | ||
var presetMap = { | ||
'html': { | ||
skipScheme: 'html', | ||
lineBreakScheme: 'html', | ||
whitespace: 'collapse' | ||
} | ||
}; | ||
'html': { | ||
skipScheme: 'html', | ||
lineBreakScheme: 'html', | ||
whitespace: 'collapse' | ||
} | ||
} | ||
// lineBreak Schemes | ||
var brPat = /<\s*br(?:[\s/]*|\s[^>]*)>/gi; | ||
var brPat = /<\s*br(?:[\s/]*|\s[^>]*)>/gi | ||
var lineBreakSchemeMap = { | ||
'unix': [/\n/g, '\n'], | ||
'dos': [/\r\n/g, '\r\n'], | ||
'mac': [/\r/g, '\r'], | ||
'html': [brPat, '<br>'], | ||
'xhtml': [brPat, '<br/>'] | ||
}; | ||
'unix': [/\n/g, '\n'], | ||
'dos': [/\r\n/g, '\r\n'], | ||
'mac': [/\r/g, '\r'], | ||
'html': [brPat, '<br>'], | ||
'xhtml': [brPat, '<br/>'] | ||
} | ||
// skip Schemes | ||
var skipSchemeMap = { | ||
'ansi-color': /\x1B\[[^m]*m/g, | ||
'html': /<[^>]*>/g, | ||
'bbcode': /\[[^]]*\]/g | ||
}; | ||
'ansi-color': /\x1B\[[^m]*m/g, | ||
'html': /<[^>]*>/g, | ||
'bbcode': /\[[^]]*\]/g | ||
} | ||
var modeMap = { | ||
'soft': 1, | ||
'hard': 1 | ||
}; | ||
'soft': 1, | ||
'hard': 1 | ||
} | ||
var wsMap = { | ||
'collapse': 1, | ||
'default': 1, | ||
'line': 1, | ||
'all': 1 | ||
}; | ||
'collapse': 1, | ||
'default': 1, | ||
'line': 1, | ||
'all': 1 | ||
} | ||
var rlbMap = { | ||
'all': 1, | ||
'multi': 1, | ||
'none': 1 | ||
}; | ||
var rlbSMPat = /([sm])(\d+)/; | ||
'all': 1, | ||
'multi': 1, | ||
'none': 1 | ||
} | ||
var rlbSMPat = /([sm])(\d+)/ | ||
var escapePat = /[-/\\^$*+?.()|[\]{}]/g; | ||
function escapeRegExp(s) { | ||
return s.replace(escapePat, '\\$&'); | ||
var escapePat = /[-/\\^$*+?.()|[\]{}]/g | ||
function escapeRegExp (s) { | ||
return s.replace(escapePat, '\\$&') | ||
} | ||
var linewrap = module.exports = function (start, stop, params) { | ||
if (typeof start === 'object') { | ||
params = start; | ||
start = params.start; | ||
stop = params.stop; | ||
} | ||
if (typeof start === 'object') { | ||
params = start | ||
start = params.start | ||
stop = params.stop | ||
} | ||
if (typeof stop === 'object') { | ||
params = stop; | ||
start = start || params.start; | ||
stop = undefined; | ||
} | ||
if (typeof stop === 'object') { | ||
params = stop | ||
start = start || params.start | ||
stop = undefined | ||
} | ||
if (!stop) { | ||
stop = start; | ||
start = 0; | ||
} | ||
if (!stop) { | ||
stop = start | ||
start = 0 | ||
} | ||
if (!params) { params = {}; } | ||
// Supported options and default values. | ||
var preset, | ||
mode = 'soft', | ||
whitespace = 'default', | ||
tabWidth = 4, | ||
skip, skipScheme, lineBreak, lineBreakScheme, | ||
respectLineBreaks = 'all', | ||
respectNum, | ||
preservedLineIndent, | ||
wrapLineIndent, wrapLineIndentBase; | ||
if (!params) { params = {}; } | ||
// Supported options and default values. | ||
var preset, | ||
mode = 'soft', | ||
whitespace = 'default', | ||
tabWidth = 4, | ||
skip, skipScheme, lineBreak, lineBreakScheme, | ||
respectLineBreaks = 'all', | ||
respectNum, | ||
preservedLineIndent, | ||
wrapLineIndent, wrapLineIndentBase | ||
var skipPat; | ||
var lineBreakPat, lineBreakStr; | ||
var multiLineBreakPat; | ||
var preservedLinePrefix = ''; | ||
var wrapLineIndentPat, wrapLineInitPrefix = ''; | ||
var tabRepl; | ||
var item, flags; | ||
var i; | ||
var skipPat | ||
var lineBreakPat, lineBreakStr | ||
var multiLineBreakPat | ||
var preservedLinePrefix = '' | ||
var wrapLineIndentPat, wrapLineInitPrefix = '' | ||
var tabRepl | ||
var item, flags | ||
var i | ||
// First process presets, because these settings can be overwritten later. | ||
preset = params.preset; | ||
if (preset) { | ||
if (!(preset instanceof Array)) { | ||
preset = [preset]; | ||
// First process presets, because these settings can be overwritten later. | ||
preset = params.preset | ||
if (preset) { | ||
if (!(preset instanceof Array)) { | ||
preset = [preset] | ||
} | ||
for (i = 0; i < preset.length; i++) { | ||
item = presetMap[preset[i]] | ||
if (item) { | ||
if (item.mode) { | ||
mode = item.mode | ||
} | ||
for (i = 0; i < preset.length; i++) { | ||
item = presetMap[preset[i]]; | ||
if (item) { | ||
if (item.mode) { | ||
mode = item.mode; | ||
} | ||
if (item.whitespace) { | ||
whitespace = item.whitespace; | ||
} | ||
if (item.tabWidth !== undefined) { | ||
tabWidth = item.tabWidth; | ||
} | ||
if (item.skip) { | ||
skip = item.skip; | ||
} | ||
if (item.skipScheme) { | ||
skipScheme = item.skipScheme; | ||
} | ||
if (item.lineBreak) { | ||
lineBreak = item.lineBreak; | ||
} | ||
if (item.lineBreakScheme) { | ||
lineBreakScheme = item.lineBreakScheme; | ||
} | ||
if (item.respectLineBreaks) { | ||
respectLineBreaks = item.respectLineBreaks; | ||
} | ||
if (item.preservedLineIndent !== undefined) { | ||
preservedLineIndent = item.preservedLineIndent; | ||
} | ||
if (item.wrapLineIndent !== undefined) { | ||
wrapLineIndent = item.wrapLineIndent; | ||
} | ||
if (item.wrapLineIndentBase) { | ||
wrapLineIndentBase = item.wrapLineIndentBase; | ||
} | ||
} else { | ||
throw new TypeError('preset must be one of "' + Object.keys(presetMap).join('", "') + '"'); | ||
} | ||
if (item.whitespace) { | ||
whitespace = item.whitespace | ||
} | ||
if (item.tabWidth !== undefined) { | ||
tabWidth = item.tabWidth | ||
} | ||
if (item.skip) { | ||
skip = item.skip | ||
} | ||
if (item.skipScheme) { | ||
skipScheme = item.skipScheme | ||
} | ||
if (item.lineBreak) { | ||
lineBreak = item.lineBreak | ||
} | ||
if (item.lineBreakScheme) { | ||
lineBreakScheme = item.lineBreakScheme | ||
} | ||
if (item.respectLineBreaks) { | ||
respectLineBreaks = item.respectLineBreaks | ||
} | ||
if (item.preservedLineIndent !== undefined) { | ||
preservedLineIndent = item.preservedLineIndent | ||
} | ||
if (item.wrapLineIndent !== undefined) { | ||
wrapLineIndent = item.wrapLineIndent | ||
} | ||
if (item.wrapLineIndentBase) { | ||
wrapLineIndentBase = item.wrapLineIndentBase | ||
} | ||
} else { | ||
throw new TypeError('preset must be one of "' + Object.keys(presetMap).join('", "') + '"') | ||
} | ||
} | ||
} | ||
if (params.mode) { | ||
if (modeMap[params.mode]) { | ||
mode = params.mode; | ||
} else { | ||
throw new TypeError('mode must be one of "' + Object.keys(modeMap).join('", "') + '"'); | ||
} | ||
if (params.mode) { | ||
if (modeMap[params.mode]) { | ||
mode = params.mode | ||
} else { | ||
throw new TypeError('mode must be one of "' + Object.keys(modeMap).join('", "') + '"') | ||
} | ||
// Available options: 'collapse', 'default', 'line', and 'all' | ||
if (params.whitespace) { | ||
if (wsMap[params.whitespace]) { | ||
whitespace = params.whitespace; | ||
} else { | ||
throw new TypeError('whitespace must be one of "' + Object.keys(wsMap).join('", "') + '"'); | ||
} | ||
} | ||
// Available options: 'collapse', 'default', 'line', and 'all' | ||
if (params.whitespace) { | ||
if (wsMap[params.whitespace]) { | ||
whitespace = params.whitespace | ||
} else { | ||
throw new TypeError('whitespace must be one of "' + Object.keys(wsMap).join('", "') + '"') | ||
} | ||
} | ||
if (params.tabWidth !== undefined) { | ||
if (parseInt(params.tabWidth, 10) >= 0) { | ||
tabWidth = parseInt(params.tabWidth, 10); | ||
} else { | ||
throw new TypeError('tabWidth must be a non-negative integer'); | ||
} | ||
if (params.tabWidth !== undefined) { | ||
if (parseInt(params.tabWidth, 10) >= 0) { | ||
tabWidth = parseInt(params.tabWidth, 10) | ||
} else { | ||
throw new TypeError('tabWidth must be a non-negative integer') | ||
} | ||
tabRepl = new Array(tabWidth + 1).join(' '); | ||
} | ||
tabRepl = new Array(tabWidth + 1).join(' ') | ||
// Available options: 'all', 'multi', 'm\d+', 's\d+', 'none' | ||
if (params.respectLineBreaks) { | ||
if (rlbMap[params.respectLineBreaks] || rlbSMPat.test(params.respectLineBreaks)) { | ||
respectLineBreaks = params.respectLineBreaks; | ||
} else { | ||
throw new TypeError('respectLineBreaks must be one of "' + Object.keys(rlbMap).join('", "') + | ||
'", "m<num>", "s<num>"'); | ||
} | ||
// Available options: 'all', 'multi', 'm\d+', 's\d+', 'none' | ||
if (params.respectLineBreaks) { | ||
if (rlbMap[params.respectLineBreaks] || rlbSMPat.test(params.respectLineBreaks)) { | ||
respectLineBreaks = params.respectLineBreaks | ||
} else { | ||
throw new TypeError('respectLineBreaks must be one of "' + Object.keys(rlbMap).join('", "') + | ||
'", "m<num>", "s<num>"') | ||
} | ||
// After these conversions, now we have 4 options in `respectLineBreaks`: | ||
// 'all', 'none', 'm' and 's'. | ||
// `respectNum` is applicable iff `respectLineBreaks` is either 'm' or 's'. | ||
if (respectLineBreaks === 'multi') { | ||
respectLineBreaks = 'm'; | ||
respectNum = 2; | ||
} else if (!rlbMap[respectLineBreaks]) { | ||
var match = rlbSMPat.exec(respectLineBreaks); | ||
respectLineBreaks = match[1]; | ||
respectNum = parseInt(match[2], 10); | ||
} | ||
// After these conversions, now we have 4 options in `respectLineBreaks`: | ||
// 'all', 'none', 'm' and 's'. | ||
// `respectNum` is applicable iff `respectLineBreaks` is either 'm' or 's'. | ||
if (respectLineBreaks === 'multi') { | ||
respectLineBreaks = 'm' | ||
respectNum = 2 | ||
} else if (!rlbMap[respectLineBreaks]) { | ||
var match = rlbSMPat.exec(respectLineBreaks) | ||
respectLineBreaks = match[1] | ||
respectNum = parseInt(match[2], 10) | ||
} | ||
if (params.preservedLineIndent !== undefined) { | ||
if (parseInt(params.preservedLineIndent, 10) >= 0) { | ||
preservedLineIndent = parseInt(params.preservedLineIndent, 10) | ||
} else { | ||
throw new TypeError('preservedLineIndent must be a non-negative integer') | ||
} | ||
} | ||
if (params.preservedLineIndent !== undefined) { | ||
if (parseInt(params.preservedLineIndent, 10) >= 0) { | ||
preservedLineIndent = parseInt(params.preservedLineIndent, 10); | ||
} else { | ||
throw new TypeError('preservedLineIndent must be a non-negative integer'); | ||
} | ||
if (preservedLineIndent > 0) { | ||
preservedLinePrefix = new Array(preservedLineIndent + 1).join(' ') | ||
} | ||
if (params.wrapLineIndent !== undefined) { | ||
if (!isNaN(parseInt(params.wrapLineIndent, 10))) { | ||
wrapLineIndent = parseInt(params.wrapLineIndent, 10) | ||
} else { | ||
throw new TypeError('wrapLineIndent must be an integer') | ||
} | ||
} | ||
if (params.wrapLineIndentBase) { | ||
wrapLineIndentBase = params.wrapLineIndentBase | ||
} | ||
if (preservedLineIndent > 0) { | ||
preservedLinePrefix = new Array(preservedLineIndent + 1).join(' '); | ||
if (wrapLineIndentBase) { | ||
if (wrapLineIndent === undefined) { | ||
throw new TypeError('wrapLineIndent must be specified when wrapLineIndentBase is specified') | ||
} | ||
if (wrapLineIndentBase instanceof RegExp) { | ||
wrapLineIndentPat = wrapLineIndentBase | ||
} else if (typeof wrapLineIndentBase === 'string') { | ||
wrapLineIndentPat = new RegExp(escapeRegExp(wrapLineIndentBase)) | ||
} else { | ||
throw new TypeError('wrapLineIndentBase must be either a RegExp object or a string') | ||
} | ||
} else if (wrapLineIndent > 0) { | ||
wrapLineInitPrefix = new Array(wrapLineIndent + 1).join(' ') | ||
} else if (wrapLineIndent < 0) { | ||
throw new TypeError('wrapLineIndent must be non-negative when a base is not specified') | ||
} | ||
if (params.wrapLineIndent !== undefined) { | ||
if (!isNaN(parseInt(params.wrapLineIndent, 10))) { | ||
wrapLineIndent = parseInt(params.wrapLineIndent, 10); | ||
} else { | ||
throw new TypeError('wrapLineIndent must be an integer'); | ||
} | ||
// NOTE: For the two RegExps `skipPat` and `lineBreakPat` that can be specified | ||
// by the user: | ||
// 1. We require them to be "global", so we have to convert them to global | ||
// if the user specifies a non-global regex. | ||
// 2. We cannot call `split()` on them, because they may or may not contain | ||
// capturing parentheses which affect the output of `split()`. | ||
// Precedence: Regex = Str > Scheme | ||
if (params.skipScheme) { | ||
if (skipSchemeMap[params.skipScheme]) { | ||
skipScheme = params.skipScheme | ||
} else { | ||
throw new TypeError('skipScheme must be one of "' + Object.keys(skipSchemeMap).join('", "') + '"') | ||
} | ||
if (params.wrapLineIndentBase) { | ||
wrapLineIndentBase = params.wrapLineIndentBase; | ||
} | ||
if (params.skip) { | ||
skip = params.skip | ||
} | ||
if (skip) { | ||
if (skip instanceof RegExp) { | ||
skipPat = skip | ||
if (!skipPat.global) { | ||
flags = 'g' | ||
if (skipPat.ignoreCase) { flags += 'i'; } | ||
if (skipPat.multiline) { flags += 'm'; } | ||
skipPat = new RegExp(skipPat.source, flags) | ||
} | ||
} else if (typeof skip === 'string') { | ||
skipPat = new RegExp(escapeRegExp(skip), 'g') | ||
} else { | ||
throw new TypeError('skip must be either a RegExp object or a string') | ||
} | ||
} | ||
if (!skipPat && skipScheme) { | ||
skipPat = skipSchemeMap[skipScheme] | ||
} | ||
if (wrapLineIndentBase) { | ||
if (wrapLineIndent === undefined) { | ||
throw new TypeError('wrapLineIndent must be specified when wrapLineIndentBase is specified'); | ||
} | ||
if (wrapLineIndentBase instanceof RegExp) { | ||
wrapLineIndentPat = wrapLineIndentBase; | ||
} else if (typeof wrapLineIndentBase === 'string') { | ||
wrapLineIndentPat = new RegExp(escapeRegExp(wrapLineIndentBase)); | ||
} else { | ||
throw new TypeError('wrapLineIndentBase must be either a RegExp object or a string'); | ||
} | ||
} else if (wrapLineIndent > 0) { | ||
wrapLineInitPrefix = new Array(wrapLineIndent + 1).join(' '); | ||
} else if (wrapLineIndent < 0) { | ||
throw new TypeError('wrapLineIndent must be non-negative when a base is not specified'); | ||
// Precedence: | ||
// - for lineBreakPat: Regex > Scheme > Str | ||
// - for lineBreakStr: Str > Scheme > Regex | ||
if (params.lineBreakScheme) { | ||
if (lineBreakSchemeMap[params.lineBreakScheme]) { | ||
lineBreakScheme = params.lineBreakScheme | ||
} else { | ||
throw new TypeError('lineBreakScheme must be one of "' + Object.keys(lineBreakSchemeMap).join('", "') + '"') | ||
} | ||
} | ||
if (params.lineBreak) { | ||
lineBreak = params.lineBreak | ||
} | ||
// NOTE: For the two RegExps `skipPat` and `lineBreakPat` that can be specified | ||
// by the user: | ||
// 1. We require them to be "global", so we have to convert them to global | ||
// if the user specifies a non-global regex. | ||
// 2. We cannot call `split()` on them, because they may or may not contain | ||
// capturing parentheses which affect the output of `split()`. | ||
// Precedence: Regex = Str > Scheme | ||
if (params.skipScheme) { | ||
if (skipSchemeMap[params.skipScheme]) { | ||
skipScheme = params.skipScheme; | ||
if (lineBreakScheme) { | ||
// Supported schemes: 'unix', 'dos', 'mac', 'html', 'xhtml' | ||
item = lineBreakSchemeMap[lineBreakScheme] | ||
if (item) { | ||
lineBreakPat = item[0] | ||
lineBreakStr = item[1] | ||
} | ||
} | ||
if (lineBreak) { | ||
if (lineBreak instanceof Array) { | ||
if (lineBreak.length === 1) { | ||
lineBreak = lineBreak[0] | ||
} else if (lineBreak.length >= 2) { | ||
if (lineBreak[0] instanceof RegExp) { | ||
lineBreakPat = lineBreak[0] | ||
if (typeof lineBreak[1] === 'string') { | ||
lineBreakStr = lineBreak[1] | ||
} | ||
} else if (lineBreak[1] instanceof RegExp) { | ||
lineBreakPat = lineBreak[1] | ||
if (typeof lineBreak[0] === 'string') { | ||
lineBreakStr = lineBreak[0] | ||
} | ||
} else if (typeof lineBreak[0] === 'string' && typeof lineBreak[1] === 'string') { | ||
lineBreakPat = new RegExp(escapeRegExp(lineBreak[0]), 'g') | ||
lineBreakStr = lineBreak[1] | ||
} else { | ||
throw new TypeError('skipScheme must be one of "' + Object.keys(skipSchemeMap).join('", "') + '"'); | ||
lineBreak = lineBreak[0] | ||
} | ||
} | ||
} | ||
if (params.skip) { | ||
skip = params.skip; | ||
if (typeof lineBreak === 'string') { | ||
lineBreakStr = lineBreak | ||
if (!lineBreakPat) { | ||
lineBreakPat = new RegExp(escapeRegExp(lineBreak), 'g') | ||
} | ||
} else if (lineBreak instanceof RegExp) { | ||
lineBreakPat = lineBreak | ||
} else if (!(lineBreak instanceof Array)) { | ||
throw new TypeError('lineBreak must be a RegExp object, a string, or an array consisted of a RegExp object and a string') | ||
} | ||
} | ||
// Only assign defaults when `lineBreakPat` is not assigned. | ||
// So if `params.lineBreak` is a RegExp, we don't have a value in `lineBreakStr` | ||
// yet. We will try to get the value from the input string, and if failed, we | ||
// will throw an exception. | ||
if (!lineBreakPat) { | ||
lineBreakPat = /\n/g | ||
lineBreakStr = '\n' | ||
} | ||
if (skip) { | ||
if (skip instanceof RegExp) { | ||
skipPat = skip; | ||
if (!skipPat.global) { | ||
flags = 'g'; | ||
if (skipPat.ignoreCase) { flags += 'i'; } | ||
if (skipPat.multiline) { flags += 'm'; } | ||
skipPat = new RegExp(skipPat.source, flags); | ||
} | ||
} else if (typeof skip === 'string') { | ||
skipPat = new RegExp(escapeRegExp(skip), 'g'); | ||
// Create `multiLineBreakPat` based on `lineBreakPat`, that matches strings | ||
// consisted of one or more line breaks and zero or more whitespaces. | ||
// Also convert `lineBreakPat` to global if not already so. | ||
flags = 'g' | ||
if (lineBreakPat.ignoreCase) { flags += 'i'; } | ||
if (lineBreakPat.multiline) { flags += 'm'; } | ||
multiLineBreakPat = new RegExp('\\s*(?:' + lineBreakPat.source + ')(?:' + | ||
lineBreakPat.source + '|\\s)*', flags) | ||
if (!lineBreakPat.global) { | ||
lineBreakPat = new RegExp(lineBreakPat.source, flags) | ||
} | ||
// Initialize other useful variables. | ||
var re = mode === 'hard' ? /\b/ : /(\S+\s+)/ | ||
var prefix = new Array(start + 1).join(' ') | ||
var wsStrip = (whitespace === 'default' || whitespace === 'collapse'), | ||
wsCollapse = (whitespace === 'collapse'), | ||
wsLine = (whitespace === 'line'), | ||
wsAll = (whitespace === 'all') | ||
var tabPat = /\t/g, | ||
collapsePat = / +/g, | ||
pPat = /^\s+/, | ||
tPat = /\s+$/, | ||
nonWsPat = /\S/, | ||
wsPat = /\s/ | ||
var wrapLen = stop - start | ||
return function (text) { | ||
text = text.toString().replace(tabPat, tabRepl) | ||
var match | ||
if (!lineBreakStr) { | ||
// Try to get lineBreakStr from `text` | ||
lineBreakPat.lastIndex = 0 | ||
match = lineBreakPat.exec(text) | ||
if (match) { | ||
lineBreakStr = match[0] | ||
} else { | ||
throw new TypeError('Line break string for the output not specified') | ||
} | ||
} | ||
// text -> blocks; each bloc -> segments; each segment -> chunks | ||
var blocks, base = 0 | ||
var mo, arr, b, res | ||
// Split `text` by line breaks. | ||
blocks = [] | ||
multiLineBreakPat.lastIndex = 0 | ||
match = multiLineBreakPat.exec(text) | ||
while(match) { | ||
blocks.push(text.substring(base, match.index)) | ||
if (respectLineBreaks !== 'none') { | ||
arr = [] | ||
b = 0 | ||
lineBreakPat.lastIndex = 0 | ||
mo = lineBreakPat.exec(match[0]) | ||
while(mo) { | ||
arr.push(match[0].substring(b, mo.index)) | ||
b = mo.index + mo[0].length | ||
mo = lineBreakPat.exec(match[0]) | ||
} | ||
arr.push(match[0].substring(b)) | ||
blocks.push({type: 'break', breaks: arr}) | ||
} else { | ||
// Strip line breaks and insert spaces when necessary. | ||
if (wsCollapse) { | ||
res = ' ' | ||
} else { | ||
throw new TypeError('skip must be either a RegExp object or a string'); | ||
res = match[0].replace(lineBreakPat, '') | ||
} | ||
blocks.push({type: 'break', remaining: res}) | ||
} | ||
base = match.index + match[0].length | ||
match = multiLineBreakPat.exec(text) | ||
} | ||
if (!skipPat && skipScheme) { | ||
skipPat = skipSchemeMap[skipScheme]; | ||
} | ||
blocks.push(text.substring(base)) | ||
// Precedence: | ||
// - for lineBreakPat: Regex > Scheme > Str | ||
// - for lineBreakStr: Str > Scheme > Regex | ||
if (params.lineBreakScheme) { | ||
if (lineBreakSchemeMap[params.lineBreakScheme]) { | ||
lineBreakScheme = params.lineBreakScheme; | ||
var i, j, k | ||
var segments | ||
if (skipPat) { | ||
segments = [] | ||
for (i = 0; i < blocks.length; i++) { | ||
var bloc = blocks[i] | ||
if (typeof bloc !== 'string') { | ||
// This is an object. | ||
segments.push(bloc) | ||
} else { | ||
throw new TypeError('lineBreakScheme must be one of "' + Object.keys(lineBreakSchemeMap).join('", "') + '"'); | ||
base = 0 | ||
skipPat.lastIndex = 0 | ||
match = skipPat.exec(bloc) | ||
while(match) { | ||
segments.push(bloc.substring(base, match.index)) | ||
segments.push({type: 'skip', value: match[0]}) | ||
base = match.index + match[0].length | ||
match = skipPat.exec(bloc) | ||
} | ||
segments.push(bloc.substring(base)) | ||
} | ||
} | ||
} else { | ||
segments = blocks | ||
} | ||
if (params.lineBreak) { | ||
lineBreak = params.lineBreak; | ||
} | ||
if (lineBreakScheme) { | ||
// Supported schemes: 'unix', 'dos', 'mac', 'html', 'xhtml' | ||
item = lineBreakSchemeMap[lineBreakScheme]; | ||
if (item) { | ||
lineBreakPat = item[0]; | ||
lineBreakStr = item[1]; | ||
var chunks = [] | ||
for (i = 0; i < segments.length; i++) { | ||
var segment = segments[i] | ||
if (typeof segment !== 'string') { | ||
// This is an object. | ||
chunks.push(segment) | ||
} else { | ||
if (wsCollapse) { | ||
segment = segment.replace(collapsePat, ' ') | ||
} | ||
} | ||
if (lineBreak) { | ||
if (lineBreak instanceof Array) { | ||
if (lineBreak.length === 1) { | ||
lineBreak = lineBreak[0]; | ||
} else if (lineBreak.length >= 2) { | ||
if (lineBreak[0] instanceof RegExp) { | ||
lineBreakPat = lineBreak[0]; | ||
if (typeof lineBreak[1] === 'string') { | ||
lineBreakStr = lineBreak[1]; | ||
} | ||
} else if (lineBreak[1] instanceof RegExp) { | ||
lineBreakPat = lineBreak[1]; | ||
if (typeof lineBreak[0] === 'string') { | ||
lineBreakStr = lineBreak[0]; | ||
} | ||
} else if (typeof lineBreak[0] === 'string' && typeof lineBreak[1] === 'string') { | ||
lineBreakPat = new RegExp(escapeRegExp(lineBreak[0]), 'g'); | ||
lineBreakStr = lineBreak[1]; | ||
} else { | ||
lineBreak = lineBreak[0]; | ||
} | ||
var parts = segment.split(re), | ||
acc = [] | ||
for (j = 0; j < parts.length; j++) { | ||
var x = parts[j] | ||
if (mode === 'hard') { | ||
for (k = 0; k < x.length; k += wrapLen) { | ||
acc.push(x.slice(k, k + wrapLen)) | ||
} | ||
} else { acc.push(x); } | ||
} | ||
if (typeof lineBreak === 'string') { | ||
lineBreakStr = lineBreak; | ||
if (!lineBreakPat) { | ||
lineBreakPat = new RegExp(escapeRegExp(lineBreak), 'g'); | ||
} | ||
} else if (lineBreak instanceof RegExp) { | ||
lineBreakPat = lineBreak; | ||
} else if (!(lineBreak instanceof Array)) { | ||
throw new TypeError('lineBreak must be a RegExp object, a string, or an array consisted of a RegExp object and a string'); | ||
} | ||
chunks = chunks.concat(acc) | ||
} | ||
} | ||
// Only assign defaults when `lineBreakPat` is not assigned. | ||
// So if `params.lineBreak` is a RegExp, we don't have a value in `lineBreakStr` | ||
// yet. We will try to get the value from the input string, and if failed, we | ||
// will throw an exception. | ||
if (!lineBreakPat) { | ||
lineBreakPat = /\n/g; | ||
lineBreakStr = '\n'; | ||
} | ||
// Create `multiLineBreakPat` based on `lineBreakPat`, that matches strings | ||
// consisted of one or more line breaks and zero or more whitespaces. | ||
// Also convert `lineBreakPat` to global if not already so. | ||
flags = 'g'; | ||
if (lineBreakPat.ignoreCase) { flags += 'i'; } | ||
if (lineBreakPat.multiline) { flags += 'm'; } | ||
multiLineBreakPat = new RegExp('\\s*(?:' + lineBreakPat.source + ')(?:' + | ||
lineBreakPat.source + '|\\s)*', flags); | ||
if (!lineBreakPat.global) { | ||
lineBreakPat = new RegExp(lineBreakPat.source, flags); | ||
} | ||
var curLine = 0, | ||
curLineLength = start + preservedLinePrefix.length, | ||
lines = [ prefix + preservedLinePrefix ], | ||
// Holds the "real length" (excluding trailing whitespaces) of the | ||
// current line if it exceeds `stop`, otherwise 0. | ||
// ONLY USED when `wsAll` is true, in `finishOffCurLine()`. | ||
bulge = 0, | ||
// `cleanLine` is true iff we are at the beginning of an output line. By | ||
// "beginning" we mean it doesn't contain any non-whitespace char yet. | ||
// But its `curLineLength` can be greater than `start`, or even possibly | ||
// be greater than `stop`, if `wsStrip` is false. | ||
// | ||
// Note that a "clean" line can still contain skip strings, in addition | ||
// to whitespaces. | ||
// | ||
// This variable is used to allow us strip preceding whitespaces when | ||
// `wsStrip` is true, or `wsLine` is true and `preservedLine` is false. | ||
cleanLine = true, | ||
// `preservedLine` is true iff we are in a preserved input line. | ||
// | ||
// It's used when `wsLine` is true to (combined with `cleanLine`) decide | ||
// whether a whitespace is at the beginning of a preserved input line and | ||
// should not be stripped. | ||
preservedLine = true, | ||
// The current indent prefix for wrapped lines. | ||
wrapLinePrefix = wrapLineInitPrefix, | ||
remnant | ||
// Initialize other useful variables. | ||
var re = mode === 'hard' ? /\b/ : /(\S+\s+)/; | ||
var prefix = new Array(start + 1).join(' '); | ||
var wsStrip = (whitespace === 'default' || whitespace === 'collapse'), | ||
wsCollapse = (whitespace === 'collapse'), | ||
wsLine = (whitespace === 'line'), | ||
wsAll = (whitespace === 'all'); | ||
var tabPat = /\t/g, | ||
collapsePat = / +/g, | ||
pPat = /^\s+/, | ||
tPat = /\s+$/, | ||
nonWsPat = /\S/, | ||
wsPat = /\s/; | ||
var wrapLen = stop - start; | ||
// Always returns '' if `beforeHardBreak` is true. | ||
// | ||
// Assumption: Each call of this function is always followed by a `lines.push()` call. | ||
// | ||
// This function can change the status of `cleanLine`, but we don't modify the value of | ||
// `cleanLine` in this function. It's fine because `cleanLine` will be set to the correct | ||
// value after the `lines.push()` call following this function call. We also don't update | ||
// `curLineLength` when pushing a new line and it's safe for the same reason. | ||
function finishOffCurLine (beforeHardBreak) { | ||
var str = lines[curLine], | ||
idx, ln, rBase | ||
return function (text) { | ||
text = text.toString().replace(tabPat, tabRepl); | ||
if (!wsAll) { | ||
// Strip all trailing whitespaces past `start`. | ||
idx = str.length - 1 | ||
while (idx >= start && str[idx] === ' ') { idx--; } | ||
while (idx >= start && wsPat.test(str[idx])) { idx--; } | ||
idx++ | ||
var match; | ||
if (!lineBreakStr) { | ||
// Try to get lineBreakStr from `text` | ||
lineBreakPat.lastIndex = 0; | ||
match = lineBreakPat.exec(text); | ||
if (match) { | ||
lineBreakStr = match[0]; | ||
} else { | ||
throw new TypeError('Line break string for the output not specified'); | ||
} | ||
if (idx !== str.length) { | ||
lines[curLine] = str.substring(0, idx) | ||
} | ||
// text -> blocks; each bloc -> segments; each segment -> chunks | ||
var blocks, base = 0; | ||
var mo, arr, b, res; | ||
// Split `text` by line breaks. | ||
blocks = []; | ||
multiLineBreakPat.lastIndex = 0; | ||
match = multiLineBreakPat.exec(text); | ||
while(match) { | ||
blocks.push(text.substring(base, match.index)); | ||
if (preservedLine && cleanLine && wsLine && curLineLength > stop) { | ||
// Add the remnants to the next line, just like when `wsAll` is true. | ||
rBase = str.length - (curLineLength - stop) | ||
if (rBase < idx) { | ||
// We didn't reach `stop` when stripping due to a bulge. | ||
rBase = idx | ||
} | ||
} | ||
} else { | ||
// Strip trailing whitespaces exceeding stop. | ||
if (curLineLength > stop) { | ||
bulge = bulge || stop | ||
rBase = str.length - (curLineLength - bulge) | ||
lines[curLine] = str.substring(0, rBase) | ||
} | ||
bulge = 0 | ||
} | ||
if (respectLineBreaks !== 'none') { | ||
arr = []; | ||
b = 0; | ||
lineBreakPat.lastIndex = 0; | ||
mo = lineBreakPat.exec(match[0]); | ||
while(mo) { | ||
arr.push(match[0].substring(b, mo.index)); | ||
b = mo.index + mo[0].length; | ||
mo = lineBreakPat.exec(match[0]); | ||
} | ||
arr.push(match[0].substring(b)); | ||
blocks.push({type: 'break', breaks: arr}); | ||
} else { | ||
// Strip line breaks and insert spaces when necessary. | ||
if (wsCollapse) { | ||
res = ' '; | ||
} else { | ||
res = match[0].replace(lineBreakPat, ''); | ||
} | ||
blocks.push({type: 'break', remaining: res}); | ||
} | ||
// Bug: the current implementation of `wrapLineIndent` is buggy: we are not | ||
// taking the extra space occupied by the additional indentation into account | ||
// when wrapping the line. For example, in "hard" mode, we should hard-wrap | ||
// long words at `wrapLen - wrapLinePrefix.length` instead of `wrapLen` | ||
// and remnants should also be wrapped at `wrapLen - wrapLinePrefix.length`. | ||
if (preservedLine) { | ||
// This is a preserved line, and the next output line isn't a | ||
// preserved line. | ||
preservedLine = false | ||
if (wrapLineIndentPat) { | ||
idx = lines[curLine].substring(start).search(wrapLineIndentPat) | ||
if (idx >= 0 && idx + wrapLineIndent > 0) { | ||
wrapLinePrefix = new Array(idx + wrapLineIndent + 1).join(' ') | ||
} else { | ||
wrapLinePrefix = '' | ||
} | ||
} | ||
} | ||
base = match.index + match[0].length; | ||
match = multiLineBreakPat.exec(text); | ||
// Some remnants are left to the next line. | ||
if (rBase) { | ||
while (rBase + wrapLen < str.length) { | ||
if (wsAll) { | ||
ln = str.substring(rBase, rBase + wrapLen) | ||
lines.push(prefix + wrapLinePrefix + ln) | ||
} else { | ||
lines.push(prefix + wrapLinePrefix) | ||
} | ||
rBase += wrapLen | ||
curLine++ | ||
} | ||
blocks.push(text.substring(base)); | ||
var i, j, k; | ||
var segments; | ||
if (skipPat) { | ||
segments = []; | ||
for (i = 0; i < blocks.length; i++) { | ||
var bloc = blocks[i]; | ||
if (typeof bloc !== 'string') { | ||
// This is an object. | ||
segments.push(bloc); | ||
} else { | ||
base = 0; | ||
skipPat.lastIndex = 0; | ||
match = skipPat.exec(bloc); | ||
while(match) { | ||
segments.push(bloc.substring(base, match.index)); | ||
segments.push({type: 'skip', value: match[0]}); | ||
base = match.index + match[0].length; | ||
match = skipPat.exec(bloc); | ||
} | ||
segments.push(bloc.substring(base)); | ||
} | ||
} | ||
if (beforeHardBreak) { | ||
if (wsAll) { | ||
ln = str.substring(rBase) | ||
lines.push(prefix + wrapLinePrefix + ln) | ||
} else { | ||
lines.push(prefix + wrapLinePrefix) | ||
} | ||
curLine++ | ||
} else { | ||
segments = blocks; | ||
ln = str.substring(rBase) | ||
return wrapLinePrefix + ln | ||
} | ||
} | ||
var chunks = []; | ||
for (i = 0; i < segments.length; i++) { | ||
var segment = segments[i]; | ||
if (typeof segment !== 'string') { | ||
// This is an object. | ||
chunks.push(segment); | ||
} else { | ||
if (wsCollapse) { | ||
segment = segment.replace(collapsePat, ' '); | ||
} | ||
return '' | ||
} | ||
var parts = segment.split(re), | ||
acc = []; | ||
for (i = 0; i < chunks.length; i++) { | ||
var chunk = chunks[i] | ||
for (j = 0; j < parts.length; j++) { | ||
var x = parts[j]; | ||
if (mode === 'hard') { | ||
for (k = 0; k < x.length; k += wrapLen) { | ||
acc.push(x.slice(k, k + wrapLen)); | ||
} | ||
} | ||
else { acc.push(x); } | ||
} | ||
chunks = chunks.concat(acc); | ||
} | ||
} | ||
if (chunk === '') { continue; } | ||
var curLine = 0, | ||
curLineLength = start + preservedLinePrefix.length, | ||
lines = [ prefix + preservedLinePrefix ], | ||
// Holds the "real length" (excluding trailing whitespaces) of the | ||
// current line if it exceeds `stop`, otherwise 0. | ||
// ONLY USED when `wsAll` is true, in `finishOffCurLine()`. | ||
bulge = 0, | ||
// `cleanLine` is true iff we are at the beginning of an output line. By | ||
// "beginning" we mean it doesn't contain any non-whitespace char yet. | ||
// But its `curLineLength` can be greater than `start`, or even possibly | ||
// be greater than `stop`, if `wsStrip` is false. | ||
// | ||
// Note that a "clean" line can still contain skip strings, in addition | ||
// to whitespaces. | ||
// | ||
// This variable is used to allow us strip preceding whitespaces when | ||
// `wsStrip` is true, or `wsLine` is true and `preservedLine` is false. | ||
cleanLine = true, | ||
// `preservedLine` is true iff we are in a preserved input line. | ||
// | ||
// It's used when `wsLine` is true to (combined with `cleanLine`) decide | ||
// whether a whitespace is at the beginning of a preserved input line and | ||
// should not be stripped. | ||
preservedLine = true, | ||
// The current indent prefix for wrapped lines. | ||
wrapLinePrefix = wrapLineInitPrefix, | ||
remnant; | ||
if (typeof chunk !== 'string') { | ||
if (chunk.type === 'break') { | ||
// This is one or more line breaks. | ||
// Each entry in `breaks` is just zero or more whitespaces. | ||
if (respectLineBreaks !== 'none') { | ||
// Note that if `whitespace` is "collapse", we still need | ||
// to collapse whitespaces in entries of `breaks`. | ||
var breaks = chunk.breaks | ||
var num = breaks.length - 1 | ||
// Always returns '' if `beforeHardBreak` is true. | ||
// | ||
// Assumption: Each call of this function is always followed by a `lines.push()` call. | ||
// | ||
// This function can change the status of `cleanLine`, but we don't modify the value of | ||
// `cleanLine` in this function. It's fine because `cleanLine` will be set to the correct | ||
// value after the `lines.push()` call following this function call. We also don't update | ||
// `curLineLength` when pushing a new line and it's safe for the same reason. | ||
function finishOffCurLine(beforeHardBreak) { | ||
var str = lines[curLine], | ||
idx, ln, rBase; | ||
if (respectLineBreaks === 's') { | ||
// This is the most complex scenario. We have to check | ||
// the line breaks one by one. | ||
for (j = 0; j < num; j++) { | ||
if (breaks[j + 1].length < respectNum) { | ||
// This line break should be stripped. | ||
if (wsCollapse) { | ||
breaks[j + 1] = ' ' | ||
} else { | ||
breaks[j + 1] = breaks[j] + breaks[j + 1] | ||
} | ||
} else { | ||
// This line break should be preserved. | ||
// First finish off the current line. | ||
if (wsAll) { | ||
lines[curLine] += breaks[j] | ||
curLineLength += breaks[j].length | ||
} | ||
finishOffCurLine(true) | ||
if (!wsAll) { | ||
// Strip all trailing whitespaces past `start`. | ||
idx = str.length - 1; | ||
while (idx >= start && str[idx] === ' ') { idx--; } | ||
while (idx >= start && wsPat.test(str[idx])) { idx--; } | ||
idx++; | ||
lines.push(prefix + preservedLinePrefix) | ||
curLine++ | ||
curLineLength = start + preservedLinePrefix.length | ||
if (idx !== str.length) { | ||
lines[curLine] = str.substring(0, idx); | ||
preservedLine = cleanLine = true | ||
} | ||
if (preservedLine && cleanLine && wsLine && curLineLength > stop) { | ||
// Add the remnants to the next line, just like when `wsAll` is true. | ||
rBase = str.length - (curLineLength - stop); | ||
if (rBase < idx) { | ||
// We didn't reach `stop` when stripping due to a bulge. | ||
rBase = idx; | ||
} | ||
} | ||
// We are adding to either the existing line (if no line break | ||
// is qualified for preservance) or a "new" line. | ||
if (!cleanLine || wsAll || (wsLine && preservedLine)) { | ||
if (wsCollapse || (!cleanLine && breaks[num] === '')) { | ||
breaks[num] = ' ' | ||
} | ||
} else { | ||
// Strip trailing whitespaces exceeding stop. | ||
if (curLineLength > stop) { | ||
bulge = bulge || stop; | ||
rBase = str.length - (curLineLength - bulge); | ||
lines[curLine] = str.substring(0, rBase); | ||
lines[curLine] += breaks[num] | ||
curLineLength += breaks[num].length | ||
} | ||
} else if (respectLineBreaks === 'm' && num < respectNum) { | ||
// These line breaks should be stripped. | ||
if (!cleanLine || wsAll || (wsLine && preservedLine)) { | ||
if (wsCollapse) { | ||
chunk = ' ' | ||
} else { | ||
chunk = breaks.join('') | ||
if (!cleanLine && chunk === '') { | ||
chunk = ' ' | ||
} | ||
} | ||
bulge = 0; | ||
} | ||
lines[curLine] += chunk | ||
curLineLength += chunk.length | ||
} | ||
} else { // 'all' || ('m' && num >= respectNum) | ||
// These line breaks should be preserved. | ||
if (wsStrip) { | ||
// Finish off the current line. | ||
finishOffCurLine(true) | ||
// Bug: the current implementation of `wrapLineIndent` is buggy: we are not | ||
// taking the extra space occupied by the additional indentation into account | ||
// when wrapping the line. For example, in "hard" mode, we should hard-wrap | ||
// long words at `wrapLen - wrapLinePrefix.length` instead of `wrapLen`; | ||
// and remnants should also be wrapped at `wrapLen - wrapLinePrefix.length`. | ||
if (preservedLine) { | ||
// This is a preserved line, and the next output line isn't a | ||
// preserved line. | ||
preservedLine = false; | ||
if (wrapLineIndentPat) { | ||
idx = lines[curLine].substring(start).search(wrapLineIndentPat); | ||
if (idx >= 0 && idx + wrapLineIndent > 0) { | ||
wrapLinePrefix = new Array(idx + wrapLineIndent + 1).join(' '); | ||
} else { | ||
wrapLinePrefix = ''; | ||
} | ||
for (j = 0; j < num; j++) { | ||
lines.push(prefix + preservedLinePrefix) | ||
curLine++ | ||
} | ||
} | ||
// Some remnants are left to the next line. | ||
if (rBase) { | ||
while (rBase + wrapLen < str.length) { | ||
if (wsAll) { | ||
ln = str.substring(rBase, rBase + wrapLen); | ||
lines.push(prefix + wrapLinePrefix + ln); | ||
} else { | ||
lines.push(prefix + wrapLinePrefix); | ||
} | ||
rBase += wrapLen; | ||
curLine++; | ||
curLineLength = start + preservedLinePrefix.length | ||
preservedLine = cleanLine = true | ||
} else { | ||
if (wsAll || (preservedLine && cleanLine)) { | ||
lines[curLine] += breaks[0] | ||
curLineLength += breaks[0].length | ||
} | ||
if (beforeHardBreak) { | ||
if (wsAll) { | ||
ln = str.substring(rBase); | ||
lines.push(prefix + wrapLinePrefix + ln); | ||
} else { | ||
lines.push(prefix + wrapLinePrefix); | ||
} | ||
curLine++; | ||
} else { | ||
ln = str.substring(rBase); | ||
return wrapLinePrefix + ln; | ||
} | ||
} | ||
return ''; | ||
} | ||
for (j = 0; j < num; j++) { | ||
// Finish off the current line. | ||
finishOffCurLine(true) | ||
for (i = 0; i < chunks.length; i++) { | ||
var chunk = chunks[i]; | ||
lines.push(prefix + preservedLinePrefix + breaks[j + 1]) | ||
curLine++ | ||
curLineLength = start + preservedLinePrefix.length + breaks[j + 1].length | ||
if (chunk === '') { continue; } | ||
preservedLine = cleanLine = true | ||
} | ||
} | ||
} | ||
} else { | ||
// These line breaks should be stripped. | ||
if (!cleanLine || wsAll || (wsLine && preservedLine)) { | ||
chunk = chunk.remaining | ||
if (typeof chunk !== 'string') { | ||
if (chunk.type === 'break') { | ||
// This is one or more line breaks. | ||
// Each entry in `breaks` is just zero or more whitespaces. | ||
if (respectLineBreaks !== 'none') { | ||
// Note that if `whitespace` is "collapse", we still need | ||
// to collapse whitespaces in entries of `breaks`. | ||
var breaks = chunk.breaks; | ||
var num = breaks.length - 1; | ||
// Bug: If `wsAll` is true, `cleanLine` is false, and `chunk` | ||
// is '', we insert a space to replace the line break. This | ||
// space will be preserved even if we are at the end of an | ||
// output line, which is wrong behavior. However, I'm not | ||
// sure it's worth it to fix this edge case. | ||
if (wsCollapse || (!cleanLine && chunk === '')) { | ||
chunk = ' ' | ||
} | ||
lines[curLine] += chunk | ||
curLineLength += chunk.length | ||
} | ||
} | ||
} else if (chunk.type === 'skip') { | ||
// This is a skip string. | ||
// Assumption: skip strings don't end with whitespaces. | ||
if (curLineLength > stop) { | ||
remnant = finishOffCurLine(false) | ||
if (respectLineBreaks === 's') { | ||
// This is the most complex scenario. We have to check | ||
// the line breaks one by one. | ||
for (j = 0; j < num; j++) { | ||
if (breaks[j+1].length < respectNum) { | ||
// This line break should be stripped. | ||
if (wsCollapse) { | ||
breaks[j+1] = ' '; | ||
} else { | ||
breaks[j+1] = breaks[j] + breaks[j+1]; | ||
} | ||
} else { | ||
// This line break should be preserved. | ||
// First finish off the current line. | ||
if (wsAll) { | ||
lines[curLine] += breaks[j]; | ||
curLineLength += breaks[j].length; | ||
} | ||
finishOffCurLine(true); | ||
lines.push(prefix + wrapLinePrefix) | ||
curLine++ | ||
curLineLength = start + wrapLinePrefix.length | ||
lines.push(prefix + preservedLinePrefix); | ||
curLine++; | ||
curLineLength = start + preservedLinePrefix.length; | ||
preservedLine = cleanLine = true; | ||
} | ||
} | ||
// We are adding to either the existing line (if no line break | ||
// is qualified for preservance) or a "new" line. | ||
if (!cleanLine || wsAll || (wsLine && preservedLine)) { | ||
if (wsCollapse || (!cleanLine && breaks[num] === '')) { | ||
breaks[num] = ' '; | ||
} | ||
lines[curLine] += breaks[num]; | ||
curLineLength += breaks[num].length; | ||
} | ||
} else if (respectLineBreaks === 'm' && num < respectNum) { | ||
// These line breaks should be stripped. | ||
if (!cleanLine || wsAll || (wsLine && preservedLine)) { | ||
if (wsCollapse) { | ||
chunk = ' '; | ||
} else { | ||
chunk = breaks.join(''); | ||
if (!cleanLine && chunk === '') { | ||
chunk = ' '; | ||
} | ||
} | ||
lines[curLine] += chunk; | ||
curLineLength += chunk.length; | ||
} | ||
} else { // 'all' || ('m' && num >= respectNum) | ||
// These line breaks should be preserved. | ||
if (wsStrip) { | ||
// Finish off the current line. | ||
finishOffCurLine(true); | ||
for (j = 0; j < num; j++) { | ||
lines.push(prefix + preservedLinePrefix); | ||
curLine++; | ||
} | ||
curLineLength = start + preservedLinePrefix.length; | ||
preservedLine = cleanLine = true; | ||
} else { | ||
if (wsAll || (preservedLine && cleanLine)) { | ||
lines[curLine] += breaks[0]; | ||
curLineLength += breaks[0].length; | ||
} | ||
for (j = 0; j < num; j++) { | ||
// Finish off the current line. | ||
finishOffCurLine(true); | ||
lines.push(prefix + preservedLinePrefix + breaks[j+1]); | ||
curLine++; | ||
curLineLength = start + preservedLinePrefix.length + breaks[j+1].length; | ||
preservedLine = cleanLine = true; | ||
} | ||
} | ||
} | ||
} else { | ||
// These line breaks should be stripped. | ||
if (!cleanLine || wsAll || (wsLine && preservedLine)) { | ||
chunk = chunk.remaining; | ||
// Bug: If `wsAll` is true, `cleanLine` is false, and `chunk` | ||
// is '', we insert a space to replace the line break. This | ||
// space will be preserved even if we are at the end of an | ||
// output line, which is wrong behavior. However, I'm not | ||
// sure it's worth it to fix this edge case. | ||
if (wsCollapse || (!cleanLine && chunk === '')) { | ||
chunk = ' '; | ||
} | ||
lines[curLine] += chunk; | ||
curLineLength += chunk.length; | ||
} | ||
} | ||
} else if (chunk.type === 'skip') { | ||
// This is a skip string. | ||
// Assumption: skip strings don't end with whitespaces. | ||
if (curLineLength > stop) { | ||
remnant = finishOffCurLine(false); | ||
lines.push(prefix + wrapLinePrefix); | ||
curLine++; | ||
curLineLength = start + wrapLinePrefix.length; | ||
if (remnant) { | ||
lines[curLine] += remnant; | ||
curLineLength += remnant.length; | ||
} | ||
cleanLine = true; | ||
} | ||
lines[curLine] += chunk.value; | ||
} | ||
continue; | ||
if (remnant) { | ||
lines[curLine] += remnant | ||
curLineLength += remnant.length | ||
} | ||
var chunk2; | ||
while (1) { | ||
chunk2 = undefined; | ||
if (curLineLength + chunk.length > stop && | ||
curLineLength + (chunk2 = chunk.replace(tPat, '')).length > stop && | ||
chunk2 !== '' && | ||
curLineLength > start) { | ||
// This line is full, add `chunk` to the next line | ||
remnant = finishOffCurLine(false); | ||
cleanLine = true | ||
} | ||
lines[curLine] += chunk.value | ||
} | ||
continue | ||
} | ||
lines.push(prefix + wrapLinePrefix); | ||
curLine++; | ||
curLineLength = start + wrapLinePrefix.length; | ||
var chunk2 | ||
while (1) { | ||
chunk2 = undefined | ||
if (curLineLength + chunk.length > stop && | ||
curLineLength + (chunk2 = chunk.replace(tPat, '')).length > stop && | ||
chunk2 !== '' && | ||
curLineLength > start) { | ||
// This line is full, add `chunk` to the next line | ||
remnant = finishOffCurLine(false) | ||
if (remnant) { | ||
lines[curLine] += remnant; | ||
curLineLength += remnant.length; | ||
cleanLine = true; | ||
continue; | ||
} | ||
lines.push(prefix + wrapLinePrefix) | ||
curLine++ | ||
curLineLength = start + wrapLinePrefix.length | ||
if (wsStrip || (wsLine && !(preservedLine && cleanLine))) { | ||
chunk = chunk.replace(pPat, ''); | ||
} | ||
cleanLine = false; | ||
if (remnant) { | ||
lines[curLine] += remnant | ||
curLineLength += remnant.length | ||
cleanLine = true | ||
continue | ||
} | ||
} else { | ||
// Add `chunk` to this line | ||
if (cleanLine) { | ||
if (wsStrip || (wsLine && !(preservedLine && cleanLine))) { | ||
chunk = chunk.replace(pPat, ''); | ||
if (chunk !== '') { | ||
cleanLine = false; | ||
} | ||
} else { | ||
if (nonWsPat.test(chunk)) { | ||
cleanLine = false; | ||
} | ||
} | ||
} | ||
} | ||
break; | ||
if (wsStrip || (wsLine && !(preservedLine && cleanLine))) { | ||
chunk = chunk.replace(pPat, '') | ||
} | ||
cleanLine = false | ||
} else { | ||
// Add `chunk` to this line | ||
if (cleanLine) { | ||
if (wsStrip || (wsLine && !(preservedLine && cleanLine))) { | ||
chunk = chunk.replace(pPat, '') | ||
if (chunk !== '') { | ||
cleanLine = false | ||
} | ||
} else { | ||
if (nonWsPat.test(chunk)) { | ||
cleanLine = false | ||
} | ||
} | ||
if (wsAll && chunk2 && curLineLength + chunk2.length > stop) { | ||
bulge = curLineLength + chunk2.length; | ||
} | ||
lines[curLine] += chunk; | ||
curLineLength += chunk.length; | ||
} | ||
} | ||
// Finally, finish off the last line. | ||
finishOffCurLine(true); | ||
return lines.join(lineBreakStr); | ||
}; | ||
}; | ||
break | ||
} | ||
if (wsAll && chunk2 && curLineLength + chunk2.length > stop) { | ||
bulge = curLineLength + chunk2.length | ||
} | ||
lines[curLine] += chunk | ||
curLineLength += chunk.length | ||
} | ||
// Finally, finish off the last line. | ||
finishOffCurLine(true) | ||
return lines.join(lineBreakStr) | ||
} | ||
} | ||
linewrap.soft = linewrap; | ||
linewrap.soft = linewrap | ||
linewrap.hard = function (/*start, stop, params*/) { | ||
var args = [].slice.call(arguments); | ||
var last = args.length - 1; | ||
if (typeof args[last] === 'object') { | ||
args[last].mode = 'hard'; | ||
} else { | ||
args.push({ mode : 'hard' }); | ||
} | ||
return linewrap.apply(null, args); | ||
}; | ||
linewrap.hard = function ( /*start, stop, params*/) { | ||
var args = [].slice.call(arguments) | ||
var last = args.length - 1 | ||
if (typeof args[last] === 'object') { | ||
args[last].mode = 'hard' | ||
} else { | ||
args.push({ mode: 'hard' }) | ||
} | ||
return linewrap.apply(null, args) | ||
} | ||
linewrap.wrap = function(text/*, start, stop, params*/) { | ||
var args = [].slice.call(arguments); | ||
args.shift(); | ||
return linewrap.apply(null, args)(text); | ||
}; | ||
linewrap.wrap = function (text /*, start, stop, params*/) { | ||
var args = [].slice.call(arguments) | ||
args.shift() | ||
return linewrap.apply(null, args)(text) | ||
} |
@@ -1,19 +0,20 @@ | ||
'use strict'; | ||
'use strict' | ||
let color = require('./color'); | ||
let color = require('./color') | ||
function open (url) { | ||
let opn = require('opn'); | ||
return new Promise((fulfill, reject) => { | ||
let opn = require('opn') | ||
return new Promise((resolve, reject) => { | ||
opn(url, {wait: false}, err => { | ||
if (err) reject(new Error( | ||
`Error opening web browser. | ||
if (err) { | ||
reject(new Error( | ||
`Error opening web browser. | ||
${err} | ||
Manually visit ${color.cyan(url)} in your browser.`)); | ||
else fulfill(err); | ||
}); | ||
}); | ||
Manually visit ${color.cyan(url)} in your browser.`)) | ||
} else resolve(err) | ||
}) | ||
}) | ||
} | ||
module.exports = open; | ||
module.exports = open |
@@ -1,3 +0,3 @@ | ||
'use strict'; | ||
let util = require('./util'); | ||
'use strict' | ||
let util = require('./util') | ||
@@ -21,7 +21,7 @@ /** | ||
method: 'PUT', | ||
path: `/apps/${app}/pre-authorizations`, | ||
path: `/apps/${app}/pre-authorizations`, | ||
headers: { 'Heroku-Two-Factor-Code': secondFactor } | ||
}); | ||
}) | ||
} | ||
module.exports = util.promiseOrCallback(preauth); | ||
module.exports = util.promiseOrCallback(preauth) |
@@ -1,14 +0,14 @@ | ||
function Process() { | ||
this.env = process.env; | ||
function Process () { | ||
this.env = process.env | ||
} | ||
Process.prototype.mock = function () { | ||
this.mocking = true; | ||
}; | ||
this.mocking = true | ||
} | ||
Process.prototype.exit = function (code) { | ||
if (this.mocking) { | ||
this.exitCode = code; | ||
this.exitCode = code | ||
} else { | ||
process.exit(code); | ||
process.exit(code) | ||
} | ||
}; | ||
module.exports = new Process(); | ||
} | ||
module.exports = new Process() |
@@ -1,102 +0,105 @@ | ||
'use strict'; | ||
'use strict' | ||
let cli = require('../'); | ||
let errors = require('./errors'); | ||
let util = require('./util'); | ||
let cli = require('../') | ||
let errors = require('./errors') | ||
let util = require('./util') | ||
function promptMasked (options) { | ||
function refresh (input, mask) { | ||
process.stderr.clearLine(); | ||
process.stderr.cursorTo(0); | ||
process.stderr.write(options.prompt + (mask ? input.replace(/./g, '*') : input)); | ||
process.stderr.clearLine() | ||
process.stderr.cursorTo(0) | ||
process.stderr.write(options.prompt + (mask ? input.replace(/./g, '*') : input)) | ||
} | ||
function start () { | ||
process.stdin.setEncoding('utf8'); | ||
process.stderr.write(options.prompt); | ||
process.stdin.resume(); | ||
process.stdin.setEncoding('utf8') | ||
process.stderr.write(options.prompt) | ||
process.stdin.resume() | ||
if (!process.stdin.isTTY) { | ||
throw new Error(`need to prompt for ${options.name || options.prompt} but stdin is not a tty`); | ||
throw new Error(`need to prompt for ${options.name || options.prompt} but stdin is not a tty`) | ||
} | ||
process.stdin.setRawMode(true); | ||
process.stdin.setRawMode(true) | ||
} | ||
function stop () { | ||
console.error(); | ||
process.stdin.setRawMode(false); | ||
process.stdin.pause(); | ||
console.error() | ||
process.stdin.setRawMode(false) | ||
process.stdin.pause() | ||
} | ||
return new Promise(function (fulfill, reject) { | ||
start(); | ||
let input = ''; | ||
return new Promise(function (resolve, reject) { | ||
start() | ||
let input = '' | ||
let fn = function (c) { | ||
switch(c) { | ||
case "\u0004": // Ctrl-d | ||
case "\r": | ||
case "\n": | ||
if (input.length === 0) return; | ||
refresh(input, true); | ||
stop(); | ||
process.stdin.removeListener('data', fn); | ||
fulfill(input); | ||
return; | ||
case "\u0003": | ||
// Ctrl-c | ||
reject(''); | ||
stop(); | ||
process.stdin.removeListener('data', fn); | ||
return; | ||
default: | ||
// backspace | ||
if (c.charCodeAt(0) === 127) input = input.substr(0, input.length-1); | ||
else input += c; | ||
refresh(input, options.hide); | ||
return; | ||
switch (c) { | ||
case '\u0004': // Ctrl-d | ||
case '\r': | ||
case '\n': | ||
if (input.length === 0) return | ||
refresh(input, true) | ||
stop() | ||
process.stdin.removeListener('data', fn) | ||
resolve(input) | ||
return | ||
case '\u0003': | ||
// Ctrl-c | ||
reject('') | ||
stop() | ||
process.stdin.removeListener('data', fn) | ||
return | ||
default: | ||
// backspace | ||
if (c.charCodeAt(0) === 127) input = input.substr(0, input.length - 1) | ||
else input += c | ||
refresh(input, options.hide) | ||
return | ||
} | ||
}; | ||
process.stdin.on('data', fn); | ||
}); | ||
} | ||
process.stdin.on('data', fn) | ||
}) | ||
} | ||
function prompt (name, options) { | ||
options = options || {}; | ||
options.prompt = name ? name + ': ' : '> '; | ||
if (options.mask || options.hide) return promptMasked(options); | ||
return new Promise(function (fulfill) { | ||
process.stdin.setEncoding('utf8'); | ||
process.stderr.write(options.prompt); | ||
process.stdin.resume(); | ||
options = options || {} | ||
options.prompt = name ? name + ': ' : '> ' | ||
if (options.mask || options.hide) return promptMasked(options) | ||
return new Promise(function (resolve) { | ||
process.stdin.setEncoding('utf8') | ||
process.stderr.write(options.prompt) | ||
process.stdin.resume() | ||
process.stdin.once('data', function (data) { | ||
process.stdin.pause(); | ||
data = data.trim(); | ||
process.stdin.pause() | ||
data = data.trim() | ||
if (data === '') { | ||
fulfill(prompt(name)); | ||
resolve(prompt(name)) | ||
} else { | ||
fulfill(data); | ||
resolve(data) | ||
} | ||
}); | ||
}); | ||
}) | ||
}) | ||
} | ||
function confirmApp (app, confirm, message) { | ||
return new Promise(function (fulfill, reject) { | ||
return new Promise(function (resolve, reject) { | ||
if (confirm) { | ||
if (confirm === app) return fulfill(); | ||
return reject(`Confirmation ${cli.color.bold.red(confirm)} did not match ${cli.color.bold.red(app)}. Aborted.`); | ||
if (confirm === app) return resolve() | ||
return reject(`Confirmation ${cli.color.bold.red(confirm)} did not match ${cli.color.bold.red(app)}. Aborted.`) | ||
} | ||
if (!message) message = `WARNING: Destructive Action\nThis command will affect the app ${cli.color.bold.red(app)}`; | ||
errors.warn(message); | ||
errors.warn(`To proceed, type ${cli.color.bold.red(app)} or re-run this command with ${cli.color.bold.red('--confirm', app)}`); | ||
console.error(); | ||
if (!message) { | ||
message = `WARNING: Destructive Action | ||
This command will affect the app ${cli.color.bold.red(app)}` | ||
} | ||
errors.warn(message) | ||
errors.warn(`To proceed, type ${cli.color.bold.red(app)} or re-run this command with ${cli.color.bold.red('--confirm', app)}`) | ||
console.error() | ||
prompt().then(function (confirm) { | ||
if (confirm === app) { | ||
return fulfill(); | ||
return resolve() | ||
} | ||
return reject(`Confirmation did not match ${cli.color.bold.red(app)}. Aborted.`); | ||
}); | ||
}); | ||
return reject(`Confirmation did not match ${cli.color.bold.red(app)}. Aborted.`) | ||
}) | ||
}) | ||
} | ||
exports.prompt = util.promiseOrCallback(prompt); | ||
exports.confirmApp = util.promiseOrCallback(confirmApp); | ||
exports.prompt = util.promiseOrCallback(prompt) | ||
exports.confirmApp = util.promiseOrCallback(confirmApp) |
@@ -1,56 +0,54 @@ | ||
'use strict'; | ||
'use strict' | ||
const GLOBAL_CRED = 'b66ca6f60fe049d6bedfe3e2ccb28d8c'; | ||
const ROLLBAR_URL = 'https://api.rollbar.com/api/1/item/'; | ||
const GLOBAL_CRED = 'b66ca6f60fe049d6bedfe3e2ccb28d8c' | ||
const ROLLBAR_URL = 'https://api.rollbar.com/api/1/item/' | ||
function concat (stream, callback) { | ||
var strings = []; | ||
var strings = [] | ||
stream.on('data', function (data) { | ||
strings.push(data); | ||
}); | ||
strings.push(data) | ||
}) | ||
stream.on('end', function () { | ||
callback(strings.join('')); | ||
}); | ||
callback(strings.join('')) | ||
}) | ||
} | ||
function request (method, url, payload) { | ||
const https = require('https'); | ||
const parseUrl = require('url').parse; | ||
const https = require('https') | ||
const parseUrl = require('url').parse | ||
return new Promise(function (fulfill, reject) { | ||
let body = JSON.stringify(payload); | ||
url = parseUrl(url); | ||
return new Promise(function (resolve, reject) { | ||
let body = JSON.stringify(payload) | ||
url = parseUrl(url) | ||
let req = https.request({ | ||
hostname: url.hostname, | ||
path: url.path, | ||
method: method | ||
path: url.path, | ||
method: method | ||
}, function (res) { | ||
concat(res, function (data) { | ||
if (res.statusCode >= 200 && res.statusCode < 300) | ||
fulfill(data); | ||
else | ||
reject(data); | ||
}); | ||
}); | ||
req.setHeader('Content-Length', Buffer.byteLength(body)); | ||
req.write(body); | ||
}); | ||
if (res.statusCode >= 200 && res.statusCode < 300) resolve(data) | ||
else reject(data) | ||
}) | ||
}) | ||
req.setHeader('Content-Length', Buffer.byteLength(body)) | ||
req.write(body) | ||
}) | ||
} | ||
module.exports = function (cred, opts) { | ||
if (!cred) cred = GLOBAL_CRED; | ||
if (!cred) cred = GLOBAL_CRED | ||
function error (err) { | ||
const regex = /^\s*at (?:([^(]+(?: \[\w\s+\])?) )?\(?(.+?)(?::(\d+):(\d+)(?:, <js>:(\d+):(\d+))?)?\)?$/; | ||
const regex = /^\s*at (?:([^(]+(?: \[\w\s+\])?) )?\(?(.+?)(?::(\d+):(\d+)(?:, <js>:(\d+):(\d+))?)?\)?$/ | ||
let frames = (err.stack || '').split('\n').map(function (line) { | ||
let r = line.match(regex); | ||
if (!r) { return; } | ||
let r = line.match(regex) | ||
if (!r) return | ||
return { | ||
method: r[1], | ||
method: r[1], | ||
filename: r[2], | ||
lineno: r[3], | ||
colno: r[4] | ||
}; | ||
}); | ||
frames.shift(); // discard first line | ||
lineno: r[3], | ||
colno: r[4] | ||
} | ||
}) | ||
frames.shift() // discard first line | ||
return request('POST', ROLLBAR_URL, { | ||
@@ -60,17 +58,16 @@ access_token: cred, | ||
code_version: opts.version, | ||
context: opts.context, | ||
platform: 'client', | ||
environment: 'production', | ||
framework: 'node', | ||
context: opts.context, | ||
platform: 'client', | ||
environment: 'production', | ||
framework: 'node', | ||
body: { | ||
trace: { | ||
exception: { | ||
class: err.name, | ||
message: err.message || err, | ||
class: err.name, | ||
message: err.message || err | ||
}, | ||
frames | ||
} | ||
frames} | ||
} | ||
} | ||
}).catch(err => require('./errors').log(err)); | ||
}).catch(err => require('./errors').log(err)) | ||
} | ||
@@ -80,3 +77,3 @@ | ||
error | ||
}; | ||
}; | ||
} | ||
} |
@@ -1,94 +0,94 @@ | ||
'use strict'; | ||
'use strict' | ||
// code mostly from https://github.com/sindresorhus/ora | ||
let console = require('./console'); | ||
let color = require('./color'); | ||
let errors = require('./errors'); | ||
let console = require('./console') | ||
let color = require('./color') | ||
let errors = require('./errors') | ||
class Spinner { | ||
constructor(options) { | ||
constructor (options) { | ||
this.options = Object.assign({ | ||
text: '', | ||
}, options); | ||
text: '' | ||
}, options) | ||
this.cursor = require('cli-cursor'); | ||
let spinners = require('./spinners.json'); | ||
this.cursor = require('cli-cursor') | ||
let spinners = require('./spinners.json') | ||
this.color = this.options.color || 'heroku'; | ||
this.spinner = process.platform === 'win32' ? spinners.line : (this.options.spinner ? spinners[this.options.spinner] : spinners.dots2); | ||
this.text = this.options.text; | ||
this.interval = this.options.interval || this.spinner.interval || 100; | ||
this.id = null; | ||
this.frameIndex = 0; | ||
this.enabled = !console.mocking() && (process.stderr && process.stderr.isTTY) && !process.env.CI; | ||
this.color = this.options.color || 'heroku' | ||
this.spinner = process.platform === 'win32' ? spinners.line : (this.options.spinner ? spinners[this.options.spinner] : spinners.dots2) | ||
this.text = this.options.text | ||
this.interval = this.options.interval || this.spinner.interval || 100 | ||
this.id = null | ||
this.frameIndex = 0 | ||
this.enabled = !console.mocking() && (process.stderr && process.stderr.isTTY) && !process.env.CI | ||
} | ||
frame() { | ||
var frames = this.spinner.frames; | ||
var frame = frames[this.frameIndex]; | ||
if (this.color) frame = color[this.color](frame); | ||
this.frameIndex = ++this.frameIndex % frames.length; | ||
return frame; | ||
frame () { | ||
var frames = this.spinner.frames | ||
var frame = frames[this.frameIndex] | ||
if (this.color) frame = color[this.color](frame) | ||
this.frameIndex = ++this.frameIndex % frames.length | ||
return frame | ||
} | ||
clear() { | ||
clear () { | ||
if (!this.enabled) { | ||
return; | ||
return | ||
} | ||
process.stderr.clearLine(); | ||
process.stderr.cursorTo(0); | ||
process.stderr.clearLine() | ||
process.stderr.cursorTo(0) | ||
} | ||
render() { | ||
process.stderr.write('\b' + this.frame()); | ||
render () { | ||
process.stderr.write('\b' + this.frame()) | ||
} | ||
start() { | ||
if (this.id) return; | ||
console.writeError(this.text); | ||
if (!this.enabled) return; | ||
console.writeError(' '); | ||
start () { | ||
if (this.id) return | ||
console.writeError(this.text) | ||
if (!this.enabled) return | ||
console.writeError(' ') | ||
this.cursor.hide(); | ||
this.render(); | ||
this.id = setInterval(this.render.bind(this), this.interval); | ||
this.cursor.hide() | ||
this.render() | ||
this.id = setInterval(this.render.bind(this), this.interval) | ||
} | ||
stop() { | ||
stop () { | ||
if (!this.enabled) { | ||
return; | ||
return | ||
} | ||
clearInterval(this.id); | ||
this.id = null; | ||
this.frameIndex = 0; | ||
this.clear(); | ||
process.stderr.write(this.text); | ||
this.cursor.show(); | ||
clearInterval(this.id) | ||
this.id = null | ||
this.frameIndex = 0 | ||
this.clear() | ||
process.stderr.write(this.text) | ||
this.cursor.show() | ||
} | ||
update(text) { | ||
this.text = text; | ||
update (text) { | ||
this.text = text | ||
if (!this.enabled) { | ||
console.writeError('\n' + this.text); | ||
console.writeError('\n' + this.text) | ||
} else { | ||
this.clear(); | ||
process.stderr.write(this.text + ' '); | ||
this.clear() | ||
process.stderr.write(this.text + ' ') | ||
} | ||
} | ||
warn(msg) { | ||
warn (msg) { | ||
if (this.enabled) { | ||
this.stop(); | ||
this.clear(); | ||
this.stop() | ||
this.clear() | ||
} else { | ||
console.error(color.yellow.bold('!')); | ||
console.error(color.yellow.bold('!')) | ||
} | ||
errors.warn(msg); | ||
this.start(); | ||
errors.warn(msg) | ||
this.start() | ||
} | ||
} | ||
module.exports = Spinner; | ||
module.exports = Spinner |
@@ -1,5 +0,5 @@ | ||
'use strict'; | ||
'use strict' | ||
let cli = require('..'); | ||
let util = require('util'); | ||
let cli = require('..') | ||
let util = require('util') | ||
@@ -17,10 +17,10 @@ /** | ||
*/ | ||
function styledJSON(obj) { | ||
let json = JSON.stringify(obj, null, 2); | ||
function styledJSON (obj) { | ||
let json = JSON.stringify(obj, null, 2) | ||
if (cli.color.enabled) { | ||
let cardinal = require('cardinal'); | ||
let theme = require('cardinal/themes/jq'); | ||
cli.log(cardinal.highlight(json, {json: true, theme: theme})); | ||
let cardinal = require('cardinal') | ||
let theme = require('cardinal/themes/jq') | ||
cli.log(cardinal.highlight(json, {json: true, theme: theme})) | ||
} else { | ||
cli.log(json); | ||
cli.log(json) | ||
} | ||
@@ -38,4 +38,4 @@ } | ||
*/ | ||
function styledHeader(header) { | ||
cli.log(cli.color.gray('=== ') + cli.color.bold(header)); | ||
function styledHeader (header) { | ||
cli.log(cli.color.gray('=== ') + cli.color.bold(header)) | ||
} | ||
@@ -56,28 +56,28 @@ | ||
*/ | ||
function styledObject(obj, keys) { | ||
let keyLengths = Object.keys(obj).map(function(key) { return key.toString().length; }); | ||
let maxKeyLength = Math.max.apply(Math, keyLengths) + 2; | ||
function pp(obj) { | ||
function styledObject (obj, keys) { | ||
let keyLengths = Object.keys(obj).map(key => key.toString().length) | ||
let maxKeyLength = Math.max.apply(Math, keyLengths) + 2 | ||
function pp (obj) { | ||
if (typeof obj === 'string' || typeof obj === 'number') { | ||
return obj; | ||
return obj | ||
} else if (typeof obj === 'object') { | ||
return Object.keys(obj).map(k => k + ': ' + util.inspect(obj[k])).join(', '); | ||
return Object.keys(obj).map(k => k + ': ' + util.inspect(obj[k])).join(', ') | ||
} else { | ||
return util.inspect(obj); | ||
return util.inspect(obj) | ||
} | ||
} | ||
function logKeyValue(key, value) { | ||
cli.log(`${key}:`+' '.repeat(maxKeyLength - key.length-1)+pp(value)); | ||
function logKeyValue (key, value) { | ||
cli.log(`${key}:` + ' '.repeat(maxKeyLength - key.length - 1) + pp(value)) | ||
} | ||
for (var key of (keys || Object.keys(obj).sort())) { | ||
let value = obj[key]; | ||
let value = obj[key] | ||
if (Array.isArray(value)) { | ||
if (value.length > 0) { | ||
logKeyValue(key, value[0]); | ||
logKeyValue(key, value[0]) | ||
for (var e of value.slice(1)) { | ||
cli.log(" ".repeat(maxKeyLength) + pp(e)); | ||
cli.log(' '.repeat(maxKeyLength) + pp(e)) | ||
} | ||
} | ||
} else if (value !== null && value !== undefined) { | ||
logKeyValue(key, value); | ||
logKeyValue(key, value) | ||
} | ||
@@ -100,29 +100,29 @@ } | ||
*/ | ||
function styledNameValues(nameValues) { | ||
let keys = nameValues.map(function(nameValue) { return nameValue.name; }); | ||
let keyLengths = keys.map(function(name) { return name.toString().length; }); | ||
let maxKeyLength = Math.max.apply(Math, keyLengths) + 2; | ||
function pp(obj) { | ||
function styledNameValues (nameValues) { | ||
let keys = nameValues.map(nameValue => nameValue.name) | ||
let keyLengths = keys.map(name => name.toString().length) | ||
let maxKeyLength = Math.max.apply(Math, keyLengths) + 2 | ||
function pp (obj) { | ||
if (typeof obj === 'string' || typeof obj === 'number') { | ||
return obj; | ||
return obj | ||
} else if (typeof obj === 'object') { | ||
return Object.keys(obj).map(k => k + ': ' + cli.inspect(obj[k])).join(', '); | ||
return Object.keys(obj).map(k => k + ': ' + cli.inspect(obj[k])).join(', ') | ||
} else { | ||
return cli.inspect(obj); | ||
return cli.inspect(obj) | ||
} | ||
} | ||
function logKeyValue(key, value) { | ||
cli.log(`${key}:`+' '.repeat(maxKeyLength - key.length-1)+pp(value)); | ||
function logKeyValue (key, value) { | ||
cli.log(`${key}:` + ' '.repeat(maxKeyLength - key.length - 1) + pp(value)) | ||
} | ||
for (var nameValue of nameValues) { | ||
let value = nameValue.values; | ||
let value = nameValue.values | ||
if (Array.isArray(value)) { | ||
if (value.length > 0) { | ||
logKeyValue(nameValue.name, value[0]); | ||
logKeyValue(nameValue.name, value[0]) | ||
for (var e of value.slice(1)) { | ||
cli.log(" ".repeat(maxKeyLength) + pp(e)); | ||
cli.log(' '.repeat(maxKeyLength) + pp(e)) | ||
} | ||
} | ||
} else if (value !== null && value !== undefined) { | ||
logKeyValue(nameValue.name, value); | ||
logKeyValue(nameValue.name, value) | ||
} | ||
@@ -132,5 +132,5 @@ } | ||
module.exports.styledJSON = styledJSON; | ||
module.exports.styledHeader = styledHeader; | ||
module.exports.styledObject = styledObject; | ||
module.exports.styledNameValues = styledNameValues; | ||
module.exports.styledJSON = styledJSON | ||
module.exports.styledHeader = styledHeader | ||
module.exports.styledObject = styledObject | ||
module.exports.styledNameValues = styledNameValues |
190
lib/table.js
@@ -1,5 +0,5 @@ | ||
'use strict'; | ||
'use strict' | ||
const stripAnsi = require('..').color.stripColor; | ||
const cli = require('..'); | ||
const stripAnsi = require('..').color.stripColor | ||
const cli = require('..') | ||
@@ -29,114 +29,114 @@ /** | ||
function table (data, options) { | ||
const ary = require('lodash.ary'); | ||
const defaults = require('lodash.defaults'); | ||
const get = require('lodash.get'); | ||
const identity = require('lodash.identity'); | ||
const keys = require('lodash.keys'); | ||
const noop = require('lodash.noop'); | ||
const partial = require('lodash.partial'); | ||
const property = require('lodash.property'); | ||
const repeat = require('lodash.repeat'); | ||
const result = require('lodash.result'); | ||
const ary = require('lodash.ary') | ||
const defaults = require('lodash.defaults') | ||
const get = require('lodash.get') | ||
const identity = require('lodash.identity') | ||
const keys = require('lodash.keys') | ||
const noop = require('lodash.noop') | ||
const partial = require('lodash.partial') | ||
const property = require('lodash.property') | ||
const repeat = require('lodash.repeat') | ||
const result = require('lodash.result') | ||
let _defaults = { | ||
colSep: ' ', | ||
after: noop, | ||
headerAnsi: identity, | ||
printLine: cli.log, | ||
printRow: function(cells) { | ||
this.printLine(cells.join(this.colSep).trimRight()); | ||
}, | ||
printHeader: function(cells) { | ||
this.printRow(cells.map(ary(this.headerAnsi, 1))); | ||
this.printRow(cells.map(function(hdr) { return hdr.replace(/./g, '─'); })); | ||
} | ||
}; | ||
let _defaults = { | ||
colSep: ' ', | ||
after: noop, | ||
headerAnsi: identity, | ||
printLine: cli.log, | ||
printRow: function (cells) { | ||
this.printLine(cells.join(this.colSep).trimRight()) | ||
}, | ||
printHeader: function (cells) { | ||
this.printRow(cells.map(ary(this.headerAnsi, 1))) | ||
this.printRow(cells.map(hdr => hdr.replace(/./g, '─'))) | ||
} | ||
} | ||
let colDefaults = { | ||
format: value => value ? value.toString() : '', | ||
width: 0, | ||
label: function() { return this.key.toString(); }, | ||
let colDefaults = { | ||
format: value => value ? value.toString() : '', | ||
width: 0, | ||
label: function () { return this.key.toString() }, | ||
get: function(row) { | ||
let value; | ||
let path = result(this, 'key'); | ||
get: function (row) { | ||
let value | ||
let path = result(this, 'key') | ||
if(!path) { | ||
value = row; | ||
} else { | ||
value = get(row, path); | ||
} | ||
if (!path) { | ||
value = row | ||
} else { | ||
value = get(row, path) | ||
} | ||
return this.format(value, row); | ||
}, | ||
}; | ||
function calcWidth(cell) { | ||
let lines = stripAnsi(cell).split(/[\r\n]+/); | ||
let lineLengths = lines.map(property('length')); | ||
return Math.max.apply(Math, lineLengths); | ||
return this.format(value, row) | ||
} | ||
} | ||
function pad(string, length) { | ||
let visibleLength = stripAnsi(string).length; | ||
let diff = length - visibleLength; | ||
function calcWidth (cell) { | ||
let lines = stripAnsi(cell).split(/[\r\n]+/) | ||
let lineLengths = lines.map(property('length')) | ||
return Math.max.apply(Math, lineLengths) | ||
} | ||
return string + repeat(' ', Math.max(0, diff)); | ||
} | ||
function pad (string, length) { | ||
let visibleLength = stripAnsi(string).length | ||
let diff = length - visibleLength | ||
function render () { | ||
let columns = options.columns || keys(data[0] || {}); | ||
return string + repeat(' ', Math.max(0, diff)) | ||
} | ||
if(typeof columns[0] === 'string') { | ||
columns = columns.map(function(k) { return {key: k}; }); | ||
} | ||
function render () { | ||
let columns = options.columns || keys(data[0] || {}) | ||
let defaultsApplied = false; | ||
for(let row of data) { | ||
row.height = 1; | ||
for(let col of columns) { | ||
if(!defaultsApplied) { defaults(col, colDefaults); } | ||
if (typeof columns[0] === 'string') { | ||
columns = columns.map(key => ({key})) | ||
} | ||
let cell = col.get(row); | ||
let defaultsApplied = false | ||
for (let row of data) { | ||
row.height = 1 | ||
for (let col of columns) { | ||
if (!defaultsApplied) defaults(col, colDefaults) | ||
col.width = Math.max( | ||
result(col, 'label').length, | ||
col.width, | ||
calcWidth(cell) | ||
); | ||
let cell = col.get(row) | ||
row.height = Math.max( | ||
row.height, | ||
cell.split(/[\r\n]+/).length | ||
); | ||
} | ||
defaultsApplied = true; | ||
} | ||
col.width = Math.max( | ||
result(col, 'label').length, | ||
col.width, | ||
calcWidth(cell) | ||
) | ||
if (options.printHeader) { | ||
options.printHeader(columns.map(function(col) { | ||
let label = result(col, 'label'); | ||
return pad(label, col.width || label.length ); | ||
})); | ||
} | ||
row.height = Math.max( | ||
row.height, | ||
cell.split(/[\r\n]+/).length | ||
) | ||
} | ||
defaultsApplied = true | ||
} | ||
function getNthLineOfCell(n, row, col) { | ||
// TODO memoize this | ||
let lines = col.get(row).split(/[\r\n]+/); | ||
return pad(lines[n] || '', col.width); | ||
} | ||
if (options.printHeader) { | ||
options.printHeader(columns.map(function (col) { | ||
let label = result(col, 'label') | ||
return pad(label, col.width || label.length) | ||
})) | ||
} | ||
for(let row of data) { | ||
for(let i = 0; i < row.height; i++) { | ||
let cells = columns.map(partial(getNthLineOfCell, i, row)); | ||
options.printRow(cells); | ||
} | ||
options.after(row, options); | ||
} | ||
function getNthLineOfCell (n, row, col) { | ||
// TODO memoize this | ||
let lines = col.get(row).split(/[\r\n]+/) | ||
return pad(lines[n] || '', col.width) | ||
} | ||
defaults(options, _defaults); | ||
render(); | ||
for (let row of data) { | ||
for (let i = 0; i < row.height; i++) { | ||
let cells = columns.map(partial(getNthLineOfCell, i, row)) | ||
options.printRow(cells) | ||
} | ||
options.after(row, options) | ||
} | ||
} | ||
defaults(options, _defaults) | ||
render() | ||
} | ||
module.exports = table; | ||
module.exports = table |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
'use strict' | ||
@@ -11,7 +11,7 @@ /** | ||
* // deal with input | ||
* }); | ||
* var prompt2 = promiseOrCallback(prompt); | ||
* }) | ||
* var prompt2 = promiseOrCallback(prompt) | ||
* prompt('input? ', function (err, input) { | ||
* // deal with input | ||
* }); | ||
* }) | ||
* | ||
@@ -21,20 +21,20 @@ * @param {Function} fn a promise returning function to wrap | ||
*/ | ||
function promiseOrCallback(fn) { | ||
function promiseOrCallback (fn) { | ||
return function () { | ||
if (typeof arguments[arguments.length-1] === 'function') { | ||
let args = Array.prototype.slice.call(arguments); | ||
let callback = args.pop(); | ||
if (typeof arguments[arguments.length - 1] === 'function') { | ||
let args = Array.prototype.slice.call(arguments) | ||
let callback = args.pop() | ||
fn.apply(null, args).then(function () { | ||
let args = Array.prototype.slice.call(arguments); | ||
args.unshift(null); | ||
callback.apply(null, args); | ||
let args = Array.prototype.slice.call(arguments) | ||
args.unshift(null) | ||
callback.apply(null, args) | ||
}).catch(function (err) { | ||
callback.call(null, err); | ||
}); | ||
callback(err) | ||
}) | ||
} else { | ||
return fn.apply(null, arguments); | ||
return fn.apply(null, arguments) | ||
} | ||
}; | ||
} | ||
} | ||
exports.promiseOrCallback = promiseOrCallback; | ||
exports.promiseOrCallback = promiseOrCallback |
@@ -1,14 +0,14 @@ | ||
'use strict'; | ||
'use strict' | ||
function toggle (onoff) { | ||
const cp = require('child_process'); | ||
if (exports.platform !== 'darwin') return; | ||
const cp = require('child_process') | ||
if (exports.platform !== 'darwin') return | ||
try { | ||
cp.execSync(`osascript -e 'if application "yubiswitch" is running then tell application "yubiswitch" to ${onoff}'`, {stdio: 'inherit'}); | ||
cp.execSync(`osascript -e 'if application "yubiswitch" is running then tell application "yubiswitch" to ${onoff}'`, {stdio: 'inherit'}) | ||
} catch (err) {} | ||
} | ||
exports.enable = () => toggle('KeyOn'); | ||
exports.disable = () => toggle('KeyOff'); | ||
exports.enable = () => toggle('KeyOn') | ||
exports.disable = () => toggle('KeyOff') | ||
exports.platform = process.platform; | ||
exports.platform = process.platform |
{ | ||
"name": "heroku-cli-util", | ||
"description": "Set of helpful CLI utilities", | ||
"version": "6.0.1", | ||
"version": "6.0.2", | ||
"author": "Jeff Dickey (@dickeyxxx)", | ||
@@ -15,3 +15,3 @@ "bugs": { | ||
"got": "^6.3.0", | ||
"heroku-client": "3.0.0-alpha3", | ||
"heroku-client": "3.0.0-beta1", | ||
"lodash.ary": "4.0.1", | ||
@@ -30,2 +30,3 @@ "lodash.defaults": "4.0.1", | ||
"opn": "^3.0.3", | ||
"standard": "7.1.0", | ||
"supports-color": "^3.1.2", | ||
@@ -41,3 +42,2 @@ "tunnel-agent": "^0.4.3" | ||
"jsdoc": "*", | ||
"jshint": "*", | ||
"mocha": "^2.2.4", | ||
@@ -48,3 +48,3 @@ "nock": "8.0.0", | ||
"sinon": "1.17.4", | ||
"unexpected": "10.13.2" | ||
"unexpected": "10.13.3" | ||
}, | ||
@@ -61,4 +61,9 @@ "homepage": "https://github.com/heroku/heroku-cli-util", | ||
"preversion": "npm test", | ||
"test": "nyc mocha && jshint ." | ||
"test": "nyc mocha && standard" | ||
}, | ||
"standard": { | ||
"ignore": [ | ||
"lib/linewrap.js" | ||
] | ||
}, | ||
"nyc": { | ||
@@ -65,0 +70,0 @@ "exclude": [ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Mixed license
License(Experimental) Package contains multiple licenses.
Found 1 instance in 1 package
12
0
29
223659
22
28
2637
5
+ Addedstandard@7.1.0
+ Addedacorn@3.3.0(transitive)
+ Addedacorn-jsx@3.0.1(transitive)
+ Addedajv@4.11.8(transitive)
+ Addedajv-keywords@1.5.1(transitive)
+ Addedansi-escapes@1.4.0(transitive)
+ Addedansi-regex@3.0.1(transitive)
+ Addedargparse@1.0.10(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedbuffer-from@1.1.2(transitive)
+ Addedcall-bind@1.0.7(transitive)
+ Addedcaller-path@0.1.0(transitive)
+ Addedcallsites@0.2.0(transitive)
+ Addedcircular-json@0.3.3(transitive)
+ Addedcli-width@2.2.1(transitive)
+ Addedclone@1.0.4(transitive)
+ Addedcode-point-at@1.1.0(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedconcat-stream@1.6.2(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addedd@1.0.2(transitive)
+ Addeddebug@2.6.9(transitive)
+ Addeddebug-log@1.0.1(transitive)
+ Addeddeep-is@0.1.4(transitive)
+ Addeddefaults@1.0.4(transitive)
+ Addeddefine-data-property@1.1.4(transitive)
+ Addeddeglob@1.1.2(transitive)
+ Addeddoctrine@1.5.0(transitive)
+ Addedes-define-property@1.0.0(transitive)
+ Addedes-errors@1.3.0(transitive)
+ Addedes5-ext@0.10.64(transitive)
+ Addedes6-iterator@2.0.3(transitive)
+ Addedes6-map@0.1.5(transitive)
+ Addedes6-set@0.1.6(transitive)
+ Addedes6-symbol@3.1.4(transitive)
+ Addedes6-weak-map@2.0.3(transitive)
+ Addedescope@3.6.0(transitive)
+ Addedeslint@2.10.2(transitive)
+ Addedeslint-config-standard@5.3.1(transitive)
+ Addedeslint-config-standard-jsx@1.2.0(transitive)
+ Addedeslint-plugin-promise@1.3.2(transitive)
+ Addedeslint-plugin-react@5.2.2(transitive)
+ Addedeslint-plugin-standard@1.3.3(transitive)
+ Addedesniff@2.0.1(transitive)
+ Addedespree@3.1.4(transitive)
+ Addedesprima@4.0.1(transitive)
+ Addedesrecurse@4.3.0(transitive)
+ Addedestraverse@4.3.05.3.0(transitive)
+ Addedesutils@2.0.3(transitive)
+ Addedevent-emitter@0.3.5(transitive)
+ Addedext@1.7.0(transitive)
+ Addedfast-levenshtein@2.0.6(transitive)
+ Addedfigures@1.7.0(transitive)
+ Addedfile-entry-cache@1.3.1(transitive)
+ Addedfind-root@1.1.0(transitive)
+ Addedflat-cache@1.3.4(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedgenerate-function@2.3.1(transitive)
+ Addedgenerate-object-property@1.2.0(transitive)
+ Addedget-intrinsic@1.2.4(transitive)
+ Addedget-stdin@4.0.15.0.1(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedglobals@9.18.0(transitive)
+ Addedgopd@1.0.1(transitive)
+ Addedgraceful-fs@4.2.11(transitive)
+ Addedhas-property-descriptors@1.0.2(transitive)
+ Addedhas-proto@1.0.3(transitive)
+ Addedhas-symbols@1.0.3(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedheroku-client@3.0.0-beta1(transitive)
+ Addedignore@3.3.10(transitive)
+ Addedimurmurhash@0.1.4(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedinquirer@0.12.0(transitive)
+ Addedis-fullwidth-code-point@1.0.02.0.0(transitive)
+ Addedis-my-ip-valid@1.0.1(transitive)
+ Addedis-my-json-valid@2.20.6(transitive)
+ Addedis-property@1.0.2(transitive)
+ Addedis-resolvable@1.1.0(transitive)
+ Addedisarray@1.0.02.0.5(transitive)
+ Addedjs-yaml@3.14.1(transitive)
+ Addedjson-stable-stringify@1.1.1(transitive)
+ Addedjsonify@0.0.1(transitive)
+ Addedjsonpointer@5.0.1(transitive)
+ Addedjsx-ast-utils@1.4.1(transitive)
+ Addedlevn@0.3.0(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedmkdirp@0.5.6(transitive)
+ Addedms@2.0.0(transitive)
+ Addedmultiline@1.0.2(transitive)
+ Addedmute-stream@0.0.5(transitive)
+ Addednext-tick@1.1.0(transitive)
+ Addednumber-is-nan@1.0.1(transitive)
+ Addedobject-keys@1.1.1(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedoptionator@0.8.3(transitive)
+ Addedos-homedir@1.0.2(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedpath-is-inside@1.0.2(transitive)
+ Addedpkg-config@1.1.1(transitive)
+ Addedpluralize@1.2.1(transitive)
+ Addedprelude-ls@1.1.2(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedprogress@1.1.8(transitive)
+ Addedqueue-microtask@1.2.3(transitive)
+ Addedreadable-stream@2.3.8(transitive)
+ Addedreadline2@1.0.1(transitive)
+ Addedrequire-uncached@1.0.3(transitive)
+ Addedresolve-from@1.0.1(transitive)
+ Addedrimraf@2.6.3(transitive)
+ Addedrun-async@0.1.0(transitive)
+ Addedrun-parallel@1.2.0(transitive)
+ Addedrx-lite@3.1.2(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedset-function-length@1.2.2(transitive)
+ Addedshelljs@0.6.1(transitive)
+ Addedslice-ansi@0.0.4(transitive)
+ Addedsprintf-js@1.0.3(transitive)
+ Addedstandard@7.1.0(transitive)
+ Addedstandard-engine@4.1.3(transitive)
+ Addedstring-width@1.0.22.1.1(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedstrip-ansi@4.0.0(transitive)
+ Addedstrip-indent@1.0.1(transitive)
+ Addedstrip-json-comments@1.0.4(transitive)
+ Addedtable@3.8.3(transitive)
+ Addedtext-table@0.2.0(transitive)
+ Addedthrough@2.3.8(transitive)
+ Addedtype@2.7.3(transitive)
+ Addedtype-check@0.3.2(transitive)
+ Addedtypedarray@0.0.6(transitive)
+ Addeduniq@1.0.1(transitive)
+ Addeduser-home@2.0.0(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedword-wrap@1.2.5(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedwrite@0.2.1(transitive)
+ Addedxtend@4.0.2(transitive)
- Removedheroku-client@3.0.0-alpha3(transitive)
Updatedheroku-client@3.0.0-beta1