import { memoizeWithLRU } from '../memoize.js' import specs from './specs/index.js' export type CommandSpec = { name: string description?: string subcommands?: CommandSpec[] args?: Argument | Argument[] options?: Option[] } export type Argument = { name?: string description?: string isDangerous?: boolean isVariadic?: boolean // repeats infinitely e.g. echo hello world isOptional?: boolean isCommand?: boolean // wrapper commands e.g. timeout, sudo isModule?: string | boolean // for python -m and similar module args isScript?: boolean // script files e.g. node script.js } export type Option = { name: string | string[] description?: string args?: Argument | Argument[] isRequired?: boolean } export async function loadFigSpec( command: string, ): Promise { if (!command || command.includes('/') || command.includes('\\')) return null if (command.includes('..')) return null if (command.startsWith('-') && command !== '-') return null try { const module = await import(`@withfig/autocomplete/build/${command}.js`) return module.default || module } catch { return null } } export const getCommandSpec = memoizeWithLRU( async (command: string): Promise => { const spec = specs.find(s => s.name === command) || (await loadFigSpec(command)) || null return spec }, (command: string) => command, )