Added CLI support for stand-alone (no sub-command) tools.
This commit is contained in:
parent
74dbc281ed
commit
b67b121239
@ -7,7 +7,7 @@ import { join as pathJoin } from "path";
|
|||||||
|
|
||||||
import { ethers } from 'ethers';
|
import { ethers } from 'ethers';
|
||||||
|
|
||||||
import { ArgParser, CLI, Plugin } from '../cli';
|
import { ArgParser, CLI, Help, Plugin } from '../cli';
|
||||||
import { header as Header, generate as generateTypeScript } from "../typescript";
|
import { header as Header, generate as generateTypeScript } from "../typescript";
|
||||||
import { compile, ContractCode } from "../solc";
|
import { compile, ContractCode } from "../solc";
|
||||||
|
|
||||||
@ -50,7 +50,11 @@ function walkFilenames(filenames: Array<string>): Array<string> {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
let cli = new CLI("generate");
|
let cli = new CLI(null, {
|
||||||
|
account: false,
|
||||||
|
provider: false,
|
||||||
|
transaction: false
|
||||||
|
});
|
||||||
|
|
||||||
class GeneratePlugin extends Plugin {
|
class GeneratePlugin extends Plugin {
|
||||||
|
|
||||||
@ -60,12 +64,39 @@ class GeneratePlugin extends Plugin {
|
|||||||
optimize: boolean;
|
optimize: boolean;
|
||||||
noBytecode: boolean;
|
noBytecode: boolean;
|
||||||
|
|
||||||
|
static getHelp(): Help {
|
||||||
|
return {
|
||||||
|
name: "FILENAME [ ... ]",
|
||||||
|
help: "Generates a TypeScript file of all Contracts. May specify folders."
|
||||||
|
};
|
||||||
|
}
|
||||||
|
static getOptionHelp(): Array<Help> {
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
name: "--output FILENAME",
|
||||||
|
help: "Write the output to FILENAME (default: stdout)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "--force",
|
||||||
|
help: "Overwrite files if they already exist"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "--no-optimize",
|
||||||
|
help: "Do not run the solc optimizer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "--no-bytecode",
|
||||||
|
help: "Do not include bytecode and Factory methods"
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
async prepareOptions(argParser: ArgParser): Promise<void> {
|
async prepareOptions(argParser: ArgParser): Promise<void> {
|
||||||
await super.prepareOptions(argParser);
|
await super.prepareOptions(argParser);
|
||||||
|
|
||||||
this.output = argParser.consumeOption("output");
|
this.output = argParser.consumeOption("output");
|
||||||
this.force = argParser.consumeFlag("force");
|
this.force = argParser.consumeFlag("force");
|
||||||
this.optimize = argParser.consumeFlag("no-optimize");
|
this.optimize = !argParser.consumeFlag("no-optimize");
|
||||||
this.noBytecode = argParser.consumeFlag("no-bytecode");
|
this.noBytecode = argParser.consumeFlag("no-bytecode");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,6 +152,6 @@ class GeneratePlugin extends Plugin {
|
|||||||
return Promise.resolve(null);
|
return Promise.resolve(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cli.addPlugin("generate", GeneratePlugin);
|
cli.setPlugin(GeneratePlugin);
|
||||||
|
|
||||||
cli.run(process.argv.slice(2))
|
cli.run(process.argv.slice(2))
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
import { basename } from "path";
|
||||||
|
|
||||||
import { ethers } from "ethers";
|
import { ethers } from "ethers";
|
||||||
import scrypt from "scrypt-js";
|
import scrypt from "scrypt-js";
|
||||||
|
|
||||||
import { getChoice, getPassword, getProgressBar } from "./prompt";
|
import { getChoice, getPassword, getProgressBar } from "./prompt";
|
||||||
|
|
||||||
|
import { version } from "./_version";
|
||||||
|
|
||||||
class UsageError extends Error { }
|
class UsageError extends Error { }
|
||||||
|
|
||||||
|
|
||||||
@ -473,7 +476,7 @@ export interface PluginType {
|
|||||||
getOptionHelp?: () => Array<Help>;
|
getOptionHelp?: () => Array<Help>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Plugin {
|
export abstract class Plugin {
|
||||||
network: ethers.providers.Network;
|
network: ethers.providers.Network;
|
||||||
provider: ethers.providers.Provider;
|
provider: ethers.providers.Provider;
|
||||||
|
|
||||||
@ -654,110 +657,212 @@ export class Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (address === ethers.constants.AddressZero && !allowZero) {
|
if (address === ethers.constants.AddressZero && !allowZero) {
|
||||||
this.throwError(message);
|
this.throwError(message || "cannot use the zero address");
|
||||||
}
|
}
|
||||||
|
|
||||||
return address;
|
return address;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dumps formatted data
|
||||||
|
dump(header: string, info: any): void {
|
||||||
|
dump(header, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Throwing a UsageError causes the --help to be shown above
|
||||||
|
// the error.message
|
||||||
throwUsageError(message?: string): never {
|
throwUsageError(message?: string): never {
|
||||||
throw new UsageError(message);
|
throw new UsageError(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shows error.message
|
||||||
throwError(message: string): never {
|
throwError(message: string): never {
|
||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CheckPlugin extends Plugin { }
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// Command Line Runner
|
// Command Line Runner
|
||||||
|
|
||||||
|
export type Options = {
|
||||||
|
account?: boolean;
|
||||||
|
provider?: boolean;
|
||||||
|
transaction?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export class CLI {
|
export class CLI {
|
||||||
readonly defaultCommand: string;
|
readonly defaultCommand: string;
|
||||||
readonly plugins: { [ command: string ]: PluginType };
|
readonly plugins: { [ command: string ]: PluginType };
|
||||||
|
readonly standAlone: PluginType;
|
||||||
|
readonly options: Options;
|
||||||
|
|
||||||
|
constructor(defaultCommand?: string, options?: Options) {
|
||||||
|
ethers.utils.defineReadOnly(this, "options", {
|
||||||
|
account: true,
|
||||||
|
provider: true,
|
||||||
|
transaction: true
|
||||||
|
});
|
||||||
|
|
||||||
|
if (options) {
|
||||||
|
["account", "provider", "transaction"].forEach((key) => {
|
||||||
|
if ((<any>options)[key] == null) { return; }
|
||||||
|
(<any>(this.options))[key] = !!((<any>options)[key]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Object.freeze(this.options);
|
||||||
|
|
||||||
constructor(defaultCommand: string) {
|
|
||||||
ethers.utils.defineReadOnly(this, "defaultCommand", defaultCommand || null);
|
ethers.utils.defineReadOnly(this, "defaultCommand", defaultCommand || null);
|
||||||
ethers.utils.defineReadOnly(this, "plugins", { });
|
ethers.utils.defineReadOnly(this, "plugins", { });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getAppName(): string {
|
||||||
|
let appName = "ethers";
|
||||||
|
try {
|
||||||
|
appName = basename(process.mainModule.filename).split(".")[0];
|
||||||
|
} catch (error) { }
|
||||||
|
return appName;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @TODO: Better way to specify default; i.e. may not have args
|
||||||
|
|
||||||
addPlugin(command: string, plugin: PluginType) {
|
addPlugin(command: string, plugin: PluginType) {
|
||||||
this.plugins[command] = plugin;
|
if (this.standAlone) {
|
||||||
|
ethers.errors.throwError("only setPlugin or addPlugin may be used at once", ethers.errors.UNSUPPORTED_OPERATION, {
|
||||||
|
operation: "addPlugin"
|
||||||
|
});
|
||||||
|
} else if (this.plugins[command]) {
|
||||||
|
ethers.errors.throwError("command already exists", ethers.errors.UNSUPPORTED_OPERATION, {
|
||||||
|
operation: "addPlugin",
|
||||||
|
command: command
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ethers.utils.defineReadOnly(this.plugins, command, plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlugin(plugin: PluginType) {
|
||||||
|
if (Object.keys(this.plugins).length !== 0) {
|
||||||
|
ethers.errors.throwError("only setPlugin or addPlugin may be used at once", ethers.errors.UNSUPPORTED_OPERATION, {
|
||||||
|
operation: "setPlugin"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.standAlone) {
|
||||||
|
ethers.errors.throwError("cannot setPlugin more than once", ethers.errors.UNSUPPORTED_OPERATION, {
|
||||||
|
operation: "setPlugin"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ethers.utils.defineReadOnly(this, "standAlone", plugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
showUsage(message?: string, status?: number): never {
|
showUsage(message?: string, status?: number): never {
|
||||||
// Limit: | |
|
// Limit: | |
|
||||||
console.log("Usage:");
|
console.log("Usage:");
|
||||||
|
|
||||||
let lines: Array<string> = [];
|
if (this.standAlone) {
|
||||||
for (let cmd in this.plugins) {
|
let help = ethers.utils.getStatic<() => Help>(this.standAlone, "getHelp")();
|
||||||
let plugin = this.plugins[cmd];
|
console.log(` ${ CLI.getAppName() } ${ help.name } [ OPTIONS ]`);
|
||||||
let help = (plugin.getHelp ? plugin.getHelp(): null);
|
console.log("");
|
||||||
if (help == null) { continue; }
|
|
||||||
let helpLine = " " + help.name;
|
let lines: Array<string> = [];
|
||||||
if (helpLine.length > 28) {
|
let optionHelp = ethers.utils.getStatic<() => Array<Help>>(this.standAlone, "getOptionHelp")();
|
||||||
lines.push(helpLine);
|
optionHelp.forEach((help) => {
|
||||||
lines.push(repeat(" ", 30) + help.help);
|
lines.push(" " + help.name + repeat(" ", 28 - help.name.length) + help.help);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (lines.length) {
|
||||||
|
console.log("OPTIONS");
|
||||||
|
lines.forEach((line) => {
|
||||||
|
console.log(line);
|
||||||
|
});
|
||||||
|
console.log("");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (this.defaultCommand) {
|
||||||
|
console.log(` ${ CLI.getAppName() } [ COMMAND ] [ ARGS ] [ OPTIONS ]`);
|
||||||
|
console.log("");
|
||||||
} else {
|
} else {
|
||||||
helpLine += repeat(" ", 30 - helpLine.length);
|
console.log(` ${ CLI.getAppName() } COMMAND [ ARGS ] [ OPTIONS ]`);
|
||||||
lines.push(helpLine + help.help);
|
console.log("");
|
||||||
}
|
}
|
||||||
|
|
||||||
let optionHelp = (plugin.getOptionHelp ? plugin.getOptionHelp(): [ ]);
|
let lines: Array<string> = [];
|
||||||
optionHelp.forEach((help) => {
|
for (let cmd in this.plugins) {
|
||||||
lines.push(" " + help.name + repeat(" ", 27 - help.name.length) + help.help);
|
let plugin = this.plugins[cmd];
|
||||||
});
|
let help = ethers.utils.getStatic<() => Help>(plugin, "getHelp")();
|
||||||
|
if (help == null) { continue; }
|
||||||
|
let helpLine = " " + help.name;
|
||||||
|
if (helpLine.length > 28) {
|
||||||
|
lines.push(helpLine);
|
||||||
|
lines.push(repeat(" ", 30) + help.help);
|
||||||
|
} else {
|
||||||
|
helpLine += repeat(" ", 30 - helpLine.length);
|
||||||
|
lines.push(helpLine + help.help);
|
||||||
|
}
|
||||||
|
|
||||||
|
let optionHelp = ethers.utils.getStatic<() => Array<Help>>(plugin, "getOptionHelp")();
|
||||||
|
optionHelp.forEach((help) => {
|
||||||
|
lines.push(" " + help.name + repeat(" ", 27 - help.name.length) + help.help);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lines.length) {
|
||||||
|
if (this.defaultCommand) {
|
||||||
|
console.log(`COMMANDS (default: ${ this.defaultCommand })`);
|
||||||
|
} else {
|
||||||
|
console.log("COMMANDS");
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.forEach((line) => {
|
||||||
|
console.log(line);
|
||||||
|
});
|
||||||
|
console.log("");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lines.length) {
|
if (this.options.account) {
|
||||||
if (this.defaultCommand) {
|
console.log("ACCOUNT OPTIONS");
|
||||||
console.log(" ethers [ COMMAND ] [ ARGS ] [ OPTIONS ]");
|
console.log(" --account FILENAME Load from a file (JSON, RAW or mnemonic)");
|
||||||
console.log("");
|
console.log(" --account RAW_KEY Use a private key (insecure *)");
|
||||||
console.log(`COMMANDS (default: ${this.defaultCommand})`);
|
console.log(" --account 'MNEMONIC' Use a mnemonic (insecure *)");
|
||||||
} else {
|
console.log(" --account - Use secure entry for a raw key or mnemonic");
|
||||||
console.log(" ethers COMMAND [ ARGS ] [ OPTIONS ]");
|
console.log(" --account-void ADDRESS Udd an address as a void signer");
|
||||||
console.log("");
|
console.log(" --account-void ENS_NAME Add the resolved address as a void signer");
|
||||||
console.log("COMMANDS");
|
console.log(" --account-rpc ADDRESS Add the address from a JSON-RPC provider");
|
||||||
}
|
console.log(" --account-rpc INDEX Add the index from a JSON-RPC provider");
|
||||||
|
console.log(" --mnemonic-password Prompt for a password for mnemonics");
|
||||||
lines.forEach((line) => {
|
console.log(" --xxx-mnemonic-password Prompt for a (experimental) hard password");
|
||||||
console.log(line);
|
console.log("");
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (this.options.provider) {
|
||||||
|
console.log("PROVIDER OPTIONS (default: all + homestead)");
|
||||||
|
console.log(" --alchemy Include Alchemy");
|
||||||
|
console.log(" --etherscan Include Etherscan");
|
||||||
|
console.log(" --infura Include INFURA");
|
||||||
|
console.log(" --nodesmith Include nodesmith");
|
||||||
|
console.log(" --rpc URL Include a custom JSON-RPC");
|
||||||
|
console.log(" --offline Dump signed transactions (no send)");
|
||||||
|
console.log(" --network NETWORK Network to connect to (default: homestead)");
|
||||||
|
console.log("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.options.transaction) {
|
||||||
|
console.log("TRANSACTION OPTIONS (default: query network)");
|
||||||
|
console.log(" --gasPrice GWEI Default gas price for transactions(in wei)");
|
||||||
|
console.log(" --gasLimit GAS Default gas limit for transactions");
|
||||||
|
console.log(" --nonce NONCE Initial nonce for the first transaction");
|
||||||
|
console.log(" --value VALUE Default value (in ether) for transactions");
|
||||||
|
console.log(" --yes Always accept Siging and Sending");
|
||||||
console.log("");
|
console.log("");
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log("ACCOUNT OPTIONS");
|
|
||||||
console.log(" --account FILENAME Load from a file (JSON, RAW or mnemonic)");
|
|
||||||
console.log(" --account RAW_KEY Use a private key (insecure *)");
|
|
||||||
console.log(" --account 'MNEMONIC' Use a mnemonic (insecure *)");
|
|
||||||
console.log(" --account - Use secure entry for a raw key or mnemonic");
|
|
||||||
console.log(" --account-void ADDRESS Udd an address as a void signer");
|
|
||||||
console.log(" --account-void ENS_NAME Add the resolved address as a void signer");
|
|
||||||
console.log(" --account-rpc ADDRESS Add the address from a JSON-RPC provider");
|
|
||||||
console.log(" --account-rpc INDEX Add the index from a JSON-RPC provider");
|
|
||||||
console.log(" --mnemonic-password Prompt for a password for mnemonics");
|
|
||||||
console.log(" --xxx-mnemonic-password Prompt for a (experimental) hard password");
|
|
||||||
console.log("");
|
|
||||||
console.log("PROVIDER OPTIONS (default: getDefaultProvider)");
|
|
||||||
console.log(" --alchemy Include Alchemy");
|
|
||||||
console.log(" --etherscan Include Etherscan");
|
|
||||||
console.log(" --infura Include INFURA");
|
|
||||||
console.log(" --nodesmith Include nodesmith");
|
|
||||||
console.log(" --rpc URL Include a custom JSON-RPC");
|
|
||||||
console.log(" --offline Dump signed transactions (no send)");
|
|
||||||
console.log(" --network NETWORK Network to connect to (default: homestead)");
|
|
||||||
console.log("");
|
|
||||||
console.log("TRANSACTION OPTIONS (default: query the network)");
|
|
||||||
console.log(" --gasPrice GWEI Default gas price for transactions(in wei)");
|
|
||||||
console.log(" --gasLimit GAS Default gas limit for transactions");
|
|
||||||
console.log(" --nonce NONCE Initial nonce for the first transaction");
|
|
||||||
console.log(" --value VALUE Default value (in ether) for transactions");
|
|
||||||
console.log(" --yes Always accept Siging and Sending");
|
|
||||||
console.log("");
|
|
||||||
console.log("OTHER OPTIONS");
|
console.log("OTHER OPTIONS");
|
||||||
console.log(" --help Show this usage and quit");
|
console.log(" --debug Show stack traces for errors");
|
||||||
|
console.log(" --help Show this usage and exit");
|
||||||
|
console.log(" --version Show this version and exit");
|
||||||
console.log("");
|
console.log("");
|
||||||
console.log("(*) By including mnemonics or private keys on the command line they are");
|
console.log("(*) By including mnemonics or private keys on the command line they are");
|
||||||
console.log(" possibly readable by other users on your system and may get stored in");
|
console.log(" possibly readable by other users on your system and may get stored in");
|
||||||
@ -776,13 +881,25 @@ export class CLI {
|
|||||||
async run(args: Array<string>): Promise<void> {
|
async run(args: Array<string>): Promise<void> {
|
||||||
args = args.slice();
|
args = args.slice();
|
||||||
|
|
||||||
|
if (this.defaultCommand && !this.plugins[this.defaultCommand]) {
|
||||||
|
throw new Error("missing defaultCommand plugin");
|
||||||
|
}
|
||||||
|
|
||||||
let command: string = null;
|
let command: string = null;
|
||||||
|
|
||||||
// We run a temporary argument parser to check for a command by processing standard options
|
// We run a temporary argument parser to check for a command by processing standard options
|
||||||
{
|
{
|
||||||
let argParser = new ArgParser(args);
|
let argParser = new ArgParser(args);
|
||||||
|
|
||||||
[ "debug", "help", "mnemonic-password", "offline", "xxx-mnemonic-password", "yes"].forEach((key) => {
|
let plugin = new CheckPlugin();
|
||||||
|
await plugin.prepareOptions(argParser);
|
||||||
|
|
||||||
|
[ "debug", "help", "version"].forEach((key) => {
|
||||||
|
argParser.consumeFlag(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
[ "mnemonic-password", "offline", "xxx-mnemonic-password", "yes"].forEach((key) => {
|
||||||
argParser.consumeFlag(key);
|
argParser.consumeFlag(key);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -792,31 +909,49 @@ export class CLI {
|
|||||||
[ "network", "rpc", "account", "account-rpc", "account-void", "gas-price", "gas-limit", "nonce" ].forEach((option) => {
|
[ "network", "rpc", "account", "account-rpc", "account-void", "gas-price", "gas-limit", "nonce" ].forEach((option) => {
|
||||||
argParser.consumeOption(option);
|
argParser.consumeOption(option);
|
||||||
});
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
let commandIndex = argParser._checkCommandIndex();
|
// Find the first unconsumed argument
|
||||||
if (commandIndex === -1) {
|
if (!this.standAlone) {
|
||||||
command = this.defaultCommand;
|
let commandIndex = argParser._checkCommandIndex();
|
||||||
} else {
|
if (commandIndex === -1) {
|
||||||
command = args[commandIndex];
|
command = this.defaultCommand;
|
||||||
args.splice(commandIndex, 1);
|
} else {
|
||||||
|
command = args[commandIndex];
|
||||||
|
args.splice(commandIndex, 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset the argument parser
|
// Reset the argument parser
|
||||||
let argParser = new ArgParser(args);
|
let argParser = new ArgParser(args);
|
||||||
|
|
||||||
|
if (argParser.consumeFlag("version")) {
|
||||||
|
let app = "ethers";
|
||||||
|
try {
|
||||||
|
app = basename(process.mainModule.filename).split(".")[0];
|
||||||
|
} catch (error) { }
|
||||||
|
console.log(app + "/" + version);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (argParser.consumeFlag("help")) {
|
if (argParser.consumeFlag("help")) {
|
||||||
return this.showUsage();
|
return this.showUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
let debug = argParser.consumeFlag("debug");
|
let debug = argParser.consumeFlag("debug");
|
||||||
|
|
||||||
// Create PLug-in instance
|
// Create Plug-in instance
|
||||||
let plugin: Plugin = null;
|
let plugin: Plugin = null;
|
||||||
try {
|
if (this.standAlone) {
|
||||||
plugin = new this.plugins[command]();
|
plugin = new this.standAlone;
|
||||||
} catch (error) {
|
} else {
|
||||||
if (command) { this.showUsage("unknown command - " + command); }
|
try {
|
||||||
return this.showUsage("no command provided", 1);
|
plugin = new this.plugins[command]();
|
||||||
|
} catch (error) {
|
||||||
|
if (command) { this.showUsage("unknown command - " + command); }
|
||||||
|
return this.showUsage("no command provided", 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -825,14 +960,16 @@ export class CLI {
|
|||||||
await plugin.run();
|
await plugin.run();
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
if (error instanceof UsageError) {
|
||||||
|
return this.showUsage(error.message, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
console.log("----- <DEBUG> ------")
|
console.log("----- <DEBUG> ------")
|
||||||
console.log(error);
|
console.log(error);
|
||||||
console.log("----- </DEBUG> -----")
|
console.log("----- </DEBUG> -----")
|
||||||
}
|
}
|
||||||
if (error instanceof UsageError) {
|
|
||||||
return this.showUsage(error.message, 1);
|
|
||||||
}
|
|
||||||
console.log("Error: " + error.message);
|
console.log("Error: " + error.message);
|
||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user