import type { StandardSchemaV1 } from '@standard-schema/spec'; import type { PadroneSignal } from '../core/runtime.ts'; import type { Drained, IsGeneric, MaybePromise } from '../util/type-utils.ts'; import type { AnyPadroneCommand } from './command.ts'; type EmptyRecord = Record; type NormalizeArguments = IsGeneric extends true ? void | EmptyRecord : TArgs; export type GetArguments = TDir extends 'in' ? NormalizeArguments : NormalizeArguments; export type GetResults = ReturnType>; /** * Result of `drain()` — a discriminated union that never throws. * On success, `value` holds the fully resolved/collected result; on failure, `error` holds the error. */ export type PadroneDrainResult = { value: Drained; error?: never } | { error: unknown; value?: never }; /** * Result returned by `eval()`, `cli()`, and `run()`. Never thrown — errors are captured in the `error` field. * Discriminated union: check `error` to distinguish success from failure. * * On success: `command`, `args`, `argsResult`, `result` are populated; `error` is absent. * On failure: `error` is populated; `command` may be present if routing succeeded. */ export type PadroneCommandResult = | (PadroneParseResult & { result: GetResults; error?: never; /** The signal that caused cancellation, if any. */ signal?: PadroneSignal; /** Suggested exit code (e.g. 130 for SIGINT). Present when a signal caused termination. */ exitCode?: number; /** Flattens the result: awaits Promises, collects iterables, catches errors. Never throws. */ drain: () => Promise>>; }) | { command?: TCommand; args?: GetArguments<'out', TCommand>; argsResult?: StandardSchemaV1.Result>; error: unknown; result?: never; /** The signal that caused cancellation, if any. */ signal?: PadroneSignal; /** Suggested exit code (e.g. 130 for SIGINT). Present when a signal caused termination. */ exitCode?: number; /** Returns `{ error }` since there is no result to drain. */ drain: () => Promise>>; }; /** * Like `MaybePromise, TAsync>` but ensures `drain()` is available * at the outer level in all cases — both sync (Thenable) and async (Promise). */ export type MaybePromiseCommandResult = MaybePromise, TAsync> & { drain: () => Promise>>; }; export type PadroneParseResult = { command: TCommand; args?: GetArguments<'out', TCommand>; argsResult?: StandardSchemaV1.Result>; }; export type PadroneAPI = PadroneAPICommand & { [K in TCommand['~types']['commands'][number] as K['name']]: PadroneAPI; }; type PadroneAPICommand = (args: GetArguments<'in', TCommand>) => GetResults;