UNPKG

nadle

Version:

A type-safe, Gradle-inspired task runner for Node.js. Sharp tasks. Fast builds.

244 lines (233 loc) 8.69 kB
#!/usr/bin/env node // packages/nadle/src/core/utilities/utils.ts import Path from "path"; import c from "tinyrainbow"; // packages/nadle/src/core/utilities/constants.ts var ESC = "\x1B["; var ERASE_DOWN = `${ESC}J`; var ERASE_SCROLLBACK = `${ESC}3J`; var CURSOR_TO_START = `${ESC}1;1H`; var HIDE_CURSOR = `${ESC}?25l`; var CLEAR_SCREEN = "\x1Bc"; var COLON = ":"; var DOT = "."; var UNDERSCORE = "_"; var CROSS = "\xD7"; var CHECK = "\u2713"; var DASH = "-"; var CURVE_ARROW = "\u21A9"; var RIGHT_ARROW = "\u2192"; var VERTICAL_BAR = "|"; var LINES = { UP_RIGHT: "\u2514", VERTICAL: "\u2502", HORIZONTAL: "\u2500", VERTICAL_RIGHT: "\u251C" }; var DEFAULT_CACHE_DIR_NAME = "node_modules/.cache/nadle"; // packages/nadle/src/core/utilities/utils.ts function noop() { } function capitalize(str) { if (str.length === 0) { return str; } return str.charAt(0).toUpperCase() + str.slice(1); } var MILLISECONDS_PER_SECOND = 1e3; var MILLISECONDS_PER_MINUTE = 60 * MILLISECONDS_PER_SECOND; var MILLISECONDS_PER_HOUR = 60 * MILLISECONDS_PER_MINUTE; function formatTime(ms) { const hours = Math.floor(ms / MILLISECONDS_PER_HOUR); const minutes = Math.floor(ms % MILLISECONDS_PER_HOUR / MILLISECONDS_PER_MINUTE); const seconds = Math.floor(ms % MILLISECONDS_PER_MINUTE / MILLISECONDS_PER_SECOND); const milliseconds = Math.floor(ms % MILLISECONDS_PER_SECOND); if (hours > 0) { if (minutes > 0) { return `${hours}h${minutes}m`; } return `${hours}h`; } if (minutes > 0) { if (seconds > 0) { return `${minutes}m${seconds}s`; } return `${minutes}m`; } if (seconds > 0) { return `${seconds}s`; } return `${milliseconds}ms`; } function normalizeGlobPath(path) { if (path.startsWith(DOT)) { return path; } return `.${Path.sep}${path}`; } function clamp(value, min, max) { return Math.min(Math.max(value, min), max); } function bindObject(obj, keys) { return Object.fromEntries( keys.map((key) => { const value = obj[key]; if (typeof value !== "function") { throw new Error(`Property ${String(key)} is not a function`); } return [key, value.bind(obj)]; }) ); } function highlight(text) { return c.bold(c.yellow(text)); } // packages/nadle/src/core/utilities/maybe-array.ts var MaybeArray; ((MaybeArray2) => { function toArray(value) { return Array.isArray(value) ? value : [value]; } MaybeArray2.toArray = toArray; })(MaybeArray || (MaybeArray = {})); // packages/nadle/src/core/utilities/nadle-error.ts var NadleError = class extends Error { constructor(message, errorCode = 1, options) { super(message, options); this.name = "NadleError"; this.errorCode = errorCode; } }; var ConfigurationError = class extends NadleError { constructor(message) { super(message, 2); this.name = "ConfigurationError"; } }; var TaskNotFoundError = class extends NadleError { constructor(message) { super(message, 3); this.name = "TaskNotFoundError"; } }; var CyclicDependencyError = class extends NadleError { constructor(message) { super(message, 4); this.name = "CyclicDependencyError"; } }; var TaskExecutionError = class extends NadleError { constructor(message, options) { super(message, 1, options); this.name = "TaskExecutionError"; } }; // packages/nadle/src/core/utilities/consola.ts import { isCI, isTest } from "std-env"; import { LogLevels, createConsola } from "consola"; var [BasicReporter] = createConsola({ fancy: false }).options.reporters; var [FancyReporter] = createConsola({ fancy: true }).options.reporters; var CIReporter = class { log(logObj, ctx) { BasicReporter.log({ ...logObj, type: "" }, ctx); } }; function createConsolaReporters() { if (isTest) { return [BasicReporter]; } if (isCI) { return [new CIReporter()]; } return [FancyReporter]; } function createPlainReporters() { return [new CIReporter()]; } function createNadleConsola(logLevel = "log") { return createConsola({ level: LogLevels[logLevel], formatOptions: { date: false }, reporters: createConsolaReporters() }); } var SupportLogLevels = ["error", "log", "info", "debug"]; // packages/nadle/src/core/utilities/messages.ts import { CONFIG_FILE_PATTERN } from "@nadle/project-resolver"; var Messages = { InvalidConfigureUsage: () => `configure function can only be called from the root workspace.`, SpecifiedConfigFileNotFound: (filePath) => `Config file not found at ${highlight(filePath)}. Please check the path.`, InvalidWorkerConfig: (type, value) => `Invalid value for --${type}-workers. Expect to be an integer or a percentage (e.g., 50%). Got: ${highlight(value)}`, ConfigFileNotFound: (projectPath) => `No ${CONFIG_FILE_PATTERN}} found in ${highlight(projectPath)} directory or parent directories. Please use --config to specify a custom path.`, CycleDetected: (cyclePath) => `Cycle detected in task ${cyclePath}. Please resolve the cycle before executing tasks.`, DuplicatedTaskName: (taskName, workspaceId) => `Task ${highlight(taskName)} already registered in workspace ${highlight(workspaceId)}`, NoTasksFound: () => `No tasks were specified. Please specify one or more tasks to execute, or use the ${highlight("--list")} option to view available tasks.`, PassthroughArgsNotice: (args, taskLabels) => `Passing extra arguments [${args.join(" ")}] to ${taskLabels.length} tasks: ${taskLabels.join(", ")}`, UnresolvedTaskWithoutSuggestions: (taskNameInput, targetWorkspaceId) => `Task ${highlight(taskNameInput)} not found in ${highlight(targetWorkspaceId)} workspace.`, InvalidTaskName: (taskName) => `Invalid task name: ${highlight(taskName)}. Task names must contain only letters, numbers, and dashes; start with a letter, and not end with a dash.`, UnresolvedTaskWithSuggestions: (options) => `Task ${highlight(options.taskNameInput)} not found in ${highlight(options.targetWorkspaceId)}${options.fallbackWorkspaceId ? ` nor ${highlight(options.fallbackWorkspaceId)}` : ""} workspace. ${options.suggestions}`, UnresolvedTaskPattern: (options) => `No task matching pattern ${highlight(options.pattern)} found in ${highlight(options.targetWorkspaceId)}${options.fallbackWorkspaceId ? ` nor ${highlight(options.fallbackWorkspaceId)}` : ""} workspace.`, EmptyWorkspaceLabel: (workspaceId) => `Workspace ${highlight(workspaceId)} alias can not be empty.`, UnresolvedWorkspace: (workspaceInput, suggestions) => `Workspace ${highlight(workspaceInput)} not found. ${suggestions}`, WorkspaceNotFound: (workspaceInput, availableWorkspaces) => `Workspace ${highlight(workspaceInput)} not found. Available workspaces: ${availableWorkspaces}.`, WorkspaceIdNotFound: (workspaceId, availableWorkspaces) => `Workspace with id ${highlight(workspaceId)} not found. Available workspaces: ${availableWorkspaces}.`, DuplicatedWorkspaceLabelWithOtherLabel: (workspaceId, workspaceLabel, duplicatedWorkspaceId) => `Workspace ${highlight(workspaceId)} has a duplicated label ${highlight(workspaceLabel)} with workspace ${highlight(duplicatedWorkspaceId)}. Please check the alias configuration in the configuration file.`, DuplicatedWorkspaceLabelWithOtherId: (workspaceId, workspaceLabel, duplicatedWorkspaceId) => `Workspace ${highlight(workspaceId)} has a label ${highlight(workspaceLabel)} that is the same as workspace ${highlight(duplicatedWorkspaceId)}'s id. Please check the alias configuration in the configuration file.` }; // packages/nadle/src/core/utilities/fs.ts import Fs from "fs/promises"; async function isPathExists(path) { try { await Fs.access(path); return true; } catch { return false; } } // packages/nadle/src/core/nadle-context.ts import AsyncHooks from "async_hooks"; var nadleContext = new AsyncHooks.AsyncLocalStorage(); function runWithInstance(instance, fn) { return nadleContext.run(instance, fn); } function getCurrentInstance() { const instance = nadleContext.getStore(); if (!instance) { throw new Error("No active Nadle instance \u2014 tasks must be registered during config loading"); } return instance; } export { ERASE_DOWN, ERASE_SCROLLBACK, CURSOR_TO_START, HIDE_CURSOR, CLEAR_SCREEN, COLON, UNDERSCORE, CROSS, CHECK, DASH, CURVE_ARROW, RIGHT_ARROW, VERTICAL_BAR, LINES, DEFAULT_CACHE_DIR_NAME, noop, capitalize, formatTime, normalizeGlobPath, clamp, bindObject, highlight, Messages, isPathExists, MaybeArray, NadleError, ConfigurationError, TaskNotFoundError, CyclicDependencyError, TaskExecutionError, runWithInstance, getCurrentInstance, LogLevels, createPlainReporters, createNadleConsola, SupportLogLevels };