{"version":3,"file":"auto-output.mjs","names":[],"sources":["../../src/extension/auto-output.ts"],"sourcesContent":["import { defineInterceptor } from '../core/interceptors.ts';\nimport { isAsyncIterator, isIterator } from '../core/results.ts';\nimport type { OutputConfig } from '../output/output-indicator.ts';\nimport { createOutputIndicator, formatDeclarativeOutput } from '../output/output-indicator.ts';\nimport { resolveOutputFormat } from '../output/styling.ts';\nimport type {\n  AnyPadroneBuilder,\n  CommandTypesBase,\n  InterceptorErrorContext,\n  InterceptorErrorResult,\n  InterceptorExecuteContext,\n  InterceptorExecuteResult,\n} from '../types/index.ts';\n\n// ── Helpers ─────────────────────────────────────────────────────────────\n\n/**\n * Outputs each value and collects into a result.\n * For iterators: outputs each yielded value, returns collected array.\n * For promises: awaits, then recurses.\n * For other values: outputs directly, returns as-is.\n */\nfunction outputAndCollect(value: unknown, output: (...args: unknown[]) => void): unknown {\n  if (value == null) return value;\n\n  if (isAsyncIterator(value)) {\n    return (async () => {\n      const items: unknown[] = [];\n      const iter = (value as any)[Symbol.asyncIterator]();\n      while (true) {\n        const { done, value: item } = await iter.next();\n        if (done) break;\n        items.push(item);\n        if (item != null) output(item);\n      }\n      return items;\n    })();\n  }\n\n  if (typeof value !== 'string' && !Array.isArray(value) && isIterator(value)) {\n    const items: unknown[] = [];\n    const iter = (value as any)[Symbol.iterator]();\n    while (true) {\n      const { done, value: item } = iter.next();\n      if (done) break;\n      items.push(item);\n      if (item != null) output(item);\n    }\n    return items;\n  }\n\n  if (value instanceof Promise) {\n    return value.then((resolved) => outputAndCollect(resolved, output));\n  }\n\n  output(value);\n  return value;\n}\n\n// ── Interceptor ─────────────────────────────────────────────────────────\n\nconst autoOutputMeta = { id: 'padrone:auto-output', name: 'padrone:auto-output', order: -1100 } as const;\n\nfunction createAutoOutputInterceptor(outputConfig?: OutputConfig, errorOutput?: boolean) {\n  return defineInterceptor(autoOutputMeta, () => ({\n    error(ctx: InterceptorErrorContext, next: () => InterceptorErrorResult | Promise<InterceptorErrorResult>) {\n      const handleResult = (er: InterceptorErrorResult): InterceptorErrorResult => {\n        if (!er.error || errorOutput === false || ctx.caller !== 'cli' || ctx.phase !== 'execute') return er;\n        const message = er.error instanceof Error ? er.error.message : String(er.error);\n        ctx.runtime.error(message);\n        return er;\n      };\n\n      const result = next();\n      if (result instanceof Promise) return result.then(handleResult);\n      return handleResult(result);\n    },\n    execute(ctx: InterceptorExecuteContext, next) {\n      const outputCtx = resolveOutputFormat(ctx.runtime, ctx.caller);\n      const indicator = createOutputIndicator(ctx.runtime.output, outputCtx);\n\n      const handleResult = (e: InterceptorExecuteResult): InterceptorExecuteResult | Promise<InterceptorExecuteResult> => {\n        // If the action already called output.*, skip auto-output\n        if (indicator.called) return e;\n\n        const autoOutput = (value: unknown): unknown => {\n          if (value == null) return value;\n\n          // Declarative output config: format the return value through the primitive\n          if (outputConfig) {\n            const rendered = formatDeclarativeOutput(value, outputConfig, outputCtx);\n            if (rendered !== undefined) {\n              ctx.runtime.output(rendered);\n              return value;\n            }\n          }\n\n          return outputAndCollect(value, ctx.runtime.output);\n        };\n\n        if (e.result instanceof Promise) {\n          return { result: e.result.then(autoOutput) };\n        }\n\n        const collected = autoOutput(e.result);\n        if (collected instanceof Promise) return collected.then((v) => ({ result: v }));\n        return { result: collected };\n      };\n\n      const executedOrPromise = next({ context: { output: indicator } });\n      if (executedOrPromise instanceof Promise) return executedOrPromise.then(handleResult);\n      return handleResult(executedOrPromise);\n    },\n  }));\n}\n\n// ── Extension ───────────────────────────────────────────────────────────\n\nexport type PadroneAutoOutputOptions = {\n  /** Disable auto-output entirely. */\n  disabled?: boolean;\n  /**\n   * Declarative output format for the command's return value.\n   * When set, auto-output formats the return value through the specified primitive\n   * instead of passing it raw to `runtime.output`.\n   * Ignored when the action calls `ctx.context.output.*` explicitly.\n   *\n   * ```ts\n   * // Format return value as a table\n   * c.extend(padroneAutoOutput({ output: 'table' }))\n   *\n   * // Format with options\n   * c.extend(padroneAutoOutput({ output: { type: 'table', options: { border: false } } }))\n   * ```\n   */\n  output?: OutputConfig;\n  /**\n   * Automatically print unhandled errors to stderr in CLI mode.\n   * Skips errors already handled by other extensions (routing, validation, signal).\n   * @default true\n   */\n  errorOutput?: boolean;\n};\n\n/**\n * Extension that automatically writes a command's return value to output after execution.\n *\n * - Values are passed directly to the runtime's `output` function (no stringification).\n * - Promises are awaited before output.\n * - Iterators and async iterators are consumed, outputting each yielded value as it arrives.\n *   The result is replaced with the collected array so `drain()` still works.\n * - `undefined` and `null` results produce no output.\n *\n * Also injects `ctx.context.output` with format-aware output primitives (table, tree, list, kv).\n * When action handlers use these methods, auto-output skips to avoid double output.\n *\n * Included in the default extensions. Can also be applied per-command:\n * ```ts\n * createPadrone('my-cli')\n *   .command('users', (c) =>\n *     c.extend(padroneAutoOutput({ output: 'table' }))\n *       .action(() => fetchUsers())\n *   )\n * ```\n */\nexport function padroneAutoOutput(options?: PadroneAutoOutputOptions): <T extends CommandTypesBase>(builder: T) => T {\n  const interceptor = options?.disabled\n    ? defineInterceptor({ ...autoOutputMeta, disabled: true }, () => ({}))\n    : createAutoOutputInterceptor(options?.output, options?.errorOutput);\n  return ((builder: AnyPadroneBuilder) => builder.intercept(interceptor)) as any;\n}\n"],"mappings":"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"}