@oclif/plugin-update
Advanced tools
Comparing version 1.0.5 to 1.1.0
@@ -1,1 +0,1 @@ | ||
{"version":"1.0.5","commands":{"update":{"id":"update","description":"update the <%= config.bin %> CLI","pluginName":"@oclif/plugin-update","pluginType":"core","aliases":[],"flags":{"autoupdate":{"name":"autoupdate","type":"boolean","hidden":true}},"args":[{"name":"channel"}]}}} | ||
{"version":"1.1.0","commands":{"update":{"id":"update","description":"update the <%= config.bin %> CLI","pluginName":"@oclif/plugin-update","pluginType":"core","aliases":[],"flags":{"autoupdate":{"name":"autoupdate","type":"boolean","hidden":true}},"args":[{"name":"channel"}]}}} |
@@ -0,1 +1,14 @@ | ||
<a name="1.1.0"></a> | ||
# [1.1.0](https://github.com/oclif/plugin-update/compare/v1.0.5...v1.1.0) (2018-04-07) | ||
### Bug Fixes | ||
* fixed github check ([7fe3d42](https://github.com/oclif/plugin-update/commit/7fe3d42)) | ||
### Features | ||
* added github updater ([cbd2a4f](https://github.com/oclif/plugin-update/commit/cbd2a4f)) | ||
<a name="1.0.5"></a> | ||
@@ -2,0 +15,0 @@ ## [1.0.5](https://github.com/oclif/plugin-update/compare/v1.0.4...v1.0.5) (2018-04-07) |
@@ -12,3 +12,3 @@ import Command from '@oclif/command'; | ||
name: string; | ||
char?: "a" | "b" | "i" | "p" | "q" | "s" | "u" | "g" | "c" | "d" | "e" | "f" | "h" | "j" | "k" | "l" | "m" | "n" | "o" | "r" | "t" | "v" | "x" | "y" | "z" | "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "X" | "Y" | "Z" | undefined; | ||
char?: "a" | "b" | "i" | "p" | "q" | "s" | "u" | "g" | "A" | "c" | "d" | "e" | "f" | "h" | "j" | "k" | "l" | "m" | "n" | "o" | "r" | "t" | "v" | "x" | "y" | "z" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "X" | "Y" | "Z" | undefined; | ||
description?: string | undefined; | ||
@@ -29,4 +29,3 @@ hidden?: boolean | undefined; | ||
private mtime(f); | ||
private shouldUpdate(manifest); | ||
private debounce(); | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const color_1 = require("@heroku-cli/color"); | ||
const command_1 = require("@oclif/command"); | ||
@@ -15,3 +14,3 @@ const cli_ux_1 = require("cli-ux"); | ||
super(...arguments); | ||
this.updater = new __1.Updater(this.config); | ||
this.updater = __1.fetchUpdater(this.config); | ||
} | ||
@@ -21,3 +20,3 @@ async run() { | ||
this.autoupdate = !!flags.autoupdate; | ||
if (flags.autoupdate) { | ||
if (this.autoupdate) { | ||
await this.debounce(); | ||
@@ -29,9 +28,5 @@ } | ||
} | ||
// if (this.config.updateDisabled) { | ||
// // cli.warn(this.config.updateDisabled) | ||
// } else { | ||
cli_ux_1.default.action.start(`${this.config.name}: Updating CLI`); | ||
let channel = args.channel || this.updater.channel; | ||
let manifest = await this.updater.fetchManifest(channel); | ||
if (this.config.version === manifest.version && channel === this.updater.channel) { | ||
if (!await this.updater.needsUpdate(channel)) { | ||
if (!process.env.OCLIF_HIDE_UPDATED_MESSAGE) { | ||
@@ -41,11 +36,5 @@ cli_ux_1.default.action.stop(`already on latest version: ${this.config.version}`); | ||
} | ||
else if (this.shouldUpdate(manifest)) { | ||
cli_ux_1.default.action.start(`${this.config.name}: Updating CLI from ${color_1.color.green(this.config.version)} to ${color_1.color.green(manifest.version)}${channel === 'stable' ? '' : ' (' + color_1.color.yellow(channel) + ')'}`); | ||
await this.updater.update(manifest); | ||
else { | ||
await this.updater.update({ channel }); | ||
} | ||
// } | ||
this.debug('fetch version'); | ||
await this.updater.fetchVersion(true); | ||
this.debug('plugins update'); | ||
// await PluginsUpdate.run([], this.config) | ||
this.debug('log chop'); | ||
@@ -55,3 +44,2 @@ await this.logChop(); | ||
await this.updater.tidy(); | ||
// const hooks = new Hooks(this.config) | ||
await this.config.runHook('update', { channel }); | ||
@@ -74,17 +62,5 @@ this.debug('done'); | ||
} | ||
shouldUpdate(manifest) { | ||
try { | ||
const chance = Math.random() * 100; | ||
if (this.autoupdate && manifest.priority && chance < manifest.priority) { | ||
cli_ux_1.default.log(`skipping update. priority is ${manifest.priority} but chance is ${chance}`); | ||
return false; | ||
} | ||
} | ||
catch (err) { | ||
cli_ux_1.default.warn(err); | ||
} | ||
return true; | ||
} | ||
async debounce() { | ||
const m = await this.mtime(this.updater.lastrunfile); | ||
const lastrunfile = path.join(this.config.cacheDir, 'lastrun'); | ||
const m = await this.mtime(lastrunfile); | ||
const waitUntil = dateAddHours(m, 1); | ||
@@ -91,0 +67,0 @@ if (dateIsAfter(waitUntil, new Date())) { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const cli_ux_1 = require("cli-ux"); | ||
const __1 = require(".."); | ||
const spawn = require("cross-spawn"); | ||
const dateIsAfter = require("date-fns/is_after"); | ||
const dateSubHours = require("date-fns/sub_hours"); | ||
const fs = require("fs-extra"); | ||
const path = require("path"); | ||
const util_1 = require("../util"); | ||
const debug = require('debug')('cli:updater'); | ||
function timestamp(msg) { | ||
return `[${new Date().toISOString()}] ${msg}`; | ||
} | ||
async function mtime(f) { | ||
const { mtime } = await fs.stat(f); | ||
return mtime; | ||
} | ||
exports.init = async function (opts) { | ||
cli_ux_1.default.config.errlog = opts.config.errlog; | ||
if (opts.id === 'update') | ||
return; | ||
const updater = new __1.Updater(opts.config); | ||
await updater.autoupdate(); | ||
cli_ux_1.default.config.errlog = opts.config.errlog; | ||
const binPath = this.config.scopedEnvVar('CLI_BINPATH') || this.config.bin; | ||
const lastrunfile = path.join(this.config.cacheDir, 'lastrun'); | ||
const autoupdatefile = path.join(this.config.cacheDir, 'autoupdate'); | ||
const autoupdatelogfile = path.join(this.config.cacheDir, 'autoupdate.log'); | ||
const clientRoot = path.join(this.config.dataDir, 'client'); | ||
const autoupdateEnv = Object.assign({}, process.env, { [this.config.scopedEnvVarKey('TIMESTAMPS')]: '1', [this.config.scopedEnvVarKey('SKIP_ANALYTICS')]: '1' }); | ||
async function autoupdateNeeded() { | ||
try { | ||
const m = await mtime(autoupdatefile); | ||
return dateIsAfter(m, dateSubHours(new Date(), 5)); | ||
} | ||
catch (err) { | ||
if (err.code !== 'ENOENT') | ||
cli_ux_1.default.error(err.stack); | ||
if (global.testing) | ||
return false; | ||
debug('autoupdate ENOENT'); | ||
return true; | ||
} | ||
} | ||
await util_1.touch(lastrunfile); | ||
const clientDir = path.join(clientRoot, this.config.version); | ||
if (await fs.pathExists(clientDir)) { | ||
await util_1.touch(clientDir); | ||
} | ||
if (!await autoupdateNeeded()) | ||
return; | ||
debug('autoupdate running'); | ||
await fs.outputFile(autoupdatefile, ''); | ||
debug(`spawning autoupdate on ${binPath}`); | ||
let fd = await fs.open(autoupdatelogfile, 'a'); | ||
// @ts-ignore | ||
fs.write(fd, timestamp(`starting \`${binPath} update --autoupdate\` from ${process.argv.slice(1, 3).join(' ')}\n`)); | ||
spawn(binPath, ['update', '--autoupdate'], { | ||
detached: !this.config.windows, | ||
stdio: ['ignore', fd, fd], | ||
env: autoupdateEnv, | ||
}) | ||
.on('error', (e) => process.emitWarning(e)) | ||
.unref(); | ||
}; |
import * as Config from '@oclif/config'; | ||
export interface IVersion { | ||
version: string; | ||
channel: string; | ||
message?: string; | ||
} | ||
export interface IManifest { | ||
version: string; | ||
channel: string; | ||
sha256gz: string; | ||
priority?: number; | ||
} | ||
export declare class Updater { | ||
export declare function fetchUpdater(config: Config.IConfig): Updater; | ||
export declare abstract class Updater { | ||
config: Config.IConfig; | ||
@@ -18,29 +8,16 @@ constructor(config: Config.IConfig); | ||
readonly reexecBin: string | undefined; | ||
readonly name: string; | ||
readonly autoupdatefile: string; | ||
readonly autoupdatelogfile: string; | ||
readonly versionFile: string; | ||
readonly lastrunfile: string; | ||
private readonly clientRoot; | ||
private readonly clientBin; | ||
private readonly binPath; | ||
private readonly s3Host; | ||
s3url(channel: string, p: string): string; | ||
fetchManifest(channel: string): Promise<IManifest>; | ||
fetchVersion(download: boolean): Promise<IVersion>; | ||
warnIfUpdateAvailable(): Promise<void>; | ||
autoupdate(force?: boolean): Promise<void>; | ||
update(manifest: IManifest): Promise<void>; | ||
update({version, url, sha256, channel}: { | ||
url: string; | ||
version: string; | ||
sha256?: string; | ||
channel?: string; | ||
}): Promise<void>; | ||
tidy(): Promise<void>; | ||
private extract(stream, dir, sha); | ||
private base(manifest); | ||
private autoupdateNeeded(); | ||
readonly timestampEnvVar: string; | ||
readonly skipAnalyticsEnvVar: string; | ||
readonly autoupdateEnv: { | ||
[k: string]: string | undefined; | ||
}; | ||
private reexecUpdate(); | ||
private _createBin(manifest); | ||
private _catch(fn); | ||
abstract needsUpdate(channel: string): Promise<boolean>; | ||
protected base(version: string): string; | ||
private extract(stream, dir, sha?); | ||
private reexec(); | ||
private _createBin(version); | ||
} |
240
lib/index.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const color_1 = require("@heroku-cli/color"); | ||
const cli_ux_1 = require("cli-ux"); | ||
@@ -7,3 +8,2 @@ const spawn = require("cross-spawn"); | ||
const dateSubDays = require("date-fns/sub_days"); | ||
const dateSubHours = require("date-fns/sub_hours"); | ||
const fs = require("fs-extra"); | ||
@@ -13,13 +13,15 @@ const path = require("path"); | ||
const debug = require('debug')('cli:updater'); | ||
async function mtime(f) { | ||
const { mtime } = await fs.stat(f); | ||
return mtime; | ||
function fetchUpdater(config) { | ||
switch (config.pjson.oclif.autoupdate) { | ||
case 'github': | ||
return new (require('./github').GithubUpdater)(config); | ||
case 's3': | ||
return new (require('./s3').S3Updater)(config); | ||
} | ||
throw new Error('oclif.autoupdate must be set to "github" or "s3"'); | ||
} | ||
function timestamp(msg) { | ||
return `[${new Date().toISOString()}] ${msg}`; | ||
} | ||
exports.fetchUpdater = fetchUpdater; | ||
class Updater { | ||
constructor(config) { | ||
this.config = config; | ||
this.config = config; | ||
} | ||
@@ -35,17 +37,2 @@ get channel() { | ||
} | ||
get name() { | ||
return this.config.name === '@oclif/plugin-update' ? 'heroku-cli' : this.config.name; | ||
} | ||
get autoupdatefile() { | ||
return path.join(this.config.cacheDir, 'autoupdate'); | ||
} | ||
get autoupdatelogfile() { | ||
return path.join(this.config.cacheDir, 'autoupdate.log'); | ||
} | ||
get versionFile() { | ||
return path.join(this.config.cacheDir, `${this.channel}.version`); | ||
} | ||
get lastrunfile() { | ||
return path.join(this.config.cacheDir, 'lastrun'); | ||
} | ||
get clientRoot() { | ||
@@ -58,99 +45,14 @@ return path.join(this.config.dataDir, 'client'); | ||
} | ||
get binPath() { | ||
return this.reexecBin || this.config.bin; | ||
} | ||
get s3Host() { | ||
const pjson = this.config.pjson.oclif; | ||
return (pjson.s3 && pjson.s3.host) || this.config.scopedEnvVar('S3_HOST'); | ||
} | ||
s3url(channel, p) { | ||
if (!this.s3Host) | ||
throw new Error('S3 host not defined'); | ||
return `https://${this.s3Host}/${this.name}/channels/${channel}/${p}`; | ||
} | ||
async fetchManifest(channel) { | ||
const http = require('http-call').HTTP; | ||
try { | ||
let { body } = await http.get(this.s3url(channel, `${this.config.platform}-${this.config.arch}`)); | ||
return body; | ||
} | ||
catch (err) { | ||
if (err.statusCode === 403) | ||
throw new Error(`HTTP 403: Invalid channel ${channel}`); | ||
throw err; | ||
} | ||
} | ||
async fetchVersion(download) { | ||
const http = require('http-call').HTTP; | ||
let v; | ||
try { | ||
if (!download) | ||
v = await fs.readJSON(this.versionFile); | ||
} | ||
catch (err) { | ||
if (err.code !== 'ENOENT') | ||
throw err; | ||
} | ||
if (!v) { | ||
debug('fetching latest %s version', this.channel); | ||
let { body } = await http.get(this.s3url(this.channel, 'version')); | ||
v = body; | ||
await this._catch(() => fs.outputJSON(this.versionFile, v)); | ||
} | ||
return v; | ||
} | ||
async warnIfUpdateAvailable() { | ||
await this._catch(async () => { | ||
if (!this.s3Host) | ||
return; | ||
let v = await this.fetchVersion(false); | ||
if (util_1.minorVersionGreater(this.config.version, v.version)) { | ||
cli_ux_1.cli.warn(`${this.name}: update available from ${this.config.version} to ${v.version}`); | ||
} | ||
if (v.message) { | ||
cli_ux_1.cli.warn(`${this.name}: ${v.message}`); | ||
} | ||
}); | ||
} | ||
async autoupdate(force = false) { | ||
try { | ||
await util_1.touch(this.lastrunfile); | ||
const clientDir = path.join(this.clientRoot, this.config.version); | ||
if (await fs.pathExists(clientDir)) { | ||
await util_1.touch(clientDir); | ||
} | ||
await this.warnIfUpdateAvailable(); | ||
if (!force && !await this.autoupdateNeeded()) | ||
return; | ||
debug('autoupdate running'); | ||
await fs.outputFile(this.autoupdatefile, ''); | ||
debug(`spawning autoupdate on ${this.binPath}`); | ||
let fd = await fs.open(this.autoupdatelogfile, 'a'); | ||
// @ts-ignore | ||
fs.write(fd, timestamp(`starting \`${this.binPath} update --autoupdate\` from ${process.argv.slice(1, 3).join(' ')}\n`)); | ||
spawn(this.binPath, ['update', '--autoupdate'], { | ||
detached: !this.config.windows, | ||
stdio: ['ignore', fd, fd], | ||
env: this.autoupdateEnv, | ||
}) | ||
.on('error', (e) => process.emitWarning(e)) | ||
.unref(); | ||
} | ||
catch (e) { | ||
process.emitWarning(e); | ||
} | ||
} | ||
async update(manifest) { | ||
async update({ version, url, sha256, channel }) { | ||
if (!channel) | ||
channel = 'stable'; | ||
cli_ux_1.cli.action.start(`${this.config.name}: Updating CLI from ${color_1.default.green(this.config.version)} to ${color_1.default.green(version)}${channel === 'stable' ? '' : ' (' + color_1.default.yellow(channel) + ')'}`); | ||
const _ = require('lodash'); | ||
const http = require('http-call').HTTP; | ||
const filesize = require('filesize'); | ||
let base = this.base(manifest); | ||
const output = path.join(this.clientRoot, manifest.version); | ||
const tmp = path.join(this.clientRoot, base); | ||
if (!this.s3Host) | ||
throw new Error('S3 host not defined'); | ||
let url = `https://${this.s3Host}/${this.name}/channels/${manifest.channel}/${base}.tar.gz`; | ||
const output = path.join(this.clientRoot, version); | ||
const tmp = path.join(this.clientRoot, this.config.bin); | ||
let { response: stream } = await http.stream(url); | ||
await fs.emptyDir(tmp); | ||
let extraction = this.extract(stream, this.clientRoot, manifest.sha256gz); | ||
let extraction = this.extract(stream, this.clientRoot, sha256); | ||
// TODO: use cli.action.type | ||
@@ -177,4 +79,4 @@ if (cli_ux_1.cli.action.frames) { | ||
await util_1.touch(output); | ||
await this._createBin(manifest); | ||
await this.reexecUpdate(); | ||
await this._createBin(version); | ||
await this.reexec(); | ||
} | ||
@@ -205,2 +107,5 @@ async tidy() { | ||
} | ||
base(version) { | ||
return `${this.config.bin}-v${version}-${this.config.platform}-${this.config.arch}`; | ||
} | ||
extract(stream, dir, sha) { | ||
@@ -223,15 +128,20 @@ const zlib = require('zlib'); | ||
}; | ||
let hasher = crypto.createHash('sha256'); | ||
stream.on('error', fail); | ||
stream.on('data', d => hasher.update(d)); | ||
stream.on('end', () => { | ||
let shasum = hasher.digest('hex'); | ||
if (sha === shasum) { | ||
shaValidated = true; | ||
check(); | ||
} | ||
else { | ||
reject(new Error(`SHA mismatch: expected ${shasum} to be ${sha}`)); | ||
} | ||
}); | ||
if (sha) { | ||
let hasher = crypto.createHash('sha256'); | ||
stream.on('error', fail); | ||
stream.on('data', d => hasher.update(d)); | ||
stream.on('end', () => { | ||
let shasum = hasher.digest('hex'); | ||
if (sha === shasum) { | ||
shaValidated = true; | ||
check(); | ||
} | ||
else { | ||
reject(new Error(`SHA mismatch: expected ${shasum} to be ${sha}`)); | ||
} | ||
}); | ||
} | ||
else { | ||
shaValidated = true; | ||
} | ||
let ignore = (_, header) => { | ||
@@ -241,3 +151,3 @@ switch (header.type) { | ||
case 'file': | ||
if (process.env.CLI_ENGINE_DEBUG_UPDATE_FILES) | ||
if (process.env.OCLIF_DEBUG_UPDATE_FILES) | ||
debug(header.name); | ||
@@ -262,32 +172,3 @@ return false; | ||
} | ||
base(manifest) { | ||
return `${this.name}-v${manifest.version}-${this.config.platform}-${this.config.arch}`; | ||
} | ||
async autoupdateNeeded() { | ||
try { | ||
const m = await mtime(this.autoupdatefile); | ||
return dateIsAfter(m, dateSubHours(new Date(), 5)); | ||
} | ||
catch (err) { | ||
if (err.code !== 'ENOENT') | ||
cli_ux_1.cli.error(err.stack); | ||
if (global.testing) | ||
return false; | ||
debug('autoupdate ENOENT'); | ||
return true; | ||
} | ||
} | ||
get timestampEnvVar() { | ||
// TODO: use function from @cli-engine/config | ||
let bin = this.config.bin.replace('-', '_').toUpperCase(); | ||
return `${bin}_TIMESTAMPS`; | ||
} | ||
get skipAnalyticsEnvVar() { | ||
let bin = this.config.bin.replace('-', '_').toUpperCase(); | ||
return `${bin}_SKIP_ANALYTICS`; | ||
} | ||
get autoupdateEnv() { | ||
return Object.assign({}, process.env, { [this.timestampEnvVar]: '1', [this.skipAnalyticsEnvVar]: '1' }); | ||
} | ||
async reexecUpdate() { | ||
async reexec() { | ||
cli_ux_1.cli.action.stop(); | ||
@@ -311,25 +192,34 @@ return new Promise((_, reject) => { | ||
} | ||
async _createBin(manifest) { | ||
async _createBin(version) { | ||
let dst = this.clientBin; | ||
if (this.config.windows) { | ||
let body = `@echo off | ||
"%~dp0\\..\\${manifest.version}\\bin\\${this.config.bin}.cmd" %* | ||
"%~dp0\\..\\${version}\\bin\\${this.config.bin}.cmd" %* | ||
`; | ||
await fs.outputFile(dst, body); | ||
return; | ||
} | ||
let src = path.join('..', manifest.version, 'bin', this.config.bin); | ||
await fs.mkdirp(path.dirname(dst)); | ||
await fs.remove(dst); | ||
await fs.symlink(src, dst); | ||
} | ||
async _catch(fn) { | ||
try { | ||
return await Promise.resolve(fn()); | ||
else { | ||
let body = `#!/usr/bin/env bash | ||
set -e | ||
get_script_dir () { | ||
SOURCE="\${BASH_SOURCE[0]}" | ||
# While $SOURCE is a symlink, resolve it | ||
while [ -h "$SOURCE" ]; do | ||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" | ||
SOURCE="$( readlink "$SOURCE" )" | ||
# If $SOURCE was a relative symlink (so no "/" as prefix, need to resolve it relative to the symlink base directory | ||
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" | ||
done | ||
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" | ||
echo "$DIR" | ||
} | ||
DIR=$(get_script_dir) | ||
HEROKU_CLI_REDIRECTED=1 "$DIR/../${version}/bin/${this.config.bin}" "$@" | ||
`; | ||
await fs.remove(dst); | ||
await fs.outputFile(dst, body); | ||
await fs.chmod(dst, 0o755); | ||
} | ||
catch (err) { | ||
debug(err); | ||
} | ||
} | ||
} | ||
exports.Updater = Updater; |
/// <reference types="node" /> | ||
import * as fs from 'fs-extra'; | ||
export declare function minorVersionGreater(fromString: string, toString: string): boolean; | ||
export declare function touch(p: string): Promise<void>; | ||
@@ -5,0 +4,0 @@ export declare function ls(dir: string): Promise<{ |
@@ -5,13 +5,2 @@ "use strict"; | ||
const path = require("path"); | ||
function minorVersionGreater(fromString, toString) { | ||
const semver = require('semver'); | ||
const from = semver.parse(fromString); | ||
const to = semver.parse(toString); | ||
if (from.major < to.major) | ||
return true; | ||
if (from.major === to.major && from.minor < to.minor) | ||
return true; | ||
return false; | ||
} | ||
exports.minorVersionGreater = minorVersionGreater; | ||
async function touch(p) { | ||
@@ -18,0 +7,0 @@ try { |
{ | ||
"name": "@oclif/plugin-update", | ||
"version": "1.0.5", | ||
"version": "1.1.0", | ||
"author": "Jeff Dickey @jdxcode", | ||
@@ -9,3 +9,3 @@ "bugs": "https://github.com/oclif/plugin-update/issues", | ||
"@oclif/command": "^1.4.7", | ||
"@oclif/config": "^1.3.66", | ||
"@oclif/config": "^1.3.67", | ||
"@oclif/errors": "^1.0.3", | ||
@@ -26,3 +26,3 @@ "@types/semver": "^5.5.0", | ||
"devDependencies": { | ||
"@oclif/dev-cli": "^1.7.2", | ||
"@oclif/dev-cli": "^1.7.3", | ||
"@oclif/plugin-help": "^1.2.3", | ||
@@ -59,7 +59,5 @@ "@oclif/test": "^1.0.4", | ||
"oclif": { | ||
"autoupdate": "github", | ||
"commands": "./lib/commands", | ||
"bin": "oclif-example", | ||
"s3": { | ||
"host": "cli-assets.heroku.com" | ||
}, | ||
"hooks": { | ||
@@ -66,0 +64,0 @@ "init": "./lib/hooks/init" |
@@ -24,3 +24,3 @@ @oclif/plugin-update | ||
$ oclif-example (-v|--version|version) | ||
@oclif/plugin-update/1.0.5 linux-x64 node-v9.11.1 | ||
@oclif/plugin-update/1.1.0 linux-x64 node-v9.11.1 | ||
$ oclif-example --help [COMMAND] | ||
@@ -45,3 +45,3 @@ USAGE | ||
_See code: [src/commands/update.ts](https://github.com/oclif/plugin-update/blob/v1.0.5/src/commands/update.ts)_ | ||
_See code: [src/commands/update.ts](https://github.com/oclif/plugin-update/blob/v1.1.0/src/commands/update.ts)_ | ||
<!-- commandsstop --> |
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
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
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
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
17
25427
529
9
Updated@oclif/config@^1.3.67