UNPKG

yargs-file-commands

Version:

A yargs helper function that lets you define your commands structure via directory and file naming conventions.

86 lines (85 loc) 3.33 kB
import fs from 'fs'; import {} from 'yargs'; /** * Imports a command module from a file * @async * @param {string} filePath - Path to the command file * @param {string} name - Command name * @param {ImportCommandOptions} options - Import options * @returns {Promise<CommandModule>} Imported command module * * @description * Dynamically imports a command file and constructs a Yargs command module. * Supports two styles of command declaration: * 1. Single export of CommandModule named 'command' * 2. Individual exports of command parts (command, describe, alias, etc.) * If no handler is provided, creates a null implementation. */ export const importCommandFromFile = async (filePath, name, options) => { // ensure file exists using fs node library if (!fs.existsSync(filePath)) { throw new Error(`Can not import command from non-existent file path: ${filePath}`); } const url = 'file://' + filePath; const { logLevel = 'info' } = options; // Import the module const imported = await import(url); // Check if this is the default command const isDefault = name === '$default'; // First try to use the CommandModule export if it exists if ('command' in imported && typeof imported.command === 'object' && imported.command !== null) { const commandModule = imported.command; // Ensure the command property exists or use the filename if (!commandModule.command && !isDefault) { commandModule.command = name; } else if (isDefault && !commandModule.command) { commandModule.command = '$0'; } if (logLevel === 'debug') { console.debug('Importing CommandModule from', filePath, 'as', name, 'with description', commandModule.describe); } // Return the command module directly without wrapping return { command: commandModule.command, describe: commandModule.describe, builder: commandModule.builder, handler: commandModule.handler, deprecated: commandModule.deprecated, aliases: commandModule.aliases }; } // Fall back to individual exports const handlerModule = imported; const command = { command: handlerModule.command ?? (isDefault ? '$0' : name), describe: handlerModule.describe, aliases: handlerModule.aliases, builder: handlerModule.builder, deprecated: handlerModule.deprecated, handler: handlerModule.handler ?? (async (args) => { // null implementation }) }; // Validate exports const supportedNames = [ 'command', 'describe', 'alias', 'builder', 'deprecated', 'handler' ]; const module = imported; const unsupportedExports = Object.keys(module).filter((key) => !supportedNames.includes(key)); if (unsupportedExports.length > 0) { throw new Error(`Command module ${name} in ${filePath} has some unsupported exports, probably a misspelling: ${unsupportedExports.join(', ')}`); } if (logLevel === 'debug') { console.debug('Importing individual exports from', filePath, 'as', name, 'with description', command.describe); } return command; };