import { promisify } from 'node:util'; import child_process from 'node:child_process'; export const exec = promisify(child_process.exec); export const { execSync } = child_process; import { Command, Option } from '../../src/t.js'; import { packageJsonScriptCompletion, packageJsonDependencyCompletion, } from '../completions/completion-producers.js'; import { getWorkspacePatterns } from './filesystem-utils.js'; export interface LazyCommand extends Command { _lazyCommand?: string; _optionsLoaded?: boolean; optionsRaw?: Map; } export type CompletionHandler = ( complete: (value: string, description: string) => void ) => void; export type OptionHandlers = Record; export const commonOptionHandlers: OptionHandlers = { workspace(complete) { const patterns = getWorkspacePatterns(); patterns.forEach((p) => complete(p, `Workspace pattern: ${p}`)); }, }; export function setupLazyOptionLoading( cmd: LazyCommand, command: string, _packageManager: string, loadOptionsSync: (cmd: LazyCommand, command: string) => void ): void { cmd._lazyCommand = command; cmd._optionsLoaded = false; const store = cmd.options; cmd.optionsRaw = store; Object.defineProperty(cmd, 'options', { get() { if (!this._optionsLoaded) { this._optionsLoaded = true; loadOptionsSync(this, this._lazyCommand); } return store; }, configurable: true, }); } export function setupCommandArguments( cmd: LazyCommand, command: string, _packageManager: string ): void { if (['remove', 'rm', 'uninstall', 'un', 'update', 'up'].includes(command)) { cmd.argument('package', packageJsonDependencyCompletion); } if (['run', 'run-script'].includes(command)) { cmd.argument('script', packageJsonScriptCompletion, true); } } export async function safeExec( command: string, options: any = {} ): Promise { try { const { stdout } = await exec(command, { encoding: 'utf8' as const, timeout: 500, maxBuffer: 4 * 1024 * 1024, ...options, }); return stdout as unknown as string; } catch (error) { if (error instanceof Error && 'stdout' in error) { return (error as any).stdout as string; } return ''; } } export function safeExecSync(command: string, options: any = {}): string { try { return execSync(command, { encoding: 'utf8' as const, timeout: 500, ...options, }) as unknown as string; } catch (error: any) { return error?.stdout ? (error.stdout as string) : ''; } } export function createLogLevelHandler(levels: string[]): CompletionHandler { return (complete) => levels.forEach((lvl) => complete(lvl, ' ')); }