UNPKG

hereby

Version:
94 lines 3.38 kB
import fs from "node:fs"; import path from "node:path"; import { pathToFileURL } from "node:url"; import pc from "picocolors"; import { Task } from "../index.js"; import { UserError } from "./utils.js"; function isHerebyfile(p) { p = p.toLowerCase(); return p === "herebyfile.mjs" || p === "herebyfile.js"; } export async function findHerebyfile(dir) { const root = path.parse(dir).root; for (; dir !== root; dir = path.dirname(dir)) { const entries = await fs.promises.readdir(dir); const matching = entries.filter(isHerebyfile); if (matching.length > 1) { throw new UserError(`Found more than one Herebyfile: ${matching.join(", ")}`); } if (matching.length === 1) { const candidate = path.join(dir, matching[0]); const stat = await fs.promises.stat(candidate); if (!stat.isFile()) { throw new UserError(`${matching[0]} is not a file.`); } return candidate; } if (entries.includes("package.json")) { break; } } throw new UserError("Unable to find Herebyfile."); } export async function loadHerebyfile(herebyfilePath) { // Note: calling pathToFileURL is required on Windows to disambiguate URLs // from drive letters. const herebyfile = await import(pathToFileURL(herebyfilePath).toString()); const exportedTasks = new Set(); let defaultTask; for (const [key, value] of Object.entries(herebyfile)) { if (value instanceof Task) { if (key === "default") { defaultTask = value; } else if (exportedTasks.has(value)) { throw new UserError(`Task "${pc.blue(value.options.name)}" has been exported twice.`); } else { exportedTasks.add(value); } } } if (defaultTask) { exportedTasks.add(defaultTask); } if (exportedTasks.size === 0) { throw new UserError("No tasks found. Did you forget to export your tasks?"); } const tasks = [...exportedTasks.values()]; // We check this here by walking the DAG, as some dependencies may not be // exported and therefore would not be seen by the above loop. checkTaskInvariants(tasks); return { tasks, defaultTask, }; } function checkTaskInvariants(tasks) { const checkedTasks = new Set(); const taskStack = new Set(); const seenNames = new Set(); checkTaskInvariantsWorker(tasks); function checkTaskInvariantsWorker(tasks) { for (const task of tasks) { if (checkedTasks.has(task)) { continue; } if (taskStack.has(task)) { throw new UserError(`Task "${pc.blue(task.options.name)}" references itself.`); } const name = task.options.name; if (seenNames.has(name)) { throw new UserError(`Task "${pc.blue(name)}" was declared twice.`); } seenNames.add(name); if (task.options.dependencies) { taskStack.add(task); checkTaskInvariantsWorker(task.options.dependencies); taskStack.delete(task); } checkedTasks.add(task); } } } //# sourceMappingURL=loadHerebyfile.js.map