163 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import * as plugins from './smartcli.plugins.js';
 | 
						|
import { getUserArgs } from './smartcli.helpers.js';
 | 
						|
 | 
						|
// interfaces
 | 
						|
export interface ICommandObservableObject {
 | 
						|
  commandName: string;
 | 
						|
  subject: plugins.smartrx.rxjs.Subject<any>;
 | 
						|
}
 | 
						|
 | 
						|
const logger = new plugins.smartlog.ConsoleLog();
 | 
						|
 | 
						|
/**
 | 
						|
 * class to create a new instance of Smartcli. Handles parsing of command line arguments.
 | 
						|
 */
 | 
						|
export class Smartcli {
 | 
						|
  /**
 | 
						|
   * this Deferred contains the parsed result in the end
 | 
						|
   */
 | 
						|
  public parseCompleted = plugins.smartpromise.defer<any>();
 | 
						|
 | 
						|
  public version: string;
 | 
						|
 | 
						|
  /**
 | 
						|
   * map of all Trigger/Observable objects to keep track
 | 
						|
   */
 | 
						|
  private commandObservableMap = new plugins.lik.ObjectMap<ICommandObservableObject>();
 | 
						|
 | 
						|
  /**
 | 
						|
   * maps alias
 | 
						|
   */
 | 
						|
  public aliasObject: { [key: string]: string[] } = {};
 | 
						|
 | 
						|
  /**
 | 
						|
   * The constructor of Smartcli
 | 
						|
   */
 | 
						|
  constructor() {}
 | 
						|
 | 
						|
  /**
 | 
						|
   * adds an alias, meaning one equals the other in terms of command execution.
 | 
						|
   */
 | 
						|
  public addCommandAlias(originalArg: string, aliasArg: string): void {
 | 
						|
    this.aliasObject[originalArg] = this.aliasObject[originalArg] || [];
 | 
						|
    this.aliasObject[originalArg].push(aliasArg);
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * adds a Command by returning a Promise that reacts to the specific commandString given.
 | 
						|
   * Note: in e.g. "npm install something" the "install" is considered the command.
 | 
						|
   */
 | 
						|
  public addCommand(commandNameArg: string): plugins.smartrx.rxjs.Subject<any> {
 | 
						|
    let commandSubject: plugins.smartrx.rxjs.Subject<any>;
 | 
						|
    const existingCommandSubject = this.getCommandSubject(commandNameArg);
 | 
						|
    commandSubject = existingCommandSubject || new plugins.smartrx.rxjs.Subject<any>();
 | 
						|
 | 
						|
    this.commandObservableMap.add({
 | 
						|
      commandName: commandNameArg,
 | 
						|
      subject: commandSubject,
 | 
						|
    });
 | 
						|
    return commandSubject;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * execute trigger by name
 | 
						|
   * @param commandNameArg - the name of the command to trigger
 | 
						|
   */
 | 
						|
  public triggerCommand(commandNameArg: string, argvObject: any) {
 | 
						|
    const triggerSubject = this.getCommandSubject(commandNameArg);
 | 
						|
    triggerSubject.next(argvObject);
 | 
						|
    return triggerSubject;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * gets the command subject for the specified name.
 | 
						|
   * call this before calling .parse()
 | 
						|
   * @param commandNameArg 
 | 
						|
   * @returns 
 | 
						|
   */
 | 
						|
  public getCommandSubject(commandNameArg: string) {
 | 
						|
    const triggerObservableObject = this.commandObservableMap.findSync(
 | 
						|
      (triggerObservableObjectArg) => {
 | 
						|
        return triggerObservableObjectArg.commandName === commandNameArg;
 | 
						|
      }
 | 
						|
    );
 | 
						|
    if (triggerObservableObject) {
 | 
						|
      return triggerObservableObject.subject;
 | 
						|
    } else {
 | 
						|
      return null;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * getOption
 | 
						|
   */
 | 
						|
  public getOption(optionNameArg: string) {
 | 
						|
    const userArgs = getUserArgs(process.argv);
 | 
						|
    const parsedYargs = plugins.yargsParser(userArgs);
 | 
						|
    return parsedYargs[optionNameArg];
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * allows to specify help text to be printed above the rest of the help text
 | 
						|
   */
 | 
						|
  public addHelp(optionsArg: { helpText: string }) {
 | 
						|
    this.addCommand('help').subscribe((argvArg) => {
 | 
						|
      logger.log('info', optionsArg.helpText);
 | 
						|
    });
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * specify version to be printed for -v --version
 | 
						|
   */
 | 
						|
  public addVersion(versionArg: string) {
 | 
						|
    this.version = versionArg;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * adds a trigger that is called when no command is specified
 | 
						|
   */
 | 
						|
  public standardCommand(): plugins.smartrx.rxjs.Subject<any> {
 | 
						|
    const standardSubject = this.addCommand('standardCommand');
 | 
						|
    return standardSubject;
 | 
						|
  }
 | 
						|
 | 
						|
  /**
 | 
						|
   * start the process of evaluating commands
 | 
						|
   */
 | 
						|
  public startParse(): void {
 | 
						|
    // Get user arguments, properly handling Node.js, Deno (run/compiled), and Bun
 | 
						|
    // Pass process.argv explicitly to handle test scenarios where it's modified
 | 
						|
    const userArgs = getUserArgs(process.argv);
 | 
						|
    const parsedYArgs = plugins.yargsParser(userArgs);
 | 
						|
    const wantedCommand = parsedYArgs._[0];
 | 
						|
 | 
						|
    // lets handle some standards
 | 
						|
    if (!wantedCommand && (parsedYArgs.v || parsedYArgs.version)) {
 | 
						|
      console.log(this.version || 'unknown version');
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    console.log(`Wanted command: ${wantedCommand}`);
 | 
						|
    for (const command of this.commandObservableMap.getArray()) {
 | 
						|
      if (!wantedCommand) {
 | 
						|
        const standardCommand = this.commandObservableMap.findSync((commandArg) => {
 | 
						|
          return commandArg.commandName === 'standardCommand';
 | 
						|
        });
 | 
						|
        if (standardCommand) {
 | 
						|
          standardCommand.subject.next(parsedYArgs);
 | 
						|
        } else {
 | 
						|
          console.log('no smartcli standard task was created or assigned.');
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      if (command.commandName === parsedYArgs._[0]) {
 | 
						|
        command.subject.next(parsedYArgs);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      if (this.aliasObject[parsedYArgs[0]]) {
 | 
						|
      }
 | 
						|
    }
 | 
						|
    this.parseCompleted.resolve(parsedYArgs);
 | 
						|
    return;
 | 
						|
  }
 | 
						|
}
 |