poku
Version:
🐷 Poku makes testing easy for Node.js, Bun, Deno, and you at the same time.
151 lines (149 loc) • 7.83 kB
JavaScript
import { env, exit } from "node:process";
import { GLOBAL, log$1 as log, format, isWindows, hasArg, VERSION, getArg, getPaths, argToArray, states, hr, escapeRegExp, kill, envFile, poku } from "../modules/_shared.js";
import { existsSync } from "node:fs";
import { readFile } from "node:fs/promises";
import { join } from "node:path";
import "node:os";
import "node:child_process";
import "node:assert";
import "node:assert/strict";
import "node:net";
const getConfigs = async (customPath) => {
const expectedFiles = customPath ? [customPath] : ["poku.config.js", ".pokurc.json", ".pokurc.jsonc"];
for (const file of expectedFiles) {
const filePath = join(GLOBAL.cwd, file), path = isWindows ? `file://${filePath}` : filePath;
try {
if (!existsSync(filePath)) continue;
if (filePath.endsWith("js") || filePath.endsWith("ts")) {
const mod = await import(path);
return mod?.default ?? mod;
}
const [{ JSONC }, configsFile] = await Promise.all([
import("./jsonc.js"),
readFile(filePath, "utf8")
]);
return JSONC.parse(configsFile);
} catch (error) {
log(
`${format("\u26A0").bold()} Failed to load config file ${format(file).bold()}:`
);
const message = error instanceof Error ? error.message : String(error);
log(`${format(message).fail()}`);
}
}
return /* @__PURE__ */ Object.create(null);
};
(async () => {
if (hasArg("version") || hasArg("v", "-")) {
log(VERSION);
return;
}
if (hasArg("help") || hasArg("h", "-")) {
(await import("./help.js")).help();
return;
}
const enforce = hasArg("enforce") || hasArg("x", "-"), configFile = getArg("config") || getArg("c", "-");
GLOBAL.configsFromFile = await getConfigs(configFile);
const { configsFromFile } = GLOBAL, dirs = getPaths("-") ?? (configsFromFile?.include ? Array.prototype.concat(configsFromFile?.include) : ["."]), filter = getArg("filter") ?? configsFromFile?.filter, exclude = getArg("exclude") ?? configsFromFile?.exclude, killPort = getArg("killPort"), killRange = getArg("killRange"), killPID = getArg("killPid"), reporter = getArg("reporter") ?? getArg("r", "-") ?? GLOBAL.configsFromFile.reporter ?? "poku", denoAllow = argToArray("denoAllow") ?? configsFromFile?.deno?.allow, denoDeny = argToArray("denoDeny") ?? configsFromFile?.deno?.deny, quiet = hasArg("quiet") || hasArg("q", "-") || configsFromFile?.quiet, debug = hasArg("debug") || hasArg("d", "-") || configsFromFile?.debug, failFast = hasArg("failFast") || configsFromFile?.failFast, watchMode = hasArg("watch") || hasArg("w", "-"), hasEnvFile = hasArg("envFile"), concurrency = (() => {
const value = Number(getArg("concurrency"));
return Number.isNaN(value) ? configsFromFile?.concurrency : value;
})(), timeout = (() => {
const value = Number(getArg("timeout"));
return Number.isNaN(value) ? configsFromFile?.timeout : value;
})(), sequential = hasArg("sequential") || configsFromFile?.sequential, isolation = getArg("isolation") || configsFromFile?.isolation, testNamePattern = getArg("testNamePattern") ?? getArg("t", "-") ?? configsFromFile?.testNamePattern, testSkipPattern = getArg("testSkipPattern") ?? configsFromFile?.testSkipPattern;
if (dirs.length === 1 && (states.isSinglePath = !0), hasArg("listFiles")) {
const { listFiles } = await import("../modules/_shared.js").then(function(n) {
return n.listFiles$1;
}), files = [];
hr();
for (const dir of dirs)
files.push(
...await listFiles(dir, {
filter: typeof filter == "string" ? new RegExp(escapeRegExp(filter)) : filter,
exclude: typeof exclude == "string" ? new RegExp(escapeRegExp(exclude)) : exclude
})
);
log(
files.sort().map((file) => `${format("-").dim()} ${file}`).join(`
`)
), hr(), log(`Total test files: ${format(String(files.length)).bold()}`), hr();
return;
}
if (GLOBAL.configFile = configFile, env.POKU_RUNTIME = GLOBAL.runtime, env.POKU_REPORTER = typeof reporter == "string" ? reporter : "poku", GLOBAL.configs = {
filter: typeof filter == "string" ? new RegExp(escapeRegExp(filter)) : filter,
exclude: typeof exclude == "string" ? new RegExp(escapeRegExp(exclude)) : exclude,
concurrency,
timeout,
sequential,
isolation,
quiet,
debug,
failFast,
deno: {
allow: denoAllow,
deny: denoDeny
},
noExit: watchMode,
reporter,
testNamePattern: typeof testNamePattern == "string" ? new RegExp(escapeRegExp(testNamePattern)) : testNamePattern,
testSkipPattern: typeof testSkipPattern == "string" ? new RegExp(escapeRegExp(testSkipPattern)) : testSkipPattern,
beforeEach: "beforeEach" in configsFromFile ? configsFromFile.beforeEach : void 0,
afterEach: "afterEach" in configsFromFile ? configsFromFile.afterEach : void 0,
plugins: "plugins" in configsFromFile ? configsFromFile.plugins : void 0
}, hasArg("coverage")) {
const customPkg = getArg("coverage");
customPkg && !/^(@[a-z0-9][a-z0-9-_.]*\/)?[a-z0-9][a-z0-9-_.]*$/i.test(customPkg) && (log("Coverage plugin must be a valid package name."), exit(1));
const coveragePackages = customPkg ? [customPkg] : [
"@pokujs/c8",
"@pokujs/monocart",
"@pokujs/one-double-zero",
"@pokujs/istanbul",
"@pokujs/coverage"
], existingPlugins = GLOBAL.configs.plugins ?? [];
if (!existingPlugins.some(
(plugin) => plugin.name !== void 0 && coveragePackages.includes(plugin.name)
)) {
let loaded = !1;
for (const pkg of coveragePackages)
try {
const { coverage } = await import(pkg);
GLOBAL.configs.plugins = existingPlugins, GLOBAL.configs.plugins.push(coverage()), loaded = !0;
break;
} catch {
}
loaded || (hr(), log(
customPkg ? `Coverage plugin not found: ${format(customPkg).bold()}` : `To use ${format("--coverage").bold()}, install a coverage plugin, for example:
${coveragePackages.map((pkg) => ` ${format("npm i -D").dim()} ${format(pkg).underline()}`).join(`
`)}`
), hr(), exit(1));
}
}
typeof testNamePattern == "string" && (env.POKU_TEST_NAME_PATTERN = testNamePattern), typeof testSkipPattern == "string" && (env.POKU_TEST_SKIP_PATTERN = testSkipPattern);
const tasks = [];
if ((hasEnvFile || configsFromFile?.envFile) && (GLOBAL.envFile = getArg("envFile") ?? configsFromFile?.envFile ?? ".env"), enforce && (await import("./enforce.js")).enforce(), killPort || configsFromFile?.kill?.port) {
const ports = killPort?.split(",").map(Number) || configsFromFile?.kill?.port || [];
tasks.push(kill.port(ports));
}
if (killRange || configsFromFile?.kill?.range) {
const ranges = killRange?.split(",") || configsFromFile?.kill?.range?.map((range) => `${range[0]}-${range[1]}`) || [];
for (const range of ranges) {
const ports = range.split("-").map(Number), startsAt = ports[0], endsAt = ports[1];
tasks.push(kill.range(startsAt, endsAt));
}
}
if (killPID || configsFromFile?.kill?.pid) {
const PIDs = killPID?.split(",").map(Number) || configsFromFile?.kill?.pid || [];
tasks.push(kill.pid(PIDs));
}
GLOBAL.envFile && tasks.push(envFile(GLOBAL.envFile)), (debug || configsFromFile?.debug) && (hr(), log(`${format(" Debug Enabled ").bg("brightBlue")}
`), log(`${format("\u2026").info().italic()} ${format("Options").bold()}`), console.dir(GLOBAL.configs, {
depth: Number.POSITIVE_INFINITY,
colors: !0
}), log(
`
${format("\u{1F4A1}")} To list all test files, run: ${format("poku --listFiles").bold()}`
)), await Promise.all(tasks), await poku(dirs), watchMode ? import("./watch.js").then((mod) => {
mod.startWatch(dirs);
}) : GLOBAL.runtime === "deno" && setImmediate(exit);
})();