{"version":3,"file":"serve.mjs","names":[],"sources":["../../src/feature/serve.ts"],"sourcesContent":["import { buildInputSchema, type CollectedEndpoint, collectEndpoints, serializeArgsToFlags } from '../core/commands.ts';\nimport { RoutingError, ValidationError } from '../core/errors.ts';\nimport { generateHelp } from '../output/help.ts';\nimport type { AnyPadroneCommand, AnyPadroneProgram } from '../types/index.ts';\nimport { readStreamAsText } from '../util/stream.ts';\n\nexport type PadroneServePreferences = {\n  /** Port to listen on. Default: 3000 */\n  port?: number;\n  /** Host to bind to. Default: '127.0.0.1' */\n  host?: string;\n  /** Base path prefix for all routes. Default: '/' */\n  basePath?: string;\n  /** CORS allowed origin. Default: '*'. Set to `false` to disable CORS headers. */\n  cors?: string | false;\n  /** Control built-in utility endpoints. All enabled by default. */\n  builtins?: {\n    /** GET /_health — returns 200 OK. */\n    health?: boolean;\n    /** GET /_help and GET /_help/:command — returns help text. */\n    help?: boolean;\n    /** GET /_schema and GET /_schema/:command — returns JSON Schema. */\n    schema?: boolean;\n    /** GET /_docs — Scalar OpenAPI docs viewer. */\n    docs?: boolean;\n  };\n  /** Hook to run before each request. Return a Response to short-circuit. */\n  onRequest?: (req: Request) => Response | void | Promise<Response | void>;\n  /** Transform errors into responses. */\n  onError?: (error: unknown, req: Request) => Response;\n};\n\n/** Convert an endpoint dot-path to a URL path segment. */\nfunction toUrlPath(name: string): string {\n  return name.replace(/\\./g, '/');\n}\n\n/** Convert a URL path segment back to a command path (slash → space). */\nfunction toCommandPath(urlPath: string): string {\n  return urlPath.replace(/\\//g, ' ');\n}\n\nfunction jsonResponse(body: unknown, status = 200, headers?: Record<string, string>): Response {\n  return new Response(JSON.stringify(body), {\n    status,\n    headers: { 'Content-Type': 'application/json', ...headers },\n  });\n}\n\nfunction errorToStatus(error: unknown): number {\n  if (error instanceof RoutingError) return 404;\n  if (error instanceof ValidationError) return 400;\n  return 500;\n}\n\nfunction errorToResponse(error: unknown): Response {\n  const status = errorToStatus(error);\n  if (error instanceof ValidationError) {\n    return jsonResponse(\n      {\n        ok: false,\n        error: 'validation',\n        message: error.message,\n        issues: error.issues.map((i) => ({ path: i.path?.map(String), message: i.message })),\n      },\n      status,\n    );\n  }\n  if (error instanceof RoutingError) {\n    return jsonResponse({ ok: false, error: 'not_found', message: error.message, suggestions: error.suggestions }, status);\n  }\n  const message = error instanceof Error ? error.message : String(error);\n  return jsonResponse({ ok: false, error: 'action_error', message }, status);\n}\n\n/** Generate an OpenAPI 3.1.0 spec from the command tree. */\nfunction buildOpenApiSpec(existingCommand: AnyPadroneCommand, endpoints: CollectedEndpoint[], basePath: string): Record<string, unknown> {\n  const paths: Record<string, unknown> = {};\n\n  const responseSchema = {\n    '200': {\n      description: 'Successful response',\n      content: { 'application/json': { schema: { type: 'object', properties: { ok: { type: 'boolean', const: true }, result: {} } } } },\n    },\n    '400': {\n      description: 'Validation error',\n      content: {\n        'application/json': {\n          schema: {\n            type: 'object',\n            properties: {\n              ok: { type: 'boolean', const: false },\n              error: { type: 'string', const: 'validation' },\n              message: { type: 'string' },\n              issues: { type: 'array', items: { type: 'object', properties: { path: { type: 'array' }, message: { type: 'string' } } } },\n            },\n          },\n        },\n      },\n    },\n    '404': {\n      description: 'Command not found',\n      content: {\n        'application/json': {\n          schema: {\n            type: 'object',\n            properties: {\n              ok: { type: 'boolean', const: false },\n              error: { type: 'string', const: 'not_found' },\n              message: { type: 'string' },\n            },\n          },\n        },\n      },\n    },\n    '500': {\n      description: 'Action error',\n      content: {\n        'application/json': {\n          schema: {\n            type: 'object',\n            properties: {\n              ok: { type: 'boolean', const: false },\n              error: { type: 'string', const: 'action_error' },\n              message: { type: 'string' },\n            },\n          },\n        },\n      },\n    },\n  };\n\n  for (const { name, command: cmd } of endpoints) {\n    const urlPath = `${basePath}${toUrlPath(name)}`;\n    const inputSchema = buildInputSchema(cmd);\n    const description = cmd.description || cmd.title || `Run the \"${name}\" command`;\n    const pathItem: Record<string, unknown> = {};\n\n    const postOp = {\n      summary: cmd.title || name,\n      description,\n      operationId: `post_${name.replace(/\\./g, '_')}`,\n      requestBody: { content: { 'application/json': { schema: inputSchema } } },\n      responses: responseSchema,\n    };\n\n    if (cmd.mutation) {\n      pathItem.post = postOp;\n    } else {\n      // GET: args as query parameters\n      const properties = (inputSchema.properties ?? {}) as Record<string, Record<string, unknown>>;\n      const queryParams = Object.entries(properties).map(([key, schema]) => ({\n        name: key,\n        in: 'query',\n        schema,\n        required: (inputSchema.required as string[] | undefined)?.includes(key) ?? false,\n      }));\n      pathItem.get = {\n        summary: cmd.title || name,\n        description,\n        operationId: `get_${name.replace(/\\./g, '_')}`,\n        parameters: queryParams,\n        responses: responseSchema,\n      };\n      pathItem.post = postOp;\n    }\n\n    paths[urlPath] = pathItem;\n  }\n\n  return {\n    openapi: '3.1.0',\n    info: {\n      title: existingCommand.title || existingCommand.name,\n      description: existingCommand.description,\n      version: existingCommand.version ?? '0.0.0',\n    },\n    paths,\n  };\n}\n\nfunction scalarDocsHtml(openapiUrl: string, title: string): string {\n  return `<!doctype html>\n<html>\n<head>\n  <title>${title} — API Docs</title>\n  <meta charset=\"utf-8\" />\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n</head>\n<body>\n  <script id=\"api-reference\" data-url=\"${openapiUrl}\"></script>\n  <script src=\"https://cdn.jsdelivr.net/npm/@scalar/api-reference\"></script>\n</body>\n</html>`;\n}\n\n/** Create the serve request handler. */\nexport function createServeHandler(\n  existingCommand: AnyPadroneCommand,\n  evalCommand: AnyPadroneProgram['eval'],\n  prefs?: PadroneServePreferences,\n): (req: Request) => Promise<Response> {\n  const basePath = (prefs?.basePath ?? '/').replace(/\\/$/, '/');\n  const corsOrigin = prefs?.cors !== false ? (prefs?.cors ?? '*') : undefined;\n  const builtins = { health: true, help: true, schema: true, docs: true, ...prefs?.builtins };\n\n  const endpoints = collectEndpoints(existingCommand.commands, '');\n  if (existingCommand.action || existingCommand.argsSchema) {\n    endpoints.unshift({ name: '', command: existingCommand });\n  }\n\n  const routeMap = new Map<string, CollectedEndpoint>();\n  for (const ep of endpoints) {\n    routeMap.set(toUrlPath(ep.name), ep);\n  }\n\n  let cachedOpenApiSpec: Record<string, unknown> | undefined;\n  const getOpenApiSpec = () => (cachedOpenApiSpec ??= buildOpenApiSpec(existingCommand, endpoints, basePath));\n\n  function addCorsHeaders(res: Response): Response {\n    if (!corsOrigin) return res;\n    const headers = new Headers(res.headers);\n    headers.set('Access-Control-Allow-Origin', corsOrigin);\n    headers.set('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n    headers.set('Access-Control-Allow-Headers', 'Content-Type');\n    return new Response(res.body, { status: res.status, statusText: res.statusText, headers });\n  }\n\n  async function evalAndRespond(commandString: string, request: Request): Promise<Response> {\n    const output: string[] = [];\n    const errors: string[] = [];\n    const result = await evalCommand(commandString || (undefined as any), {\n      caller: 'serve',\n      runtime: {\n        output: (...args: unknown[]) => output.push(args.map(String).join(' ')),\n        error: (text: string) => errors.push(text),\n        interactive: 'unsupported',\n        format: 'json',\n      },\n    });\n\n    if (result.error) {\n      return prefs?.onError ? prefs.onError(result.error, request) : errorToResponse(result.error);\n    }\n\n    if (result.argsResult?.issues) {\n      const issues = (result.argsResult.issues as { path?: PropertyKey[]; message: string }[]).map((i) => ({\n        path: i.path?.map(String),\n        message: i.message,\n      }));\n      return jsonResponse({ ok: false, error: 'validation', issues }, 400);\n    }\n\n    return jsonResponse({ ok: true, result: result.result ?? null });\n  }\n\n  return async function handleRequest(req: Request): Promise<Response> {\n    // CORS preflight\n    if (req.method === 'OPTIONS') {\n      return addCorsHeaders(new Response(null, { status: corsOrigin ? 204 : 405 }));\n    }\n\n    // onRequest hook\n    if (prefs?.onRequest) {\n      const hookResponse = await prefs.onRequest(req);\n      if (hookResponse) return addCorsHeaders(hookResponse);\n    }\n\n    const url = new URL(req.url, 'http://localhost');\n    let pathname = url.pathname;\n\n    // Strip basePath prefix\n    if (basePath !== '/' && pathname.startsWith(basePath)) {\n      pathname = pathname.slice(basePath.length - 1);\n    }\n    // Remove leading slash for route matching\n    const routePath = pathname.replace(/^\\//, '');\n\n    // Built-in endpoints\n    if (req.method === 'GET') {\n      if (builtins.health && routePath === '_health') {\n        return addCorsHeaders(jsonResponse({ status: 'ok' }));\n      }\n\n      if (builtins.schema && routePath === '_schema') {\n        const schemaMap: Record<string, unknown> = {};\n        for (const ep of endpoints) {\n          schemaMap[toUrlPath(ep.name) || '/'] = buildInputSchema(ep.command);\n        }\n        return addCorsHeaders(jsonResponse(schemaMap));\n      }\n\n      if (builtins.schema && routePath.startsWith('_schema/')) {\n        const cmdPath = routePath.slice('_schema/'.length);\n        const ep = routeMap.get(cmdPath);\n        if (!ep) return addCorsHeaders(jsonResponse({ ok: false, error: 'not_found', message: `Command not found: ${cmdPath}` }, 404));\n        return addCorsHeaders(jsonResponse(buildInputSchema(ep.command)));\n      }\n\n      if (builtins.help && routePath === '_help') {\n        const accept = req.headers.get('accept') ?? '';\n        const format = accept.includes('application/json') ? 'json' : 'markdown';\n        const helpText = generateHelp(existingCommand, existingCommand, { format, detail: 'full' });\n        if (format === 'json') return addCorsHeaders(jsonResponse(JSON.parse(helpText)));\n        return addCorsHeaders(new Response(helpText, { status: 200, headers: { 'Content-Type': 'text/markdown' } }));\n      }\n\n      if (builtins.help && routePath.startsWith('_help/')) {\n        const cmdPath = routePath.slice('_help/'.length);\n        const ep = routeMap.get(cmdPath);\n        if (!ep) return addCorsHeaders(jsonResponse({ ok: false, error: 'not_found', message: `Command not found: ${cmdPath}` }, 404));\n        const accept = req.headers.get('accept') ?? '';\n        const format = accept.includes('application/json') ? 'json' : 'markdown';\n        const helpText = generateHelp(existingCommand, ep.command, { format, detail: 'full' });\n        if (format === 'json') return addCorsHeaders(jsonResponse(JSON.parse(helpText)));\n        return addCorsHeaders(new Response(helpText, { status: 200, headers: { 'Content-Type': 'text/markdown' } }));\n      }\n\n      if (builtins.docs && routePath === '_openapi') {\n        return addCorsHeaders(jsonResponse(getOpenApiSpec()));\n      }\n\n      if (builtins.docs && routePath === '_docs') {\n        const openapiUrl = `${basePath}_openapi`;\n        const title = existingCommand.title || existingCommand.name;\n        const html = scalarDocsHtml(openapiUrl, title);\n        return addCorsHeaders(new Response(html, { status: 200, headers: { 'Content-Type': 'text/html' } }));\n      }\n    }\n\n    // Route to command\n    const endpoint = routeMap.get(routePath);\n    if (!endpoint) {\n      return addCorsHeaders(jsonResponse({ ok: false, error: 'not_found', message: `Command not found: ${routePath || '/'}` }, 404));\n    }\n\n    // Enforce method based on mutation flag\n    if (endpoint.command.mutation && req.method === 'GET') {\n      return addCorsHeaders(\n        new Response(JSON.stringify({ ok: false, error: 'method_not_allowed', message: 'Mutation commands only accept POST' }), {\n          status: 405,\n          headers: { 'Content-Type': 'application/json', Allow: 'POST' },\n        }),\n      );\n    }\n\n    if (req.method !== 'GET' && req.method !== 'POST') {\n      return addCorsHeaders(new Response(null, { status: 405, headers: { Allow: endpoint.command.mutation ? 'POST' : 'GET, POST' } }));\n    }\n\n    // Build command string from request\n    const commandPath = toCommandPath(routePath);\n    let argParts: string[];\n\n    if (req.method === 'POST') {\n      try {\n        const body = (await req.json()) as Record<string, unknown>;\n        argParts = serializeArgsToFlags(body);\n      } catch {\n        return addCorsHeaders(jsonResponse({ ok: false, error: 'bad_request', message: 'Invalid JSON body' }, 400));\n      }\n    } else {\n      // GET: query string → flags\n      argParts = [];\n      for (const [key, value] of url.searchParams.entries()) {\n        if (key === '_') {\n          // Positional args\n          argParts.push(value);\n        } else {\n          argParts.push(value === '' ? `--${key}` : `--${key}=${value}`);\n        }\n      }\n    }\n\n    const commandString = [commandPath, ...argParts].filter(Boolean).join(' ');\n    const response = await evalAndRespond(commandString, req);\n    return addCorsHeaders(response);\n  };\n}\n\n/** Start the serve HTTP server. */\nexport async function startServeServer(\n  _program: AnyPadroneProgram,\n  existingCommand: AnyPadroneCommand,\n  evalCommand: AnyPadroneProgram['eval'],\n  prefs?: PadroneServePreferences,\n): Promise<void> {\n  const handler = createServeHandler(existingCommand, evalCommand, prefs);\n  const http = await import('node:http');\n\n  const port = prefs?.port ?? 3000;\n  const host = prefs?.host ?? '127.0.0.1';\n  const basePath = (prefs?.basePath ?? '/').replace(/\\/$/, '/');\n\n  const server = http.createServer(async (req, res) => {\n    const url = `http://${host}:${port}${req.url}`;\n    const headers = new Headers();\n    for (const [key, value] of Object.entries(req.headers)) {\n      if (value) headers.set(key, Array.isArray(value) ? value.join(', ') : value);\n    }\n\n    const fetchReq = new Request(url, {\n      method: req.method,\n      headers,\n      body: req.method !== 'GET' && req.method !== 'HEAD' ? await readBody(req) : undefined,\n    });\n\n    const response = await handler(fetchReq);\n    const resHeaders: Record<string, string> = {};\n    response.headers.forEach((v, k) => {\n      resHeaders[k] = v;\n    });\n    res.writeHead(response.status, resHeaders);\n    const body = await response.text();\n    res.end(body);\n  });\n\n  const { getCommandRuntime } = await import('../core/commands.ts');\n  const runtime = getCommandRuntime(existingCommand);\n\n  return new Promise<void>((resolve, reject) => {\n    server.listen(port, host, () => {\n      runtime.error(`REST server listening on http://${host}:${port}${basePath}`);\n      const builtins = { health: true, help: true, schema: true, docs: true, ...prefs?.builtins };\n      if (builtins.docs) runtime.error(`API docs: http://${host}:${port}${basePath}_docs`);\n    });\n    server.on('error', reject);\n    const unsubscribe = runtime.onSignal?.(() => {\n      server.close(() => resolve());\n    });\n    server.on('close', () => unsubscribe?.());\n  });\n}\n\n/** Read the full body from a Node.js IncomingMessage. */\nasync function readBody(req: import('node:http').IncomingMessage): Promise<string> {\n  return readStreamAsText(req as AsyncIterable<Uint8Array>);\n}\n"],"mappings":"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"}