@ganache/cli
Version:
229 lines • 8.99 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const core_1 = __importStar(require("@ganache/core"));
const args_1 = require("./args");
const flavor_1 = require("@ganache/flavor");
const detach_1 = require("./detach");
const colors_1 = require("@ganache/colors");
const cli_table_1 = __importDefault(require("cli-table"));
const chalk_1 = __importDefault(require("chalk"));
const porscheColor = chalk_1.default.hex(colors_1.TruffleColors.porsche);
const logAndForceExit = (messages, exitCode = 0) => {
// https://nodejs.org/api/process.html#process_process_exit_code
// writes to process.stdout in Node.js are sometimes asynchronous and may occur over
// multiple ticks of the Node.js event loop. Calling process.exit(), however, forces
// the process to exit before those additional writes to stdout can be performed.
// se we set stdout to block in order to successfully log before exiting
if (process.stdout._handle) {
process.stdout._handle.setBlocking(true);
}
try {
messages.forEach(message => console.log(message));
}
catch (e) {
console.log(e);
}
// force the process to exit
process.exit(exitCode);
};
const version = process.env.VERSION || "DEV";
const cliVersion = process.env.CLI_VERSION || "DEV";
const coreVersion = process.env.CORE_VERSION || "DEV";
const detailedVersion = `ganache v${version} (@ganache/cli: ${cliVersion}, @ganache/core: ${coreVersion})`;
const argv = (0, args_1.parseArgs)(detailedVersion);
if (argv.action === "start") {
const flavorName = argv.flavor;
let { server: cliSettings } = flavor_1.CliOptionsConfig.normalize(argv);
let flavor;
if (flavorName === "ethereum") {
flavor = require("@ganache/ethereum").default;
}
else {
flavor = (0, flavor_1.load)(flavorName);
// if the flavor handler has a cli section, merge it with our cli settings
// as it might have a section for overriding the port and the host
if (flavor.options.cli) {
Object.assign(cliSettings, flavor.options.cli.normalize(argv));
}
}
console.log(detailedVersion);
let server;
try {
server = core_1.default.server(argv);
}
catch (error) {
console.error(error.message);
process.exit(1);
}
let started = false;
process.on("uncaughtException", function (e) {
if (started) {
logAndForceExit([e], 1);
}
else {
logAndForceExit([e.stack], 1);
}
});
let receivedShutdownSignal = false;
const handleSignal = async (signal) => {
console.log(`\nReceived shutdown signal: ${signal}`);
closeHandler();
};
const closeHandler = async () => {
try {
// graceful shutdown
switch (server.status) {
case core_1.ServerStatus.opening:
receivedShutdownSignal = true;
console.log("Server is currently starting; waiting…");
return;
case core_1.ServerStatus.open:
console.log("Shutting down…");
await server.close();
console.log("Server has been shut down");
break;
}
// don't just call `process.exit()` here, as we don't want to hide shutdown
// errors behind a forced shutdown. Note: `process.exitCode` doesn't do
// anything other than act as a place to anchor this comment :-)
process.exitCode = 0;
}
catch (err) {
logAndForceExit([
"\nReceived an error while attempting to shut down the server: ",
err.stack || err
], 1);
}
};
// See http://stackoverflow.com/questions/10021373/what-is-the-windows-equivalent-of-process-onsigint-in-node-js
if (process.platform === "win32") {
const rl = require("readline")
.createInterface({
input: process.stdin,
output: process.stdout
})
.on("SIGINT", () => {
// we must "close" the RL interface otherwise the process will think we
// are still listening
// https://nodejs.org/api/readline.html#readline_event_sigint
rl.close();
handleSignal("SIGINT");
});
}
process.on("SIGINT", handleSignal);
process.on("SIGTERM", handleSignal);
process.on("SIGHUP", handleSignal);
console.log("Starting RPC server");
server.listen(cliSettings.port, cliSettings.host, async (err) => {
if (err) {
console.error(err);
process.exitCode = 1;
return;
}
else if (receivedShutdownSignal) {
closeHandler();
return;
}
started = true;
await flavor.ready({
provider: server.provider,
options: { server: cliSettings }
});
// if process.send is defined, this is a child_process (we assume a detached
// instance), so we need to notify that we are ready.
const isDetachedInstance = process.send !== undefined;
if (isDetachedInstance) {
(0, detach_1.notifyDetachedInstanceReady)(cliSettings);
}
});
}
else if (argv.action === "stop") {
const instanceName = argv.name;
(0, detach_1.stopDetachedInstance)(instanceName).then(instanceFound => {
if (instanceFound) {
console.log("Instance stopped");
}
else {
console.error("Instance not found");
}
});
}
else if (argv.action === "start-detached") {
(0, detach_1.startDetachedInstance)(process.argv, argv, version)
.then(instance => {
const highlightedName = porscheColor(instance.name);
// output only the instance name to allow users to capture stdout and use to
// programmatically stop the instance
console.log(highlightedName);
})
.catch(err => {
// the child process would have output its error to stdout, so no need to
// output anything more
});
}
else if (argv.action === "list") {
(0, detach_1.getDetachedInstances)().then(instances => {
if (instances.length === 0) {
console.log(`No detached instances found - try ${porscheColor("ganache --detach")} to start a detached instance`);
}
else {
const now = Date.now();
const table = new cli_table_1.default({
head: [
chalk_1.default.bold("PID"),
chalk_1.default.bold("Name"),
chalk_1.default.bold("Flavor"),
chalk_1.default.bold("Version"),
chalk_1.default.bold("Host"),
chalk_1.default.bold("Uptime")
],
colAligns: ["right", "left", "left", "left", "left", "right"],
style: {
head: ["white", "white", "white", "white", "white", "white"]
}
});
instances.sort((a, b) => b.startTime - a.startTime);
for (let i = 0; i < instances.length; i++) {
const instance = instances[i];
const uptime = now - instance.startTime;
table.push([
instance.pid.toString(),
porscheColor(instance.name),
instance.flavor,
instance.version,
`${instance.host}:${instance.port.toString()}`,
(0, detach_1.formatUptime)(uptime)
]);
}
console.log(table.toString());
}
});
}
//# sourceMappingURL=cli.js.map