Skip to content

Commit 2e049fa

Browse files
committed
feat: add a built-in console task
1 parent ca8ee82 commit 2e049fa

File tree

5 files changed

+148
-1
lines changed

5 files changed

+148
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import type { HardhatPlugin } from "@ignored/hardhat-vnext-core/types/plugins";
2+
3+
import { task } from "@ignored/hardhat-vnext-core/config";
4+
5+
const hardhatPlugin: HardhatPlugin = {
6+
id: "console",
7+
tasks: [
8+
task("console", "Opens a hardhat console")
9+
.setAction(import.meta.resolve("./task-action.js"))
10+
.addVariadicArgument({
11+
name: "commands",
12+
description: "Commands to run in the console",
13+
defaultValue: [".help"],
14+
})
15+
.build(),
16+
],
17+
};
18+
19+
export default hardhatPlugin;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import type { NewTaskActionFunction } from "@ignored/hardhat-vnext-core/types/tasks";
2+
import type { REPLServer } from "node:repl";
3+
4+
import path from "node:path";
5+
import repl from "node:repl";
6+
7+
import { getCacheDir } from "@ignored/hardhat-vnext-core/global-dir";
8+
import debug from "debug";
9+
10+
const log = debug("hardhat:core:tasks:console");
11+
12+
interface ConsoleActionArguments {
13+
commands: string[];
14+
}
15+
16+
const consoleAction: NewTaskActionFunction<ConsoleActionArguments> = async (
17+
{ commands },
18+
_hre,
19+
) => {
20+
const globalCacheDir = await getCacheDir();
21+
22+
return new Promise<REPLServer>((resolve) => {
23+
// Start a new REPL server with the default options
24+
const replServer = repl.start();
25+
26+
// Set up the REPL history file in the global cache directory
27+
const historyPath = path.join(globalCacheDir, "console-history.txt");
28+
replServer.setupHistory(historyPath, (err: Error | null) => {
29+
if (err !== null) {
30+
log(`Failed to setup REPL history: ${err.message}`);
31+
}
32+
});
33+
34+
// Execute each command in the REPL server
35+
for (const command of commands) {
36+
replServer.write(`${command}\n`);
37+
}
38+
39+
// Resolve the task action promise when the REPL server exits
40+
replServer.on("exit", () => {
41+
resolve(replServer);
42+
});
43+
});
44+
};
45+
46+
export default consoleAction;
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,20 @@
11
import type { HardhatPlugin } from "@ignored/hardhat-vnext-core/types/plugins";
22

33
import clean from "./clean/index.js";
4+
import console from "./console/index.js";
45
import hardhatFoo from "./hardhat-foo/index.js";
56
import run from "./run/index.js";
67

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

13-
export const builtinPlugins: HardhatPlugin[] = [clean, hardhatFoo, run];
15+
export const builtinPlugins: HardhatPlugin[] = [
16+
clean,
17+
console,
18+
hardhatFoo,
19+
run,
20+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import type { HardhatRuntimeEnvironment } from "@ignored/hardhat-vnext-core/types/hre";
2+
3+
import assert from "node:assert/strict";
4+
import { before, describe, it } from "node:test";
5+
6+
import { ensureError } from "@ignored/hardhat-vnext-utils/error";
7+
8+
import { createHardhatRuntimeEnvironment } from "../../../../src/hre.js";
9+
import consoleAction from "../../../../src/internal/builtin-plugins/console/task-action.js";
10+
import { useFixtureProject } from "../../../helpers/project.js";
11+
12+
describe("console/task-action", function () {
13+
let hre: HardhatRuntimeEnvironment;
14+
15+
before(async function () {
16+
hre = await createHardhatRuntimeEnvironment({});
17+
});
18+
19+
describe("javascript", function () {
20+
useFixtureProject("run-js-script");
21+
22+
it("should throw inside the console if script does not exist", async function () {
23+
const replServer = await consoleAction(
24+
{ commands: ['await import("./scripts/non-existent.js");', ".exit"] },
25+
hre,
26+
);
27+
ensureError(replServer.lastError);
28+
});
29+
30+
it("should run a script inside the console successfully", async function () {
31+
const replServer = await consoleAction(
32+
{ commands: ['await import("./scripts/success.js");', ".exit"] },
33+
hre,
34+
);
35+
assert.equal(replServer.lastError, undefined);
36+
});
37+
38+
it("should throw inside the console if the script throws", async function () {
39+
const replServer = await consoleAction(
40+
{ commands: ['await import("./scripts/throws.js");', ".exit"] },
41+
hre,
42+
);
43+
ensureError(replServer.lastError);
44+
});
45+
});
46+
47+
describe("typescript", function () {
48+
useFixtureProject("run-ts-script");
49+
50+
it("should throw inside the console if script does not exist", async function () {
51+
const replServer = await consoleAction(
52+
{ commands: ['await import("./scripts/non-existent.ts");', ".exit"] },
53+
hre,
54+
);
55+
ensureError(replServer.lastError);
56+
});
57+
58+
it("should run a script inside the console successfully", async function () {
59+
const replServer = await consoleAction(
60+
{ commands: ['await import("./scripts/success.ts");', ".exit"] },
61+
hre,
62+
);
63+
assert.equal(replServer.lastError, undefined);
64+
});
65+
66+
it("should throw inside the console if the script throws", async function () {
67+
const replServer = await consoleAction(
68+
{ commands: ['await import("./scripts/throws.ts");', ".exit"] },
69+
hre,
70+
);
71+
ensureError(replServer.lastError);
72+
});
73+
});
74+
});

v-next/hardhat/test/internal/cli/main.ts

+1
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ Usage: hardhat [GLOBAL OPTIONS] <TASK> [SUBTASK] [TASK OPTIONS] [--] [TASK ARGUM
223223
AVAILABLE TASKS:
224224
225225
clean Clears the cache and deletes all artifacts
226+
console Opens a hardhat console
226227
example Example task
227228
run Runs a user-defined script after compiling the project
228229
task A task that uses arg1

0 commit comments

Comments
 (0)