From 1697cc32a335b0510725621be6023cf2ec7cc497 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Tue, 26 Mar 2019 16:21:03 -0400 Subject: [PATCH] Use commander instead of oclif --- packages/server/package.json | 5 +- packages/server/src/cli.ts | 484 ++++++++++---------- packages/server/src/vscode/bootstrapFork.ts | 4 +- packages/server/yarn.lock | 168 +------ 4 files changed, 265 insertions(+), 396 deletions(-) diff --git a/packages/server/package.json b/packages/server/package.json index fea167c9..797c24d4 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -10,9 +10,7 @@ }, "dependencies": { "@coder/nbin": "^1.0.0", - "@oclif/config": "^1.10.4", - "@oclif/errors": "^1.2.2", - "@oclif/plugin-help": "^2.1.4", + "commander": "^2.19.0", "express": "^4.16.4", "express-static-gzip": "^1.1.3", "httpolyglot": "^0.1.2", @@ -25,6 +23,7 @@ "xhr2": "^0.1.4" }, "devDependencies": { + "@types/commander": "^2.12.2", "@types/express": "^4.16.0", "@types/fs-extra": "^5.0.4", "@types/mime-types": "^2.1.0", diff --git a/packages/server/src/cli.ts b/packages/server/src/cli.ts index e2a6ea9f..e5ccc3c5 100644 --- a/packages/server/src/cli.ts +++ b/packages/server/src/cli.ts @@ -1,6 +1,5 @@ import { field, logger } from "@coder/logger"; import { ServerMessage, SharedProcessActiveMessage } from "@coder/protocol/src/proto"; -import { Command, flags } from "@oclif/command"; import { ChildProcess, fork, ForkOptions, spawn } from "child_process"; import { randomFillSync } from "crypto"; import * as fs from "fs"; @@ -15,244 +14,253 @@ import { forkModule, requireFork, requireModule } from "./vscode/bootstrapFork"; import { SharedProcess, SharedProcessState } from "./vscode/sharedProcess"; import opn = require("opn"); -export class Entry extends Command { - public static description = "Start your own self-hosted browser-accessible VS Code"; - public static flags = { - cert: flags.string(), - "cert-key": flags.string(), - "data-dir": flags.string({ char: "d" }), - help: flags.help(), - host: flags.string({ char: "h", default: "0.0.0.0" }), - open: flags.boolean({ char: "o", description: "Open in browser on startup" }), - port: flags.integer({ char: "p", default: 8443, description: "Port to bind on" }), - version: flags.version({ char: "v" }), - "no-auth": flags.boolean({ default: false }), - "allow-http": flags.boolean({ default: false }), - password: flags.string(), +import * as commander from "commander"; - // Dev flags - "bootstrap-fork": flags.string({ hidden: true }), - "fork": flags.string({ hidden: true }), +commander.version(process.env.VERSION || "development") + .name("code-server") + .description("Run VS Code on a remote server.") + .option("--cert") + .option("--cert-key") + .option("-d, --data-dir ", "Customize where user-data is stored.") + .option("-h, --host ", "Customize the hostname.", "0.0.0.0") + .option("-o, --open", "Open in the browser on startup.", false) + .option("-p, --port ", "Port to bind on.", 8443) + .option("-N, --no-auth", "Start without requiring authentication.", undefined) + .option("-H, --allow-http", "Allow http connections.", false) + .option("-P, --password ", "Specify a password for authentication.") + .option("--bootstrap-fork ", "Used for development. Never set.") + .option("--fork ", "Used for development. Never set.") + .option("--extra-args ", "Used for development. Never set.") + .arguments("Specify working directory.") + .parse(process.argv); - args: flags.string({ hidden: true }), - }; - public static args = [{ - name: "workdir", - description: "Specify working dir", - default: (): string => process.cwd(), - }]; - - public async run(): Promise { - Error.stackTraceLimit = Infinity; - - if (isCli) { - require("nbin").shimNativeFs("/home/kyle/node/coder/code-server/packages/server"); - } - - const { args, flags } = this.parse(Entry); - const dataDir = path.resolve(flags["data-dir"] || path.join(dataHome, "code-server")); - const workingDir = path.resolve(args["workdir"]); - - if (!fs.existsSync(dataDir)) { - const oldDataDir = path.resolve(path.join(os.homedir(), ".code-server")); - if (fs.existsSync(oldDataDir)) { - await fse.move(oldDataDir, dataDir); - logger.info(`Moved data directory from ${oldDataDir} to ${dataDir}`); - } - } - - await Promise.all([ - fse.mkdirp(cacheHome), - fse.mkdirp(dataDir), - fse.mkdirp(workingDir), - ]); - - setupNativeModules(dataDir); - const builtInExtensionsDir = path.resolve(buildDir || path.join(__dirname, ".."), "build/extensions"); - if (flags["bootstrap-fork"]) { - const modulePath = flags["bootstrap-fork"]; - if (!modulePath) { - logger.error("No module path specified to fork!"); - process.exit(1); - } - - ((flags.args ? JSON.parse(flags.args) : []) as string[]).forEach((arg, i) => { - // [0] contains the binary running the script (`node` for example) and - // [1] contains the script name, so the arguments come after that. - process.argv[i + 2] = arg; - }); - - return requireModule(modulePath, dataDir, builtInExtensionsDir); - } - - if (flags["fork"]) { - const modulePath = flags["fork"]; - - return requireFork(modulePath, JSON.parse(flags.args!), builtInExtensionsDir); - } - - const logDir = path.join(cacheHome, "code-server/logs", new Date().toISOString().replace(/[-:.TZ]/g, "")); - process.env.VSCODE_LOGS = logDir; - - const certPath = flags.cert ? path.resolve(flags.cert) : undefined; - const certKeyPath = flags["cert-key"] ? path.resolve(flags["cert-key"]) : undefined; - - if (certPath && !certKeyPath) { - logger.error("'--cert-key' flag is required when specifying a certificate!"); - process.exit(1); - } - - if (!certPath && certKeyPath) { - logger.error("'--cert' flag is required when specifying certificate key!"); - process.exit(1); - } - - let certData: Buffer | undefined; - let certKeyData: Buffer | undefined; - - if (typeof certPath !== "undefined" && typeof certKeyPath !== "undefined") { - try { - certData = fs.readFileSync(certPath); - } catch (ex) { - logger.error(`Failed to read certificate: ${ex.message}`); - process.exit(1); - } - - try { - certKeyData = fs.readFileSync(certKeyPath); - } catch (ex) { - logger.error(`Failed to read certificate key: ${ex.message}`); - process.exit(1); - } - } - - logger.info(`\u001B[1mcode-server ${process.env.VERSION ? `v${process.env.VERSION}` : "development"}`); - // TODO: fill in appropriate doc url - logger.info("Additional documentation: http://github.com/codercom/code-server"); - logger.info("Initializing", field("data-dir", dataDir), field("working-dir", workingDir), field("log-dir", logDir)); - const sharedProcess = new SharedProcess(dataDir, builtInExtensionsDir); - const sendSharedProcessReady = (socket: WebSocket): void => { - const active = new SharedProcessActiveMessage(); - active.setSocketPath(sharedProcess.socketPath); - active.setLogPath(logDir); - const serverMessage = new ServerMessage(); - serverMessage.setSharedProcessActive(active); - socket.send(serverMessage.serializeBinary()); - }; - sharedProcess.onState((event) => { - if (event.state === SharedProcessState.Ready) { - app.wss.clients.forEach((c) => sendSharedProcessReady(c)); - } - }); - - let password = flags.password; - if (!password) { - // Generate a random password with a length of 24. - const buffer = Buffer.alloc(12); - randomFillSync(buffer); - password = buffer.toString("hex"); - } - - const hasCustomHttps = certData && certKeyData; - const app = await createApp({ - allowHttp: flags["allow-http"], - bypassAuth: flags["no-auth"], - registerMiddleware: (app): void => { - app.use((req, res, next) => { - res.on("finish", () => { - logger.trace(`\u001B[1m${req.method} ${res.statusCode} \u001B[0m${req.url}`, field("host", req.hostname), field("ip", req.ip)); - }); - - next(); - }); - // If we're not running from the binary and we aren't serving the static - // pre-built version, use webpack to serve the web files. - if (!isCli && !serveStatic) { - const webpackConfig = require(path.resolve(__dirname, "..", "..", "web", "webpack.config.js")); - const compiler = require("webpack")(webpackConfig); - app.use(require("webpack-dev-middleware")(compiler, { - logger, - publicPath: webpackConfig.output.publicPath, - stats: webpackConfig.stats, - })); - app.use(require("webpack-hot-middleware")(compiler)); - } - }, - serverOptions: { - builtInExtensionsDirectory: builtInExtensionsDir, - dataDirectory: dataDir, - workingDirectory: workingDir, - cacheDirectory: cacheHome, - fork: (modulePath: string, args?: string[], options?: ForkOptions): ChildProcess => { - if (options && options.env && options.env.AMD_ENTRYPOINT) { - return forkModule(options.env.AMD_ENTRYPOINT, args, options, dataDir); - } - - if (isCli) { - return spawn(process.execPath, [path.join(buildDir, "out", "cli.js"), "--fork", modulePath, "--args", JSON.stringify(args), "--data-dir", dataDir], { - ...options, - stdio: [null, null, null, "ipc"], - }); - } else { - return fork(modulePath, args, options); - } - }, - }, - password, - httpsOptions: hasCustomHttps ? { - key: certKeyData, - cert: certData, - } : undefined, - }); - - logger.info("Starting webserver...", field("host", flags.host), field("port", flags.port)); - app.server.listen(flags.port, flags.host); - let clientId = 1; - app.wss.on("connection", (ws, req) => { - const id = clientId++; - - if (sharedProcess.state === SharedProcessState.Ready) { - sendSharedProcessReady(ws); - } - - logger.info(`WebSocket opened \u001B[0m${req.url}`, field("client", id), field("ip", req.socket.remoteAddress)); - - ws.on("close", (code) => { - logger.info(`WebSocket closed \u001B[0m${req.url}`, field("client", id), field("code", code)); - }); - }); - - if (!flags["cert-key"] && !flags.cert) { - logger.warn("No certificate specified. \u001B[1mThis could be insecure."); - // TODO: fill in appropriate doc url - logger.warn("Documentation on securing your setup: https://coder.com/docs"); - } - - if (!flags["no-auth"]) { - logger.info(" "); - logger.info(`Password:\u001B[1m ${password}`); - } else { - logger.warn("Launched without authentication."); - } - - const url = `http://localhost:${flags.port}/`; - logger.info(" "); - logger.info("Started (click the link below to open):"); - logger.info(url); - logger.info(" "); - - if (flags.open) { - try { - await opn(url); - } catch (e) { - logger.warn("Url couldn't be opened automatically.", field("url", url), field("exception", e)); - } - } - } +Error.stackTraceLimit = Infinity; +if (isCli) { + require("nbin").shimNativeFs(buildDir); } -Entry.run(undefined, { - root: buildDir || __dirname, - version: process.env.VERSION || "development", - //@ts-ignore -}).catch(require("@oclif/errors/handle")); +(async (): Promise => { + const args = commander.args; + const options = commander.opts() as { + noAuth: boolean; + readonly allowHttp: boolean; + readonly host: string; + readonly port: number; + + readonly dataDir?: string; + readonly password?: string; + readonly open?: boolean; + readonly cert?: string; + readonly certKey?: string; + + readonly bootstrapFork?: string; + readonly fork?: string; + readonly extraArgs?: string; + }; + + // Commander has an exception for `--no` prefixes. Here we'll adjust that. + // tslint:disable-next-line:no-any + const noAuthValue = (commander as any).auth; + options.noAuth = !noAuthValue; + + const dataDir = path.resolve(options.dataDir || path.join(dataHome, "code-server")); + const workingDir = path.resolve(args[0] || process.cwd()); + + if (!fs.existsSync(dataDir)) { + const oldDataDir = path.resolve(path.join(os.homedir(), ".code-server")); + if (fs.existsSync(oldDataDir)) { + await fse.move(oldDataDir, dataDir); + logger.info(`Moved data directory from ${oldDataDir} to ${dataDir}`); + } + } + + await Promise.all([ + fse.mkdirp(cacheHome), + fse.mkdirp(dataDir), + fse.mkdirp(workingDir), + ]); + + setupNativeModules(dataDir); + const builtInExtensionsDir = path.resolve(buildDir || path.join(__dirname, ".."), "build/extensions"); + if (options.bootstrapFork) { + const modulePath = options.bootstrapFork; + if (!modulePath) { + logger.error("No module path specified to fork!"); + process.exit(1); + } + + ((options.extraArgs ? JSON.parse(options.extraArgs) : []) as string[]).forEach((arg, i) => { + // [0] contains the binary running the script (`node` for example) and + // [1] contains the script name, so the arguments come after that. + process.argv[i + 2] = arg; + }); + + return requireModule(modulePath, dataDir, builtInExtensionsDir); + } + + if (options.fork) { + const modulePath = options.fork; + + return requireFork(modulePath, JSON.parse(options.extraArgs!), builtInExtensionsDir); + } + + const logDir = path.join(cacheHome, "code-server/logs", new Date().toISOString().replace(/[-:.TZ]/g, "")); + process.env.VSCODE_LOGS = logDir; + + const certPath = options.cert ? path.resolve(options.cert) : undefined; + const certKeyPath = options.certKey ? path.resolve(options.certKey) : undefined; + + if (certPath && !certKeyPath) { + logger.error("'--cert-key' flag is required when specifying a certificate!"); + process.exit(1); + } + + if (!certPath && certKeyPath) { + logger.error("'--cert' flag is required when specifying certificate key!"); + process.exit(1); + } + + let certData: Buffer | undefined; + let certKeyData: Buffer | undefined; + + if (typeof certPath !== "undefined" && typeof certKeyPath !== "undefined") { + try { + certData = fs.readFileSync(certPath); + } catch (ex) { + logger.error(`Failed to read certificate: ${ex.message}`); + process.exit(1); + } + + try { + certKeyData = fs.readFileSync(certKeyPath); + } catch (ex) { + logger.error(`Failed to read certificate key: ${ex.message}`); + process.exit(1); + } + } + + logger.info(`\u001B[1mcode-server ${process.env.VERSION ? `v${process.env.VERSION}` : "development"}`); + // TODO: fill in appropriate doc url + logger.info("Additional documentation: http://github.com/codercom/code-server"); + logger.info("Initializing", field("data-dir", dataDir), field("working-dir", workingDir), field("log-dir", logDir)); + const sharedProcess = new SharedProcess(dataDir, builtInExtensionsDir); + const sendSharedProcessReady = (socket: WebSocket): void => { + const active = new SharedProcessActiveMessage(); + active.setSocketPath(sharedProcess.socketPath); + active.setLogPath(logDir); + const serverMessage = new ServerMessage(); + serverMessage.setSharedProcessActive(active); + socket.send(serverMessage.serializeBinary()); + }; + sharedProcess.onState((event) => { + if (event.state === SharedProcessState.Ready) { + app.wss.clients.forEach((c) => sendSharedProcessReady(c)); + } + }); + + let password = options.password; + if (!password) { + // Generate a random password with a length of 24. + const buffer = Buffer.alloc(12); + randomFillSync(buffer); + password = buffer.toString("hex"); + } + + const hasCustomHttps = certData && certKeyData; + const app = await createApp({ + allowHttp: options.allowHttp, + bypassAuth: options.noAuth, + registerMiddleware: (app): void => { + app.use((req, res, next) => { + res.on("finish", () => { + logger.trace(`\u001B[1m${req.method} ${res.statusCode} \u001B[0m${req.url}`, field("host", req.hostname), field("ip", req.ip)); + }); + + next(); + }); + // If we're not running from the binary and we aren't serving the static + // pre-built version, use webpack to serve the web files. + if (!isCli && !serveStatic) { + const webpackConfig = require(path.resolve(__dirname, "..", "..", "web", "webpack.config.js")); + const compiler = require("webpack")(webpackConfig); + app.use(require("webpack-dev-middleware")(compiler, { + logger, + publicPath: webpackConfig.output.publicPath, + stats: webpackConfig.stats, + })); + app.use(require("webpack-hot-middleware")(compiler)); + } + }, + serverOptions: { + builtInExtensionsDirectory: builtInExtensionsDir, + dataDirectory: dataDir, + workingDirectory: workingDir, + cacheDirectory: cacheHome, + fork: (modulePath: string, args?: string[], options?: ForkOptions): ChildProcess => { + if (options && options.env && options.env.AMD_ENTRYPOINT) { + return forkModule(options.env.AMD_ENTRYPOINT, args, options, dataDir); + } + + if (isCli) { + return spawn(process.execPath, [path.join(buildDir, "out", "cli.js"), "--fork", modulePath, "--extra-args", JSON.stringify(args), "--data-dir", dataDir], { + ...options, + stdio: [null, null, null, "ipc"], + }); + } else { + return fork(modulePath, args, options); + } + }, + }, + password, + httpsOptions: hasCustomHttps ? { + key: certKeyData, + cert: certData, + } : undefined, + }); + + logger.info("Starting webserver...", field("host", options.host), field("port", options.port)); + app.server.listen(options.port, options.host); + let clientId = 1; + app.wss.on("connection", (ws, req) => { + const id = clientId++; + + if (sharedProcess.state === SharedProcessState.Ready) { + sendSharedProcessReady(ws); + } + + logger.info(`WebSocket opened \u001B[0m${req.url}`, field("client", id), field("ip", req.socket.remoteAddress)); + + ws.on("close", (code) => { + logger.info(`WebSocket closed \u001B[0m${req.url}`, field("client", id), field("code", code)); + }); + }); + + if (!options.certKey && !options.cert) { + logger.warn("No certificate specified. \u001B[1mThis could be insecure."); + // TODO: fill in appropriate doc url + logger.warn("Documentation on securing your setup: https://coder.com/docs"); + } + + if (!options.noAuth) { + logger.info(" "); + logger.info(`Password:\u001B[1m ${password}`); + } else { + logger.warn("Launched without authentication."); + } + + const url = `http://localhost:${options.port}/`; + logger.info(" "); + logger.info("Started (click the link below to open):"); + logger.info(url); + logger.info(" "); + + if (options.open) { + try { + await opn(url); + } catch (e) { + logger.warn("Url couldn't be opened automatically.", field("url", url), field("exception", e)); + } + } +})().catch((ex) => { + logger.error(ex); +}); diff --git a/packages/server/src/vscode/bootstrapFork.ts b/packages/server/src/vscode/bootstrapFork.ts index 5b2349ff..c7cb5811 100644 --- a/packages/server/src/vscode/bootstrapFork.ts +++ b/packages/server/src/vscode/bootstrapFork.ts @@ -105,7 +105,7 @@ export const requireModule = (modulePath: string, dataDir: string, builtInExtens */ // tslint:disable-next-line:no-any (cp).fork = (modulePath: string, args: ReadonlyArray = [], options?: cp.ForkOptions): cp.ChildProcess => { - return cp.spawn(process.execPath, [path.join(buildDir, "out", "cli.js"), "--fork", modulePath, "--args", JSON.stringify(args), "--data-dir", dataDir], { + return cp.spawn(process.execPath, [path.join(buildDir, "out", "cli.js"), "--fork", modulePath, "--extra-args", JSON.stringify(args), "--data-dir", dataDir], { ...options, stdio: [null, null, null, "ipc"], }); @@ -141,7 +141,7 @@ export const forkModule = (modulePath: string, args?: string[], options?: cp.For } const forkArgs = ["--bootstrap-fork", modulePath]; if (args) { - forkArgs.push("--args", JSON.stringify(args)); + forkArgs.push("--extra-args", JSON.stringify(args)); } if (dataDir) { forkArgs.push("--data-dir", dataDir); diff --git a/packages/server/yarn.lock b/packages/server/yarn.lock index d07319f8..fc0262d3 100644 --- a/packages/server/yarn.lock +++ b/packages/server/yarn.lock @@ -18,63 +18,6 @@ node-fetch "^2.3.0" ora "^3.2.0" -"@oclif/command@^1.5.4": - version "1.5.8" - resolved "https://registry.yarnpkg.com/@oclif/command/-/command-1.5.8.tgz#cd09d4f3183123548cb25d1b12b92e41277ac3e9" - integrity sha512-+Xuqp7by9jmB+GvR2r450wUXkCpZVdeOXQD0mLSEm3h+Mxhp0NPHuhzXZQvLI0/2fXR+cmJLv1CfpaCYaflL/g== - dependencies: - "@oclif/errors" "^1.2.2" - "@oclif/parser" "^3.7.2" - debug "^4.1.0" - semver "^5.6.0" - -"@oclif/config@^1.10.4": - version "1.10.4" - resolved "https://registry.yarnpkg.com/@oclif/config/-/config-1.10.4.tgz#7205c8ba4f90f02a73a3b016bbf4779bf33bc37d" - integrity sha512-anRUBTVhW5B0dRxogOtQPbIFIaqiABc8aQfEk4cBZBUBHF1YHWyxHxaKydi/APNuLX9xcdy2GzPXcBV/V1JIzw== - dependencies: - debug "^4.1.0" - tslib "^1.9.3" - -"@oclif/errors@^1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@oclif/errors/-/errors-1.2.2.tgz#9d8f269b15f13d70aa93316fed7bebc24688edc2" - integrity sha512-Eq8BFuJUQcbAPVofDxwdE0bL14inIiwt5EaKRVY9ZDIG11jwdXZqiQEECJx0VfnLyUZdYfRd/znDI/MytdJoKg== - dependencies: - clean-stack "^1.3.0" - fs-extra "^7.0.0" - indent-string "^3.2.0" - strip-ansi "^5.0.0" - wrap-ansi "^4.0.0" - -"@oclif/linewrap@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@oclif/linewrap/-/linewrap-1.0.0.tgz#aedcb64b479d4db7be24196384897b5000901d91" - integrity sha512-Ups2dShK52xXa8w6iBWLgcjPJWjais6KPJQq3gQ/88AY6BXoTX+MIGFPrWQO1KLMiQfoTpcLnUwloN4brrVUHw== - -"@oclif/parser@^3.7.2": - version "3.7.2" - resolved "https://registry.yarnpkg.com/@oclif/parser/-/parser-3.7.2.tgz#b06c73377a1f027f10444109a8a4a6cc31ffd8ba" - integrity sha512-ssYXztaf9TuOGCJQOYMg62L1Q4y2lB4wZORWng+Iy0ckP2A6IUnQy97V8YjAJkkohYZOu3Mga8LGfQcf+xdIIw== - dependencies: - "@oclif/linewrap" "^1.0.0" - chalk "^2.4.1" - tslib "^1.9.3" - -"@oclif/plugin-help@^2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@oclif/plugin-help/-/plugin-help-2.1.4.tgz#b530fa3147d5ae91ba9c84d085f53a829b2914dc" - integrity sha512-wG4eR/UxYangQlyn4XvslVV4wpBNQrEC/PvRibQq+0jNop/7zfK3jdWuK5PVB0mxZfhPwBSMZzV/3ur6DN+Bbg== - dependencies: - "@oclif/command" "^1.5.4" - chalk "^2.4.1" - indent-string "^3.2.0" - lodash.template "^4.4.0" - string-width "^2.1.1" - strip-ansi "^5.0.0" - widest-line "^2.0.1" - wrap-ansi "^4.0.0" - "@types/body-parser@*": version "1.17.0" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" @@ -83,6 +26,13 @@ "@types/connect" "*" "@types/node" "*" +"@types/commander@^2.12.2": + version "2.12.2" + resolved "https://registry.yarnpkg.com/@types/commander/-/commander-2.12.2.tgz#183041a23842d4281478fa5d23c5ca78e6fd08ae" + integrity sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q== + dependencies: + commander "*" + "@types/connect@*": version "3.4.32" resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.32.tgz#aa0e9616b9435ccad02bc52b5b454ffc2c70ba28" @@ -193,17 +143,12 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - ansi-regex@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.0.0.tgz#70de791edf021404c3fd615aa89118ae0432e5a9" integrity sha512-iB5Dda8t/UqpPI/IjsejXu5jOGDrzn41wJyljwPH65VCIbk6+1BzFIMJGFwTNrYXT1CrD+B4l19U7awiQ8rk7w== -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== @@ -292,7 +237,7 @@ bytes@3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= -chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -306,11 +251,6 @@ charenc@~0.0.1: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -clean-stack@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-1.3.0.tgz#9e821501ae979986c46b1d66d2d432db2fd4ae31" - integrity sha1-noIVAa6XmYbEax1m0tQy2y/UrjE= - cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -340,6 +280,11 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +commander@*, commander@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" + integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -391,13 +336,6 @@ debug@2.6.9: dependencies: ms "2.0.0" -debug@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - deepmerge@^2.0.1: version "2.2.1" resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.2.1.tgz#5d3ff22a01c00f645405a2fbc17d0778a1801170" @@ -561,7 +499,7 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -fs-extra@^7.0.0, fs-extra@^7.0.1: +fs-extra@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-7.0.1.tgz#4f189c44aa123b895f722804f55ea23eadc348e9" integrity sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw== @@ -636,11 +574,6 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" -indent-string@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" - integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= - inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -674,11 +607,6 @@ is-date-object@^1.0.1: resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - is-regex@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" @@ -732,26 +660,6 @@ loader-utils@^0.2.5, loader-utils@~0.2.2, loader-utils@~0.2.3, loader-utils@~0.2 json5 "^0.5.0" object-assign "^4.0.1" -lodash._reinterpolate@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" - integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= - -lodash.template@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.4.0.tgz#e73a0385c8355591746e020b99679c690e68fba0" - integrity sha1-5zoDhcg1VZF0bgILmWecaQ5o+6A= - dependencies: - lodash._reinterpolate "~3.0.0" - lodash.templatesettings "^4.0.0" - -lodash.templatesettings@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.1.0.tgz#2b4d4e95ba440d915ff08bc899e4553666713316" - integrity sha1-K01OlbpEDZFf8IvImeRVNmZxMxY= - dependencies: - lodash._reinterpolate "~3.0.0" - log-symbols@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -839,11 +747,6 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= -ms@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - negotiator@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.1.tgz#2b327184e8992101177b28563fb5e7102acd0ca9" @@ -1003,11 +906,6 @@ safe-compare@^1.1.4: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -semver@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" - integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== - send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" @@ -1089,21 +987,6 @@ string-replace-webpack-plugin@^0.1.3: file-loader "^0.8.1" style-loader "^0.8.3" -string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - strip-ansi@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.0.0.tgz#f78f68b5d0866c20b2c9b8c61b5298508dc8756f" @@ -1155,11 +1038,6 @@ tsconfig-paths@^3.7.0: minimist "^1.2.0" strip-bom "^3.0.0" -tslib@^1.9.3: - version "1.9.3" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" - integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== - type-is@~1.6.16: version "1.6.16" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.16.tgz#f89ce341541c672b25ee7ae3c73dee3b2be50194" @@ -1207,22 +1085,6 @@ which@^1.3.1: dependencies: isexe "^2.0.0" -widest-line@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" - integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== - dependencies: - string-width "^2.1.1" - -wrap-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-4.0.0.tgz#b3570d7c70156159a2d42be5cc942e957f7b1131" - integrity sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg== - dependencies: - ansi-styles "^3.2.0" - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"