UNPKG

@nomicfoundation/hardhat-foundry

Version:

Hardhat plugin that provides compatibility with Foundry-based projects remappings.

90 lines 3.25 kB
import { exec } from "node:child_process"; import * as path from "node:path"; import { promisify } from "node:util"; import { HardhatError } from "@nomicfoundation/hardhat-errors"; import { ensureError } from "@nomicfoundation/hardhat-utils/error"; import { exists } from "@nomicfoundation/hardhat-utils/fs"; const execAsync = promisify(exec); const FORGE_TIMEOUT_MS = 500; const FORGE_VERSION_TIMEOUT_MS = 500; // 0.5 seconds // Module-level mock for testing let execMock; /** * Set a mock exec function for testing. * @param mockExec - The mock exec function to use. */ export function setExecMock(mockExec) { execMock = mockExec; } /** * Reset the mock exec function. */ export function resetExecMock() { execMock = undefined; } /** * Check if a package has a foundry.toml configuration file. * * @param packagePath - The absolute filesystem path to the package root. * @returns True if foundry.toml exists in the package. */ export async function hasFoundryConfig(packagePath) { const foundryTomlPath = path.join(packagePath, "foundry.toml"); return await exists(foundryTomlPath); } /** * Check if forge is installed and available in PATH. * * @returns True if forge is installed, false otherwise. */ export async function isForgeInstalled() { const _execAsync = execMock ?? execAsync; try { await _execAsync("forge --version", { timeout: FORGE_VERSION_TIMEOUT_MS }); return true; } catch { return false; } } /** * Execute `forge remappings` in the given package directory to get Solidity remappings. * * @param packagePath - The absolute filesystem path to the package root. * @returns An array of remapping strings (e.g., ["@openzeppelin/=lib/openzeppelin-contracts/"]). * @throws {HardhatError} If the command fails. */ export async function getForgeRemappings(packagePath) { const _execAsync = execMock ?? execAsync; try { const { stdout, stderr } = await _execAsync("forge remappings", { cwd: packagePath, timeout: FORGE_TIMEOUT_MS, env: process.env, }); // If there's stderr output but no stdout, it might be an error if (stderr.length > 0 && stdout.length === 0) { throw new HardhatError(HardhatError.ERRORS.HARDHAT_FOUNDRY.GENERAL.FORGE_REMAPPINGS_FAILED, { packagePath, stderr: stderr.trim() }); } // Parse the output into individual remappings const remappings = stdout .split(/\r?\n/) // Handle both Unix and Windows line endings .map((line) => line.trim()) .filter((line) => line.length > 0); return remappings; } catch (error) { ensureError(error); // Re-throw HardhatErrors as-is, as it's a FORGE_REMAPPINGS_FAILED error if (HardhatError.isHardhatError(error)) { throw error; } const errorMessage = "stderr" in error && typeof error.stderr === "string" && error.stderr.length > 0 ? error.stderr : error.message; throw new HardhatError(HardhatError.ERRORS.HARDHAT_FOUNDRY.GENERAL.FORGE_REMAPPINGS_FAILED, { packagePath, stderr: errorMessage }); } } //# sourceMappingURL=forge.js.map