cli-engine-heroku
Advanced tools
Comparing version 5.0.3 to 6.0.0-ts.0
@@ -1,169 +0,145 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.HerokuAPIError = undefined; | ||
var _httpCall = require('http-call'); | ||
var _httpCall2 = _interopRequireDefault(_httpCall); | ||
var _yubikey = require('./yubikey'); | ||
var _yubikey2 = _interopRequireDefault(_yubikey); | ||
var _mutex = require('./mutex'); | ||
var _mutex2 = _interopRequireDefault(_mutex); | ||
var _vars = require('./vars'); | ||
var _vars2 = _interopRequireDefault(_vars); | ||
var _url = require('url'); | ||
var _cliUx = require('cli-ux'); | ||
var _cliUx2 = _interopRequireDefault(_cliUx); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const http_call_1 = require("http-call"); | ||
const mutex_1 = require("./mutex"); | ||
const vars_1 = require("./vars"); | ||
const url_1 = require("url"); | ||
const cli_ux_1 = require("cli-ux"); | ||
const yubikey_1 = require("./yubikey"); | ||
class HerokuAPIError extends Error { | ||
constructor(httpError) { | ||
let options = httpError.body; | ||
if (!options.message) throw httpError; | ||
let info = []; | ||
if (options.id) info.push(`Error ID: ${options.id}`); | ||
if (options.app && options.app.name) info.push(`App: ${options.app.name}`); | ||
if (options.url) info.push(`See ${options.url} for more information.`); | ||
if (info.length) super([options.message, ''].concat(info).join('\n'));else super(options.message); | ||
this.http = httpError; | ||
this.body = options; | ||
} | ||
constructor(httpError) { | ||
let options = httpError.body; | ||
if (!options.message) | ||
throw httpError; | ||
let info = []; | ||
if (options.id) | ||
info.push(`Error ID: ${options.id}`); | ||
if (options.app && options.app.name) | ||
info.push(`App: ${options.app.name}`); | ||
if (options.url) | ||
info.push(`See ${options.url} for more information.`); | ||
if (info.length) | ||
super([options.message, ''].concat(info).join('\n')); | ||
else | ||
super(options.message); | ||
this.http = httpError; | ||
this.body = options; | ||
} | ||
} | ||
exports.HerokuAPIError = HerokuAPIError; | ||
class Heroku { | ||
constructor({ config } = {}, options = {}) { | ||
this.config = config; | ||
if (options.required === undefined) options.required = true; | ||
options.preauth = options.preauth !== false; | ||
this.options = options; | ||
let apiUrl = new _url.URL(_vars2.default.apiUrl); | ||
let envHeaders = JSON.parse(process.env.HEROKU_HEADERS || '{}'); | ||
this.twoFactorMutex = new _mutex2.default(); | ||
this.preauthPromises = {}; | ||
let auth = this.auth; | ||
let self = this; | ||
this.http = class extends _httpCall2.default { | ||
static get defaultOptions() { | ||
let opts = { | ||
...super.defaultOptions, | ||
host: apiUrl.host, | ||
headers: { | ||
...super.defaultOptions.headers, | ||
'user-agent': `heroku-cli/${self.config.version} ${self.config.platform}`, | ||
accept: 'application/vnd.heroku+json; version=3', | ||
...envHeaders | ||
} | ||
class APIClient { | ||
constructor({ config }, options = {}) { | ||
this.config = config; | ||
if (options.required === undefined) | ||
options.required = true; | ||
options.preauth = options.preauth !== false; | ||
this.options = options; | ||
let apiUrl = new url_1.URL(vars_1.vars.apiUrl); | ||
let envHeaders = JSON.parse(process.env.HEROKU_HEADERS || '{}'); | ||
this.preauthPromises = {}; | ||
let auth = this.auth; | ||
let self = this; | ||
this.http = class APIHTTPClient extends http_call_1.HTTP { | ||
static get defaultOptions() { | ||
let opts = Object.assign({}, super.defaultOptions, { host: apiUrl.host, headers: Object.assign({}, super.defaultOptions.headers, { 'user-agent': `heroku-cli/${self.config.version} ${self.config.platform}`, accept: 'application/vnd.heroku+json; version=3' }, envHeaders) }); | ||
if (auth) | ||
opts.headers.authorization = `Bearer ${auth}`; | ||
return opts; | ||
} | ||
static async twoFactorRetry(err, url, opts = {}, retries = 3) { | ||
const app = err.body.app ? err.body.app.name : null; | ||
if (!app || !options.preauth) { | ||
opts.headers = opts.headers || {}; | ||
opts.headers['Heroku-Two-Factor-Code'] = await self.twoFactorPrompt(); | ||
return this.request(url, opts, retries); | ||
} | ||
else { | ||
// if multiple requests are run in parallel for the same app, we should | ||
// only preauth for the first so save the fact we already preauthed | ||
if (!self.preauthPromises[app]) { | ||
self.preauthPromises[app] = self.twoFactorPrompt().then(factor => self.preauth(app, factor)); | ||
} | ||
await self.preauthPromises[app]; | ||
return this.request(url, opts, retries); | ||
} | ||
} | ||
static async request(url, opts = {}, retries = 3) { | ||
retries--; | ||
try { | ||
return await super.request(url, opts); | ||
} | ||
catch (err) { | ||
if (!(err instanceof http_call_1.HTTPError)) | ||
throw err; | ||
if (retries > 0) { | ||
if (err.http.statusCode === 403 && err.body.id === 'two_factor') { | ||
return this.twoFactorRetry(err, url, opts, retries); | ||
} | ||
} | ||
throw new HerokuAPIError(err); | ||
} | ||
} | ||
}; | ||
if (auth) opts.headers.authorization = `Bearer ${auth}`; | ||
return opts; | ||
} | ||
static async twoFactorRetry(err, url, opts = {}, retries = 3) { | ||
const app = err.body.app ? err.body.app.name : null; | ||
if (!app || !options.preauth) { | ||
// flow$ignore | ||
opts.headers['Heroku-Two-Factor-Code'] = await self.twoFactorPrompt(); | ||
return this.request(url, opts, retries); | ||
} else { | ||
// if multiple requests are run in parallel for the same app, we should | ||
// only preauth for the first so save the fact we already preauthed | ||
if (!self.preauthPromises[app]) { | ||
self.preauthPromises[app] = self.twoFactorPrompt().then(factor => self.preauth(app, factor)); | ||
} | ||
await self.preauthPromises[app]; | ||
return this.request(url, opts, retries); | ||
} | ||
get twoFactorMutex() { | ||
if (!this._twoFactorMutex) { | ||
this._twoFactorMutex = new mutex_1.Mutex(); | ||
} | ||
} | ||
static async request(url, opts, retries = 3) { | ||
retries--; | ||
try { | ||
return await super.request(url, opts); | ||
} catch (err) { | ||
if (!err.__httpcall) throw err; | ||
let apiError = new HerokuAPIError(err); | ||
if (retries > 0) { | ||
if (apiError.http.statusCode === 403 && apiError.body.id === 'two_factor') { | ||
return this.twoFactorRetry(apiError, url, opts, retries); | ||
} | ||
} | ||
throw apiError; | ||
return this._twoFactorMutex; | ||
} | ||
get auth() { | ||
if (process.env.HEROKU_API_TOKEN) | ||
cli_ux_1.cli.warn('HEROKU_API_TOKEN is set but you probably meant HEROKU_API_KEY'); | ||
let auth = process.env.HEROKU_API_KEY; | ||
if (!auth) { | ||
const Netrc = require('netrc-parser'); | ||
const netrc = new Netrc(); | ||
auth = netrc.machines[vars_1.vars.apiHost].password; | ||
} | ||
} | ||
}; | ||
} | ||
get auth() { | ||
if (process.env.HEROKU_API_TOKEN) _cliUx2.default.warn('HEROKU_API_TOKEN is set but you probably meant HEROKU_API_KEY'); | ||
let auth = process.env.HEROKU_API_KEY; | ||
if (!auth) { | ||
const Netrc = require('netrc-parser'); | ||
const netrc = new Netrc(); | ||
auth = netrc.machines[_vars2.default.apiHost].password; | ||
return auth; | ||
} | ||
// TODO: handle required | ||
return auth; | ||
} | ||
twoFactorPrompt() { | ||
_yubikey2.default.enable(); | ||
return this.twoFactorMutex.synchronize(async () => { | ||
try { | ||
let factor = await _cliUx2.default.prompt('Two-factor code', { type: 'mask' }); | ||
_yubikey2.default.disable(); | ||
return factor; | ||
} catch (err) { | ||
_yubikey2.default.disable(); | ||
throw err; | ||
} | ||
}); | ||
} | ||
preauth(app, factor) { | ||
return this.put(`/apps/${app}/pre-authorizations`, { | ||
headers: { 'Heroku-Two-Factor-Code': factor } | ||
}); | ||
} | ||
get(url, options = {}) { | ||
return this.http.get(url, options); | ||
} | ||
post(url, options = {}) { | ||
return this.http.post(url, options); | ||
} | ||
put(url, options = {}) { | ||
return this.http.put(url, options); | ||
} | ||
patch(url, options = {}) { | ||
return this.http.patch(url, options); | ||
} | ||
delete(url, options = {}) { | ||
return this.http.delete(url, options); | ||
} | ||
stream(url, options = {}) { | ||
return this.http.stream(url, options); | ||
} | ||
request(url, options = {}) { | ||
return this.http.request(url, options); | ||
} | ||
get defaultOptions() { | ||
return this.http.defaultOptions; | ||
} | ||
twoFactorPrompt() { | ||
yubikey_1.yubikey.enable(); | ||
return this.twoFactorMutex.synchronize(async () => { | ||
try { | ||
let factor = await cli_ux_1.cli.prompt('Two-factor code', { type: 'mask' }); | ||
yubikey_1.yubikey.disable(); | ||
return factor; | ||
} | ||
catch (err) { | ||
yubikey_1.yubikey.disable(); | ||
throw err; | ||
} | ||
}); | ||
} | ||
preauth(app, factor) { | ||
return this.put(`/apps/${app}/pre-authorizations`, { | ||
headers: { 'Heroku-Two-Factor-Code': factor }, | ||
}); | ||
} | ||
get(url, options = {}) { | ||
return this.http.get(url, options); | ||
} | ||
post(url, options = {}) { | ||
return this.http.post(url, options); | ||
} | ||
put(url, options = {}) { | ||
return this.http.put(url, options); | ||
} | ||
patch(url, options = {}) { | ||
return this.http.patch(url, options); | ||
} | ||
delete(url, options = {}) { | ||
return this.http.delete(url, options); | ||
} | ||
stream(url, options = {}) { | ||
return this.http.stream(url, options); | ||
} | ||
request(url, options = {}) { | ||
return this.http.request(url, options); | ||
} | ||
get defaultOptions() { | ||
return this.http.defaultOptions; | ||
} | ||
} | ||
exports.default = Heroku; | ||
exports.APIClient = APIClient; |
@@ -1,45 +0,30 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const supports = require("supports-color"); | ||
const chalk_1 = require("chalk"); | ||
const ansiStyles = require("ansi-styles"); | ||
exports.CustomColors = { | ||
supports, | ||
// map gray -> dim because it's not solarized compatible | ||
gray: chalk_1.default.dim, | ||
grey: chalk_1.default.dim, | ||
attachment: chalk_1.default.cyan, | ||
addon: chalk_1.default.yellow, | ||
configVar: chalk_1.default.green, | ||
release: chalk_1.default.blue.bold, | ||
cmd: chalk_1.default.cyan.bold, | ||
app: (s) => exports.color.heroku(`⬢ ${s}`), | ||
heroku: (s) => { | ||
if (!exports.color.supports) | ||
return s; | ||
let has256 = exports.color.supports.has256 || (process.env.TERM || '').indexOf('256') !== -1; | ||
return has256 ? '\u001b[38;5;104m' + s + ansiStyles.reset.open : chalk_1.default.magenta(s); | ||
}, | ||
}; | ||
exports.color = new Proxy(chalk_1.default, { | ||
get: (chalk, name) => { | ||
if (exports.CustomColors[name]) | ||
return exports.CustomColors[name]; | ||
return chalk[name]; | ||
}, | ||
}); | ||
exports.color = exports.CustomColors = undefined; | ||
var _supportsColor = require('supports-color'); | ||
var _supportsColor2 = _interopRequireDefault(_supportsColor); | ||
var _chalk = require('chalk'); | ||
var _chalk2 = _interopRequireDefault(_chalk); | ||
var _ansiStyles = require('ansi-styles'); | ||
var _ansiStyles2 = _interopRequireDefault(_ansiStyles); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
const CustomColors = exports.CustomColors = { | ||
supports: _supportsColor2.default, | ||
// map gray -> dim because it's not solarized compatible | ||
gray: s => _chalk2.default.dim(s), | ||
grey: s => _chalk2.default.dim(s), | ||
attachment: s => _chalk2.default.cyan(s), | ||
addon: s => _chalk2.default.yellow(s), | ||
configVar: s => _chalk2.default.green(s), | ||
release: s => _chalk2.default.blue.bold(s), | ||
cmd: s => _chalk2.default.cyan.bold(s), | ||
app: s => CustomColors.heroku(`⬢ ${s}`), | ||
heroku: s => { | ||
if (!CustomColors.supports) return s; | ||
let has256 = CustomColors.supports.has256 || (process.env.TERM || '').indexOf('256') !== -1; | ||
return has256 ? '\u001b[38;5;104m' + s + _ansiStyles2.default.reset.open : _chalk2.default.magenta(s); | ||
} | ||
}; | ||
const color = exports.color = new Proxy(_chalk2.default, { | ||
get: (chalk, name) => { | ||
if (CustomColors[name]) return CustomColors[name]; | ||
return chalk[name]; | ||
} | ||
}); |
@@ -1,44 +0,32 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _cliEngineCommand = require('cli-engine-command'); | ||
var _cliEngineCommand2 = _interopRequireDefault(_cliEngineCommand); | ||
var _api_client = require('./api_client'); | ||
var _api_client2 = _interopRequireDefault(_api_client); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
class HerokuCommand extends _cliEngineCommand2.default { | ||
async init() { | ||
await super.init(); | ||
if (this.flags.app) this.app = this.flags.app; | ||
} | ||
get heroku() { | ||
if (this._heroku) return this._heroku; | ||
this._heroku = new _api_client2.default(this); | ||
return this._heroku; | ||
} | ||
get legacyHerokuClient() { | ||
if (this._legacyHerokuClient) return this._legacyHerokuClient; | ||
const HerokuClient = require('heroku-client'); | ||
let options = { | ||
// flow$ignore | ||
userAgent: this.heroku.defaultOptions.headers['user-agent'], | ||
debug: this.config.debug, | ||
token: this.heroku.auth, | ||
host: `${this.heroku.defaultOptions.protocol || 'https:'}//${this.heroku.defaultOptions.host || 'api.heroku.com'}` | ||
}; | ||
this._legacyHerokuClient = new HerokuClient(options); | ||
return this._legacyHerokuClient; | ||
} | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const cli_engine_command_1 = require("cli-engine-command"); | ||
const api_client_1 = require("./api_client"); | ||
class Command extends cli_engine_command_1.Command { | ||
async init() { | ||
await super.init(); | ||
if (this.flags.app) | ||
this.app = this.flags.app; | ||
} | ||
get heroku() { | ||
if (this._heroku) | ||
return this._heroku; | ||
this._heroku = new api_client_1.APIClient(this); | ||
return this._heroku; | ||
} | ||
get legacyHerokuClient() { | ||
if (this._legacyHerokuClient) | ||
return this._legacyHerokuClient; | ||
const HerokuClient = require('heroku-client'); | ||
let options = { | ||
userAgent: this.heroku.defaultOptions.headers['user-agent'], | ||
debug: this.config.debug, | ||
token: this.heroku.auth, | ||
host: `${this.heroku.defaultOptions.protocol || 'https:'}//${this.heroku.defaultOptions.host || | ||
'api.heroku.com'}`, | ||
}; | ||
this._legacyHerokuClient = new HerokuClient(options); | ||
return this._legacyHerokuClient; | ||
} | ||
} | ||
exports.default = HerokuCommand; | ||
exports.Command = Command; |
@@ -1,172 +0,154 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.TeamCompletion = exports.StageCompletion = exports.StackCompletion = exports.SpaceCompletion = exports.ScopeCompletion = exports.RoleCompletion = exports.RemoteCompletion = exports.RegionCompletion = exports.ProcessTypeCompletion = exports.PipelineCompletion = exports.FileCompletion = exports.DynoSizeCompletion = exports.AppDynoCompletion = exports.AppAddonCompletion = exports.BuildpackCompletion = exports.AppCompletion = exports._herokuGet = undefined; | ||
var _api_client = require('./api_client'); | ||
var _api_client2 = _interopRequireDefault(_api_client); | ||
var _app = require('./flags/app'); | ||
var _fsExtra = require('fs-extra'); | ||
var _fsExtra2 = _interopRequireDefault(_fsExtra); | ||
var _path = require('path'); | ||
var _path2 = _interopRequireDefault(_path); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const api_client_1 = require("./api_client"); | ||
const app_1 = require("./flags/app"); | ||
const fs = require("fs-extra"); | ||
const path = require("path"); | ||
const oneDay = 60 * 60 * 24; | ||
const _herokuGet = exports._herokuGet = async function (resource, ctx) { | ||
const heroku = new _api_client2.default({ config: ctx.config }); | ||
let { body: resources } = await heroku.get(`/${resource}`); | ||
if (typeof resources === 'string') resources = JSON.parse(resources); | ||
return resources.map(a => a.name).sort(); | ||
exports._herokuGet = async function (resource, ctx) { | ||
const heroku = new api_client_1.APIClient({ config: ctx.config }); | ||
let { body: resources } = await heroku.get(`/${resource}`); | ||
if (typeof resources === 'string') | ||
resources = JSON.parse(resources); | ||
return resources.map((a) => a.name).sort(); | ||
}; | ||
const AppCompletion = exports.AppCompletion = { | ||
cacheDuration: oneDay, | ||
options: async ctx => { | ||
let apps = await _herokuGet('apps', ctx); | ||
return apps; | ||
} | ||
exports.AppCompletion = { | ||
cacheDuration: oneDay, | ||
options: async (ctx) => { | ||
let apps = await exports._herokuGet('apps', ctx); | ||
return apps; | ||
}, | ||
}; | ||
const BuildpackCompletion = exports.BuildpackCompletion = { | ||
skipCache: true, | ||
options: async ctx => { | ||
return ['heroku/ruby', 'heroku/nodejs', 'heroku/clojure', 'heroku/python', 'heroku/java', 'heroku/gradle', 'heroku/scala', 'heroku/php', 'heroku/go']; | ||
} | ||
exports.BuildpackCompletion = { | ||
skipCache: true, | ||
options: async () => { | ||
return [ | ||
'heroku/ruby', | ||
'heroku/nodejs', | ||
'heroku/clojure', | ||
'heroku/python', | ||
'heroku/java', | ||
'heroku/gradle', | ||
'heroku/scala', | ||
'heroku/php', | ||
'heroku/go', | ||
]; | ||
}, | ||
}; | ||
const AppAddonCompletion = exports.AppAddonCompletion = { | ||
cacheDuration: oneDay, | ||
cacheKey: async ctx => { | ||
return ctx.flags && ctx.flags.app ? `${ctx.flags.app}_addons` : ''; | ||
}, | ||
options: async ctx => { | ||
const heroku = new _api_client2.default({ config: ctx.config }); | ||
let addons = ctx.flags && ctx.flags.app ? await heroku.get(`/apps/${ctx.flags.app}/addons`) : []; | ||
return addons.map(a => a.name).sort(); | ||
} | ||
exports.AppAddonCompletion = { | ||
cacheDuration: oneDay, | ||
cacheKey: async (ctx) => { | ||
return ctx.flags && ctx.flags.app ? `${ctx.flags.app}_addons` : ''; | ||
}, | ||
options: async (ctx) => { | ||
const heroku = new api_client_1.APIClient({ config: ctx.config }); | ||
let addons = ctx.flags && ctx.flags.app ? await heroku.get(`/apps/${ctx.flags.app}/addons`) : []; | ||
return addons.map((a) => a.name).sort(); | ||
}, | ||
}; | ||
const AppDynoCompletion = exports.AppDynoCompletion = { | ||
cacheDuration: oneDay, | ||
cacheKey: async ctx => { | ||
return ctx.flags && ctx.flags.app ? `${ctx.flags.app}_dynos` : ''; | ||
}, | ||
options: async ctx => { | ||
const heroku = new _api_client2.default({ config: ctx.config }); | ||
let dynos = ctx.flags && ctx.flags.app ? await heroku.get(`/apps/${ctx.flags.app}/dynos`) : []; | ||
return dynos.map(a => a.type).sort(); | ||
} | ||
exports.AppDynoCompletion = { | ||
cacheDuration: oneDay, | ||
cacheKey: async (ctx) => { | ||
return ctx.flags && ctx.flags.app ? `${ctx.flags.app}_dynos` : ''; | ||
}, | ||
options: async (ctx) => { | ||
const heroku = new api_client_1.APIClient({ config: ctx.config }); | ||
let dynos = ctx.flags && ctx.flags.app ? await heroku.get(`/apps/${ctx.flags.app}/dynos`) : []; | ||
return dynos.map((a) => a.type).sort(); | ||
}, | ||
}; | ||
const DynoSizeCompletion = exports.DynoSizeCompletion = { | ||
cacheDuration: oneDay * 90, | ||
options: async ctx => { | ||
let sizes = await _herokuGet('dyno-sizes', ctx); | ||
return sizes; | ||
} | ||
exports.DynoSizeCompletion = { | ||
cacheDuration: oneDay * 90, | ||
options: async (ctx) => { | ||
let sizes = await exports._herokuGet('dyno-sizes', ctx); | ||
return sizes; | ||
}, | ||
}; | ||
const FileCompletion = exports.FileCompletion = { | ||
skipCache: true, | ||
options: async ctx => { | ||
let files = await _fsExtra2.default.readdir(process.cwd()); | ||
return files; | ||
} | ||
exports.FileCompletion = { | ||
skipCache: true, | ||
options: async () => { | ||
let files = await fs.readdir(process.cwd()); | ||
return files; | ||
}, | ||
}; | ||
const PipelineCompletion = exports.PipelineCompletion = { | ||
cacheDuration: oneDay, | ||
options: async ctx => { | ||
let pipelines = await _herokuGet('pipelines', ctx); | ||
return pipelines; | ||
} | ||
exports.PipelineCompletion = { | ||
cacheDuration: oneDay, | ||
options: async (ctx) => { | ||
let pipelines = await exports._herokuGet('pipelines', ctx); | ||
return pipelines; | ||
}, | ||
}; | ||
const ProcessTypeCompletion = exports.ProcessTypeCompletion = { | ||
skipCache: true, | ||
options: async ctx => { | ||
let types = []; | ||
let procfile = _path2.default.join(process.cwd(), 'Procfile'); | ||
if (await _fsExtra2.default.exists(procfile)) { | ||
let buff = await _fsExtra2.default.readFile(procfile); | ||
types = buff.toString().split('\n').map(s => { | ||
if (!s) return false; | ||
let m = s.match(/^([A-Za-z0-9_-]+)/); | ||
return m ? m[0] : false; | ||
}).filter(t => t); | ||
} | ||
return types; | ||
} | ||
exports.ProcessTypeCompletion = { | ||
skipCache: true, | ||
options: async () => { | ||
let types = []; | ||
let procfile = path.join(process.cwd(), 'Procfile'); | ||
if (fs.existsSync(procfile)) { | ||
let buff = await fs.readFile(procfile); | ||
types = buff | ||
.toString() | ||
.split('\n') | ||
.map(s => { | ||
if (!s) | ||
return false; | ||
let m = s.match(/^([A-Za-z0-9_-]+)/); | ||
return m ? m[0] : false; | ||
}) | ||
.filter(t => t); | ||
} | ||
return types; | ||
}, | ||
}; | ||
const RegionCompletion = exports.RegionCompletion = { | ||
cacheDuration: oneDay * 7, | ||
options: async ctx => { | ||
let regions = await _herokuGet('regions', ctx); | ||
return regions; | ||
} | ||
exports.RegionCompletion = { | ||
cacheDuration: oneDay * 7, | ||
options: async (ctx) => { | ||
let regions = await exports._herokuGet('regions', ctx); | ||
return regions; | ||
}, | ||
}; | ||
const RemoteCompletion = exports.RemoteCompletion = { | ||
skipCache: true, | ||
options: async ctx => { | ||
let remotes = (0, _app.getGitRemotes)((0, _app.configRemote)()); | ||
return remotes.map(r => r.remote); | ||
} | ||
exports.RemoteCompletion = { | ||
skipCache: true, | ||
options: async () => { | ||
let remotes = app_1.getGitRemotes(app_1.configRemote()); | ||
return remotes.map(r => r.remote); | ||
}, | ||
}; | ||
const RoleCompletion = exports.RoleCompletion = { | ||
skipCache: true, | ||
options: async ctx => { | ||
return ['admin', 'collaborator', 'member', 'owner']; | ||
} | ||
exports.RoleCompletion = { | ||
skipCache: true, | ||
options: async () => { | ||
return ['admin', 'collaborator', 'member', 'owner']; | ||
}, | ||
}; | ||
const ScopeCompletion = exports.ScopeCompletion = { | ||
skipCache: true, | ||
options: async ctx => { | ||
return ['global', 'identity', 'read', 'write', 'read-protected', 'write-protected']; | ||
} | ||
exports.ScopeCompletion = { | ||
skipCache: true, | ||
options: async () => { | ||
return ['global', 'identity', 'read', 'write', 'read-protected', 'write-protected']; | ||
}, | ||
}; | ||
const SpaceCompletion = exports.SpaceCompletion = { | ||
cacheDuration: oneDay, | ||
options: async ctx => { | ||
let spaces = await _herokuGet('spaces', ctx); | ||
return spaces; | ||
} | ||
exports.SpaceCompletion = { | ||
cacheDuration: oneDay, | ||
options: async (ctx) => { | ||
let spaces = await exports._herokuGet('spaces', ctx); | ||
return spaces; | ||
}, | ||
}; | ||
const StackCompletion = exports.StackCompletion = { | ||
cacheDuration: oneDay, | ||
options: async ctx => { | ||
let stacks = await _herokuGet('stacks', ctx); | ||
return stacks; | ||
} | ||
exports.StackCompletion = { | ||
cacheDuration: oneDay, | ||
options: async (ctx) => { | ||
let stacks = await exports._herokuGet('stacks', ctx); | ||
return stacks; | ||
}, | ||
}; | ||
const StageCompletion = exports.StageCompletion = { | ||
skipCache: true, | ||
options: async ctx => { | ||
return ['test', 'review', 'development', 'staging', 'production']; | ||
} | ||
exports.StageCompletion = { | ||
skipCache: true, | ||
options: async () => { | ||
return ['test', 'review', 'development', 'staging', 'production']; | ||
}, | ||
}; | ||
const TeamCompletion = exports.TeamCompletion = { | ||
cacheDuration: oneDay, | ||
options: async ctx => { | ||
let teams = await _herokuGet('teams', ctx); | ||
return teams; | ||
} | ||
}; | ||
exports.TeamCompletion = { | ||
cacheDuration: oneDay, | ||
options: async (ctx) => { | ||
let teams = await exports._herokuGet('teams', ctx); | ||
return teams; | ||
}, | ||
}; |
@@ -1,26 +0,10 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.app = app; | ||
exports.remote = remote; | ||
exports.configRemote = configRemote; | ||
exports.getGitRemotes = getGitRemotes; | ||
var _vars = require('../vars'); | ||
var _vars2 = _interopRequireDefault(_vars); | ||
var _git = require('../git'); | ||
var _git2 = _interopRequireDefault(_git); | ||
var _completions = require('../completions'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const vars_1 = require("../vars"); | ||
const cli_engine_command_1 = require("cli-engine-command"); | ||
const git_1 = require("../git"); | ||
const completions_1 = require("../completions"); | ||
class MultipleRemotesError extends Error { | ||
constructor(gitRemotes) { | ||
super(`Multiple apps in git remotes | ||
constructor(gitRemotes) { | ||
super(`Multiple apps in git remotes | ||
Usage: --remote ${gitRemotes[1].remote} | ||
@@ -35,68 +19,62 @@ or: --app ${gitRemotes[1].app} | ||
https://devcenter.heroku.com/articles/multiple-environments`); | ||
} | ||
} | ||
} | ||
function app(options = {}) { | ||
return { | ||
exports.app = cli_engine_command_1.flags.option({ | ||
description: 'app to run command against', | ||
char: 'a', | ||
description: 'app to run command against', | ||
parse: (input, cmd) => { | ||
const envApp = process.env.HEROKU_APP; | ||
if (cmd && cmd.flags.app) return cmd.flags.app; | ||
if (input) return input; | ||
if (envApp) return envApp; | ||
if (cmd) { | ||
let gitRemotes = getGitRemotes(cmd.flags.remote || configRemote()); | ||
if (gitRemotes.length === 1) return gitRemotes[0].app; | ||
if (cmd.flags.remote && gitRemotes.length === 0) { | ||
throw new Error(`remote ${cmd.flags.remote} not found in git remotes`); | ||
default: ({ options, flags }) => { | ||
const envApp = process.env.HEROKU_APP; | ||
if (envApp) | ||
return envApp; | ||
let gitRemotes = getGitRemotes(flags.remote || configRemote()); | ||
if (gitRemotes.length === 1) | ||
return gitRemotes[0].app; | ||
if (flags.remote && gitRemotes.length === 0) { | ||
throw new Error(`remote ${flags.remote} not found in git remotes`); | ||
} | ||
if (gitRemotes.length > 1 && options.required) { | ||
throw new MultipleRemotesError(gitRemotes); | ||
throw new MultipleRemotesError(gitRemotes); | ||
} | ||
} | ||
if (options.required) throw new Error('No app specified'); | ||
}, | ||
completion: _completions.AppCompletion, | ||
...options | ||
}; | ||
} | ||
function remote(options = {}) { | ||
return { | ||
completion: completions_1.AppCompletion, | ||
}); | ||
exports.remote = cli_engine_command_1.flags.option({ | ||
char: 'r', | ||
description: 'git remote of app to use', | ||
parse: v => v, | ||
completion: _completions.RemoteCompletion, | ||
...options | ||
}; | ||
} | ||
completion: completions_1.RemoteCompletion, | ||
}); | ||
function configRemote() { | ||
let git = new _git2.default(); | ||
try { | ||
return git.exec('config heroku.remote').trim(); | ||
} catch (err) {} | ||
let git = new git_1.Git(); | ||
try { | ||
return git.exec('config heroku.remote').trim(); | ||
} | ||
catch (err) { } | ||
} | ||
exports.configRemote = configRemote; | ||
function getGitRemotes(onlyRemote) { | ||
let git = new _git2.default(); | ||
let appRemotes = []; | ||
let remotes = []; | ||
try { | ||
remotes = git.remotes; | ||
} catch (err) {} | ||
for (let remote of remotes) { | ||
if (onlyRemote && remote.name !== onlyRemote) continue; | ||
for (let prefix of _vars2.default.gitPrefixes) { | ||
const suffix = '.git'; | ||
let match = remote.url.match(`${prefix}(.*)${suffix}`); | ||
if (!match) continue; | ||
appRemotes.push({ | ||
remote: remote.name, | ||
app: match[1] | ||
}); | ||
let git = new git_1.Git(); | ||
let appRemotes = []; | ||
let remotes; | ||
try { | ||
remotes = git.remotes; | ||
} | ||
} | ||
return appRemotes; | ||
} | ||
catch (err) { | ||
return []; | ||
} | ||
for (let remote of remotes) { | ||
if (onlyRemote && remote.name !== onlyRemote) | ||
continue; | ||
for (let prefix of vars_1.vars.gitPrefixes) { | ||
const suffix = '.git'; | ||
let match = remote.url.match(`${prefix}(.*)${suffix}`); | ||
if (!match) | ||
continue; | ||
appRemotes.push({ | ||
remote: remote.name, | ||
app: match[1], | ||
}); | ||
} | ||
} | ||
return appRemotes; | ||
} | ||
exports.getGitRemotes = getGitRemotes; |
@@ -1,34 +0,8 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _cliEngineCommand = require('cli-engine-command'); | ||
var _app = require('./app'); | ||
var _team = require('./team'); | ||
var _team2 = _interopRequireDefault(_team); | ||
var _org = require('./org'); | ||
var _org2 = _interopRequireDefault(_org); | ||
var _pipeline = require('./pipeline'); | ||
var _pipeline2 = _interopRequireDefault(_pipeline); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
exports.default = { | ||
app: _app.app, | ||
remote: _app.remote, | ||
org: _org2.default, | ||
team: _team2.default, | ||
pipeline: _pipeline2.default, | ||
boolean: _cliEngineCommand.flags.boolean, | ||
number: _cliEngineCommand.flags.number, | ||
string: _cliEngineCommand.flags.string | ||
}; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const cli_engine_command_1 = require("cli-engine-command"); | ||
const app_1 = require("./app"); | ||
const team_1 = require("./team"); | ||
const org_1 = require("./org"); | ||
const pipeline_1 = require("./pipeline"); | ||
exports.flags = Object.assign({}, cli_engine_command_1.flags, { app: app_1.app, remote: app_1.remote, org: org_1.org, team: team_1.team, pipeline: pipeline_1.pipeline }); |
@@ -1,17 +0,9 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = OrgFlag; | ||
function OrgFlag(options = {}) { | ||
return { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const cli_engine_command_1 = require("cli-engine-command"); | ||
exports.org = cli_engine_command_1.flags.option({ | ||
description: 'name of org', | ||
char: 'o', | ||
hidden: true, | ||
parse: input => { | ||
if (input) return input; | ||
if (process.env.HEROKU_ORGANIZATION) return process.env.HEROKU_ORGANIZATION; | ||
}, | ||
...options | ||
}; | ||
} | ||
default: () => process.env.HEROKU_ORGANIZATION, | ||
}); |
@@ -1,14 +0,7 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = PipelineFlag; | ||
function PipelineFlag(options = {}) { | ||
return { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const cli_engine_command_1 = require("cli-engine-command"); | ||
exports.pipeline = cli_engine_command_1.flags.option({ | ||
char: 'p', | ||
description: 'name of pipeline', | ||
parse: v => v, | ||
...options | ||
}; | ||
} | ||
}); |
@@ -1,24 +0,18 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.default = TeamFlag; | ||
var _completions = require('../completions'); | ||
function TeamFlag(options = {}) { | ||
return { | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const completions_1 = require("../completions"); | ||
const cli_engine_command_1 = require("cli-engine-command"); | ||
exports.team = cli_engine_command_1.flags.option({ | ||
description: 'team to use', | ||
char: 't', | ||
description: 'team to use', | ||
parse: (input, cmd, name) => { | ||
if (input) return input; | ||
if (process.env.HEROKU_TEAM) return process.env.HEROKU_TEAM; | ||
if (cmd && cmd.flags.org) return cmd.flags.org; | ||
if (process.env.HEROKU_ORGANIZATION) return process.env.HEROKU_ORGANIZATION; | ||
if (options.required) throw new Error('No team specified'); | ||
default: ({ flags }) => { | ||
let { HEROKU_ORGANIZATION: org, HEROKU_TEAM: team } = process.env; | ||
if (team) | ||
return team; | ||
if (org) | ||
return org; | ||
if (flags.org) | ||
return flags.org; | ||
}, | ||
completion: _completions.TeamCompletion, | ||
...options | ||
}; | ||
} | ||
completion: completions_1.TeamCompletion, | ||
}); |
@@ -1,26 +0,29 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class Git { | ||
get remotes() { | ||
return this.exec('remote -v').split('\n').filter(l => l.endsWith('(fetch)')).map(l => { | ||
const [name, url] = l.split('\t'); | ||
return { name, url: url.split(' ')[0] }; | ||
}); | ||
} | ||
exec(cmd) { | ||
const { execSync: exec } = require('child_process'); | ||
try { | ||
return exec(`git ${cmd}`, { encoding: 'utf8', stdio: [null, 'pipe', null] }); | ||
} catch (error) { | ||
if (error.code === 'ENOENT') { | ||
throw new Error('Git must be installed to use the Heroku CLI. See instructions here: http://git-scm.com'); | ||
} | ||
throw error; | ||
get remotes() { | ||
return this.exec('remote -v') | ||
.split('\n') | ||
.filter(l => l.endsWith('(fetch)')) | ||
.map(l => { | ||
const [name, url] = l.split('\t'); | ||
return { name, url: url.split(' ')[0] }; | ||
}); | ||
} | ||
} | ||
exec(cmd) { | ||
const { execSync: exec } = require('child_process'); | ||
try { | ||
return exec(`git ${cmd}`, { | ||
encoding: 'utf8', | ||
stdio: [null, 'pipe', null], | ||
}); | ||
} | ||
catch (error) { | ||
if (error.code === 'ENOENT') { | ||
throw new Error('Git must be installed to use the Heroku CLI. See instructions here: http://git-scm.com'); | ||
} | ||
throw error; | ||
} | ||
} | ||
} | ||
exports.default = Git; | ||
exports.Git = Git; |
@@ -1,43 +0,10 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
var _flags = require('./flags'); | ||
Object.defineProperty(exports, 'flags', { | ||
enumerable: true, | ||
get: function () { | ||
return _interopRequireDefault(_flags).default; | ||
} | ||
}); | ||
var _command = require('./command'); | ||
Object.defineProperty(exports, 'Command', { | ||
enumerable: true, | ||
get: function () { | ||
return _interopRequireDefault(_command).default; | ||
} | ||
}); | ||
var _api_client = require('./api_client'); | ||
Object.defineProperty(exports, 'APIClient', { | ||
enumerable: true, | ||
get: function () { | ||
return _interopRequireDefault(_api_client).default; | ||
} | ||
}); | ||
var _color = require('./color'); | ||
Object.defineProperty(exports, 'color', { | ||
enumerable: true, | ||
get: function () { | ||
return _color.color; | ||
} | ||
}); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var flags_1 = require("./flags"); | ||
exports.flags = flags_1.flags; | ||
var command_1 = require("./command"); | ||
exports.Command = command_1.Command; | ||
var api_client_1 = require("./api_client"); | ||
exports.APIClient = api_client_1.APIClient; | ||
var color_1 = require("./color"); | ||
exports.color = color_1.color; |
"use strict"; | ||
// Adapted from https://blog.jcoglan.com/2016/07/12/mutexes-and-javascript/ | ||
let Mutex = function () { | ||
this._busy = false; | ||
this._queue = []; | ||
}; | ||
Mutex.prototype.synchronize = function (task) { | ||
let self = this; | ||
return new Promise(function (resolve, reject) { | ||
self._queue.push([task, resolve, reject]); | ||
if (!self._busy) { | ||
self._dequeue(); | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
class Mutex { | ||
constructor() { | ||
this.busy = false; | ||
this.queue = []; | ||
} | ||
}); | ||
}; | ||
Mutex.prototype._dequeue = function () { | ||
this._busy = true; | ||
let next = this._queue.shift(); | ||
if (next) { | ||
this._execute(next); | ||
} else { | ||
this._busy = false; | ||
} | ||
}; | ||
Mutex.prototype._execute = function (record) { | ||
let [task, resolve, reject] = record; | ||
let self = this; | ||
task().then(resolve, reject).then(function () { | ||
self._dequeue(); | ||
}); | ||
}; | ||
module.exports = Mutex; | ||
synchronize(task) { | ||
return new Promise((resolve, reject) => { | ||
this.queue.push([task, resolve, reject]); | ||
if (!this.busy) { | ||
this.dequeue(); | ||
} | ||
}); | ||
} | ||
dequeue() { | ||
this.busy = true; | ||
let next = this.queue.shift(); | ||
if (next) { | ||
this.execute(next); | ||
} | ||
else { | ||
this.busy = false; | ||
} | ||
} | ||
execute(record) { | ||
let [task, resolve, reject] = record; | ||
task() | ||
.then(resolve, reject) | ||
.then(() => { | ||
this.dequeue(); | ||
}); | ||
} | ||
} | ||
exports.Mutex = Mutex; |
@@ -1,55 +0,50 @@ | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
}); | ||
exports.Vars = undefined; | ||
var _url = require('url'); | ||
var _url2 = _interopRequireDefault(_url); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const url = require("url"); | ||
class Vars { | ||
constructor(env) { | ||
this.env = env; | ||
} | ||
get host() { | ||
return this.env.HEROKU_HOST || 'heroku.com'; | ||
} | ||
get apiUrl() { | ||
return this.host.startsWith('http') ? this.host : `https://api.${this.host}`; | ||
} | ||
get apiHost() { | ||
if (this.host.startsWith('http')) { | ||
const u = _url2.default.parse(this.host); | ||
if (u.host) return u.host; | ||
get host() { | ||
return this.envHost || 'heroku.com'; | ||
} | ||
return `api.${this.host}`; | ||
} | ||
get gitHost() { | ||
if (this.env.HEROKU_GIT_HOST) return this.env.HEROKU_GIT_HOST; | ||
if (this.host.startsWith('http')) { | ||
const u = _url2.default.parse(this.host); | ||
if (u.host) return u.host; | ||
get apiUrl() { | ||
return this.host.startsWith('http') ? this.host : `https://api.${this.host}`; | ||
} | ||
return this.host; | ||
} | ||
get httpGitHost() { | ||
if (this.env.HEROKU_GIT_HOST) return this.env.HEROKU_GIT_HOST; | ||
if (this.host.startsWith('http')) { | ||
const u = _url2.default.parse(this.host); | ||
if (u.host) return u.host; | ||
get apiHost() { | ||
if (this.host.startsWith('http')) { | ||
const u = url.parse(this.host); | ||
if (u.host) | ||
return u.host; | ||
} | ||
return `api.${this.host}`; | ||
} | ||
return `git.${this.host}`; | ||
} | ||
get gitPrefixes() { | ||
return [`git@${this.gitHost}:`, `ssh://git@${this.gitHost}/`, `https://${this.httpGitHost}/`]; | ||
} | ||
get envHost() { | ||
return process.env.HEROKU_HOST; | ||
} | ||
get envGitHost() { | ||
return process.env.HEROKU_GIT_HOST; | ||
} | ||
get gitHost() { | ||
if (this.envGitHost) | ||
return this.envGitHost; | ||
if (this.host.startsWith('http')) { | ||
const u = url.parse(this.host); | ||
if (u.host) | ||
return u.host; | ||
} | ||
return this.host; | ||
} | ||
get httpGitHost() { | ||
if (this.envGitHost) | ||
return this.envGitHost; | ||
if (this.host.startsWith('http')) { | ||
const u = url.parse(this.host); | ||
if (u.host) | ||
return u.host; | ||
} | ||
return `git.${this.host}`; | ||
} | ||
get gitPrefixes() { | ||
return [`git@${this.gitHost}:`, `ssh://git@${this.gitHost}/`, `https://${this.httpGitHost}/`]; | ||
} | ||
} | ||
exports.Vars = Vars; | ||
exports.default = new Vars(process.env); | ||
exports.vars = new Vars(); |
@@ -1,14 +0,16 @@ | ||
'use strict'; | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
function toggle(onoff) { | ||
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' }); | ||
} catch (err) {} | ||
const cp = require('child_process'); | ||
if (exports.yubikey.platform !== 'darwin') | ||
return; | ||
try { | ||
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.platform = process.platform; | ||
exports.yubikey = { | ||
enable: () => toggle('KeyOn'), | ||
disable: () => toggle('KeyOff'), | ||
platform: process.platform, | ||
}; |
{ | ||
"name": "cli-engine-heroku", | ||
"description": "heroku specific functionality for the cli-engine", | ||
"version": "5.0.3", | ||
"author": "Jeff Dickey @dickeyxxx", | ||
"version": "6.0.0-ts.0", | ||
"author": "Jeff Dickey @jdxcode", | ||
"bugs": "https://github.com/heroku/cli-engine-heroku/issues", | ||
"dependencies": { | ||
"cli-ux": "^2.0.4", | ||
"ansi-styles": "3.2.0", | ||
"chalk": "2.3.0", | ||
"cli-ux": "^2.0.5", | ||
"heroku-client": "^3.0.3", | ||
"http-call": "^3.0.2", | ||
"netrc-parser": "^2.0.3" | ||
"http-call": "^4.0.0", | ||
"netrc-parser": "^2.0.3", | ||
"supports-color": "5.1.0" | ||
}, | ||
"devDependencies": { | ||
"babel-cli": "^6.26.0", | ||
"babel-eslint": "8.0.1", | ||
"babel-jest": "^21.2.0", | ||
"babel-plugin-syntax-object-rest-spread": "^6.13.0", | ||
"babel-plugin-transform-class-properties": "6.24.1", | ||
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0", | ||
"babel-plugin-transform-flow-strip-types": "6.22.0", | ||
"cli-engine-command": "^9.0.0", | ||
"cli-engine-config": "^3.3.1", | ||
"eslint": "^4.7.2", | ||
"eslint-config-standard": "10.2.1", | ||
"eslint-plugin-flowtype": "^2.36.0", | ||
"eslint-plugin-import": "^2.7.0", | ||
"eslint-plugin-jest": "^21.2.0", | ||
"eslint-plugin-node": "^5.2.0", | ||
"eslint-plugin-promise": "3.5.0", | ||
"eslint-plugin-standard": "3.0.1", | ||
"flow-bin": "^0.55.0", | ||
"flow-copy-source": "^1.2.1", | ||
"flow-typed": "^2.1.5", | ||
"@types/ansi-styles": "2.0.30", | ||
"@types/chalk": "2.2.0", | ||
"@types/fs-extra": "5.0.0", | ||
"@types/jest": "21.1.8", | ||
"@types/nock": "8.2.1", | ||
"@types/node": "8.0.58", | ||
"@types/supports-color": "3.1.0", | ||
"cli-engine-command": "ts", | ||
"cli-engine-config": "ts", | ||
"del-cli": "1.1.0", | ||
"husky": "0.14.3", | ||
"jest": "^21.2.1", | ||
"nock": "^9.0.14", | ||
"nodemon": "^1.12.1", | ||
"rimraf": "2.6.2" | ||
"lint-staged": "6.0.0", | ||
"nock": "9.1.4", | ||
"prettier": "1.9.2", | ||
"ts-jest": "21.2.4", | ||
"typescript": "2.6.2" | ||
}, | ||
@@ -46,8 +42,2 @@ "engines": { | ||
"homepage": "https://github.com/heroku/cli-engine-heroku", | ||
"jest": { | ||
"testEnvironment": "node", | ||
"rootDir": "./src", | ||
"coveragePathIgnorePatterns": [], | ||
"setupTestFrameworkScriptFile": "../test/init.js" | ||
}, | ||
"keywords": [ | ||
@@ -59,14 +49,13 @@ "heroku" | ||
"peerDependencies": { | ||
"cli-engine-command": "^9.0.0", | ||
"cli-engine-config": "^3.0.0" | ||
"cli-engine-command": "^10.0.0", | ||
"cli-engine-config": "^4.0.0" | ||
}, | ||
"repository": "heroku/cli-engine-heroku", | ||
"scripts": { | ||
"build": "babel src -d lib --ignore '*.test.js'", | ||
"clean": "rimraf lib", | ||
"copy-flow": "flow-copy-source -v -i '**/*.test.js' src lib", | ||
"prepare": "npm run clean && npm run build && npm run copy-flow", | ||
"test": "jest && flow && eslint .", | ||
"watch": "nodemon -e js -i lib --exec \"npm run prepare\"" | ||
"posttest": "prettier -l 'src/**/*.ts'", | ||
"precommit": "lint-staged", | ||
"prepare": "del-cli lib && tsc && del-cli \"lib/**/*.test.+(d.ts|js)\"", | ||
"pretest": "tsc", | ||
"test": "jest" | ||
} | ||
} |
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
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
51349
17
1350
11
9
1
5
+ Addedansi-styles@3.2.0
+ Addedchalk@2.3.0
+ Addedsupports-color@5.1.0
+ Addedansi-styles@3.2.0(transitive)
+ Addedchalk@2.3.0(transitive)
+ Addedcli-engine-command@10.0.2(transitive)
+ Addedcli-engine-config@4.2.3(transitive)
+ Addedcli-flags@1.0.18(transitive)
+ Addedhas-flag@2.0.0(transitive)
+ Addedsupports-color@4.5.05.1.0(transitive)
- Removedcli-engine-command@9.0.7(transitive)
- Removedcli-engine-config@3.5.0(transitive)
- Removedfs-extra@4.0.3(transitive)
- Removedhttp-call@3.0.2(transitive)
Updatedcli-ux@^2.0.5
Updatedhttp-call@^4.0.0