Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add a built-in console task #5592

Merged
merged 13 commits into from
Aug 14, 2024
Merged
19 changes: 19 additions & 0 deletions v-next/hardhat/src/internal/builtin-plugins/console/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { HardhatPlugin } from "@ignored/hardhat-vnext-core/types/plugins";

import { task } from "@ignored/hardhat-vnext-core/config";

const hardhatPlugin: HardhatPlugin = {
id: "console",
tasks: [
task("console", "Opens a hardhat console")
.setAction(import.meta.resolve("./task-action.js"))
.addVariadicArgument({
name: "commands",
description: "Commands to run in the console",
defaultValue: [".help"],
})
.build(),
],
};

export default hardhatPlugin;
46 changes: 46 additions & 0 deletions v-next/hardhat/src/internal/builtin-plugins/console/task-action.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { NewTaskActionFunction } from "@ignored/hardhat-vnext-core/types/tasks";
import type { REPLServer } from "node:repl";

import path from "node:path";
import repl from "node:repl";

import { getCacheDir } from "@ignored/hardhat-vnext-core/global-dir";
import debug from "debug";

const log = debug("hardhat:core:tasks:console");

interface ConsoleActionArguments {
commands: string[];
}

const consoleAction: NewTaskActionFunction<ConsoleActionArguments> = async (
{ commands },
_hre,
) => {
const globalCacheDir = await getCacheDir();

return new Promise<REPLServer>((resolve) => {
// Start a new REPL server with the default options
const replServer = repl.start();

// Set up the REPL history file in the global cache directory
const historyPath = path.join(globalCacheDir, "console-history.txt");
replServer.setupHistory(historyPath, (err: Error | null) => {
if (err !== null) {
log(`Failed to setup REPL history: ${err.message}`);
}
});

// Execute each command in the REPL server
for (const command of commands) {
replServer.write(`${command}\n`);
}

// Resolve the task action promise when the REPL server exits
replServer.on("exit", () => {
resolve(replServer);
});
});
};

export default consoleAction;
9 changes: 8 additions & 1 deletion v-next/hardhat/src/internal/builtin-plugins/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import type { HardhatPlugin } from "@ignored/hardhat-vnext-core/types/plugins";

import clean from "./clean/index.js";
import console from "./console/index.js";
import hardhatFoo from "./hardhat-foo/index.js";
import run from "./run/index.js";

// Note: When importing a plugin, you have to export its types, so that its
// type extensions, if any, also get loaded.
export type * from "./clean/index.js";
export type * from "./console/index.js";
export type * from "./hardhat-foo/index.js";
export type * from "./run/index.js";

export const builtinPlugins: HardhatPlugin[] = [clean, hardhatFoo, run];
export const builtinPlugins: HardhatPlugin[] = [
clean,
console,
hardhatFoo,
run,
];
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { HardhatRuntimeEnvironment } from "@ignored/hardhat-vnext-core/types/hre";

import assert from "node:assert/strict";
import { before, describe, it } from "node:test";

import { ensureError } from "@ignored/hardhat-vnext-utils/error";

import { createHardhatRuntimeEnvironment } from "../../../../src/hre.js";
import consoleAction from "../../../../src/internal/builtin-plugins/console/task-action.js";
import { useFixtureProject } from "../../../helpers/project.js";

describe("console/task-action", function () {
let hre: HardhatRuntimeEnvironment;

before(async function () {
hre = await createHardhatRuntimeEnvironment({});
});

describe("javascript", function () {
useFixtureProject("run-js-script");

it("should throw inside the console if script does not exist", async function () {
const replServer = await consoleAction(
{ commands: ['await import("./scripts/non-existent.js");', ".exit"] },
hre,
);
ensureError(replServer.lastError);
});

it("should run a script inside the console successfully", async function () {
const replServer = await consoleAction(
{ commands: ['await import("./scripts/success.js");', ".exit"] },
hre,
);
assert.equal(replServer.lastError, undefined);
});

it("should throw inside the console if the script throws", async function () {
const replServer = await consoleAction(
{ commands: ['await import("./scripts/throws.js");', ".exit"] },
hre,
);
ensureError(replServer.lastError);
});
});

describe("typescript", function () {
useFixtureProject("run-ts-script");

it("should throw inside the console if script does not exist", async function () {
const replServer = await consoleAction(
{ commands: ['await import("./scripts/non-existent.ts");', ".exit"] },
hre,
);
ensureError(replServer.lastError);
});

it("should run a script inside the console successfully", async function () {
const replServer = await consoleAction(
{ commands: ['await import("./scripts/success.ts");', ".exit"] },
hre,
);
assert.equal(replServer.lastError, undefined);
});

it("should throw inside the console if the script throws", async function () {
const replServer = await consoleAction(
{ commands: ['await import("./scripts/throws.ts");', ".exit"] },
hre,
);
ensureError(replServer.lastError);
});
});
});
1 change: 1 addition & 0 deletions v-next/hardhat/test/internal/cli/main.ts
Original file line number Diff line number Diff line change
@@ -223,6 +223,7 @@ Usage: hardhat [GLOBAL OPTIONS] <TASK> [SUBTASK] [TASK OPTIONS] [--] [TASK ARGUM
AVAILABLE TASKS:

clean Clears the cache and deletes all artifacts
console Opens a hardhat console
example Example task
run Runs a user-defined script after compiling the project
task A task that uses arg1