import type { AppExecutor, Executor, LibExecutor, ModuleExecutor, PkgExecutor, SysExecutor, WorkspaceExecutor, } from "../executors"; import { COMMAND_META, type CommandCls } from "./targetMeta"; export const argTypes = ["Argument", "Option"] as const; export type ArgType = (typeof argTypes)[number]; export const internalArgTypes = ["Workspace", "App", "Lib", "Sys", "Pkg", "Module", "Exec"] as const; export type InternalArgType = (typeof internalArgTypes)[number]; export type PrimitiveArgType = StringConstructor | NumberConstructor | BooleanConstructor; export type NormalizedPrimitiveArgType = "string" | "number" | "boolean"; export type CommandContext = { values: Record; app?: AppExecutor; lib?: LibExecutor; sys?: SysExecutor; pkg?: PkgExecutor; module?: ModuleExecutor; exec?: Executor; }; export type EnumChoice = string | number | { label: string; value: string | number | boolean }; export type EnumChoices = readonly EnumChoice[]; export type DynamicEnum = (context: Context) => EnumChoices | Promise; export interface ArgsOption { type?: "string" | "number" | "boolean"; flag?: string; desc?: string; default?: string | number | boolean; nullable?: boolean; example?: string | number | boolean; enum?: EnumChoices | DynamicEnum; ask?: string; } export interface ArgMeta { name: string; argsOption: ArgsOption; key: string; idx: number; type: ArgType; } export interface InternalArgMeta { key: string; idx: number; type: InternalArgType; option?: { nullable?: boolean }; } export const getArgMetas = ( command: CommandCls, key: string, ): [(ArgMeta | InternalArgMeta)[], ArgMeta[], (ArgMeta | InternalArgMeta)[]] => { const allArgMetas = [...(command[COMMAND_META]?.get(key)?.args ?? [])]; const argMetas = allArgMetas.filter((argMeta): argMeta is ArgMeta => argMeta.type === "Option"); const internalArgMetas = allArgMetas.filter((argMeta) => argMeta.type !== "Option"); return [allArgMetas, argMetas, internalArgMetas]; }; export interface InternalArgToken { type: Type; _value: T; } const createInternalArgToken = (type: Type) => ({ type }) as InternalArgToken; export const normalizePrimitiveArgType = (type: PrimitiveArgType): NormalizedPrimitiveArgType => { if (type === String) return "string"; if (type === Number) return "number"; if (type === Boolean) return "boolean"; throw new Error(`Invalid primitive argument type: ${type}`); }; export const App = createInternalArgToken("App"); export type App = AppExecutor; export const Lib = createInternalArgToken("Lib"); export type Lib = LibExecutor; export const Sys = createInternalArgToken("Sys"); export type Sys = SysExecutor; export const Exec = createInternalArgToken("Exec"); export type Exec = Executor; export const Pkg = createInternalArgToken("Pkg"); export type Pkg = PkgExecutor; export const Module = createInternalArgToken("Module"); export type Module = ModuleExecutor; export const Workspace = createInternalArgToken("Workspace"); export type Workspace = WorkspaceExecutor;