{"version":3,"file":"capabilities-C0TDQoMY.cjs","names":[],"sources":["../../src/runtime/capabilities.ts"],"sourcesContent":["// --- Adapter capabilities contract (§8.5) ---\n//\n// Every runtime host (Node CLI, Vite dev, Node/Bun adapters, Vercel, Netlify)\n// declares an explicit `AdapterCapabilities` object. The framework uses it to\n// decide which features are safe to enable: streaming, filesystem access,\n// runtime image transforms, background work, body size limits, ISR persistence.\n//\n// Invalid or incompatible capability combinations fail fast during build.\n\nexport type FilesystemCapability = \"none\" | \"readonly\" | \"persistent\" | \"ephemeral\";\n\nexport interface AdapterCapabilities {\n  /** Whether the host supports streaming responses (ReadableStream bodies). */\n  streaming: boolean;\n  /** Filesystem access model of the host. */\n  filesystem: FilesystemCapability;\n  /** Whether the host can run image transforms at request time. */\n  imageRuntime: boolean;\n  /** Whether the host allows background work after the response completes. */\n  backgroundWork: boolean;\n  /** Maximum request body size in bytes accepted by the host (if any). */\n  maxBodySize?: number;\n}\n\nexport interface CapabilityOptions {\n  streaming?: boolean;\n  filesystem?: FilesystemCapability;\n  imageRuntime?: boolean;\n  backgroundWork?: boolean;\n  maxBodySize?: number;\n}\n\n/** Default capabilities for a full-featured long-lived Node/Bun process. */\nexport const DEFAULT_CAPABILITIES: AdapterCapabilities = {\n  streaming: true,\n  filesystem: \"persistent\",\n  imageRuntime: true,\n  backgroundWork: true,\n};\n\n/** Default capabilities for a stateless serverless function (Vercel/Netlify). */\nexport const SERVERLESS_CAPABILITIES: AdapterCapabilities = {\n  streaming: true,\n  filesystem: \"ephemeral\",\n  imageRuntime: false,\n  backgroundWork: false,\n  maxBodySize: 1_048_576,\n};\n\n/** Default capabilities for an edge runtime (read-only filesystem). */\nexport const EDGE_CAPABILITIES: AdapterCapabilities = {\n  streaming: true,\n  filesystem: \"readonly\",\n  imageRuntime: false,\n  backgroundWork: false,\n  maxBodySize: 1_048_576,\n};\n\nexport function createCapabilities(options: CapabilityOptions = {}): AdapterCapabilities {\n  return {\n    ...DEFAULT_CAPABILITIES,\n    ...options,\n  };\n}\n\n/** True when the host supports streaming responses (streaming !== false). */\nexport function supportsStreaming(capabilities: Pick<AdapterCapabilities, \"streaming\"> = { streaming: true }): boolean {\n  return capabilities.streaming !== false;\n}\n\n/** True when the host can write to persistent storage (for ISR/cache/image writes). */\nexport function supportsPersistentStorage(capabilities: Pick<AdapterCapabilities, \"filesystem\">): boolean {\n  return capabilities.filesystem === \"persistent\";\n}\n\n/** True when the host exposes a writable filesystem at build/runtime. */\nexport function supportsWritableFilesystem(capabilities: Pick<AdapterCapabilities, \"filesystem\">): boolean {\n  return capabilities.filesystem === \"persistent\" || capabilities.filesystem === \"ephemeral\";\n}\n\nexport interface CapabilityDiagnostics {\n  ok: boolean;\n  problems: string[];\n}\n\n/**\n * Validates a capability declaration and reports incompatible combinations.\n * Used by the build pipeline so invalid hosts fail at build time instead of\n * producing a broken runtime.\n */\nexport function validateCapabilities(\n  capabilities: AdapterCapabilities,\n  features: { isr?: boolean; images?: boolean; streaming?: boolean } = {},\n): CapabilityDiagnostics {\n  const problems: string[] = [];\n\n  if (features.isr && !supportsPersistentStorage(capabilities)) {\n    problems.push(\n      `ISR requires a persistent filesystem; the host declares filesystem=\"${capabilities.filesystem}\".`,\n    );\n  }\n  if (features.images && capabilities.imageRuntime === false && capabilities.filesystem === \"none\") {\n    problems.push(\n      \"On-demand image transforms require either imageRuntime=true or a readable filesystem; the host has neither.\",\n    );\n  }\n  if (features.streaming && capabilities.streaming === false) {\n    problems.push(\"Streaming was requested but the host declares streaming=false.\");\n  }\n\n  return { ok: problems.length === 0, problems };\n}\n"],"mappings":"AAiCA,IAAa,EAA4C,CACvD,UAAW,GACX,WAAY,aACZ,aAAc,GACd,eAAgB,EAClB,EAGa,EAA+C,CAC1D,UAAW,GACX,WAAY,YACZ,aAAc,GACd,eAAgB,GAChB,YAAa,OACf,EAGa,EAAyC,CACpD,UAAW,GACX,WAAY,WACZ,aAAc,GACd,eAAgB,GAChB,YAAa,OACf,EAEA,SAAgB,EAAmB,EAA6B,CAAC,EAAwB,CACvF,MAAO,CACL,GAAG,EACH,GAAG,CACL,CACF,CAGA,SAAgB,EAAkB,EAAuD,CAAE,UAAW,EAAK,EAAY,CACrH,OAAO,EAAa,YAAc,EACpC,CAGA,SAAgB,EAA0B,EAAgE,CACxG,OAAO,EAAa,aAAe,YACrC,CAGA,SAAgB,EAA2B,EAAgE,CACzG,OAAO,EAAa,aAAe,cAAgB,EAAa,aAAe,WACjF,CAYA,SAAgB,EACd,EACA,EAAqE,CAAC,EAC/C,CACvB,IAAM,EAAqB,CAAC,EAgB5B,OAdI,EAAS,KAAO,CAAC,EAA0B,CAAY,GACzD,EAAS,KACP,uEAAuE,EAAa,WAAW,GACjG,EAEE,EAAS,QAAU,EAAa,eAAiB,IAAS,EAAa,aAAe,QACxF,EAAS,KACP,6GACF,EAEE,EAAS,WAAa,EAAa,YAAc,IACnD,EAAS,KAAK,gEAAgE,EAGzE,CAAE,GAAI,EAAS,SAAW,EAAG,UAAS,CAC/C"}