#!/usr/bin/env bun /** * Mixed machine-readable JSON and human-readable side-channel output. * * Demonstrates: machine-readable `out.json()` stdout, `out.status()` stderr * side channels suppressible with `--quiet`, and `--json` for CLI-managed * structured errors. * * Usage: * npx tsx examples/json-mode.ts list # JSON stdout + plain stderr side channel * npx tsx examples/json-mode.ts list --format table # JSON stdout + table stderr side channel * npx tsx examples/json-mode.ts list --quiet # JSON stdout only, status lines suppressed * npx tsx examples/json-mode.ts list --json # same success output; CLI-managed errors stay JSON-safe * npx tsx examples/json-mode.ts show web-api * npx tsx examples/json-mode.ts show nonexistent # structured error * npx tsx examples/json-mode.ts show nonexistent --json # JSON error */ import { arg, CLIError, cli, command, flag } from '@kjanat/dreamcli'; // --- Sample data --- type Service = { readonly name: string; readonly status: 'healthy' | 'degraded' | 'down'; readonly uptime: number; }; const services: readonly Service[] = [ { name: 'web-api', status: 'healthy', uptime: 99.9 }, { name: 'worker', status: 'degraded', uptime: 95.2 }, { name: 'database', status: 'healthy', uptime: 99.99 }, { name: 'cache', status: 'down', uptime: 0 }, ]; // --- Commands --- const list = command('list') .description('List all services') .flag( 'format', flag.enum(['table', 'plain']).default('plain').alias('f').describe('Output format'), ) .action(({ flags, out }) => { // This example always emits machine-readable JSON to stdout. `--json` // still matters for DreamCLI-managed output such as structured errors. out.json(services); if (flags.format === 'table') { out.table( services, [ { key: 'name', header: 'Service' }, { key: 'status', header: 'Status' }, { key: 'uptime', header: 'Uptime %' }, ], { format: 'text', stream: 'stderr' }, ); } else { // `out.status()` writes to stderr (stdout stays pipeable JSON) and // is suppressed under `--quiet`, unlike `out.error()`. for (const s of services) { out.status(`${s.name}: ${s.status} (${s.uptime}%)`); } } }); const show = command('show') .description('Show details for a service') .arg('name', arg.string().describe('Service name')) .action(({ args, out }) => { const service = services.find((s) => s.name === args.name); if (!service) { // CLIError with details serializes cleanly in --json mode. throw new CLIError(`Service '${args.name}' not found`, { code: 'NOT_FOUND', exitCode: 1, suggest: `Available: ${services.map((s) => s.name).join(', ')}`, details: { requested: args.name, available: services.map((s) => s.name) }, }); } out.json(service); out.status(`${service.name}: ${service.status} (uptime ${service.uptime}%)`); }); // --- CLI with --json support --- void cli('services') .version('1.0.0') .description('Service status dashboard') .command(list) .command(show) .run();