@kidd-cli/core 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["match"],"sources":["../src/context/error.ts","../src/context/output.ts","../src/context/prompts.ts","../src/context/store.ts","../src/context/create-context.ts","../src/autoloader.ts","../src/runtime/args/zod.ts","../src/runtime/args/parser.ts","../src/runtime/args/register.ts","../src/runtime/register.ts","../src/runtime/runner.ts","../src/runtime/runtime.ts","../src/cli.ts","../src/command.ts","../src/compose.ts"],"sourcesContent":["import type { Tagged } from '@kidd-cli/utils/tag'\nimport { TAG, hasTag, withTag } from '@kidd-cli/utils/tag'\n\nimport { DEFAULT_EXIT_CODE } from '@/utils/constants.js'\n\nexport { DEFAULT_EXIT_CODE }\n\n/**\n * Plain data representation of a ContextError (no Error prototype).\n *\n * Useful for serializing error data without carrying the Error prototype chain,\n * for example when logging or forwarding errors across process boundaries.\n */\nexport type ContextErrorData = Tagged<\n {\n readonly code: string | undefined\n readonly exitCode: number\n readonly message: string\n },\n 'ContextError'\n>\n\n/**\n * An Error subtype carrying an exit code and optional error code.\n *\n * Created by {@link createContextError} and thrown by `ctx.fail()`.\n * The CLI boundary catches these to produce clean, user-facing error output\n * with the correct process exit code.\n */\nexport type ContextError = Error &\n Tagged<\n {\n readonly code: string | undefined\n readonly exitCode: number\n },\n 'ContextError'\n >\n\n/**\n * Create a ContextError with an exit code and optional error code.\n *\n * Used to surface user-facing CLI errors with clean messages.\n * The error carries a Symbol-based tag for reliable type-narrowing\n * via {@link isContextError}.\n *\n * @param message - Human-readable error message.\n * @param options - Optional error code and exit code overrides.\n * @returns A ContextError instance.\n */\nexport function createContextError(\n message: string,\n options?: { code?: string; exitCode?: number }\n): ContextError {\n const data = createContextErrorData(message, options)\n // Accepted exception: Error construction requires `new Error()` then property decoration.\n // The `as` cast and Object.defineProperty mutations are the only way to produce a\n // Tagged Error subtype without using a class.\n const error = new Error(data.message) as ContextError\n error.name = 'ContextError'\n // Intentional mutation: decorating an Error object with immutable properties.\n Object.defineProperty(error, TAG, { enumerable: false, value: 'ContextError', writable: false })\n Object.defineProperty(error, 'code', { enumerable: true, value: data.code, writable: false })\n Object.defineProperty(error, 'exitCode', {\n enumerable: true,\n value: data.exitCode,\n writable: false,\n })\n return error\n}\n\n/**\n * Type guard that narrows an unknown value to {@link ContextError}.\n *\n * Checks that the value is an Error instance whose `[TAG]` property\n * equals `'ContextError'`, which distinguishes CLI-layer errors from\n * unexpected exceptions.\n *\n * @param error - The value to check.\n * @returns `true` when the value is a ContextError.\n */\nexport function isContextError(error: unknown): error is ContextError {\n if (error instanceof Error) {\n return hasTag(error, 'ContextError')\n }\n return false\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\nfunction resolveExitCode(options: { code?: string; exitCode?: number } | undefined): number {\n if (options && options.exitCode !== undefined) {\n return options.exitCode\n }\n return DEFAULT_EXIT_CODE\n}\n\nfunction resolveCode(\n options: { code?: string; exitCode?: number } | undefined\n): string | undefined {\n if (options && options.code !== undefined) {\n return options.code\n }\n return undefined\n}\n\nfunction createContextErrorData(\n message: string,\n options?: { code?: string; exitCode?: number }\n): ContextErrorData {\n return withTag(\n {\n code: resolveCode(options),\n exitCode: resolveExitCode(options),\n message,\n },\n 'ContextError'\n )\n}\n","import { jsonStringify } from '@kidd-cli/utils/json'\n\nimport type { Output, OutputOptions } from './types.js'\n\n/**\n * Create the structured output methods for a context.\n *\n * @private\n * @param stream - The writable stream to write output to.\n * @returns An Output instance backed by the given stream.\n */\nexport function createContextOutput(stream: NodeJS.WriteStream): Output {\n return {\n markdown(content: string): void {\n stream.write(`${content}\\n`)\n },\n raw(content: string): void {\n stream.write(content)\n },\n table(rows: Record<string, unknown>[], options?: OutputOptions): void {\n if (options && options.json) {\n const [, json] = jsonStringify(rows, { pretty: true })\n stream.write(`${json}\\n`)\n return\n }\n if (rows.length === 0) {\n return\n }\n const [firstRow] = rows\n if (!firstRow) {\n return\n }\n writeTableToStream(stream, rows, Object.keys(firstRow))\n },\n write(data: unknown, options?: OutputOptions): void {\n if ((options && options.json) || (typeof data === 'object' && data !== null)) {\n const [, json] = jsonStringify(data, { pretty: true })\n stream.write(`${json}\\n`)\n } else {\n stream.write(`${String(data)}\\n`)\n }\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Format an unknown value as a string for table cell display.\n *\n * @private\n * @param val - The value to format.\n * @returns The stringified value, or empty string for undefined.\n */\nfunction formatStringValue(val: unknown): string {\n if (val === undefined) {\n return ''\n }\n return String(val)\n}\n\n/**\n * Options for creating a table header string.\n */\ninterface TableHeaderOptions {\n keys: string[]\n widths: (number | undefined)[]\n}\n\n/**\n * Create a padded header row string from column keys and widths.\n *\n * @private\n * @param options - The keys and column widths.\n * @returns A formatted header string.\n */\nfunction createTableHeader(options: TableHeaderOptions): string {\n const { keys, widths } = options\n return keys\n .map((key, idx) => {\n const width = widths[idx]\n if (width === undefined) {\n return key\n }\n return key.padEnd(width)\n })\n .join(' ')\n}\n\n/**\n * Options for creating a table row string.\n */\ninterface TableRowOptions {\n row: Record<string, unknown>\n keys: string[]\n widths: (number | undefined)[]\n}\n\n/**\n * Create a padded row string from a data record, column keys, and widths.\n *\n * @private\n * @param options - The row data, keys, and column widths.\n * @returns A formatted row string.\n */\nfunction createTableRow(options: TableRowOptions): string {\n const { row, keys, widths } = options\n return keys\n .map((key, idx) => {\n const width = widths[idx]\n const val = formatStringValue(row[key])\n if (width === undefined) {\n return val\n }\n return val.padEnd(width)\n })\n .join(' ')\n}\n\n/**\n * Compute the maximum column width for each key across all rows.\n *\n * @private\n * @param rows - The data rows.\n * @param keys - The column keys.\n * @returns An array of column widths.\n */\nfunction computeColumnWidths(rows: Record<string, unknown>[], keys: string[]): number[] {\n return keys.map((key) => {\n const values = rows.map((row) => formatStringValue(row[key]))\n return Math.max(key.length, ...values.map((val) => val.length))\n })\n}\n\n/**\n * Write a formatted table (header, separator, rows) to a writable stream.\n *\n * @private\n * @param stream - The writable stream.\n * @param rows - The data rows.\n * @param keys - The column keys.\n */\nfunction writeTableToStream(\n stream: NodeJS.WriteStream,\n rows: Record<string, unknown>[],\n keys: string[]\n): void {\n const widths = computeColumnWidths(rows, keys)\n const header = createTableHeader({ keys, widths })\n const separator = widths.map((width) => '-'.repeat(width)).join(' ')\n const dataRows = rows.map((row) => createTableRow({ keys, row, widths }))\n const content = [header, separator, ...dataRows].join('\\n')\n stream.write(`${content}\\n`)\n}\n","import * as clack from '@clack/prompts'\n\nimport { DEFAULT_EXIT_CODE, createContextError } from './error.js'\nimport type { Prompts } from './types.js'\n\n/**\n * Create the interactive prompt methods for a context.\n *\n * @returns A Prompts instance backed by clack.\n */\nexport function createContextPrompts(): Prompts {\n return {\n async confirm(opts): Promise<boolean> {\n const result = await clack.confirm(opts)\n return unwrapCancelSignal(result)\n },\n async multiselect<Type>(opts: Parameters<Prompts['multiselect']>[0]): Promise<Type[]> {\n const result = await clack.multiselect<Type>(\n opts as Parameters<typeof clack.multiselect<Type>>[0]\n )\n return unwrapCancelSignal(result)\n },\n async password(opts): Promise<string> {\n const result = await clack.password(opts)\n return unwrapCancelSignal(result)\n },\n async select<Type>(opts: Parameters<Prompts['select']>[0]): Promise<Type> {\n const result = await clack.select<Type>(opts as Parameters<typeof clack.select<Type>>[0])\n return unwrapCancelSignal(result)\n },\n async text(opts): Promise<string> {\n const result = await clack.text(opts)\n return unwrapCancelSignal(result)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Unwrap a prompt result that may be a cancel symbol.\n *\n * If the user cancelled (Ctrl-C), throws a ContextError. Otherwise returns\n * the typed result value.\n *\n * @private\n * @param result - The raw prompt result (value or cancel symbol).\n * @returns The unwrapped typed value.\n */\nfunction unwrapCancelSignal<Type>(result: Type | symbol): Type {\n if (clack.isCancel(result)) {\n clack.cancel('Operation cancelled.')\n // Accepted exception: prompt cancellation must propagate as an unwind.\n // The runner catches the thrown ContextError at the CLI boundary.\n throw createContextError('Prompt cancelled by user', {\n code: 'PROMPT_CANCELLED',\n exitCode: DEFAULT_EXIT_CODE,\n })\n }\n return result as Type\n}\n","import type { Store } from './types.js'\n\n/**\n * Create an in-memory key-value store.\n *\n * @private\n * @returns A Store instance backed by a Map.\n */\nexport function createMemoryStore<TMap extends Record<string, unknown>>(): Store<TMap> {\n const map = new Map<string, unknown>()\n\n return {\n clear(): void {\n map.clear()\n },\n delete(key: string): boolean {\n return map.delete(key)\n },\n get<Key extends Extract<keyof TMap, string>>(key: Key): TMap[Key] | undefined {\n return map.get(key) as TMap[Key] | undefined\n },\n has(key: string): boolean {\n return map.has(key)\n },\n set<Key extends Extract<keyof TMap, string>>(key: Key, value: TMap[Key]): void {\n map.set(key, value)\n },\n }\n}\n","import * as clack from '@clack/prompts'\n\nimport { createCliLogger } from '@/lib/logger.js'\nimport type { CliLogger } from '@/lib/logger.js'\nimport type { AnyRecord, KiddStore, Merge } from '@/types.js'\n\nimport { createContextError } from './error.js'\nimport { createContextOutput } from './output.js'\nimport { createContextPrompts } from './prompts.js'\nimport { createMemoryStore } from './store.js'\nimport type { Context, Meta, Output, Prompts, Spinner, Store, StoreMap } from './types.js'\n\n/**\n * Options for creating a {@link Context} instance via {@link createContext}.\n *\n * Carries the parsed args, validated config, and CLI metadata needed to\n * assemble a fully-wired context. An optional `logger` override allows\n * callers to inject a custom {@link CliLogger}; when omitted a default\n * @clack/prompts-backed instance is used.\n */\nexport interface CreateContextOptions<TArgs extends AnyRecord, TConfig extends AnyRecord> {\n readonly args: TArgs\n readonly config: TConfig\n readonly meta: { readonly name: string; readonly version: string; readonly command: string[] }\n readonly logger?: CliLogger\n readonly output?: NodeJS.WriteStream\n}\n\n/**\n * Create the {@link Context} object threaded through middleware and command handlers.\n *\n * Assembles logger, spinner, output, store, prompts, and meta from\n * the provided options into a single immutable context. Each sub-system is\n * constructed via its own factory so this function remains a lean orchestrator.\n *\n * @param options - Args, config, and meta for the current invocation.\n * @returns A fully constructed Context.\n */\nexport function createContext<TArgs extends AnyRecord, TConfig extends AnyRecord>(\n options: CreateContextOptions<TArgs, TConfig>\n): Context<TArgs, TConfig> {\n const ctxLogger: CliLogger = options.logger ?? createCliLogger()\n const ctxSpinner: Spinner = clack.spinner()\n const ctxOutput: Output = createContextOutput(options.output ?? process.stdout)\n const ctxStore: Store<Merge<KiddStore, StoreMap>> = createMemoryStore()\n const ctxPrompts: Prompts = createContextPrompts()\n const ctxMeta: Meta = {\n command: options.meta.command,\n name: options.meta.name,\n version: options.meta.version,\n }\n\n // Middleware-augmented properties (e.g. `auth`) are added at runtime.\n // See `decorateContext` — they are intentionally absent here.\n return {\n args: options.args as Context<TArgs, TConfig>['args'],\n config: options.config as Context<TArgs, TConfig>['config'],\n fail(message: string, failOptions?: { code?: string; exitCode?: number }): never {\n // Accepted exception: ctx.fail() is typed `never` and caught by the CLI boundary.\n // This is the framework's halt mechanism — the runner catches the thrown ContextError.\n throw createContextError(message, failOptions)\n },\n logger: ctxLogger,\n meta: ctxMeta as Context<TArgs, TConfig>['meta'],\n output: ctxOutput,\n prompts: ctxPrompts,\n spinner: ctxSpinner,\n store: ctxStore,\n } as Context<TArgs, TConfig>\n}\n","import type { Dirent } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { basename, extname, join, resolve } from 'node:path'\n\nimport { isPlainObject, isString } from '@kidd-cli/utils/fp'\nimport { hasTag, withTag } from '@kidd-cli/utils/tag'\n\nimport type { AutoloadOptions, Command, CommandMap } from './types.js'\n\nconst VALID_EXTENSIONS = new Set(['.ts', '.js', '.mjs'])\nconst INDEX_NAME = 'index'\n\n/**\n * Scan a directory for command files and produce a CommandMap.\n *\n * @param options - Autoload configuration (directory override, etc.).\n * @returns A promise resolving to a CommandMap built from the directory tree.\n */\nexport async function autoload(options?: AutoloadOptions): Promise<CommandMap> {\n const dir = resolveDir(options)\n const entries = await readdir(dir, { withFileTypes: true })\n\n const fileEntries = entries.filter(isCommandFile)\n const dirEntries = entries.filter(isCommandDir)\n\n const fileResults = await Promise.all(\n fileEntries.map(async (entry): Promise<[string, Command] | undefined> => {\n const cmd = await importCommand(join(dir, entry.name))\n if (!cmd) {\n return undefined\n }\n return [deriveCommandName(entry), cmd]\n })\n )\n\n const dirResults = await Promise.all(\n dirEntries.map((entry) => buildDirCommand(join(dir, entry.name)))\n )\n\n const allResults = [...fileResults, ...dirResults]\n const validPairs = allResults.filter((pair): pair is [string, Command] => pair !== undefined)\n\n const commandMap: CommandMap = Object.fromEntries(validPairs)\n return commandMap\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the target directory from autoload options.\n *\n * @private\n * @param options - Optional autoload configuration.\n * @returns The resolved absolute directory path.\n */\nfunction resolveDir(options?: AutoloadOptions): string {\n if (options && isString(options.dir)) {\n return resolve(options.dir)\n }\n return resolve('./commands')\n}\n\n/**\n * Scan a subdirectory and assemble it as a parent command with subcommands.\n *\n * If the directory contains an `index.ts`/`index.js`, that becomes the parent\n * handler. Otherwise a handler-less group command is created that demands a\n * subcommand.\n *\n * @private\n * @param dir - Absolute path to the subdirectory.\n * @returns A tuple of [name, Command] or undefined if the directory is empty.\n */\nasync function buildDirCommand(dir: string): Promise<[string, Command] | undefined> {\n const name = basename(dir)\n const dirEntries = await readdir(dir, { withFileTypes: true })\n const subCommands = await buildSubCommands(dir, dirEntries)\n const indexFile = findIndexInEntries(dirEntries)\n\n if (indexFile) {\n const parentCommand = await importCommand(join(dir, indexFile.name))\n if (parentCommand) {\n return [name, withTag({ ...parentCommand, commands: subCommands }, 'Command')]\n }\n }\n\n if (Object.keys(subCommands).length === 0) {\n return undefined\n }\n\n return [name, withTag({ commands: subCommands }, 'Command')]\n}\n\n/**\n * Build subcommands from already-read directory entries, avoiding a redundant readdir call.\n *\n * @private\n * @param dir - Absolute path to the directory.\n * @param entries - Pre-read directory entries.\n * @returns A CommandMap built from the entries.\n */\nasync function buildSubCommands(dir: string, entries: Dirent[]): Promise<CommandMap> {\n const fileEntries = entries.filter(isCommandFile)\n const dirEntries = entries.filter(isCommandDir)\n\n const fileResults = await Promise.all(\n fileEntries.map(async (entry): Promise<[string, Command] | undefined> => {\n const cmd = await importCommand(join(dir, entry.name))\n if (!cmd) {\n return undefined\n }\n return [deriveCommandName(entry), cmd]\n })\n )\n\n const dirResults = await Promise.all(\n dirEntries.map((entry) => buildDirCommand(join(dir, entry.name)))\n )\n\n const allResults = [...fileResults, ...dirResults]\n const validPairs = allResults.filter((pair): pair is [string, Command] => pair !== undefined)\n\n const commandMap: CommandMap = Object.fromEntries(validPairs)\n return commandMap\n}\n\n/**\n * Find the index file (index.ts or index.js) in pre-read directory entries.\n *\n * @private\n * @param entries - Pre-read directory entries.\n * @returns The index file's Dirent or undefined.\n */\nfunction findIndexInEntries(entries: Dirent[]): Dirent | undefined {\n return entries.find(\n (entry) =>\n entry.isFile() &&\n VALID_EXTENSIONS.has(extname(entry.name)) &&\n basename(entry.name, extname(entry.name)) === INDEX_NAME\n )\n}\n\n/**\n * Dynamically import a file and validate that its default export is a Command.\n *\n * @private\n * @param filePath - Absolute path to the file to import.\n * @returns The Command if valid, or undefined.\n */\nasync function importCommand(filePath: string): Promise<Command | undefined> {\n const mod: unknown = await import(filePath)\n if (isCommandExport(mod)) {\n return mod.default\n }\n return undefined\n}\n\n/**\n * Check whether a module's default export is a Command object.\n *\n * ES module namespace objects have a null prototype, so isPlainObject\n * rejects them. We only need to verify the namespace is a non-null\n * object with a default export that is a plain Command object.\n *\n * @private\n * @param mod - The imported module to inspect.\n * @returns True when the module has a Command as its default export.\n */\nfunction isCommandExport(mod: unknown): mod is { default: Command } {\n if (typeof mod !== 'object' || mod === null) {\n return false\n }\n if (!('default' in mod)) {\n return false\n }\n const def: unknown = mod.default\n if (!isPlainObject(def)) {\n return false\n }\n return hasTag(def, 'Command')\n}\n\n/**\n * Derive a command name from a directory entry by stripping its extension.\n *\n * @private\n * @param entry - The directory entry to derive the name from.\n * @returns The file name without its extension.\n */\nfunction deriveCommandName(entry: Dirent): string {\n return basename(entry.name, extname(entry.name))\n}\n\n/**\n * Predicate: entry is a command file (.ts/.js, not index, not _/. prefixed).\n *\n * @private\n * @param entry - The directory entry to check.\n * @returns True when the entry is a valid command file.\n */\nfunction isCommandFile(entry: Dirent): boolean {\n if (!entry.isFile()) {\n return false\n }\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) {\n return false\n }\n if (!VALID_EXTENSIONS.has(extname(entry.name))) {\n return false\n }\n return deriveCommandName(entry) !== INDEX_NAME\n}\n\n/**\n * Predicate: entry is a scannable command directory (not _/. prefixed).\n *\n * @private\n * @param entry - The directory entry to check.\n * @returns True when the entry is a valid command directory.\n */\nfunction isCommandDir(entry: Dirent): boolean {\n if (!entry.isDirectory()) {\n return false\n }\n return !entry.name.startsWith('_') && !entry.name.startsWith('.')\n}\n","import { match } from 'ts-pattern'\nimport type { Options as YargsOptions } from 'yargs'\nimport type { z } from 'zod'\n\n/**\n * Type guard that checks whether a value is a zod object schema.\n *\n * @param args - The value to check.\n * @returns True when args is a ZodObject.\n */\nexport function isZodSchema(args: unknown): args is z.ZodObject<z.ZodRawShape> {\n return (\n typeof args === 'object' &&\n args !== null &&\n '_def' in args &&\n typeof (args as { _def: unknown })._def === 'object' &&\n (args as { _def: { type?: string } })._def !== null &&\n (args as { _def: { type?: string } })._def.type === 'object'\n )\n}\n\n/**\n * Convert an entire zod object schema into a record of yargs options.\n *\n * @param schema - The zod object schema.\n * @returns A record mapping field names to yargs option definitions.\n */\nexport function zodSchemaToYargsOptions(\n schema: z.ZodObject<z.ZodRawShape>\n): Record<string, YargsOptions> {\n const shape = schema.shape as Record<string, z.ZodTypeAny>\n return Object.fromEntries(\n Object.entries(shape).map(([key, fieldSchema]): [string, YargsOptions] => [\n key,\n getZodTypeOption(fieldSchema),\n ])\n )\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\ninterface ZodDef {\n type?: string\n innerType?: z.ZodTypeAny\n defaultValue?: unknown\n}\n\ninterface ZodTypeInfo {\n defaultValue: unknown\n inner: z.ZodTypeAny\n isOptional: boolean\n}\n\ninterface UnwrapOptions {\n def: ZodDef\n current: z.ZodTypeAny\n defaultValue: unknown\n}\n\ninterface UnwrapRecursiveOptions {\n current: z.ZodTypeAny\n isOptional: boolean\n defaultValue: unknown\n}\n\n/**\n * Extract a default value from a zod definition, falling back to the provided value.\n *\n * @private\n * @param def - The zod definition to inspect.\n * @param fallback - Value to return when no default is defined.\n * @returns The resolved default value.\n */\nfunction resolveDefaultValue(def: ZodDef, fallback: unknown): unknown {\n if (def.defaultValue !== undefined) {\n return def.defaultValue\n }\n return fallback\n}\n\n/**\n * Unwrap a ZodOptional type, recursing into the inner type.\n *\n * @private\n * @param options - The unwrap options containing def, current type, and default value.\n * @returns Unwrapped type information.\n */\nfunction unwrapOptional(options: UnwrapOptions): ZodTypeInfo {\n const { def, current, defaultValue } = options\n if (def.innerType) {\n return unwrapZodTypeRecursive({ current: def.innerType, defaultValue, isOptional: true })\n }\n return { defaultValue, inner: current, isOptional: true }\n}\n\n/**\n * Unwrap a ZodDefault type, resolving its default value and recursing.\n *\n * @private\n * @param options - The unwrap options containing def, current type, and default value.\n * @returns Unwrapped type information with the resolved default.\n */\nfunction unwrapDefault(options: UnwrapOptions): ZodTypeInfo {\n const { def, current, defaultValue } = options\n const newDefault = resolveDefaultValue(def, defaultValue)\n if (def.innerType) {\n return unwrapZodTypeRecursive({\n current: def.innerType,\n defaultValue: newDefault,\n isOptional: true,\n })\n }\n return { defaultValue: newDefault, inner: current, isOptional: true }\n}\n\n/**\n * Recursively unwrap optional and default wrappers from a zod type.\n *\n * @private\n * @param options - The recursive unwrap options containing current type, optionality flag, and default value.\n * @returns The fully unwrapped type information.\n */\nfunction unwrapZodTypeRecursive(options: UnwrapRecursiveOptions): ZodTypeInfo {\n const { current, isOptional, defaultValue } = options\n const def = (current as { _def: ZodDef })._def\n if (def.type === 'optional') {\n return unwrapOptional({ current, def, defaultValue })\n }\n if (def.type === 'default') {\n return unwrapDefault({ current, def, defaultValue })\n }\n return { defaultValue, inner: current, isOptional }\n}\n\n/**\n * Unwrap a zod schema to extract its base type, optionality, and default value.\n *\n * @private\n * @param schema - The zod type to unwrap.\n * @returns The unwrapped type information.\n */\nfunction unwrapZodType(schema: z.ZodTypeAny): ZodTypeInfo {\n return unwrapZodTypeRecursive({ current: schema, defaultValue: undefined, isOptional: false })\n}\n\n/**\n * Map a zod type name to a yargs option type string.\n *\n * @private\n * @param typeName - The zod type name (e.g. 'string', 'number').\n * @returns The corresponding yargs type.\n */\nfunction resolveZodYargsType(\n typeName: string | undefined\n): 'string' | 'number' | 'boolean' | 'array' {\n return match(typeName)\n .with('string', () => 'string' as const)\n .with('number', () => 'number' as const)\n .with('boolean', () => 'boolean' as const)\n .with('array', () => 'array' as const)\n .otherwise(() => 'string' as const)\n}\n\n/**\n * Build a base yargs option from a zod schema's description and default.\n *\n * @private\n * @param inner - The unwrapped zod schema instance.\n * @param defaultValue - The resolved default value.\n * @returns A partial yargs option object.\n */\nfunction buildBaseOption(inner: z.ZodTypeAny, defaultValue: unknown): YargsOptions {\n const base: YargsOptions = {}\n const { description } = inner as { description?: string }\n if (description) {\n base.describe = description\n }\n if (defaultValue !== undefined) {\n base.default = defaultValue\n }\n return base\n}\n\n/**\n * Convert a single zod field schema into a complete yargs option definition.\n *\n * @private\n * @param schema - A single zod field type.\n * @returns A complete yargs option object.\n */\nfunction getZodTypeOption(schema: z.ZodTypeAny): YargsOptions {\n const { inner, isOptional, defaultValue } = unwrapZodType(schema)\n const innerDef = (inner as { _def: ZodDef })._def\n const base = {\n ...buildBaseOption(inner, defaultValue),\n type: resolveZodYargsType(innerDef.type),\n }\n if (!isOptional) {\n return { ...base, demandOption: true }\n }\n return base\n}\n","import { err, ok } from '@kidd-cli/utils/fp'\nimport type { Result } from '@kidd-cli/utils/fp'\nimport { formatZodIssues } from '@kidd-cli/utils/validate'\n\nimport type { Command } from '@/types.js'\n\nimport type { ArgsParser } from '../types.js'\nimport { isZodSchema } from './zod.js'\n\n/**\n * Create an args parser that cleans and validates raw parsed arguments.\n *\n * Captures the argument definition in a closure and returns an ArgsParser\n * whose `parse` method strips yargs-internal keys and validates against\n * a zod schema when one is defined.\n *\n * @param argsDef - The argument definition from the command.\n * @returns An ArgsParser with a parse method.\n */\nexport function createArgsParser(argsDef: Command['args']): ArgsParser {\n return {\n parse(rawArgs: Record<string, unknown>): Result<Record<string, unknown>, Error> {\n const cleaned = cleanParsedArgs(rawArgs)\n return validateArgs(argsDef, cleaned)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Strip yargs-internal keys (`_`, `$0`) and camelCase-duplicated hyphenated keys\n * from a parsed argv record, returning only user-defined arguments.\n *\n * @private\n * @param argv - Raw parsed argv from yargs.\n * @returns A cleaned record containing only user-defined arguments.\n */\nfunction cleanParsedArgs(argv: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(argv).filter(([key]) => key !== '_' && key !== '$0' && !key.includes('-'))\n )\n}\n\n/**\n * Validate parsed arguments against a zod schema when one is defined.\n *\n * If the command uses yargs-native args (no zod schema), the parsed args are\n * returned as-is. When a zod schema is present, validation is performed and\n * a Result error is returned on failure.\n *\n * @private\n * @param argsDef - The argument definition from the command.\n * @param parsedArgs - The cleaned parsed arguments.\n * @returns A Result containing validated arguments (zod-parsed when applicable).\n */\nfunction validateArgs(\n argsDef: Command['args'],\n parsedArgs: Record<string, unknown>\n): Result<Record<string, unknown>, Error> {\n if (!argsDef || !isZodSchema(argsDef)) {\n return ok(parsedArgs)\n }\n const result = argsDef.safeParse(parsedArgs)\n if (!result.success) {\n return err(new Error(`Invalid arguments:\\n ${formatZodIssues(result.error.issues).message}`))\n }\n return ok(result.data as Record<string, unknown>)\n}\n","import type { Argv, Options as YargsOptions } from 'yargs'\n\nimport type { Command, YargsArgDef } from '@/types.js'\n\nimport { isZodSchema, zodSchemaToYargsOptions } from './zod.js'\n\n/**\n * Register argument definitions on a yargs builder.\n *\n * Accepts either a zod object schema or a record of yargs-native arg definitions\n * and wires them as yargs options on the given builder instance.\n *\n * @param builder - The yargs Argv instance to register options on.\n * @param args - Argument definitions from a Command.\n */\nexport function registerCommandArgs(builder: Argv, args: Command['args']): void {\n if (!args) {\n return\n }\n if (isZodSchema(args)) {\n const options = zodSchemaToYargsOptions(args)\n for (const [key, opt] of Object.entries(options)) {\n builder.option(key, opt)\n }\n } else {\n for (const [key, def] of Object.entries(args)) {\n builder.option(key, yargsArgDefToOption(def))\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a yargs-native arg definition into a yargs option object.\n *\n * @private\n * @param def - The yargs arg definition.\n * @returns A yargs option object.\n */\nfunction yargsArgDefToOption(def: YargsArgDef): YargsOptions {\n return {\n alias: def.alias,\n choices: def.choices,\n default: def.default,\n demandOption: def.required ?? false,\n describe: def.description,\n type: def.type,\n }\n}\n","import { hasTag } from '@kidd-cli/utils/tag'\nimport type { Argv } from 'yargs'\n\nimport type { Context } from '@/context/types.js'\nimport type { Command, CommandMap, Middleware } from '@/types.js'\n\nimport { registerCommandArgs } from './args/index.js'\nimport type { ResolvedCommand, ResolvedRef } from './types.js'\n\n/**\n * Type guard that checks whether a value is a Command object.\n *\n * @param value - The value to test.\n * @returns True when the value has `[TAG] === 'Command'`.\n */\nexport function isCommand(value: unknown): value is Command {\n return hasTag(value, 'Command')\n}\n\n/**\n * Register all commands from a CommandMap on a yargs instance.\n *\n * Iterates over the command map, filters for valid Command objects,\n * and recursively registers each command (including subcommands) on\n * the provided yargs Argv instance.\n *\n * @param options - Registration options including the command map, yargs instance, and resolution ref.\n */\nexport function registerCommands(options: RegisterCommandsOptions): void {\n const { instance, commands, resolved, parentPath } = options\n const commandEntries = Object.entries(commands).filter((pair): pair is [string, Command] =>\n isCommand(pair[1])\n )\n\n for (const [name, entry] of commandEntries) {\n registerResolvedCommand({\n builder: instance,\n cmd: entry,\n instance,\n name,\n parentPath,\n resolved,\n })\n }\n}\n\nexport type { ResolvedCommand, ResolvedRef } from './types.js'\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\ninterface RegisterResolvedCommandOptions {\n builder: Argv\n cmd: Command\n instance: Argv\n name: string\n parentPath: string[]\n resolved: ResolvedRef\n}\n\ninterface RegisterCommandsOptions {\n commands: CommandMap\n instance: Argv\n parentPath: string[]\n resolved: ResolvedRef\n}\n\n/**\n * Register a single resolved command (and its subcommands) with yargs.\n *\n * Sets up the yargs command handler, wires argument definitions, and\n * recursively registers any nested subcommands. On match, stores the\n * resolved handler and command path in the shared ref.\n *\n * @private\n * @param options - Command registration context.\n */\nfunction registerResolvedCommand(options: RegisterResolvedCommandOptions): void {\n const { instance, name, cmd, resolved, parentPath } = options\n const description = cmd.description ?? ''\n\n instance.command(\n name,\n description,\n (builder: Argv) => {\n registerCommandArgs(builder, cmd.args)\n\n if (cmd.commands) {\n const subCommands = Object.entries(cmd.commands).filter((pair): pair is [string, Command] =>\n isCommand(pair[1])\n )\n\n for (const [subName, subEntry] of subCommands) {\n registerResolvedCommand({\n builder,\n cmd: subEntry,\n instance: builder,\n name: subName,\n parentPath: [...parentPath, name],\n resolved,\n })\n }\n\n if (cmd.handler) {\n builder.demandCommand(0)\n } else {\n builder.demandCommand(1, 'You must specify a subcommand.')\n }\n }\n\n return builder\n },\n () => {\n // Intentional mutation: yargs callback model requires mutable ref capture.\n // The `as` casts are accepted exceptions — generic handler/middleware types\n // Cannot be narrowed further inside the yargs callback boundary.\n resolved.ref = {\n args: cmd.args,\n commandPath: [...parentPath, name],\n handler: cmd.handler as ((ctx: Context) => Promise<void> | void) | undefined,\n middleware: (cmd.middleware ?? []) as Middleware[],\n }\n }\n )\n}\n","import type { Context } from '@/context/types.js'\nimport type { Middleware } from '@/types.js'\n\nimport type { Runner } from './types.js'\n\n/**\n * Create a runner that executes root and command middleware chains.\n *\n * Root middleware wraps the command middleware chain, which in turn wraps\n * the command handler — producing a nested onion lifecycle:\n *\n * ```\n * root middleware start →\n * command middleware start →\n * handler\n * command middleware end\n * root middleware end\n * ```\n *\n * @param rootMiddleware - Root-level middleware from `cli({ middleware })`.\n * @returns A Runner with an execute method.\n */\nexport function createRunner(rootMiddleware: Middleware[]): Runner {\n return {\n async execute({ ctx, handler, middleware }): Promise<void> {\n const commandHandler = async (innerCtx: Context): Promise<void> => {\n await runMiddlewareChain(middleware, innerCtx, handler)\n }\n await runMiddlewareChain(rootMiddleware, ctx, commandHandler)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Execute a middleware chain followed by a final handler.\n *\n * Runs each middleware in order, passing `ctx` and a `next` callback.\n * When all middleware have called `next()`, the final handler is invoked.\n * A middleware can short-circuit by not calling `next()`.\n *\n * @private\n * @param middlewares - Ordered array of middleware to execute.\n * @param ctx - The context object threaded through middleware and handler.\n * @param finalHandler - The command handler to invoke after all middleware.\n */\nasync function runMiddlewareChain(\n middlewares: Middleware[],\n ctx: Context,\n finalHandler: (ctx: Context) => Promise<void> | void\n): Promise<void> {\n async function executeChain(index: number): Promise<void> {\n if (index >= middlewares.length) {\n await finalHandler(ctx)\n return\n }\n const mw = middlewares[index]\n if (mw) {\n await mw.handler(ctx, () => executeChain(index + 1))\n }\n }\n\n await executeChain(0)\n}\n","import { attemptAsync, err, ok } from '@kidd-cli/utils/fp'\nimport type { AsyncResult } from '@kidd-cli/utils/fp'\nimport type { z } from 'zod'\n\nimport { createContext } from '@/context/index.js'\nimport type { Context } from '@/context/types.js'\nimport { createConfigClient } from '@/lib/config/index.js'\nimport type { CliConfigOptions, Middleware } from '@/types.js'\n\nimport { createArgsParser } from './args/index.js'\nimport { createRunner } from './runner.js'\nimport type { Runtime, RuntimeOptions } from './types.js'\n\n/**\n * Create a runtime that orchestrates config loading and middleware execution.\n *\n * Loads config up front, then captures it in a closure alongside a runner.\n * The returned `runtime.execute` method handles arg parsing, context creation,\n * and middleware chain execution for each command invocation.\n *\n * @param options - Runtime configuration including name, version, config, and middleware.\n * @returns An AsyncResult containing the runtime or an error.\n */\nexport async function createRuntime<TSchema extends z.ZodType>(\n options: RuntimeOptions<TSchema>\n): AsyncResult<Runtime, Error> {\n const config = await resolveConfig(options.config, options.name)\n\n const middleware: Middleware[] = options.middleware ?? []\n const runner = createRunner(middleware)\n\n const runtime: Runtime = {\n async execute(command): AsyncResult<void, Error> {\n const parser = createArgsParser(command.args)\n const [argsError, validatedArgs] = parser.parse(command.rawArgs)\n if (argsError) {\n return err(argsError)\n }\n\n const ctx = createContext({\n args: validatedArgs,\n config,\n meta: {\n command: [...command.commandPath],\n name: options.name,\n version: options.version,\n },\n })\n\n const finalHandler = command.handler ?? (async () => {})\n\n // Accepted exception: generic context assembly requires type assertions.\n // The generics are validated at the createContext call site.\n const [execError] = await attemptAsync(() =>\n runner.execute({\n ctx: ctx as Context,\n handler: finalHandler as (ctx: Context) => Promise<void> | void,\n middleware: command.middleware,\n })\n )\n if (execError) {\n return err(execError)\n }\n\n return ok()\n },\n }\n\n return ok(runtime)\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Load and validate a config file via the config client.\n *\n * Returns the validated config record or an empty object when no config\n * options are provided or when loading fails.\n *\n * @private\n * @param configOptions - Config loading options with schema and optional name override.\n * @param defaultName - Fallback config file name derived from the CLI name.\n * @returns The loaded config record or an empty object.\n */\nasync function resolveConfig<TSchema extends z.ZodType>(\n configOptions: CliConfigOptions<TSchema> | undefined,\n defaultName: string\n): Promise<Record<string, unknown>> {\n if (!configOptions || !configOptions.schema) {\n return {}\n }\n const client = createConfigClient({\n name: configOptions.name ?? defaultName,\n schema: configOptions.schema,\n })\n const [configError, configResult] = await client.load()\n if (configError || !configResult) {\n return {}\n }\n // Accepted exception: configResult.config is generic TOutput from zod schema.\n // The cast bridges the generic boundary to the internal Record type.\n return configResult.config as Record<string, unknown>\n}\n","import { resolve } from 'node:path'\n\nimport { loadConfig } from '@kidd-cli/config/loader'\nimport { P, attemptAsync, isPlainObject, isString, match } from '@kidd-cli/utils/fp'\nimport yargs from 'yargs'\nimport type { z } from 'zod'\n\nimport { DEFAULT_EXIT_CODE, isContextError } from '@/context/index.js'\nimport { createCliLogger } from '@/lib/logger.js'\nimport type { CliOptions, CommandMap } from '@/types.js'\n\nimport { autoload } from './autoloader.js'\nimport { createRuntime, registerCommands } from './runtime/index.js'\nimport type { ResolvedRef } from './runtime/index.js'\n\nconst ARGV_SLICE_START = 2\n\n/**\n * Bootstrap and run the CLI application.\n *\n * Parses argv, resolves the matched command, loads config, runs the\n * middleware chain, and invokes the command handler.\n *\n * @param options - CLI configuration including name, version, commands, and middleware.\n */\nexport async function cli<TSchema extends z.ZodType = z.ZodType>(\n options: CliOptions<TSchema>\n): Promise<void> {\n const logger = createCliLogger()\n\n const [uncaughtError, result] = await attemptAsync(async () => {\n const program = yargs(process.argv.slice(ARGV_SLICE_START))\n .scriptName(options.name)\n .version(options.version)\n .strict()\n .help()\n .option('cwd', {\n describe: 'Set the working directory',\n global: true,\n type: 'string',\n })\n\n if (options.description) {\n program.usage(options.description)\n }\n\n const resolved: ResolvedRef = { ref: undefined }\n\n const commands = await resolveCommands(options.commands)\n\n if (commands) {\n registerCommands({ commands, instance: program, parentPath: [], resolved })\n program.demandCommand(1, 'You must specify a command.')\n }\n\n const argv: Record<string, unknown> = await program.parseAsync()\n\n applyCwd(argv)\n\n if (!resolved.ref) {\n return undefined\n }\n\n const [runtimeError, runtime] = await createRuntime({\n config: options.config,\n middleware: options.middleware,\n name: options.name,\n version: options.version,\n })\n\n if (runtimeError) {\n return runtimeError\n }\n\n const [executeError] = await runtime.execute({\n args: resolved.ref.args,\n commandPath: resolved.ref.commandPath,\n handler: resolved.ref.handler,\n middleware: resolved.ref.middleware,\n rawArgs: argv,\n })\n\n return executeError\n })\n\n if (uncaughtError) {\n exitOnError(uncaughtError, logger)\n return\n }\n\n if (result) {\n exitOnError(result, logger)\n }\n}\n\nexport default cli\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the commands option to a CommandMap.\n *\n * Accepts a directory string (triggers autoload), a static CommandMap,\n * a Promise<CommandMap> (from autoload() called at the call site),\n * or undefined (loads `kidd.config.ts` and autoloads from its `commands` field,\n * falling back to `'./commands'`).\n *\n * @private\n * @param commands - The commands option from CliOptions.\n * @returns A CommandMap or undefined.\n */\nasync function resolveCommands(\n commands: string | CommandMap | Promise<CommandMap> | undefined\n): Promise<CommandMap | undefined> {\n if (isString(commands)) {\n return autoload({ dir: commands })\n }\n if (commands instanceof Promise) {\n return commands\n }\n if (isPlainObject(commands)) {\n return commands\n }\n return resolveCommandsFromConfig()\n}\n\n/**\n * Load `kidd.config.ts` and autoload commands from its `commands` field.\n *\n * Falls back to `'./commands'` when the config file is missing, fails to load,\n * or does not specify a `commands` field.\n *\n * @private\n * @returns A CommandMap autoloaded from the configured commands directory.\n */\nasync function resolveCommandsFromConfig(): Promise<CommandMap> {\n const DEFAULT_COMMANDS_DIR = './commands'\n\n const [configError, configResult] = await loadConfig()\n if (configError || !configResult) {\n return autoload({ dir: DEFAULT_COMMANDS_DIR })\n }\n\n const dir = configResult.config.commands ?? DEFAULT_COMMANDS_DIR\n return autoload({ dir })\n}\n\n/**\n * Change the process working directory when `--cwd` is provided.\n *\n * Resolves the value to an absolute path and calls `process.chdir()` so\n * that all downstream `process.cwd()` calls reflect the override.\n *\n * @private\n * @param argv - The parsed argv record from yargs.\n */\nfunction applyCwd(argv: Record<string, unknown>): void {\n if (isString(argv.cwd)) {\n process.chdir(resolve(argv.cwd))\n }\n}\n\n/**\n * Handle a CLI error by logging the message and exiting with the appropriate code.\n *\n * ContextErrors carry a custom exit code; all other errors exit with code 1.\n *\n * @private\n * @param error - The caught error value.\n * @param logger - Logger with an error method for output.\n */\nfunction exitOnError(error: unknown, logger: { error(msg: string): void }): void {\n const info = match(error)\n .when(isContextError, (e) => ({ exitCode: e.exitCode, message: e.message }))\n .with(P.instanceOf(Error), (e) => ({ exitCode: DEFAULT_EXIT_CODE, message: e.message }))\n .otherwise((e) => ({ exitCode: DEFAULT_EXIT_CODE, message: String(e) }))\n\n logger.error(info.message)\n process.exit(info.exitCode)\n}\n","import { withTag } from '@kidd-cli/utils/tag'\n\nimport type {\n ArgsDef,\n CommandDef,\n Middleware,\n MiddlewareEnv,\n Command as CommandType,\n} from './types.js'\n\n/**\n * Define a CLI command with typed args, config, and handler.\n *\n * The `const TMiddleware` generic preserves the middleware tuple as a literal type,\n * enabling TypeScript to extract and intersect `Variables` from each middleware\n * element onto the handler's `ctx` type.\n *\n * @param def - Command definition including description, args schema, middleware, and handler.\n * @returns A resolved Command object for registration in the command map.\n */\nexport function command<\n TArgsDef extends ArgsDef = ArgsDef,\n TConfig extends Record<string, unknown> = Record<string, unknown>,\n const TMiddleware extends readonly Middleware<MiddlewareEnv>[] =\n readonly Middleware<MiddlewareEnv>[],\n>(def: CommandDef<TArgsDef, TConfig, TMiddleware>): CommandType {\n return withTag({ ...def }, 'Command') as CommandType\n}\n","/**\n * Middleware combinator that merges multiple middleware into one.\n *\n * @module\n */\n\nimport { middleware } from './middleware.js'\nimport type { InferVariables, Middleware, MiddlewareEnv } from './types.js'\n\n/**\n * The composed return environment. Uses a conditional type to normalize\n * `unknown` (produced by empty tuples) into `Record<string, unknown>`,\n * satisfying the `MiddlewareEnv` constraint.\n */\ninterface ComposedEnv<TMiddleware extends readonly Middleware<MiddlewareEnv>[]> {\n readonly Variables: InferVariables<TMiddleware> extends infer V\n ? unknown extends V\n ? Record<string, unknown>\n : V\n : never\n}\n\n/**\n * Compose multiple middleware into a single middleware.\n *\n * Executes each middleware in order, threading `next()` through the chain.\n * The final `next()` call from the last composed middleware continues to\n * the downstream middleware or command handler.\n *\n * The returned middleware's type merges all `Variables` from the input tuple,\n * so downstream handlers see the combined context.\n *\n * @param middlewares - An ordered tuple of middleware to compose.\n * @returns A single Middleware whose Variables is the intersection of all input Variables.\n *\n * @example\n * ```ts\n * const combined = compose([auth({ strategies: [auth.env()] }), auth.require()])\n * ```\n */\nexport function compose<const TMiddleware extends readonly Middleware<MiddlewareEnv>[]>(\n middlewares: TMiddleware\n): Middleware<ComposedEnv<TMiddleware>> {\n return middleware((ctx, next) => executeChain(middlewares, 0, ctx, next)) as Middleware<\n ComposedEnv<TMiddleware>\n >\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively execute middleware in order, calling next() after the last one.\n *\n * @private\n * @param middlewares - The middleware array.\n * @param index - Current position in the array.\n * @param ctx - The context object.\n * @param next - The downstream next function.\n */\nasync function executeChain(\n middlewares: readonly Middleware<MiddlewareEnv>[],\n index: number,\n ctx: Parameters<Middleware['handler']>[0],\n next: () => Promise<void>\n): Promise<void> {\n if (index >= middlewares.length) {\n await next()\n return\n }\n\n const mw = middlewares[index]\n\n if (mw === undefined) {\n await next()\n return\n }\n\n await mw.handler(ctx, () => executeChain(middlewares, index + 1, ctx, next))\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["match"],"sources":["../src/context/error.ts","../src/context/output.ts","../src/context/prompts.ts","../src/context/store.ts","../src/context/create-context.ts","../src/autoloader.ts","../src/command.ts","../src/runtime/args/zod.ts","../src/runtime/args/parser.ts","../src/runtime/args/register.ts","../src/runtime/sort-commands.ts","../src/runtime/register.ts","../src/runtime/runner.ts","../src/runtime/runtime.ts","../src/cli.ts","../src/compose.ts"],"sourcesContent":["import type { Tagged } from '@kidd-cli/utils/tag'\nimport { TAG, hasTag, withTag } from '@kidd-cli/utils/tag'\n\nimport { DEFAULT_EXIT_CODE } from '@/utils/constants.js'\n\nexport { DEFAULT_EXIT_CODE }\n\n/**\n * Plain data representation of a ContextError (no Error prototype).\n *\n * Useful for serializing error data without carrying the Error prototype chain,\n * for example when logging or forwarding errors across process boundaries.\n */\nexport type ContextErrorData = Tagged<\n {\n readonly code: string | undefined\n readonly exitCode: number\n readonly message: string\n },\n 'ContextError'\n>\n\n/**\n * An Error subtype carrying an exit code and optional error code.\n *\n * Created by {@link createContextError} and thrown by `ctx.fail()`.\n * The CLI boundary catches these to produce clean, user-facing error output\n * with the correct process exit code.\n */\nexport type ContextError = Error &\n Tagged<\n {\n readonly code: string | undefined\n readonly exitCode: number\n },\n 'ContextError'\n >\n\n/**\n * Create a ContextError with an exit code and optional error code.\n *\n * Used to surface user-facing CLI errors with clean messages.\n * The error carries a Symbol-based tag for reliable type-narrowing\n * via {@link isContextError}.\n *\n * @param message - Human-readable error message.\n * @param options - Optional error code and exit code overrides.\n * @returns A ContextError instance.\n */\nexport function createContextError(\n message: string,\n options?: { code?: string; exitCode?: number }\n): ContextError {\n const data = createContextErrorData(message, options)\n // Accepted exception: Error construction requires `new Error()` then property decoration.\n // The `as` cast and Object.defineProperty mutations are the only way to produce a\n // Tagged Error subtype without using a class.\n const error = new Error(data.message) as ContextError\n error.name = 'ContextError'\n // Intentional mutation: decorating an Error object with immutable properties.\n Object.defineProperty(error, TAG, { enumerable: false, value: 'ContextError', writable: false })\n Object.defineProperty(error, 'code', { enumerable: true, value: data.code, writable: false })\n Object.defineProperty(error, 'exitCode', {\n enumerable: true,\n value: data.exitCode,\n writable: false,\n })\n return error\n}\n\n/**\n * Type guard that narrows an unknown value to {@link ContextError}.\n *\n * Checks that the value is an Error instance whose `[TAG]` property\n * equals `'ContextError'`, which distinguishes CLI-layer errors from\n * unexpected exceptions.\n *\n * @param error - The value to check.\n * @returns `true` when the value is a ContextError.\n */\nexport function isContextError(error: unknown): error is ContextError {\n if (error instanceof Error) {\n return hasTag(error, 'ContextError')\n }\n return false\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\nfunction resolveExitCode(options: { code?: string; exitCode?: number } | undefined): number {\n if (options && options.exitCode !== undefined) {\n return options.exitCode\n }\n return DEFAULT_EXIT_CODE\n}\n\nfunction resolveCode(\n options: { code?: string; exitCode?: number } | undefined\n): string | undefined {\n if (options && options.code !== undefined) {\n return options.code\n }\n return undefined\n}\n\nfunction createContextErrorData(\n message: string,\n options?: { code?: string; exitCode?: number }\n): ContextErrorData {\n return withTag(\n {\n code: resolveCode(options),\n exitCode: resolveExitCode(options),\n message,\n },\n 'ContextError'\n )\n}\n","import { jsonStringify } from '@kidd-cli/utils/json'\n\nimport type { Output, OutputOptions } from './types.js'\n\n/**\n * Create the structured output methods for a context.\n *\n * @private\n * @param stream - The writable stream to write output to.\n * @returns An Output instance backed by the given stream.\n */\nexport function createContextOutput(stream: NodeJS.WriteStream): Output {\n return {\n markdown(content: string): void {\n stream.write(`${content}\\n`)\n },\n raw(content: string): void {\n stream.write(content)\n },\n table(rows: Record<string, unknown>[], options?: OutputOptions): void {\n if (options && options.json) {\n const [, json] = jsonStringify(rows, { pretty: true })\n stream.write(`${json}\\n`)\n return\n }\n if (rows.length === 0) {\n return\n }\n const [firstRow] = rows\n if (!firstRow) {\n return\n }\n writeTableToStream(stream, rows, Object.keys(firstRow))\n },\n write(data: unknown, options?: OutputOptions): void {\n if ((options && options.json) || (typeof data === 'object' && data !== null)) {\n const [, json] = jsonStringify(data, { pretty: true })\n stream.write(`${json}\\n`)\n } else {\n stream.write(`${String(data)}\\n`)\n }\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Format an unknown value as a string for table cell display.\n *\n * @private\n * @param val - The value to format.\n * @returns The stringified value, or empty string for undefined.\n */\nfunction formatStringValue(val: unknown): string {\n if (val === undefined) {\n return ''\n }\n return String(val)\n}\n\n/**\n * Options for creating a table header string.\n */\ninterface TableHeaderOptions {\n keys: string[]\n widths: (number | undefined)[]\n}\n\n/**\n * Create a padded header row string from column keys and widths.\n *\n * @private\n * @param options - The keys and column widths.\n * @returns A formatted header string.\n */\nfunction createTableHeader(options: TableHeaderOptions): string {\n const { keys, widths } = options\n return keys\n .map((key, idx) => {\n const width = widths[idx]\n if (width === undefined) {\n return key\n }\n return key.padEnd(width)\n })\n .join(' ')\n}\n\n/**\n * Options for creating a table row string.\n */\ninterface TableRowOptions {\n row: Record<string, unknown>\n keys: string[]\n widths: (number | undefined)[]\n}\n\n/**\n * Create a padded row string from a data record, column keys, and widths.\n *\n * @private\n * @param options - The row data, keys, and column widths.\n * @returns A formatted row string.\n */\nfunction createTableRow(options: TableRowOptions): string {\n const { row, keys, widths } = options\n return keys\n .map((key, idx) => {\n const width = widths[idx]\n const val = formatStringValue(row[key])\n if (width === undefined) {\n return val\n }\n return val.padEnd(width)\n })\n .join(' ')\n}\n\n/**\n * Compute the maximum column width for each key across all rows.\n *\n * @private\n * @param rows - The data rows.\n * @param keys - The column keys.\n * @returns An array of column widths.\n */\nfunction computeColumnWidths(rows: Record<string, unknown>[], keys: string[]): number[] {\n return keys.map((key) => {\n const values = rows.map((row) => formatStringValue(row[key]))\n return Math.max(key.length, ...values.map((val) => val.length))\n })\n}\n\n/**\n * Write a formatted table (header, separator, rows) to a writable stream.\n *\n * @private\n * @param stream - The writable stream.\n * @param rows - The data rows.\n * @param keys - The column keys.\n */\nfunction writeTableToStream(\n stream: NodeJS.WriteStream,\n rows: Record<string, unknown>[],\n keys: string[]\n): void {\n const widths = computeColumnWidths(rows, keys)\n const header = createTableHeader({ keys, widths })\n const separator = widths.map((width) => '-'.repeat(width)).join(' ')\n const dataRows = rows.map((row) => createTableRow({ keys, row, widths }))\n const content = [header, separator, ...dataRows].join('\\n')\n stream.write(`${content}\\n`)\n}\n","import * as clack from '@clack/prompts'\n\nimport { DEFAULT_EXIT_CODE, createContextError } from './error.js'\nimport type { Prompts } from './types.js'\n\n/**\n * Create the interactive prompt methods for a context.\n *\n * @returns A Prompts instance backed by clack.\n */\nexport function createContextPrompts(): Prompts {\n return {\n async confirm(opts): Promise<boolean> {\n const result = await clack.confirm(opts)\n return unwrapCancelSignal(result)\n },\n async multiselect<Type>(opts: Parameters<Prompts['multiselect']>[0]): Promise<Type[]> {\n const result = await clack.multiselect<Type>(\n opts as Parameters<typeof clack.multiselect<Type>>[0]\n )\n return unwrapCancelSignal(result)\n },\n async password(opts): Promise<string> {\n const result = await clack.password(opts)\n return unwrapCancelSignal(result)\n },\n async select<Type>(opts: Parameters<Prompts['select']>[0]): Promise<Type> {\n const result = await clack.select<Type>(opts as Parameters<typeof clack.select<Type>>[0])\n return unwrapCancelSignal(result)\n },\n async text(opts): Promise<string> {\n const result = await clack.text(opts)\n return unwrapCancelSignal(result)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Unwrap a prompt result that may be a cancel symbol.\n *\n * If the user cancelled (Ctrl-C), throws a ContextError. Otherwise returns\n * the typed result value.\n *\n * @private\n * @param result - The raw prompt result (value or cancel symbol).\n * @returns The unwrapped typed value.\n */\nfunction unwrapCancelSignal<Type>(result: Type | symbol): Type {\n if (clack.isCancel(result)) {\n clack.cancel('Operation cancelled.')\n // Accepted exception: prompt cancellation must propagate as an unwind.\n // The runner catches the thrown ContextError at the CLI boundary.\n throw createContextError('Prompt cancelled by user', {\n code: 'PROMPT_CANCELLED',\n exitCode: DEFAULT_EXIT_CODE,\n })\n }\n return result as Type\n}\n","import type { Store } from './types.js'\n\n/**\n * Create an in-memory key-value store.\n *\n * @private\n * @returns A Store instance backed by a Map.\n */\nexport function createMemoryStore<TMap extends Record<string, unknown>>(): Store<TMap> {\n const map = new Map<string, unknown>()\n\n return {\n clear(): void {\n map.clear()\n },\n delete(key: string): boolean {\n return map.delete(key)\n },\n get<Key extends Extract<keyof TMap, string>>(key: Key): TMap[Key] | undefined {\n return map.get(key) as TMap[Key] | undefined\n },\n has(key: string): boolean {\n return map.has(key)\n },\n set<Key extends Extract<keyof TMap, string>>(key: Key, value: TMap[Key]): void {\n map.set(key, value)\n },\n }\n}\n","import * as clack from '@clack/prompts'\n\nimport { createCliLogger } from '@/lib/logger.js'\nimport type { CliLogger } from '@/lib/logger.js'\nimport type { AnyRecord, KiddStore, Merge } from '@/types.js'\n\nimport { createContextError } from './error.js'\nimport { createContextOutput } from './output.js'\nimport { createContextPrompts } from './prompts.js'\nimport { createMemoryStore } from './store.js'\nimport type { Context, Meta, Output, Prompts, Spinner, Store, StoreMap } from './types.js'\n\n/**\n * Options for creating a {@link Context} instance via {@link createContext}.\n *\n * Carries the parsed args, validated config, and CLI metadata needed to\n * assemble a fully-wired context. An optional `logger` override allows\n * callers to inject a custom {@link CliLogger}; when omitted a default\n * @clack/prompts-backed instance is used.\n */\nexport interface CreateContextOptions<TArgs extends AnyRecord, TConfig extends AnyRecord> {\n readonly args: TArgs\n readonly config: TConfig\n readonly meta: { readonly name: string; readonly version: string; readonly command: string[] }\n readonly logger?: CliLogger\n readonly output?: NodeJS.WriteStream\n}\n\n/**\n * Create the {@link Context} object threaded through middleware and command handlers.\n *\n * Assembles logger, spinner, output, store, prompts, and meta from\n * the provided options into a single immutable context. Each sub-system is\n * constructed via its own factory so this function remains a lean orchestrator.\n *\n * @param options - Args, config, and meta for the current invocation.\n * @returns A fully constructed Context.\n */\nexport function createContext<TArgs extends AnyRecord, TConfig extends AnyRecord>(\n options: CreateContextOptions<TArgs, TConfig>\n): Context<TArgs, TConfig> {\n const ctxLogger: CliLogger = options.logger ?? createCliLogger()\n const ctxSpinner: Spinner = clack.spinner()\n const ctxOutput: Output = createContextOutput(options.output ?? process.stdout)\n const ctxStore: Store<Merge<KiddStore, StoreMap>> = createMemoryStore()\n const ctxPrompts: Prompts = createContextPrompts()\n const ctxMeta: Meta = {\n command: options.meta.command,\n name: options.meta.name,\n version: options.meta.version,\n }\n\n // Middleware-augmented properties (e.g. `auth`) are added at runtime.\n // See `decorateContext` — they are intentionally absent here.\n return {\n args: options.args as Context<TArgs, TConfig>['args'],\n config: options.config as Context<TArgs, TConfig>['config'],\n fail(message: string, failOptions?: { code?: string; exitCode?: number }): never {\n // Accepted exception: ctx.fail() is typed `never` and caught by the CLI boundary.\n // This is the framework's halt mechanism — the runner catches the thrown ContextError.\n throw createContextError(message, failOptions)\n },\n logger: ctxLogger,\n meta: ctxMeta as Context<TArgs, TConfig>['meta'],\n output: ctxOutput,\n prompts: ctxPrompts,\n spinner: ctxSpinner,\n store: ctxStore,\n } as Context<TArgs, TConfig>\n}\n","import type { Dirent } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { basename, extname, join, resolve } from 'node:path'\n\nimport { isPlainObject, isString } from '@kidd-cli/utils/fp'\nimport { hasTag, withTag } from '@kidd-cli/utils/tag'\n\nimport type { AutoloadOptions, Command, CommandMap } from './types.js'\n\nconst VALID_EXTENSIONS = new Set(['.ts', '.js', '.mjs'])\nconst INDEX_NAME = 'index'\n\n/**\n * Scan a directory for command files and produce a CommandMap.\n *\n * @param options - Autoload configuration (directory override, etc.).\n * @returns A promise resolving to a CommandMap built from the directory tree.\n */\nexport async function autoload(options?: AutoloadOptions): Promise<CommandMap> {\n const dir = resolveDir(options)\n const entries = await readdir(dir, { withFileTypes: true })\n\n const fileEntries = entries.filter(isCommandFile)\n const dirEntries = entries.filter(isCommandDir)\n\n const fileResults = await Promise.all(\n fileEntries.map(async (entry): Promise<[string, Command] | undefined> => {\n const cmd = await importCommand(join(dir, entry.name))\n if (!cmd) {\n return undefined\n }\n return [deriveCommandName(entry), cmd]\n })\n )\n\n const dirResults = await Promise.all(\n dirEntries.map((entry) => buildDirCommand(join(dir, entry.name)))\n )\n\n const allResults = [...fileResults, ...dirResults]\n const validPairs = allResults.filter((pair): pair is [string, Command] => pair !== undefined)\n\n const commandMap: CommandMap = Object.fromEntries(validPairs)\n return commandMap\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Resolve the target directory from autoload options.\n *\n * @private\n * @param options - Optional autoload configuration.\n * @returns The resolved absolute directory path.\n */\nfunction resolveDir(options?: AutoloadOptions): string {\n if (options && isString(options.dir)) {\n return resolve(options.dir)\n }\n return resolve('./commands')\n}\n\n/**\n * Scan a subdirectory and assemble it as a parent command with subcommands.\n *\n * If the directory contains an `index.ts`/`index.js`, that becomes the parent\n * handler. Otherwise a handler-less group command is created that demands a\n * subcommand.\n *\n * @private\n * @param dir - Absolute path to the subdirectory.\n * @returns A tuple of [name, Command] or undefined if the directory is empty.\n */\nasync function buildDirCommand(dir: string): Promise<[string, Command] | undefined> {\n const name = basename(dir)\n const dirEntries = await readdir(dir, { withFileTypes: true })\n const subCommands = await buildSubCommands(dir, dirEntries)\n const indexFile = findIndexInEntries(dirEntries)\n\n if (indexFile) {\n const parentCommand = await importCommand(join(dir, indexFile.name))\n if (parentCommand) {\n return [name, withTag({ ...parentCommand, commands: subCommands }, 'Command')]\n }\n }\n\n if (Object.keys(subCommands).length === 0) {\n return undefined\n }\n\n return [name, withTag({ commands: subCommands }, 'Command')]\n}\n\n/**\n * Build subcommands from already-read directory entries, avoiding a redundant readdir call.\n *\n * @private\n * @param dir - Absolute path to the directory.\n * @param entries - Pre-read directory entries.\n * @returns A CommandMap built from the entries.\n */\nasync function buildSubCommands(dir: string, entries: Dirent[]): Promise<CommandMap> {\n const fileEntries = entries.filter(isCommandFile)\n const dirEntries = entries.filter(isCommandDir)\n\n const fileResults = await Promise.all(\n fileEntries.map(async (entry): Promise<[string, Command] | undefined> => {\n const cmd = await importCommand(join(dir, entry.name))\n if (!cmd) {\n return undefined\n }\n return [deriveCommandName(entry), cmd]\n })\n )\n\n const dirResults = await Promise.all(\n dirEntries.map((entry) => buildDirCommand(join(dir, entry.name)))\n )\n\n const allResults = [...fileResults, ...dirResults]\n const validPairs = allResults.filter((pair): pair is [string, Command] => pair !== undefined)\n\n const commandMap: CommandMap = Object.fromEntries(validPairs)\n return commandMap\n}\n\n/**\n * Find the index file (index.ts or index.js) in pre-read directory entries.\n *\n * @private\n * @param entries - Pre-read directory entries.\n * @returns The index file's Dirent or undefined.\n */\nfunction findIndexInEntries(entries: Dirent[]): Dirent | undefined {\n return entries.find(\n (entry) =>\n entry.isFile() &&\n VALID_EXTENSIONS.has(extname(entry.name)) &&\n basename(entry.name, extname(entry.name)) === INDEX_NAME\n )\n}\n\n/**\n * Dynamically import a file and validate that its default export is a Command.\n *\n * @private\n * @param filePath - Absolute path to the file to import.\n * @returns The Command if valid, or undefined.\n */\nasync function importCommand(filePath: string): Promise<Command | undefined> {\n const mod: unknown = await import(filePath)\n if (isCommandExport(mod)) {\n return mod.default\n }\n return undefined\n}\n\n/**\n * Check whether a module's default export is a Command object.\n *\n * ES module namespace objects have a null prototype, so isPlainObject\n * rejects them. We only need to verify the namespace is a non-null\n * object with a default export that is a plain Command object.\n *\n * @private\n * @param mod - The imported module to inspect.\n * @returns True when the module has a Command as its default export.\n */\nfunction isCommandExport(mod: unknown): mod is { default: Command } {\n if (typeof mod !== 'object' || mod === null) {\n return false\n }\n if (!('default' in mod)) {\n return false\n }\n const def: unknown = mod.default\n if (!isPlainObject(def)) {\n return false\n }\n return hasTag(def, 'Command')\n}\n\n/**\n * Derive a command name from a directory entry by stripping its extension.\n *\n * @private\n * @param entry - The directory entry to derive the name from.\n * @returns The file name without its extension.\n */\nfunction deriveCommandName(entry: Dirent): string {\n return basename(entry.name, extname(entry.name))\n}\n\n/**\n * Predicate: entry is a command file (.ts/.js, not index, not _/. prefixed).\n *\n * @private\n * @param entry - The directory entry to check.\n * @returns True when the entry is a valid command file.\n */\nfunction isCommandFile(entry: Dirent): boolean {\n if (!entry.isFile()) {\n return false\n }\n if (entry.name.startsWith('_') || entry.name.startsWith('.')) {\n return false\n }\n if (!VALID_EXTENSIONS.has(extname(entry.name))) {\n return false\n }\n return deriveCommandName(entry) !== INDEX_NAME\n}\n\n/**\n * Predicate: entry is a scannable command directory (not _/. prefixed).\n *\n * @private\n * @param entry - The directory entry to check.\n * @returns True when the entry is a valid command directory.\n */\nfunction isCommandDir(entry: Dirent): boolean {\n if (!entry.isDirectory()) {\n return false\n }\n return !entry.name.startsWith('_') && !entry.name.startsWith('.')\n}\n","import { match } from '@kidd-cli/utils/fp'\nimport { withTag } from '@kidd-cli/utils/tag'\n\nimport type {\n ArgsDef,\n CommandDef,\n CommandsConfig,\n Middleware,\n MiddlewareEnv,\n Command as CommandType,\n} from './types.js'\n\n/**\n * Check whether a value is a structured {@link CommandsConfig} object.\n *\n * Discriminates from a plain `CommandMap` by checking for the `order` (array)\n * or `path` (string) keys — neither can appear on a valid `CommandMap` whose\n * values are tagged `Command` objects.\n *\n * @param value - The value to test.\n * @returns `true` when `value` is a `CommandsConfig`.\n */\nexport function isCommandsConfig(value: unknown): value is CommandsConfig {\n if (typeof value !== 'object' || value === null || value instanceof Promise) {\n return false\n }\n return (\n ('order' in value && Array.isArray((value as CommandsConfig).order)) ||\n ('path' in value && typeof (value as CommandsConfig).path === 'string')\n )\n}\n\n/**\n * Define a CLI command with typed args, config, and handler.\n *\n * The `const TMiddleware` generic preserves the middleware tuple as a literal type,\n * enabling TypeScript to extract and intersect `Variables` from each middleware\n * element onto the handler's `ctx` type.\n *\n * When `def.commands` is a structured {@link CommandsConfig}, the factory\n * normalizes it into flat `commands` and `order` fields on the output\n * `Command` object so downstream consumers never need to handle the grouped form.\n *\n * @param def - Command definition including description, args schema, middleware, and handler.\n * @returns A resolved Command object for registration in the command map.\n */\nexport function command<\n TArgsDef extends ArgsDef = ArgsDef,\n TConfig extends Record<string, unknown> = Record<string, unknown>,\n const TMiddleware extends readonly Middleware<MiddlewareEnv>[] =\n readonly Middleware<MiddlewareEnv>[],\n>(def: CommandDef<TArgsDef, TConfig, TMiddleware>): CommandType {\n return match(def.commands)\n .when(isCommandsConfig, (cfg) => {\n const { order, commands: innerCommands } = cfg\n return withTag({ ...def, commands: innerCommands, order }, 'Command') as CommandType\n })\n .otherwise(() => withTag({ ...def }, 'Command') as CommandType)\n}\n","import { match } from 'ts-pattern'\nimport type { Options as YargsOptions } from 'yargs'\nimport type { z } from 'zod'\n\n/**\n * Type guard that checks whether a value is a zod object schema.\n *\n * @param args - The value to check.\n * @returns True when args is a ZodObject.\n */\nexport function isZodSchema(args: unknown): args is z.ZodObject<z.ZodRawShape> {\n return (\n typeof args === 'object' &&\n args !== null &&\n '_def' in args &&\n typeof (args as { _def: unknown })._def === 'object' &&\n (args as { _def: { type?: string } })._def !== null &&\n (args as { _def: { type?: string } })._def.type === 'object'\n )\n}\n\n/**\n * Convert an entire zod object schema into a record of yargs options.\n *\n * @param schema - The zod object schema.\n * @returns A record mapping field names to yargs option definitions.\n */\nexport function zodSchemaToYargsOptions(\n schema: z.ZodObject<z.ZodRawShape>\n): Record<string, YargsOptions> {\n const shape = schema.shape as Record<string, z.ZodTypeAny>\n return Object.fromEntries(\n Object.entries(shape).map(([key, fieldSchema]): [string, YargsOptions] => [\n key,\n getZodTypeOption(fieldSchema),\n ])\n )\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\ninterface ZodDef {\n type?: string\n innerType?: z.ZodTypeAny\n defaultValue?: unknown\n}\n\ninterface ZodTypeInfo {\n defaultValue: unknown\n inner: z.ZodTypeAny\n isOptional: boolean\n}\n\ninterface UnwrapOptions {\n def: ZodDef\n current: z.ZodTypeAny\n defaultValue: unknown\n}\n\ninterface UnwrapRecursiveOptions {\n current: z.ZodTypeAny\n isOptional: boolean\n defaultValue: unknown\n}\n\n/**\n * Extract a default value from a zod definition, falling back to the provided value.\n *\n * @private\n * @param def - The zod definition to inspect.\n * @param fallback - Value to return when no default is defined.\n * @returns The resolved default value.\n */\nfunction resolveDefaultValue(def: ZodDef, fallback: unknown): unknown {\n if (def.defaultValue !== undefined) {\n return def.defaultValue\n }\n return fallback\n}\n\n/**\n * Unwrap a ZodOptional type, recursing into the inner type.\n *\n * @private\n * @param options - The unwrap options containing def, current type, and default value.\n * @returns Unwrapped type information.\n */\nfunction unwrapOptional(options: UnwrapOptions): ZodTypeInfo {\n const { def, current, defaultValue } = options\n if (def.innerType) {\n return unwrapZodTypeRecursive({ current: def.innerType, defaultValue, isOptional: true })\n }\n return { defaultValue, inner: current, isOptional: true }\n}\n\n/**\n * Unwrap a ZodDefault type, resolving its default value and recursing.\n *\n * @private\n * @param options - The unwrap options containing def, current type, and default value.\n * @returns Unwrapped type information with the resolved default.\n */\nfunction unwrapDefault(options: UnwrapOptions): ZodTypeInfo {\n const { def, current, defaultValue } = options\n const newDefault = resolveDefaultValue(def, defaultValue)\n if (def.innerType) {\n return unwrapZodTypeRecursive({\n current: def.innerType,\n defaultValue: newDefault,\n isOptional: true,\n })\n }\n return { defaultValue: newDefault, inner: current, isOptional: true }\n}\n\n/**\n * Recursively unwrap optional and default wrappers from a zod type.\n *\n * @private\n * @param options - The recursive unwrap options containing current type, optionality flag, and default value.\n * @returns The fully unwrapped type information.\n */\nfunction unwrapZodTypeRecursive(options: UnwrapRecursiveOptions): ZodTypeInfo {\n const { current, isOptional, defaultValue } = options\n const def = (current as { _def: ZodDef })._def\n if (def.type === 'optional') {\n return unwrapOptional({ current, def, defaultValue })\n }\n if (def.type === 'default') {\n return unwrapDefault({ current, def, defaultValue })\n }\n return { defaultValue, inner: current, isOptional }\n}\n\n/**\n * Unwrap a zod schema to extract its base type, optionality, and default value.\n *\n * @private\n * @param schema - The zod type to unwrap.\n * @returns The unwrapped type information.\n */\nfunction unwrapZodType(schema: z.ZodTypeAny): ZodTypeInfo {\n return unwrapZodTypeRecursive({ current: schema, defaultValue: undefined, isOptional: false })\n}\n\n/**\n * Map a zod type name to a yargs option type string.\n *\n * @private\n * @param typeName - The zod type name (e.g. 'string', 'number').\n * @returns The corresponding yargs type.\n */\nfunction resolveZodYargsType(\n typeName: string | undefined\n): 'string' | 'number' | 'boolean' | 'array' {\n return match(typeName)\n .with('string', () => 'string' as const)\n .with('number', () => 'number' as const)\n .with('boolean', () => 'boolean' as const)\n .with('array', () => 'array' as const)\n .otherwise(() => 'string' as const)\n}\n\n/**\n * Build a base yargs option from a zod schema's description and default.\n *\n * @private\n * @param inner - The unwrapped zod schema instance.\n * @param defaultValue - The resolved default value.\n * @returns A partial yargs option object.\n */\nfunction buildBaseOption(inner: z.ZodTypeAny, defaultValue: unknown): YargsOptions {\n const base: YargsOptions = {}\n const { description } = inner as { description?: string }\n if (description) {\n base.describe = description\n }\n if (defaultValue !== undefined) {\n base.default = defaultValue\n }\n return base\n}\n\n/**\n * Convert a single zod field schema into a complete yargs option definition.\n *\n * @private\n * @param schema - A single zod field type.\n * @returns A complete yargs option object.\n */\nfunction getZodTypeOption(schema: z.ZodTypeAny): YargsOptions {\n const { inner, isOptional, defaultValue } = unwrapZodType(schema)\n const innerDef = (inner as { _def: ZodDef })._def\n const base = {\n ...buildBaseOption(inner, defaultValue),\n type: resolveZodYargsType(innerDef.type),\n }\n if (!isOptional) {\n return { ...base, demandOption: true }\n }\n return base\n}\n","import { err, ok } from '@kidd-cli/utils/fp'\nimport type { Result } from '@kidd-cli/utils/fp'\nimport { formatZodIssues } from '@kidd-cli/utils/validate'\n\nimport type { Command } from '@/types.js'\n\nimport type { ArgsParser } from '../types.js'\nimport { isZodSchema } from './zod.js'\n\n/**\n * Create an args parser that cleans and validates raw parsed arguments.\n *\n * Captures the argument definition in a closure and returns an ArgsParser\n * whose `parse` method strips yargs-internal keys and validates against\n * a zod schema when one is defined.\n *\n * @param argsDef - The argument definition from the command.\n * @returns An ArgsParser with a parse method.\n */\nexport function createArgsParser(argsDef: Command['args']): ArgsParser {\n return {\n parse(rawArgs: Record<string, unknown>): Result<Record<string, unknown>, Error> {\n const cleaned = cleanParsedArgs(rawArgs)\n return validateArgs(argsDef, cleaned)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Strip yargs-internal keys (`_`, `$0`) and camelCase-duplicated hyphenated keys\n * from a parsed argv record, returning only user-defined arguments.\n *\n * @private\n * @param argv - Raw parsed argv from yargs.\n * @returns A cleaned record containing only user-defined arguments.\n */\nfunction cleanParsedArgs(argv: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n Object.entries(argv).filter(([key]) => key !== '_' && key !== '$0' && !key.includes('-'))\n )\n}\n\n/**\n * Validate parsed arguments against a zod schema when one is defined.\n *\n * If the command uses yargs-native args (no zod schema), the parsed args are\n * returned as-is. When a zod schema is present, validation is performed and\n * a Result error is returned on failure.\n *\n * @private\n * @param argsDef - The argument definition from the command.\n * @param parsedArgs - The cleaned parsed arguments.\n * @returns A Result containing validated arguments (zod-parsed when applicable).\n */\nfunction validateArgs(\n argsDef: Command['args'],\n parsedArgs: Record<string, unknown>\n): Result<Record<string, unknown>, Error> {\n if (!argsDef || !isZodSchema(argsDef)) {\n return ok(parsedArgs)\n }\n const result = argsDef.safeParse(parsedArgs)\n if (!result.success) {\n return err(new Error(`Invalid arguments:\\n ${formatZodIssues(result.error.issues).message}`))\n }\n return ok(result.data as Record<string, unknown>)\n}\n","import type { Argv, Options as YargsOptions } from 'yargs'\n\nimport type { Command, YargsArgDef } from '@/types.js'\n\nimport { isZodSchema, zodSchemaToYargsOptions } from './zod.js'\n\n/**\n * Register argument definitions on a yargs builder.\n *\n * Accepts either a zod object schema or a record of yargs-native arg definitions\n * and wires them as yargs options on the given builder instance.\n *\n * @param builder - The yargs Argv instance to register options on.\n * @param args - Argument definitions from a Command.\n */\nexport function registerCommandArgs(builder: Argv, args: Command['args']): void {\n if (!args) {\n return\n }\n if (isZodSchema(args)) {\n const options = zodSchemaToYargsOptions(args)\n for (const [key, opt] of Object.entries(options)) {\n builder.option(key, opt)\n }\n } else {\n for (const [key, def] of Object.entries(args)) {\n builder.option(key, yargsArgDefToOption(def))\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Convert a yargs-native arg definition into a yargs option object.\n *\n * @private\n * @param def - The yargs arg definition.\n * @returns A yargs option object.\n */\nfunction yargsArgDefToOption(def: YargsArgDef): YargsOptions {\n return {\n alias: def.alias,\n choices: def.choices,\n default: def.default,\n demandOption: def.required ?? false,\n describe: def.description,\n type: def.type,\n }\n}\n","import { err, ok } from '@kidd-cli/utils/fp'\nimport type { Result } from '@kidd-cli/utils/fp'\n\nimport type { Command } from '@/types.js'\n\n/**\n * Validate that every name in the order array exists in the provided command names.\n *\n * @param params - The order array and available command names to validate against.\n * @returns A Result tuple — `[null, void]` on success or `[Error, null]` on failure.\n */\nexport function validateCommandOrder(params: {\n readonly order: readonly string[]\n readonly commandNames: readonly string[]\n}): Result<void, Error> {\n const { order, commandNames } = params\n\n const seen = new Set<string>()\n const duplicates = order.filter((name) => {\n if (seen.has(name)) {\n return true\n }\n seen.add(name)\n return false\n })\n\n if (duplicates.length > 0) {\n return err(\n `Invalid command order: duplicate command(s) ${[...new Set(duplicates)].map((n) => `\"${n}\"`).join(', ')}`\n )\n }\n\n const nameSet = new Set(commandNames)\n const invalid = order.filter((name) => !nameSet.has(name))\n\n if (invalid.length > 0) {\n return err(\n `Invalid command order: unknown command(s) ${invalid.map((n) => `\"${n}\"`).join(', ')}`\n )\n }\n\n return ok()\n}\n\n/**\n * Sort command entries with ordered names first (in specified order),\n * remaining names alphabetically.\n *\n * @param params - The command entries and optional order array.\n * @returns Sorted array of `[name, Command]` entries.\n */\nexport function sortCommandEntries(params: {\n readonly entries: readonly (readonly [string, Command])[]\n readonly order?: readonly string[]\n}): readonly (readonly [string, Command])[] {\n const { entries, order } = params\n\n if (!order || order.length === 0) {\n return [...entries].toSorted(([a], [b]) => a.localeCompare(b))\n }\n\n const entryMap = new Map(entries)\n\n const ordered = order\n .filter((name) => entryMap.has(name))\n .map((name): readonly [string, Command] => [name, entryMap.get(name) as Command])\n\n const orderedSet = new Set(order)\n const remaining = entries\n .filter(([name]) => !orderedSet.has(name))\n .toSorted(([a], [b]) => a.localeCompare(b))\n\n return [...ordered, ...remaining]\n}\n","import { hasTag } from '@kidd-cli/utils/tag'\nimport type { Argv } from 'yargs'\n\nimport type { Context } from '@/context/types.js'\nimport type { Command, CommandMap, Middleware } from '@/types.js'\n\nimport { registerCommandArgs } from './args/index.js'\nimport { sortCommandEntries, validateCommandOrder } from './sort-commands.js'\nimport type { ResolvedCommand, ResolvedRef } from './types.js'\n\n/**\n * Type guard that checks whether a value is a Command object.\n *\n * @param value - The value to test.\n * @returns True when the value has `[TAG] === 'Command'`.\n */\nexport function isCommand(value: unknown): value is Command {\n return hasTag(value, 'Command')\n}\n\n/**\n * Register all commands from a CommandMap on a yargs instance.\n *\n * Iterates over the command map, filters for valid Command objects,\n * validates the order array, sorts entries, and recursively registers\n * each command (including subcommands) on the provided yargs Argv instance.\n *\n * @param options - Registration options including the command map, yargs instance, and resolution ref.\n */\nexport function registerCommands(options: RegisterCommandsOptions): void {\n const { instance, commands, resolved, parentPath, order, errorRef } = options\n const commandEntries = Object.entries(commands).filter((pair): pair is [string, Command] =>\n isCommand(pair[1])\n )\n\n if (order && order.length > 0) {\n const commandNames = commandEntries.map(([name]) => name)\n const [validationError] = validateCommandOrder({ commandNames, order })\n if (validationError && errorRef) {\n // Intentional mutation: errorRef is a mutable holder for deferred error reporting.\n errorRef.error = validationError\n return\n }\n }\n\n const sorted = sortCommandEntries({ entries: commandEntries, order })\n\n sorted.map(([name, entry]) =>\n registerResolvedCommand({\n builder: instance,\n cmd: entry,\n errorRef,\n instance,\n name,\n parentPath,\n resolved,\n })\n )\n}\n\nexport type { ResolvedCommand, ResolvedRef } from './types.js'\n\n/**\n * Mutable ref holder for deferred error reporting during command registration.\n */\nexport interface ErrorRef {\n error: Error | undefined\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\ninterface RegisterResolvedCommandOptions {\n builder: Argv\n cmd: Command\n errorRef?: ErrorRef\n instance: Argv\n name: string\n parentPath: string[]\n resolved: ResolvedRef\n}\n\ninterface RegisterCommandsOptions {\n commands: CommandMap\n errorRef?: ErrorRef\n instance: Argv\n order?: readonly string[]\n parentPath: string[]\n resolved: ResolvedRef\n}\n\n/**\n * Register a single resolved command (and its subcommands) with yargs.\n *\n * Sets up the yargs command handler, wires argument definitions, and\n * recursively registers any nested subcommands. On match, stores the\n * resolved handler and command path in the shared ref.\n *\n * @private\n * @param options - Command registration context.\n */\nfunction registerResolvedCommand(options: RegisterResolvedCommandOptions): void {\n const { instance, name, cmd, resolved, parentPath, errorRef } = options\n const description = cmd.description ?? ''\n\n instance.command(\n name,\n description,\n (builder: Argv) => {\n registerCommandArgs(builder, cmd.args)\n\n if (cmd.commands) {\n const subCommands = Object.entries(cmd.commands).filter((pair): pair is [string, Command] =>\n isCommand(pair[1])\n )\n\n if (cmd.order && cmd.order.length > 0) {\n const subNames = subCommands.map(([n]) => n)\n const [validationError] = validateCommandOrder({\n commandNames: subNames,\n order: cmd.order,\n })\n if (validationError && errorRef) {\n // Intentional mutation: errorRef is a mutable holder for deferred error reporting.\n errorRef.error = validationError\n return builder\n }\n }\n\n const sortedSubs = sortCommandEntries({ entries: subCommands, order: cmd.order })\n\n sortedSubs.map(([subName, subEntry]) =>\n registerResolvedCommand({\n builder,\n cmd: subEntry,\n errorRef,\n instance: builder,\n name: subName,\n parentPath: [...parentPath, name],\n resolved,\n })\n )\n\n if (cmd.handler) {\n builder.demandCommand(0)\n } else {\n builder.demandCommand(1, 'You must specify a subcommand.')\n }\n }\n\n return builder\n },\n () => {\n // Intentional mutation: yargs callback model requires mutable ref capture.\n // The `as` casts are accepted exceptions — generic handler/middleware types\n // Cannot be narrowed further inside the yargs callback boundary.\n resolved.ref = {\n args: cmd.args,\n commandPath: [...parentPath, name],\n handler: cmd.handler as ((ctx: Context) => Promise<void> | void) | undefined,\n middleware: (cmd.middleware ?? []) as Middleware[],\n }\n }\n )\n}\n","import type { Context } from '@/context/types.js'\nimport type { Middleware } from '@/types.js'\n\nimport type { Runner } from './types.js'\n\n/**\n * Create a runner that executes root and command middleware chains.\n *\n * Root middleware wraps the command middleware chain, which in turn wraps\n * the command handler — producing a nested onion lifecycle:\n *\n * ```\n * root middleware start →\n * command middleware start →\n * handler\n * command middleware end\n * root middleware end\n * ```\n *\n * @param rootMiddleware - Root-level middleware from `cli({ middleware })`.\n * @returns A Runner with an execute method.\n */\nexport function createRunner(rootMiddleware: Middleware[]): Runner {\n return {\n async execute({ ctx, handler, middleware }): Promise<void> {\n const commandHandler = async (innerCtx: Context): Promise<void> => {\n await runMiddlewareChain(middleware, innerCtx, handler)\n }\n await runMiddlewareChain(rootMiddleware, ctx, commandHandler)\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Execute a middleware chain followed by a final handler.\n *\n * Runs each middleware in order, passing `ctx` and a `next` callback.\n * When all middleware have called `next()`, the final handler is invoked.\n * A middleware can short-circuit by not calling `next()`.\n *\n * @private\n * @param middlewares - Ordered array of middleware to execute.\n * @param ctx - The context object threaded through middleware and handler.\n * @param finalHandler - The command handler to invoke after all middleware.\n */\nasync function runMiddlewareChain(\n middlewares: Middleware[],\n ctx: Context,\n finalHandler: (ctx: Context) => Promise<void> | void\n): Promise<void> {\n async function executeChain(index: number): Promise<void> {\n if (index >= middlewares.length) {\n await finalHandler(ctx)\n return\n }\n const mw = middlewares[index]\n if (mw) {\n await mw.handler(ctx, () => executeChain(index + 1))\n }\n }\n\n await executeChain(0)\n}\n","import { attemptAsync, err, ok } from '@kidd-cli/utils/fp'\nimport type { AsyncResult } from '@kidd-cli/utils/fp'\nimport type { z } from 'zod'\n\nimport { createContext } from '@/context/index.js'\nimport type { Context } from '@/context/types.js'\nimport { createConfigClient } from '@/lib/config/index.js'\nimport type { CliConfigOptions, Middleware } from '@/types.js'\n\nimport { createArgsParser } from './args/index.js'\nimport { createRunner } from './runner.js'\nimport type { Runtime, RuntimeOptions } from './types.js'\n\n/**\n * Create a runtime that orchestrates config loading and middleware execution.\n *\n * Loads config up front, then captures it in a closure alongside a runner.\n * The returned `runtime.execute` method handles arg parsing, context creation,\n * and middleware chain execution for each command invocation.\n *\n * @param options - Runtime configuration including name, version, config, and middleware.\n * @returns An AsyncResult containing the runtime or an error.\n */\nexport async function createRuntime<TSchema extends z.ZodType>(\n options: RuntimeOptions<TSchema>\n): AsyncResult<Runtime, Error> {\n const config = await resolveConfig(options.config, options.name)\n\n const middleware: Middleware[] = options.middleware ?? []\n const runner = createRunner(middleware)\n\n const runtime: Runtime = {\n async execute(command): AsyncResult<void, Error> {\n const parser = createArgsParser(command.args)\n const [argsError, validatedArgs] = parser.parse(command.rawArgs)\n if (argsError) {\n return err(argsError)\n }\n\n const ctx = createContext({\n args: validatedArgs,\n config,\n meta: {\n command: [...command.commandPath],\n name: options.name,\n version: options.version,\n },\n })\n\n const finalHandler = command.handler ?? (async () => {})\n\n // Accepted exception: generic context assembly requires type assertions.\n // The generics are validated at the createContext call site.\n const [execError] = await attemptAsync(() =>\n runner.execute({\n ctx: ctx as Context,\n handler: finalHandler as (ctx: Context) => Promise<void> | void,\n middleware: command.middleware,\n })\n )\n if (execError) {\n return err(execError)\n }\n\n return ok()\n },\n }\n\n return ok(runtime)\n}\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\n/**\n * Load and validate a config file via the config client.\n *\n * Returns the validated config record or an empty object when no config\n * options are provided or when loading fails.\n *\n * @private\n * @param configOptions - Config loading options with schema and optional name override.\n * @param defaultName - Fallback config file name derived from the CLI name.\n * @returns The loaded config record or an empty object.\n */\nasync function resolveConfig<TSchema extends z.ZodType>(\n configOptions: CliConfigOptions<TSchema> | undefined,\n defaultName: string\n): Promise<Record<string, unknown>> {\n if (!configOptions || !configOptions.schema) {\n return {}\n }\n const client = createConfigClient({\n name: configOptions.name ?? defaultName,\n schema: configOptions.schema,\n })\n const [configError, configResult] = await client.load()\n if (configError || !configResult) {\n return {}\n }\n // Accepted exception: configResult.config is generic TOutput from zod schema.\n // The cast bridges the generic boundary to the internal Record type.\n return configResult.config as Record<string, unknown>\n}\n","import { resolve } from 'node:path'\n\nimport { loadConfig } from '@kidd-cli/config/loader'\nimport { P, attemptAsync, err, isPlainObject, isString, match, ok } from '@kidd-cli/utils/fp'\nimport type { Result } from '@kidd-cli/utils/fp'\nimport yargs from 'yargs'\nimport type { Argv } from 'yargs'\nimport { z } from 'zod'\n\nimport { DEFAULT_EXIT_CODE, isContextError } from '@/context/index.js'\nimport { createCliLogger } from '@/lib/logger.js'\nimport type { CliHelpOptions, CliOptions, CommandMap, CommandsConfig } from '@/types.js'\n\nimport { autoload } from './autoloader.js'\nimport { isCommandsConfig } from './command.js'\nimport { createRuntime, registerCommands } from './runtime/index.js'\nimport type { ErrorRef, ResolvedRef } from './runtime/index.js'\n\nconst ARGV_SLICE_START = 2\n\n/**\n * Bootstrap and run the CLI application.\n *\n * Parses argv, resolves the matched command, loads config, runs the\n * middleware chain, and invokes the command handler.\n *\n * @param options - CLI configuration including name, version, commands, and middleware.\n */\nexport async function cli<TSchema extends z.ZodType = z.ZodType>(\n options: CliOptions<TSchema>\n): Promise<void> {\n const logger = createCliLogger()\n\n const [uncaughtError, result] = await attemptAsync(async () => {\n const [versionError, version] = resolveVersion(options.version)\n\n if (versionError) {\n return versionError\n }\n\n const program = yargs(process.argv.slice(ARGV_SLICE_START))\n .scriptName(options.name)\n .version(version)\n .strict()\n .help()\n .option('cwd', {\n describe: 'Set the working directory',\n global: true,\n type: 'string',\n })\n\n if (options.description) {\n program.usage(options.description)\n }\n\n const footer = extractFooter(options.help)\n if (footer) {\n program.epilogue(footer)\n }\n\n const resolved: ResolvedRef = { ref: undefined }\n const errorRef: ErrorRef = { error: undefined }\n\n const resolvedCmds = await resolveCommands(options.commands)\n\n if (resolvedCmds) {\n registerCommands({\n commands: resolvedCmds.commands,\n errorRef,\n instance: program,\n order: resolvedCmds.order,\n parentPath: [],\n resolved,\n })\n\n if (errorRef.error) {\n return errorRef.error\n }\n }\n\n const argv: Record<string, unknown> = await program.parseAsync()\n\n applyCwd(argv)\n\n if (!resolved.ref) {\n showNoCommandHelp({ argv, commands: resolvedCmds, help: options.help, program })\n return undefined\n }\n\n const [runtimeError, runtime] = await createRuntime({\n config: options.config,\n middleware: options.middleware,\n name: options.name,\n version,\n })\n\n if (runtimeError) {\n return runtimeError\n }\n\n const [executeError] = await runtime.execute({\n args: resolved.ref.args,\n commandPath: resolved.ref.commandPath,\n handler: resolved.ref.handler,\n middleware: resolved.ref.middleware,\n rawArgs: argv,\n })\n\n return executeError\n })\n\n if (uncaughtError) {\n exitOnError(uncaughtError, logger)\n return\n }\n\n if (result) {\n exitOnError(result, logger)\n }\n}\n\nexport default cli\n\n// ---------------------------------------------------------------------------\n// Private\n// ---------------------------------------------------------------------------\n\nconst VERSION_ERROR = new Error(\n 'No CLI version available. Either pass `version` to cli() or build with the kidd bundler.'\n)\n\nconst VersionSchema = z.string().trim().min(1)\n\n/**\n * Resolve the CLI version from an explicit value or the compile-time constant.\n *\n * Resolution order:\n * 1. Explicit version string passed to `cli()`\n * 2. `__KIDD_VERSION__` injected by the kidd bundler at build time\n *\n * Returns an error when neither source provides a non-empty version.\n *\n * @private\n * @param explicit - The version string from `CliOptions.version`, if provided.\n * @returns A Result tuple with the resolved version string or an Error.\n */\nfunction resolveVersion(explicit: string | undefined): Result<string> {\n if (explicit !== undefined) {\n const parsed = VersionSchema.safeParse(explicit)\n if (parsed.success) {\n return ok(parsed.data)\n }\n return err(VERSION_ERROR)\n }\n\n if (typeof __KIDD_VERSION__ === 'string') {\n const parsed = VersionSchema.safeParse(__KIDD_VERSION__)\n if (parsed.success) {\n return ok(parsed.data)\n }\n }\n\n return err(VERSION_ERROR)\n}\n\n/**\n * Resolved commands with optional display ordering.\n *\n * @private\n */\ninterface ResolvedCommands {\n readonly commands: CommandMap\n readonly order?: readonly string[]\n}\n\n/**\n * Resolve the commands option to a {@link ResolvedCommands}.\n *\n * Accepts a directory string (triggers autoload), a static CommandMap,\n * a Promise<CommandMap>, a structured {@link CommandsConfig},\n * or undefined (loads `kidd.config.ts` and autoloads from its `commands` field,\n * falling back to `'./commands'`).\n *\n * @private\n * @param commands - The commands option from CliOptions.\n * @returns Resolved commands with optional order, or undefined.\n */\nasync function resolveCommands(\n commands: string | CommandMap | Promise<CommandMap> | CommandsConfig | undefined\n): Promise<ResolvedCommands | undefined> {\n return match(commands)\n .when(isString, async (dir) => ({ commands: await autoload({ dir }) }))\n .with(P.instanceOf(Promise), async (p) => ({ commands: await p }))\n .when(isCommandsConfig, (cfg) => resolveCommandsConfig(cfg))\n .when(isPlainObject, (cmds) => ({ commands: cmds }))\n .otherwise(() => resolveCommandsFromConfig())\n}\n\n/**\n * Resolve a structured {@link CommandsConfig} into flat commands and order.\n *\n * When `path` is provided, autoloads from that directory. Otherwise uses the\n * inline `commands` map (resolved if it is a promise).\n *\n * @private\n * @param config - The structured commands configuration.\n * @returns Resolved commands with optional order.\n */\nasync function resolveCommandsConfig(config: CommandsConfig): Promise<ResolvedCommands> {\n const { order, path, commands: innerCommands } = config\n\n const commands = await match(innerCommands)\n .when(\n () => isString(path),\n async () => autoload({ dir: path as string })\n )\n .with(P.instanceOf(Promise), async (p) => p)\n .when(isPlainObject, (cmds) => cmds)\n .otherwise(() => ({}) as CommandMap)\n\n return { commands, order }\n}\n\n/**\n * Load `kidd.config.ts` and autoload commands from its `commands` field.\n *\n * Falls back to `'./commands'` when the config file is missing, fails to load,\n * or does not specify a `commands` field.\n *\n * @private\n * @returns A CommandMap autoloaded from the configured commands directory.\n */\nasync function resolveCommandsFromConfig(): Promise<ResolvedCommands> {\n const DEFAULT_COMMANDS_DIR = './commands'\n\n const [configError, configResult] = await loadConfig()\n if (configError || !configResult) {\n return { commands: await autoload({ dir: DEFAULT_COMMANDS_DIR }) }\n }\n\n const dir = configResult.config.commands ?? DEFAULT_COMMANDS_DIR\n return { commands: await autoload({ dir }) }\n}\n\n/**\n * Change the process working directory when `--cwd` is provided.\n *\n * Resolves the value to an absolute path and calls `process.chdir()` so\n * that all downstream `process.cwd()` calls reflect the override.\n *\n * @private\n * @param argv - The parsed argv record from yargs.\n */\nfunction applyCwd(argv: Record<string, unknown>): void {\n if (isString(argv.cwd)) {\n process.chdir(resolve(argv.cwd))\n }\n}\n\n/**\n * Show help output when no command was matched.\n *\n * Prints the header (if configured) above the yargs help text. Skipped when\n * `--help` was explicitly passed, since yargs already handles that case.\n *\n * @private\n * @param params - The argv, commands, help options, and yargs program instance.\n */\nfunction showNoCommandHelp({\n argv,\n commands,\n help,\n program,\n}: {\n readonly argv: Record<string, unknown>\n readonly commands: ResolvedCommands | undefined\n readonly help: CliHelpOptions | undefined\n readonly program: Argv\n}): void {\n if (!commands) {\n return\n }\n if (argv.help) {\n return\n }\n\n const header = extractHeader(help)\n if (header) {\n console.log(header)\n console.log()\n }\n program.showHelp('log')\n}\n\n/**\n * Extract the header string from help options.\n *\n * @private\n * @param help - The help options, possibly undefined.\n * @returns The header string or undefined.\n */\nfunction extractHeader(help: CliHelpOptions | undefined): string | undefined {\n if (!help) {\n return undefined\n }\n return help.header\n}\n\n/**\n * Extract the footer string from help options.\n *\n * @private\n * @param help - The help options, possibly undefined.\n * @returns The footer string or undefined.\n */\nfunction extractFooter(help: CliHelpOptions | undefined): string | undefined {\n if (!help) {\n return undefined\n }\n return help.footer\n}\n\n/**\n * Handle a CLI error by logging the message and exiting with the appropriate code.\n *\n * ContextErrors carry a custom exit code; all other errors exit with code 1.\n *\n * @private\n * @param error - The caught error value.\n * @param logger - Logger with an error method for output.\n */\nfunction exitOnError(error: unknown, logger: { error(msg: string): void }): void {\n const info = match(error)\n .when(isContextError, (e) => ({ exitCode: e.exitCode, message: e.message }))\n .with(P.instanceOf(Error), (e) => ({ exitCode: DEFAULT_EXIT_CODE, message: e.message }))\n .otherwise((e) => ({ exitCode: DEFAULT_EXIT_CODE, message: String(e) }))\n\n logger.error(info.message)\n process.exit(info.exitCode)\n}\n","/**\n * Middleware combinator that merges multiple middleware into one.\n *\n * @module\n */\n\nimport { middleware } from './middleware.js'\nimport type { InferVariables, Middleware, MiddlewareEnv } from './types.js'\n\n/**\n * The composed return environment. Uses a conditional type to normalize\n * `unknown` (produced by empty tuples) into `Record<string, unknown>`,\n * satisfying the `MiddlewareEnv` constraint.\n */\ninterface ComposedEnv<TMiddleware extends readonly Middleware<MiddlewareEnv>[]> {\n readonly Variables: InferVariables<TMiddleware> extends infer V\n ? unknown extends V\n ? Record<string, unknown>\n : V\n : never\n}\n\n/**\n * Compose multiple middleware into a single middleware.\n *\n * Executes each middleware in order, threading `next()` through the chain.\n * The final `next()` call from the last composed middleware continues to\n * the downstream middleware or command handler.\n *\n * The returned middleware's type merges all `Variables` from the input tuple,\n * so downstream handlers see the combined context.\n *\n * @param middlewares - An ordered tuple of middleware to compose.\n * @returns A single Middleware whose Variables is the intersection of all input Variables.\n *\n * @example\n * ```ts\n * const combined = compose([auth({ strategies: [auth.env()] }), auth.require()])\n * ```\n */\nexport function compose<const TMiddleware extends readonly Middleware<MiddlewareEnv>[]>(\n middlewares: TMiddleware\n): Middleware<ComposedEnv<TMiddleware>> {\n return middleware((ctx, next) => executeChain(middlewares, 0, ctx, next)) as Middleware<\n ComposedEnv<TMiddleware>\n >\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Recursively execute middleware in order, calling next() after the last one.\n *\n * @private\n * @param middlewares - The middleware array.\n * @param index - Current position in the array.\n * @param ctx - The context object.\n * @param next - The downstream next function.\n */\nasync function executeChain(\n middlewares: readonly Middleware<MiddlewareEnv>[],\n index: number,\n ctx: Parameters<Middleware['handler']>[0],\n next: () => Promise<void>\n): Promise<void> {\n if (index >= middlewares.length) {\n await next()\n return\n }\n\n const mw = middlewares[index]\n\n if (mw === undefined) {\n await next()\n return\n }\n\n await mw.handler(ctx, () => executeChain(middlewares, index + 1, ctx, next))\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { c as Middleware, d as Context } from "../types-CTvrsrnD.js";
1
+ import { p as Context, u as Middleware } from "../types-U73X_oQ_.js";
2
2
  import { AsyncResult } from "@kidd-cli/utils/fp";
3
3
 
4
4
  //#region src/middleware/auth/require.d.ts
@@ -135,11 +135,20 @@ interface CustomSourceConfig {
135
135
  */
136
136
  type StrategyConfig = EnvSourceConfig | DotenvSourceConfig | FileSourceConfig | OAuthSourceConfig | DeviceCodeSourceConfig | TokenSourceConfig | CustomSourceConfig;
137
137
  /**
138
+ * Callback that validates a resolved credential before it is persisted.
139
+ *
140
+ * Returning a successful Result allows the credential to be saved (the
141
+ * returned credential is what gets persisted, so the callback may also
142
+ * enrich or transform it). Returning a failure Result prevents persistence
143
+ * and surfaces the error to the caller.
144
+ */
145
+ type ValidateCredential = (credential: AuthCredential) => AsyncResult<AuthCredential, AuthError>;
146
+ /**
138
147
  * Error returned by {@link AuthContext.login} or {@link AuthContext.logout}
139
148
  * when the operation fails.
140
149
  */
141
150
  interface AuthError {
142
- readonly type: "no_credential" | "save_failed" | "remove_failed";
151
+ readonly type: "no_credential" | "save_failed" | "remove_failed" | "validation_failed";
143
152
  readonly message: string;
144
153
  }
145
154
  /**
@@ -148,6 +157,7 @@ interface AuthError {
148
157
  */
149
158
  interface LoginOptions {
150
159
  readonly strategies?: readonly StrategyConfig[];
160
+ readonly validate?: ValidateCredential;
151
161
  }
152
162
  /**
153
163
  * Auth context decorated onto `ctx.auth` by the auth middleware.
@@ -200,9 +210,11 @@ type CustomStrategyFn = () => Promise<AuthCredential | null> | AuthCredential |
200
210
  * Options accepted by the `auth()` middleware factory.
201
211
  *
202
212
  * @property strategies - Ordered list of credential sources to try via `login()`.
213
+ * @property validate - Optional callback to validate a credential before persisting.
203
214
  */
204
215
  interface AuthOptions {
205
216
  readonly strategies: readonly StrategyConfig[];
217
+ readonly validate?: ValidateCredential;
206
218
  }
207
219
  /**
208
220
  * Augments the base {@link Context} with an optional `auth` property.
@@ -255,5 +267,5 @@ declare const auth: AuthFactory;
255
267
  */
256
268
  declare function createAuthHeaders(): (ctx: Context) => Readonly<Record<string, string>>;
257
269
  //#endregion
258
- export { type AuthContext, type AuthCredential, type AuthError, type AuthFactory, type AuthOptions, type AuthRequireOptions, type CustomSourceConfig, type CustomStrategyFn, type DeviceCodeSourceConfig, type DeviceCodeStrategyOptions, type DotenvSourceConfig, type DotenvStrategyOptions, type EnvSourceConfig, type EnvStrategyOptions, type FileSourceConfig, type FileStrategyOptions, type LoginOptions, type OAuthSourceConfig, type OAuthStrategyOptions, type StrategyConfig, type TokenSourceConfig, type TokenStrategyOptions, auth, createAuthHeaders, createAuthRequire };
270
+ export { type AuthContext, type AuthCredential, type AuthError, type AuthFactory, type AuthOptions, type AuthRequireOptions, type CustomSourceConfig, type CustomStrategyFn, type DeviceCodeSourceConfig, type DeviceCodeStrategyOptions, type DotenvSourceConfig, type DotenvStrategyOptions, type EnvSourceConfig, type EnvStrategyOptions, type FileSourceConfig, type FileStrategyOptions, type LoginOptions, type OAuthSourceConfig, type OAuthStrategyOptions, type StrategyConfig, type TokenSourceConfig, type TokenStrategyOptions, type ValidateCredential, auth, createAuthHeaders, createAuthRequire };
259
271
  //# sourceMappingURL=auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","names":[],"sources":["../../src/middleware/auth/require.ts","../../src/middleware/auth/types.ts","../../src/middleware/auth/auth.ts","../../src/middleware/auth/headers.ts"],"mappings":"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"}
1
+ {"version":3,"file":"auth.d.ts","names":[],"sources":["../../src/middleware/auth/require.ts","../../src/middleware/auth/types.ts","../../src/middleware/auth/auth.ts","../../src/middleware/auth/headers.ts"],"mappings":"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"}
@@ -3,6 +3,7 @@ import "../project-D0g84bZY.js";
3
3
  import { t as createStore } from "../create-store-OHdkm_Yt.js";
4
4
  import { join } from "node:path";
5
5
  import { attempt, attemptAsync, isPlainObject, match, ok } from "@kidd-cli/utils/fp";
6
+ import { z } from "zod";
6
7
  import { match as match$1 } from "ts-pattern";
7
8
  import { platform } from "node:os";
8
9
  import { readFileSync } from "node:fs";
@@ -10,7 +11,6 @@ import { execFile } from "node:child_process";
10
11
  import { createServer } from "node:http";
11
12
  import { parse } from "dotenv";
12
13
  import { attempt as attempt$1 } from "es-toolkit";
13
- import { z } from "zod";
14
14
  import { createHash, randomBytes } from "node:crypto";
15
15
  import { Buffer } from "node:buffer";
16
16
  //#region src/middleware/auth/constants.ts
@@ -940,7 +940,7 @@ async function dispatchStrategy(config, defaultTokenVar, context) {
940
940
  * @returns An AuthContext instance.
941
941
  */
942
942
  function createAuthContext(options) {
943
- const { strategies, cliName, prompts, resolveCredential } = options;
943
+ const { strategies, cliName, prompts, resolveCredential, validate } = options;
944
944
  /**
945
945
  * Resolve the current credential from passive sources (file, env).
946
946
  *
@@ -979,12 +979,14 @@ function createAuthContext(options) {
979
979
  message: "No credential resolved from any source",
980
980
  type: "no_credential"
981
981
  });
982
- const [saveError] = createStore({ dirName: `.${cliName}` }).save(DEFAULT_AUTH_FILENAME, resolved);
982
+ const [validationError, validatedCredential] = await runValidation(resolveLoginValidate(loginOptions, validate), resolved);
983
+ if (validationError) return [validationError, null];
984
+ const [saveError] = createStore({ dirName: `.${cliName}` }).save(DEFAULT_AUTH_FILENAME, validatedCredential);
983
985
  if (saveError) return authError({
984
986
  message: `Failed to save credential: ${saveError.message}`,
985
987
  type: "save_failed"
986
988
  });
987
- return ok(resolved);
989
+ return ok(validatedCredential);
988
990
  }
989
991
  /**
990
992
  * Remove the stored credential from disk.
@@ -1032,6 +1034,42 @@ function resolveLoginStrategies(loginOptions, configured) {
1032
1034
  if (loginOptions !== void 0 && loginOptions.strategies !== void 0) return loginOptions.strategies;
1033
1035
  return configured;
1034
1036
  }
1037
+ /**
1038
+ * Resolve the active validate callback for a login attempt.
1039
+ *
1040
+ * Returns the override from login options when provided,
1041
+ * otherwise falls back to the configured validate callback.
1042
+ *
1043
+ * @private
1044
+ * @param loginOptions - Optional login overrides.
1045
+ * @param configured - The default configured validate callback.
1046
+ * @returns The validate callback to use, or undefined.
1047
+ */
1048
+ function resolveLoginValidate(loginOptions, configured) {
1049
+ if (loginOptions !== void 0 && loginOptions.validate !== void 0) return loginOptions.validate;
1050
+ return configured;
1051
+ }
1052
+ /**
1053
+ * Run the validate callback against a resolved credential.
1054
+ *
1055
+ * When no validate callback is provided, returns the credential as-is.
1056
+ * When validation fails, returns the error Result.
1057
+ * When validation succeeds, returns the (possibly transformed) credential.
1058
+ *
1059
+ * @private
1060
+ * @param validateFn - The validate callback, or undefined.
1061
+ * @param credential - The resolved credential to validate.
1062
+ * @returns A Result with the validated credential or an AuthError.
1063
+ */
1064
+ async function runValidation(validateFn, credential) {
1065
+ if (validateFn === void 0) return ok(credential);
1066
+ const [validationError, validatedCredential] = await validateFn(credential);
1067
+ if (validationError) return authError({
1068
+ message: validationError.message,
1069
+ type: "validation_failed"
1070
+ });
1071
+ return ok(validatedCredential);
1072
+ }
1035
1073
  //#endregion
1036
1074
  //#region src/middleware/http/build-auth-headers.ts
1037
1075
  /**
@@ -1151,14 +1189,15 @@ function resolveMessage(options) {
1151
1189
  * @returns A Middleware that decorates ctx.auth.
1152
1190
  */
1153
1191
  function createAuth(options) {
1154
- const { strategies } = options;
1192
+ const { strategies, validate } = options;
1155
1193
  return middleware((ctx, next) => {
1156
1194
  const cliName = ctx.meta.name;
1157
1195
  decorateContext(ctx, "auth", createAuthContext({
1158
1196
  cliName,
1159
1197
  prompts: ctx.prompts,
1160
1198
  resolveCredential: () => resolveStoredCredential(cliName, strategies),
1161
- strategies
1199
+ strategies,
1200
+ validate
1162
1201
  }));
1163
1202
  return next();
1164
1203
  });