UNPKG

@megaorm/cli

Version:

This package allows you to communicate with MegaORM via commands directly from the command line interface (CLI).

170 lines 7.85 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.CommandHandler = exports.CommandHandlerError = void 0; const promises_1 = __importDefault(require("fs/promises")); const path_1 = require("path"); const test_1 = require("@megaorm/test"); /** * Custom error class for handling errors related to command operations. */ class CommandHandlerError extends Error { } exports.CommandHandlerError = CommandHandlerError; /** * Checks if the provided name matches the pattern for a valid command file. * * @param name The name to check if it matches a command file pattern. * @returns `true` if the name matches the command file pattern (e.g., `Fetch.js`), otherwise `false`. */ function isFile(name) { // Pattern example: Fetch.js return /^[A-Z][a-z0-9]*([A-Z][a-z0-9]*)*\.(ts|js)$/.test(name); } /** * Checks if the provided name matches the pattern for a valid TypeScript output file (either a map or declaration file). * * @param name - The name to check if it matches a TypeScript output file pattern. * @returns `true` if the name matches the pattern for a `.js.map` or `.d.ts` file, otherwise `false`. */ function isMappedFile(name) { // Pattern example: Fetch.js.map or Fetch.d.ts return /^[A-Z][a-z0-9]*([A-Z][a-z0-9]*)*(\.js\.map|\.d\.ts)$/.test(name); } /** * Safely deletes multiple command files at the specified paths. * * This function calls `unlink` for each path provided in the array, attempting to * remove each corresponding file. * * @param paths An array of strings representing the absolute paths of the command files to be deleted. * @returns A promise that resolves when all files are removed. */ function unlink(paths) { return new Promise((resolve, reject) => { return Promise.all(paths.map((path) => promises_1.default.unlink(path))) .then(resolve) .catch(reject); }); } /** * This class provides functionality for adding, and removing command files * */ class CommandHandler { /** * Instantiates a new CommandHandler. */ constructor() { this.assets = (0, path_1.resolve)(__dirname, '../../assets'); } /** * Collects the absolute paths of command files from the specified directory. * * @param path The directory path from which to collect command files. * @param map A boolean indicating whether to include mapped files (e.g., `.js.map`) in the resulting paths. * @returns A promise that resolves with an array of absolute paths to valid command files. * @throws `CommandHandlerError` if there is an issue collecting the files or if an invalid command file is encountered. */ collectPaths(path, map) { return new Promise((resolve, reject) => { promises_1.default.readdir(path) .then((result) => { // check if the directory is empty if ((0, test_1.isEmptyArr)(result)) return resolve(result); // filter map files const files = map ? result : result.filter((name) => !isMappedFile(name)); // validate each file for (const file of files) { if (!isFile(file)) { if (map && isMappedFile(file)) continue; return reject(new CommandHandlerError(`Invalid command file: ${String(file)}`)); } } return resolve(files.map((file) => (0, path_1.resolve)(path, file))); }) .catch((e) => reject(new CommandHandlerError(e.message))); }); } /** * Creates a new command file in the specified path. * * This method creates a new file for the specified command name in the given directory path. * You can choose to create a TypeScript file or a JavaScript file based on the provided boolean flag. * * @param name The PascalCase command name. * @param path The directory path where the command file will be created. * @param ts A boolean indicating whether to create a TypeScript file (`true`) or a JavaScript file (`false`). * @returns A promise that resolves with a success message indicating the path of the created command file. * @throws `CommandHandlerError` if the command name is invalid, the path is empty, or if any errors occur during file operations. * @note The command name must be in PascalCase, e.g., FetchCommand, RollbackCommand. */ add(name, path, ts) { return new Promise((resolve, reject) => { if (!(0, test_1.isPascalCase)(name)) { return reject(new CommandHandlerError(`Invalid command name: ${String(name)}`)); } if (!(0, test_1.isFullStr)(path)) { return reject(new CommandHandlerError(`Invalid path: ${String(path)}`)); } if (!(0, test_1.isBool)(ts)) ts = false; const ext = ts ? 'ts' : 'js'; const layout = ts ? 'ts/command.txt' : 'js/command.txt'; const content = (0, path_1.resolve)(this.assets, layout); promises_1.default.readFile(content, 'utf-8') .then((template) => { const className = name; const fileName = className.concat('.', ext); const filePath = (0, path_1.resolve)(path, fileName); const fileContent = template .replace(/\[className\]/g, className) .replace(/\[fileName\]/g, fileName); // Create command file promises_1.default.writeFile(filePath, fileContent, 'utf-8') .then(() => resolve(`Command added in: ${filePath}`)) .catch((e) => reject(new CommandHandlerError(e.message))); }) .catch((e) => reject(new CommandHandlerError(e.message))); }); } /** * Removes the command file in the specified path. * * @param name The PascalCase command name to be removed. * @param path The directory path where the command files are located. * @returns A promise that resolves with a success message indicating how many command files were removed. * @throws `CommandHandlerError` if the command name is invalid, the path is empty. * @note The command name must be in PascalCase, e.g., FetchCommand, RollbackCommand. */ remove(name, path) { return new Promise((resolve, reject) => { if (!(0, test_1.isPascalCase)(name)) { return reject(new CommandHandlerError(`Invalid command name: ${String(name)}`)); } if (!(0, test_1.isFullStr)(path)) { return reject(new CommandHandlerError(`Invalid path: ${String(path)}`)); } return this.collectPaths(path, true) .then((paths) => { const unlinkPaths = paths.filter((path) => new RegExp(`${name}\.(ts|js|js\.map|d\.ts)$`).test(path)); if (unlinkPaths.length === 0) { return Promise.reject(new CommandHandlerError(`No command file found for: ${name}`)); } const message = `${unlinkPaths.length} command file${unlinkPaths.length === 1 ? '' : 's'} removed in:\n${unlinkPaths.join('\n')}`; return unlink(unlinkPaths) .then(() => resolve(message)) .catch(reject); }) .catch(reject); }); } } exports.CommandHandler = CommandHandler; //# sourceMappingURL=CommandHandler.js.map