nadle
Version:
A type-safe, Gradle-inspired task runner for Node.js. Sharp tasks. Fast builds.
306 lines (301 loc) • 8.78 kB
JavaScript
import {
SupportReporters
} from "./chunk-AHRK4KLP.js";
import {
Nadle
} from "./chunk-32YKTXZB.js";
import {
ConfigurationError,
DASH,
Messages,
SupportLogLevels,
UNDERSCORE
} from "./chunk-U2TDD2B5.js";
// packages/nadle/src/cli.ts
import Process from "process";
import yargs from "yargs";
import { hideBin } from "yargs/helpers";
// packages/nadle/src/core/options/cli-options.ts
import { CONFIG_FILE_PATTERN } from "@nadle/project-resolver";
var CLIOptions = {
configFile: {
key: "config",
options: {
alias: "c",
type: "string",
description: "Path to config file",
defaultDescription: `<cwd>/${CONFIG_FILE_PATTERN}`
}
},
list: {
key: "list",
options: {
alias: "l",
default: false,
type: "boolean",
description: "List all available tasks"
}
},
listWorkspaces: {
key: "list-workspaces",
options: {
default: false,
type: "boolean",
description: "List all available workspaces"
}
},
parallel: {
key: "parallel",
options: {
default: false,
type: "boolean",
description: "Run all specified tasks in parallel regardless of their order, while still respecting task dependencies."
}
},
dryRun: {
key: "dry-run",
options: {
alias: "m",
default: false,
type: "boolean",
description: "Run specified tasks in dry run mode"
}
},
stacktrace: {
key: "stacktrace",
options: {
default: false,
type: "boolean",
description: "Print stacktrace on error"
}
},
showConfig: {
key: "show-config",
options: {
default: false,
type: "boolean",
description: "Print the resolved configuration"
}
},
configKey: {
key: "config-key",
options: {
type: "string",
description: "Path to a specific resolved configuration value, using dot/bracket notation",
defaultDescription: "undefined"
}
},
footer: {
key: "footer",
options: {
type: "boolean",
defaultDescription: "!isCI && isTTY",
description: "Enables the in-progress summary footer during task execution"
}
},
reporter: {
key: "reporter",
options: {
type: "string",
defaultDescription: "default",
choices: SupportReporters,
description: "Output reporter: 'default' (human) or 'agent' (compact, plain, for agents/scripts)"
}
},
cache: {
key: "cache",
options: {
hidden: true,
type: "boolean"
}
},
// @ts-expect-error to show --no-cache option when using -h
noCache: {
key: "no-cache",
options: {
type: "boolean",
defaultDescription: "false",
description: "Disable task caching. All tasks will be executed and their results will not be stored"
}
},
cacheDir: {
key: "cache-dir",
options: {
type: "string",
defaultDescription: "<projectDir>/node_modules/.cache/nadle",
description: "Directory to store task cache results"
}
},
cleanCache: {
key: "clean-cache",
options: {
type: "boolean",
default: false,
description: "Deletes all files in the cache directory. Can be used with --cache-dir to specify a custom location"
}
},
summary: {
key: "summary",
options: {
type: "boolean",
default: false,
description: "Print a summary of executed tasks at the end of the run"
}
},
exclude: {
key: "exclude",
options: {
type: "string",
alias: "x",
description: "Tasks to exclude from execution",
array: true,
coerce: coerceList
}
},
logLevel: {
key: "log-level",
options: {
type: "string",
defaultDescription: "log",
choices: SupportLogLevels,
describe: "Set the logging level"
}
},
minWorkers: {
key: "min-workers",
options: {
type: "string",
describe: "Minimum number of workers (integer or percentage)",
defaultDescription: "Os.availableParallelism() - 1",
coerce: createWorkerCoercer("min")
}
},
maxWorkers: {
key: "max-workers",
options: {
type: "string",
describe: "Maximum number of workers (integer or percentage)",
defaultDescription: "Os.availableParallelism() - 1",
coerce: createWorkerCoercer("max")
}
}
};
function coerceList(val) {
return val.flatMap((v) => v.split(",").map((s) => s.trim())).filter(Boolean);
}
function createWorkerCoercer(type) {
return (workers) => {
if (workers === void 0) {
return void 0;
}
if (/^\d+$/.test(workers)) {
return Number(workers);
}
if (/^\d+(\.\d+)?%$/.test(workers)) {
return workers;
}
throw new ConfigurationError(Messages.InvalidWorkerConfig(type, workers));
};
}
// packages/nadle/src/core/options/cli-options-resolver.ts
var aliases = Object.values(CLIOptions).map(({ options }) => options.alias).filter(Boolean);
var exclude = (keyMatcher) => (arg) => {
if (typeof keyMatcher === "function" && keyMatcher(arg.key)) {
return null;
}
if (typeof keyMatcher === "string" && arg.key === keyMatcher) {
return null;
}
return arg;
};
var transform = (targetKey, options) => (arg) => {
if (arg.key !== targetKey) {
return arg;
}
if (arg.value === void 0) {
return null;
}
return { key: options.transformKey ?? arg.key, value: options.transformValue ? options.transformValue(arg.value) : arg.value };
};
var transformers = [
transform("--", { transformKey: "passthroughArgs" }),
exclude((key) => aliases.includes(key)),
exclude((key) => key.includes(DASH)),
exclude("$0"),
exclude(UNDERSCORE),
transform("config", { transformKey: "configFile" }),
transform("cache", { transformValue: Boolean }),
transform("exclude", { transformKey: "excludedTasks" })
];
var transformer = (arg) => {
let transformedArg = arg;
for (const transformer2 of transformers) {
transformedArg = transformer2(transformedArg);
if (transformedArg === null) {
return null;
}
}
return transformedArg;
};
var CLIOptionsResolver = class {
static resolve(argv2) {
const { tasks = [], ...rest } = argv2;
const resolvedOptions = { tasks };
for (const [key, value] of Object.entries(rest)) {
const transformedArg = transformer({ key, value });
if (transformedArg) {
Object.assign(resolvedOptions, { [transformedArg.key]: transformedArg.value });
}
}
return resolvedOptions;
}
};
// packages/nadle/src/cli.ts
var argv = yargs(hideBin(Process.argv)).scriptName("nadle").command("$0 [tasks...]", "Execute one or more named tasks").options({
[CLIOptions.list.key]: CLIOptions.list.options,
[CLIOptions.cache.key]: CLIOptions.cache.options,
[CLIOptions.dryRun.key]: CLIOptions.dryRun.options,
[CLIOptions.footer.key]: CLIOptions.footer.options,
[CLIOptions.exclude.key]: CLIOptions.exclude.options,
[CLIOptions.noCache.key]: CLIOptions.noCache.options,
[CLIOptions.summary.key]: CLIOptions.summary.options,
[CLIOptions.reporter.key]: CLIOptions.reporter.options,
[CLIOptions.parallel.key]: CLIOptions.parallel.options,
[CLIOptions.cacheDir.key]: CLIOptions.cacheDir.options,
[CLIOptions.logLevel.key]: CLIOptions.logLevel.options,
[CLIOptions.configKey.key]: CLIOptions.configKey.options,
[CLIOptions.configFile.key]: CLIOptions.configFile.options,
[CLIOptions.minWorkers.key]: CLIOptions.minWorkers.options,
[CLIOptions.maxWorkers.key]: CLIOptions.maxWorkers.options,
[CLIOptions.cleanCache.key]: CLIOptions.cleanCache.options,
[CLIOptions.showConfig.key]: CLIOptions.showConfig.options,
[CLIOptions.stacktrace.key]: CLIOptions.stacktrace.options,
[CLIOptions.listWorkspaces.key]: CLIOptions.listWorkspaces.options
}).version("version", "Show version number", Nadle.version).alias("v", "version").help("help", "Show this help").alias("h", "help").group(
[
CLIOptions.parallel.key,
CLIOptions.exclude.key,
CLIOptions.noCache.key,
CLIOptions.cleanCache.key,
CLIOptions.list.key,
CLIOptions.listWorkspaces.key,
CLIOptions.dryRun.key,
CLIOptions.showConfig.key,
CLIOptions.configKey.key,
CLIOptions.stacktrace.key
],
"Execution options:"
).group(
[
CLIOptions.configFile.key,
CLIOptions.cacheDir.key,
CLIOptions.logLevel.key,
CLIOptions.minWorkers.key,
CLIOptions.maxWorkers.key,
CLIOptions.footer.key,
CLIOptions.summary.key
],
"General options:"
).group(["help", "version"], "Miscellaneous options:").example("nadle test -- -u", "Run the test task, passing -u through to its underlying command").parserConfiguration({ "populate--": true }).wrap(100).strict().parseSync();
new Nadle(CLIOptionsResolver.resolve(argv)).execute();