hardhat
Version:
Hardhat is an extensible developer tool that helps smart contract developers increase productivity by reliably bringing together the tools they want.
94 lines (78 loc) • 3.07 kB
text/typescript
import type { HardhatHooks } from "../../../types/hooks.js";
import type { NewTaskActionFunction } from "../../../types/tasks.js";
import type { REPLServer } from "node:repl";
import repl from "node:repl";
import { resolveFromRoot } from "@nomicfoundation/hardhat-utils/path";
import chalk from "chalk";
import debug from "debug";
const log = debug("hardhat:core:tasks:console");
interface ConsoleActionArguments {
commands: string[];
history: string;
noCompile: boolean;
// We accept ReplOptions as an argument to allow tests overriding the IO streams
options?: repl.ReplOptions;
}
const consoleAction: NewTaskActionFunction<ConsoleActionArguments> = async (
{ commands, history, noCompile, options },
hre,
) => {
const handlers: Partial<HardhatHooks["userInterruptions"]> = {
requestSecretInput: async () => {
console.error(
chalk.red("Secrets are not yet supported in the console task"),
);
process.exit(1);
},
};
hre.hooks.registerHandlers("userInterruptions", handlers);
try {
// Resolve the history path if it is not empty
let historyPath: string | undefined;
if (history !== "") {
const cacheDir = hre.config.paths.cache;
historyPath = resolveFromRoot(cacheDir, history);
}
if (!noCompile) {
await hre.tasks.getTask("build").run({ noTests: true, quiet: true });
}
return await new Promise<REPLServer>(async (resolve) => {
// Start a new REPL server with the default options
const replServer = repl.start(options);
// Resolve the task action promise only when the REPL server exits
replServer.on("exit", () => {
resolve(replServer);
});
// Add the Hardhat Runtime Environment to the REPL context
replServer.context.hre = hre;
replServer.context.config = hre.config;
replServer.context.tasks = hre.tasks;
replServer.context.globalOptions = hre.globalOptions;
replServer.context.hooks = hre.hooks;
replServer.context.interruptions = hre.interruptions;
// NOTE: This is a small architectural violation, as the network manager
// comes from a builtin plugin, and plugins can't add their own exports
// here. We may consider adding a hook for this in the future.
replServer.context.network = hre.network;
// Set up the REPL history file if the historyPath has been set
if (historyPath !== undefined) {
await new Promise<void>((resolveSetupHistory) => {
replServer.setupHistory(historyPath, (err: Error | null) => {
// Fail silently if the history file cannot be set up
if (err !== null) {
log("Failed to setup REPL history", err);
}
resolveSetupHistory();
});
});
}
// Execute each command in the REPL server
for (const command of commands) {
replServer.write(`${command}\n`);
}
});
} finally {
hre.hooks.unregisterHandlers("userInterruptions", handlers);
}
};
export default consoleAction;