[{"data":1,"prerenderedAt":3428},["ShallowReactive",2],{"navigation_docs":3,"-docs-essentials-contracts":493,"-docs-essentials-contracts-surround":3423},[4,46,135,218,257,292,355,377,420],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":45},"Getting Started","i-lucide-rocket","\u002Fdocs\u002Fgetting-started","docs\u002F01.getting-started",[10,15,20,25,30,35,40],{"title":11,"path":12,"stem":13,"icon":14},"What is Heximon?","\u002Fdocs\u002Fgetting-started\u002Fintroduction","docs\u002F01.getting-started\u002F01.introduction","i-lucide-info",{"title":16,"path":17,"stem":18,"icon":19},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","docs\u002F01.getting-started\u002F02.installation","i-lucide-download",{"title":21,"path":22,"stem":23,"icon":24},"Quick Start","\u002Fdocs\u002Fgetting-started\u002Fquick-start","docs\u002F01.getting-started\u002F03.quick-start","i-lucide-zap",{"title":26,"path":27,"stem":28,"icon":29},"Core Concepts","\u002Fdocs\u002Fgetting-started\u002Fcore-concepts","docs\u002F01.getting-started\u002F04.core-concepts","i-lucide-shapes",{"title":31,"path":32,"stem":33,"icon":34},"Examples","\u002Fdocs\u002Fgetting-started\u002Fexamples","docs\u002F01.getting-started\u002F05.examples","i-lucide-library",{"title":36,"path":37,"stem":38,"icon":39},"Where Next?","\u002Fdocs\u002Fgetting-started\u002Fwhere-next","docs\u002F01.getting-started\u002F06.where-next","i-lucide-signpost",{"title":41,"path":42,"stem":43,"icon":44},"Troubleshooting","\u002Fdocs\u002Fgetting-started\u002Ftroubleshooting","docs\u002F01.getting-started\u002F07.troubleshooting","i-lucide-life-buoy",false,{"title":47,"icon":48,"path":49,"stem":50,"children":51,"page":45},"Essentials","i-lucide-boxes","\u002Fdocs\u002Fessentials","docs\u002F02.essentials",[52,56,61,66,71,76,81,86,91,96,101,105,110,115,120,125,130],{"title":53,"path":54,"stem":55,"icon":48},"Modules & DI","\u002Fdocs\u002Fessentials\u002Fmodules-and-di","docs\u002F02.essentials\u002F01.modules-and-di",{"title":57,"path":58,"stem":59,"icon":60},"Controllers","\u002Fdocs\u002Fessentials\u002Fcontrollers","docs\u002F02.essentials\u002F02.controllers","i-lucide-route",{"title":62,"path":63,"stem":64,"icon":65},"Validation & DTOs","\u002Fdocs\u002Fessentials\u002Fvalidation","docs\u002F02.essentials\u002F03.validation","i-lucide-shield-check",{"title":67,"path":68,"stem":69,"icon":70},"Contracts","\u002Fdocs\u002Fessentials\u002Fcontracts","docs\u002F02.essentials\u002F04.contracts","i-lucide-file-signature",{"title":72,"path":73,"stem":74,"icon":75},"REST Client","\u002Fdocs\u002Fessentials\u002Fclient","docs\u002F02.essentials\u002F05.client","i-lucide-plug",{"title":77,"path":78,"stem":79,"icon":80},"Database","\u002Fdocs\u002Fessentials\u002Fdatabase","docs\u002F02.essentials\u002F06.database","i-lucide-database",{"title":82,"path":83,"stem":84,"icon":85},"Drizzle ORM","\u002Fdocs\u002Fessentials\u002Fdrizzle","docs\u002F02.essentials\u002F07.drizzle","i-lucide-database-zap",{"title":87,"path":88,"stem":89,"icon":90},"Persistence & Transactions","\u002Fdocs\u002Fessentials\u002Fpersistence","docs\u002F02.essentials\u002F08.persistence","i-lucide-database-backup",{"title":92,"path":93,"stem":94,"icon":95},"Migrations","\u002Fdocs\u002Fessentials\u002Fmigrations","docs\u002F02.essentials\u002F09.migrations","i-lucide-git-branch",{"title":97,"path":98,"stem":99,"icon":100},"Authentication","\u002Fdocs\u002Fessentials\u002Fauthentication","docs\u002F02.essentials\u002F10.authentication","i-lucide-key-round",{"title":102,"path":103,"stem":104,"icon":65},"Permissions & scopes","\u002Fdocs\u002Fessentials\u002Fpermissions","docs\u002F02.essentials\u002F11.permissions",{"title":106,"path":107,"stem":108,"icon":109},"Error Handling","\u002Fdocs\u002Fessentials\u002Ferrors","docs\u002F02.essentials\u002F12.errors","i-lucide-triangle-alert",{"title":111,"path":112,"stem":113,"icon":114},"Testing a Heximon App","\u002Fdocs\u002Fessentials\u002Ftesting","docs\u002F02.essentials\u002F13.testing","i-lucide-flask-conical",{"title":116,"path":117,"stem":118,"icon":119},"Test app harness","\u002Fdocs\u002Fessentials\u002Fcreatetestapp","docs\u002F02.essentials\u002F14.createtestapp","i-lucide-test-tube",{"title":121,"path":122,"stem":123,"icon":124},"Logging & Observability","\u002Fdocs\u002Fessentials\u002Flogging","docs\u002F02.essentials\u002F17.logging","i-lucide-scroll-text",{"title":126,"path":127,"stem":128,"icon":129},"Context & Lifecycle","\u002Fdocs\u002Fessentials\u002Fcontext-and-lifecycle","docs\u002F02.essentials\u002F18.context-and-lifecycle","i-lucide-radio",{"title":131,"path":132,"stem":133,"icon":134},"Project Structure","\u002Fdocs\u002Fessentials\u002Fproject-structure","docs\u002F02.essentials\u002F19.project-structure","i-lucide-folder-tree",{"title":136,"icon":137,"path":138,"stem":139,"children":140,"page":45},"Capabilities","i-lucide-sparkles","\u002Fdocs\u002Fcapabilities","docs\u002F03.capabilities",[141,145,150,155,160,164,169,174,179,184,188,193,198,203,208,213],{"title":142,"path":143,"stem":144,"icon":137},"Overview","\u002Fdocs\u002Fcapabilities\u002Foverview","docs\u002F03.capabilities\u002F01.overview",{"title":146,"path":147,"stem":148,"icon":149},"Events","\u002Fdocs\u002Fcapabilities\u002Fevents","docs\u002F03.capabilities\u002F02.events","i-lucide-radio-tower",{"title":151,"path":152,"stem":153,"icon":154},"Queue","\u002Fdocs\u002Fcapabilities\u002Fbackground-jobs","docs\u002F03.capabilities\u002F03.background-jobs","i-lucide-list-ordered",{"title":156,"path":157,"stem":158,"icon":159},"Scheduled Work","\u002Fdocs\u002Fcapabilities\u002Fscheduled-jobs","docs\u002F03.capabilities\u002F04.scheduled-jobs","i-lucide-clock",{"title":161,"path":162,"stem":163,"icon":85},"Caching","\u002Fdocs\u002Fcapabilities\u002Fcaching","docs\u002F03.capabilities\u002F05.caching",{"title":165,"path":166,"stem":167,"icon":168},"Key\u002FValue Storage","\u002Fdocs\u002Fcapabilities\u002Fkey-value","docs\u002F03.capabilities\u002F06.key-value","i-lucide-hard-drive",{"title":170,"path":171,"stem":172,"icon":173},"Blob Storage","\u002Fdocs\u002Fcapabilities\u002Fblob","docs\u002F03.capabilities\u002F07.blob","i-lucide-folder-open",{"title":175,"path":176,"stem":177,"icon":178},"Health & Readiness","\u002Fdocs\u002Fcapabilities\u002Fhealth","docs\u002F03.capabilities\u002F08.health","i-lucide-heart-pulse",{"title":180,"path":181,"stem":182,"icon":183},"Notifications","\u002Fdocs\u002Fcapabilities\u002Fnotifications","docs\u002F03.capabilities\u002F09.notifications","i-lucide-mail",{"title":185,"path":186,"stem":187,"icon":65},"Idempotency","\u002Fdocs\u002Fcapabilities\u002Fidempotency","docs\u002F03.capabilities\u002F10.idempotency",{"title":189,"path":190,"stem":191,"icon":192},"Security Hardening","\u002Fdocs\u002Fcapabilities\u002Fsecurity","docs\u002F03.capabilities\u002F11.security","i-lucide-shield",{"title":194,"path":195,"stem":196,"icon":197},"Observability & Tracing","\u002Fdocs\u002Fcapabilities\u002Fobservability","docs\u002F03.capabilities\u002F12.observability","i-lucide-activity",{"title":199,"path":200,"stem":201,"icon":202},"OpenAPI","\u002Fdocs\u002Fcapabilities\u002Fopenapi","docs\u002F03.capabilities\u002F13.openapi","i-lucide-book-marked",{"title":204,"path":205,"stem":206,"icon":207},"MCP Server","\u002Fdocs\u002Fcapabilities\u002Fmcp","docs\u002F03.capabilities\u002F14.mcp","i-lucide-bot",{"title":209,"path":210,"stem":211,"icon":212},"Schema DTOs","\u002Fdocs\u002Fcapabilities\u002Fschema","docs\u002F03.capabilities\u002F15.schema","i-lucide-file-json",{"title":214,"path":215,"stem":216,"icon":217},"Branded IDs","\u002Fdocs\u002Fcapabilities\u002Fbranded-ids","docs\u002F03.capabilities\u002F16.branded-ids","i-lucide-tag",{"title":219,"icon":220,"path":221,"stem":222,"children":223,"page":45},"Architecture","i-lucide-building","\u002Fdocs\u002Farchitecture","docs\u002F04.architecture",[224,227,232,237,242,247,252],{"title":142,"path":225,"stem":226,"icon":220},"\u002Fdocs\u002Farchitecture\u002Foverview","docs\u002F04.architecture\u002F01.overview",{"title":228,"path":229,"stem":230,"icon":231},"Domain-Driven Design","\u002Fdocs\u002Farchitecture\u002Fddd","docs\u002F04.architecture\u002F02.ddd","i-lucide-hexagon",{"title":233,"path":234,"stem":235,"icon":236},"CQRS","\u002Fdocs\u002Farchitecture\u002Fcqrs","docs\u002F04.architecture\u002F03.cqrs","i-lucide-split",{"title":238,"path":239,"stem":240,"icon":241},"Repository Pattern","\u002Fdocs\u002Farchitecture\u002Frepository-pattern","docs\u002F04.architecture\u002F04.repository-pattern","i-lucide-archive",{"title":243,"path":244,"stem":245,"icon":246},"Integration Events","\u002Fdocs\u002Farchitecture\u002Fintegration-events","docs\u002F04.architecture\u002F05.integration-events","i-lucide-send-horizontal",{"title":248,"path":249,"stem":250,"icon":251},"Saga Orchestration","\u002Fdocs\u002Farchitecture\u002Fsagas","docs\u002F04.architecture\u002F06.sagas","i-lucide-hourglass",{"title":253,"path":254,"stem":255,"icon":256},"Durable Workflows","\u002Fdocs\u002Farchitecture\u002Fworkflows","docs\u002F04.architecture\u002F07.workflows","i-lucide-workflow",{"title":258,"icon":259,"path":260,"stem":261,"children":262,"page":45},"Realtime","i-lucide-cable","\u002Fdocs\u002Frealtime","docs\u002F05.realtime",[263,266,270,274,279,284,288],{"title":142,"path":264,"stem":265,"icon":259},"\u002Fdocs\u002Frealtime\u002Foverview","docs\u002F05.realtime\u002F01.overview",{"title":267,"path":268,"stem":269,"icon":129},"WebSockets","\u002Fdocs\u002Frealtime\u002Fwebsockets","docs\u002F05.realtime\u002F02.websockets",{"title":271,"path":272,"stem":273,"icon":70},"WebSocket Contracts","\u002Fdocs\u002Frealtime\u002Fwebsocket-contracts","docs\u002F05.realtime\u002F03.websocket-contracts",{"title":275,"path":276,"stem":277,"icon":278},"Server-Sent Events","\u002Fdocs\u002Frealtime\u002Fserver-sent-events","docs\u002F05.realtime\u002F04.server-sent-events","i-lucide-rss",{"title":280,"path":281,"stem":282,"icon":283},"Typed Clients","\u002Fdocs\u002Frealtime\u002Ftyped-clients","docs\u002F05.realtime\u002F05.typed-clients","i-lucide-plug-zap",{"title":285,"path":286,"stem":287,"icon":259},"AsyncAPI","\u002Fdocs\u002Frealtime\u002Fasyncapi","docs\u002F05.realtime\u002F06.asyncapi",{"title":289,"path":290,"stem":291,"icon":80},"Durable Objects","\u002Fdocs\u002Frealtime\u002Fdurable-objects","docs\u002F05.realtime\u002F07.durable-objects",{"title":293,"icon":294,"path":295,"stem":296,"children":297,"page":45},"Deploy","i-lucide-cloud-upload","\u002Fdocs\u002Fdeploy","docs\u002F06.deploy",[298,301,306,311,316,321,326,331,336,341,345,350],{"title":142,"path":299,"stem":300,"icon":6},"\u002Fdocs\u002Fdeploy\u002Foverview","docs\u002F06.deploy\u002F01.overview",{"title":302,"path":303,"stem":304,"icon":305},"Node","\u002Fdocs\u002Fdeploy\u002Fnode","docs\u002F06.deploy\u002F02.node","la:node-js",{"title":307,"path":308,"stem":309,"icon":310},"Cloudflare","\u002Fdocs\u002Fdeploy\u002Fcloudflare","docs\u002F06.deploy\u002F03.cloudflare","simple-icons:cloudflare",{"title":312,"path":313,"stem":314,"icon":315},"Vercel","\u002Fdocs\u002Fdeploy\u002Fvercel","docs\u002F06.deploy\u002F04.vercel","ri:vercel-fill",{"title":317,"path":318,"stem":319,"icon":320},"Netlify","\u002Fdocs\u002Fdeploy\u002Fnetlify","docs\u002F06.deploy\u002F05.netlify","i-simple-icons-netlify",{"title":322,"path":323,"stem":324,"icon":325},"AWS Lambda","\u002Fdocs\u002Fdeploy\u002Faws-lambda","docs\u002F06.deploy\u002F06.aws-lambda","hugeicons:aws-lambda",{"title":327,"path":328,"stem":329,"icon":330},"Deno Deploy","\u002Fdocs\u002Fdeploy\u002Fdeno-deploy","docs\u002F06.deploy\u002F07.deno-deploy","simple-icons:denodeploy",{"title":332,"path":333,"stem":334,"icon":335},"Nitro","\u002Fdocs\u002Fdeploy\u002Fnitro","docs\u002F06.deploy\u002F08.nitro","i-unjs-nitro",{"title":337,"path":338,"stem":339,"icon":340},"Nuxt","\u002Fdocs\u002Fdeploy\u002Fnuxt","docs\u002F06.deploy\u002F09.nuxt","i-devicon-nuxt",{"title":342,"path":343,"stem":344,"icon":236},"Mixed-runtime split","\u002Fdocs\u002Fdeploy\u002Fmixed-runtime-split","docs\u002F06.deploy\u002F10.mixed-runtime-split",{"title":346,"path":347,"stem":348,"icon":349},"Hosts","\u002Fdocs\u002Fdeploy\u002Fhosts","docs\u002F06.deploy\u002F11.hosts","i-lucide-map",{"title":351,"path":352,"stem":353,"icon":354},"Cross-service events","\u002Fdocs\u002Fdeploy\u002Fcross-service-events","docs\u002F06.deploy\u002F12.cross-service-events","i-lucide-network",{"title":356,"icon":357,"path":358,"stem":359,"children":360,"page":45},"CLI","i-lucide-terminal","\u002Fdocs\u002Fcli","docs\u002F07.cli",[361,365,369,373],{"title":362,"path":363,"stem":364,"icon":357},"The heximon CLI","\u002Fdocs\u002Fcli\u002Foverview","docs\u002F07.cli\u002F01.overview",{"title":366,"path":367,"stem":368,"icon":137},"Create a New App","\u002Fdocs\u002Fcli\u002Fcreate","docs\u002F07.cli\u002F02.create",{"title":370,"path":371,"stem":372,"icon":95},"Migrations from the CLI","\u002Fdocs\u002Fcli\u002Fmigrations","docs\u002F07.cli\u002F03.migrations",{"title":374,"path":375,"stem":376,"icon":6},"Deploying a Heximon app","\u002Fdocs\u002Fcli\u002Fdeploy","docs\u002F07.cli\u002F04.deploy",{"title":378,"icon":379,"path":380,"stem":381,"children":382,"page":45},"Under the Hood","i-lucide-wrench","\u002Fdocs\u002Funder-the-hood","docs\u002F08.under-the-hood",[383,388,393,397,402,407,411,415],{"title":384,"path":385,"stem":386,"icon":387},"How the Compiler Works","\u002Fdocs\u002Funder-the-hood\u002Fhow-the-compiler-works","docs\u002F08.under-the-hood\u002F01.how-the-compiler-works","i-lucide-cog",{"title":389,"path":390,"stem":391,"icon":392},"Compiler","\u002Fdocs\u002Funder-the-hood\u002Fextending-the-compiler","docs\u002F08.under-the-hood\u002F02.extending-the-compiler","i-lucide-cpu",{"title":394,"path":395,"stem":396,"icon":357},"Compiler Diagnostics","\u002Fdocs\u002Funder-the-hood\u002Fcompiler-diagnostics","docs\u002F08.under-the-hood\u002F03.compiler-diagnostics",{"title":398,"path":399,"stem":400,"icon":401},"Library Mode","\u002Fdocs\u002Funder-the-hood\u002Flibrary-mode","docs\u002F08.under-the-hood\u002F04.library-mode","i-lucide-package",{"title":403,"path":404,"stem":405,"icon":406},"Other bundlers","\u002Fdocs\u002Funder-the-hood\u002Falternate-bundlers","docs\u002F08.under-the-hood\u002F05.alternate-bundlers","i-lucide-blocks",{"title":408,"path":409,"stem":410,"icon":401},"Packages","\u002Fdocs\u002Funder-the-hood\u002Fpackages","docs\u002F08.under-the-hood\u002F06.packages",{"title":412,"path":413,"stem":414,"icon":207},"AI Skills","\u002Fdocs\u002Funder-the-hood\u002Fai-and-agents","docs\u002F08.under-the-hood\u002F07.ai-and-agents",{"title":416,"path":417,"stem":418,"icon":419},"Advanced DI","\u002Fdocs\u002Funder-the-hood\u002Fadvanced-di","docs\u002F08.under-the-hood\u002F08.advanced-di","i-lucide-git-fork",{"title":421,"icon":422,"path":423,"stem":424,"children":425,"page":45},"Recipes","i-lucide-book-open-check","\u002Fdocs\u002Frecipes","docs\u002F09.recipes",[426,431,436,440,444,448,452,456,460,465,469,474,479,484,488],{"title":427,"path":428,"stem":429,"icon":430},"Send an Email","\u002Fdocs\u002Frecipes\u002Fsend-an-email","docs\u002F09.recipes\u002F01.send-an-email","i-lucide-send",{"title":432,"path":433,"stem":434,"icon":435},"Upload a File","\u002Fdocs\u002Frecipes\u002Fupload-a-file","docs\u002F09.recipes\u002F02.upload-a-file","i-lucide-upload",{"title":437,"path":438,"stem":439,"icon":24},"Cache an Expensive Call","\u002Fdocs\u002Frecipes\u002Fcache-an-expensive-call","docs\u002F09.recipes\u002F03.cache-an-expensive-call",{"title":441,"path":442,"stem":443,"icon":154},"Paginate a List","\u002Fdocs\u002Frecipes\u002Fpaginate-a-list","docs\u002F09.recipes\u002F04.paginate-a-list",{"title":445,"path":446,"stem":447,"icon":65},"Protect Admin Routes","\u002Fdocs\u002Frecipes\u002Fprotect-admin-routes","docs\u002F09.recipes\u002F05.protect-admin-routes",{"title":449,"path":450,"stem":451,"icon":178},"Health Probes and a Nightly Job","\u002Fdocs\u002Frecipes\u002Fhealth-probes-and-a-nightly-job","docs\u002F09.recipes\u002F06.health-probes-and-a-nightly-job",{"title":453,"path":454,"stem":455,"icon":80},"Build a CRUD API","\u002Fdocs\u002Frecipes\u002Fcrud-api","docs\u002F09.recipes\u002F07.crud-api",{"title":457,"path":458,"stem":459,"icon":100},"Add Authentication","\u002Fdocs\u002Frecipes\u002Fadd-authentication","docs\u002F09.recipes\u002F08.add-authentication",{"title":461,"path":462,"stem":463,"icon":464},"Background Jobs","\u002Fdocs\u002Frecipes\u002Fbackground-jobs","docs\u002F09.recipes\u002F09.background-jobs","i-lucide-timer",{"title":466,"path":467,"stem":468,"icon":149},"Decouple Features with Events","\u002Fdocs\u002Frecipes\u002Fevent-driven-module","docs\u002F09.recipes\u002F10.event-driven-module",{"title":470,"path":471,"stem":472,"icon":473},"Build a DDD Aggregate","\u002Fdocs\u002Frecipes\u002Fddd-aggregate","docs\u002F09.recipes\u002F11.ddd-aggregate","i-lucide-box",{"title":475,"path":476,"stem":477,"icon":478},"Publish a Feature Package","\u002Fdocs\u002Frecipes\u002Ffeature-package","docs\u002F09.recipes\u002F12.feature-package","i-lucide-package-open",{"title":480,"path":481,"stem":482,"icon":483},"Reliable Integration Events","\u002Fdocs\u002Frecipes\u002Freliable-integration-events","docs\u002F09.recipes\u002F13.reliable-integration-events","i-lucide-inbox",{"title":485,"path":486,"stem":487,"icon":95},"Reactive Choreography","\u002Fdocs\u002Frecipes\u002Freactive-choreography","docs\u002F09.recipes\u002F14.reactive-choreography",{"title":489,"path":490,"stem":491,"icon":492},"Build a Production CRUD API","\u002Fdocs\u002Frecipes\u002Fproduction-crud-api","docs\u002F09.recipes\u002F15.production-crud-api","i-lucide-layers",{"id":494,"title":67,"body":495,"description":3416,"extension":3417,"links":3418,"meta":3419,"navigation":3420,"path":68,"seo":3421,"stem":69,"__hash__":3422},"docs\u002Fdocs\u002F02.essentials\u002F04.contracts.md",{"type":496,"value":497,"toc":3407},"minimark",[498,512,861,883,888,910,1230,1233,1237,1263,1536,1539,1753,1771,1805,1809,1812,1849,2037,2050,2212,2216,2230,2674,2684,2688,2697,3108,3117,3126,3130,3142,3327,3337,3341,3403],[499,500,501,502,506,507,511],"p",{},"An API has three audiences that must agree on its shape — the server that implements it, the client that\ncalls it, the spec that documents it. Keep that shape in three places and they drift. A ",[503,504,505],"code",{},"Contract"," holds it\nin ",[508,509,510],"strong",{},"one"," place: a route table you author once, then bind everywhere.",[513,514,520],"pre",{"className":515,"code":516,"filename":517,"language":518,"meta":519,"style":519},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { Contract, Route } from \"@heximon\u002Fcontract\";\nimport { createProduct, product, productList, productParams } from \".\u002Fproduct.schema\";\n\nexport class ProductsApi extends Contract({\n  prefix: \"\u002Fapi\u002Fproducts\",\n  routes: {\n    list: Route.get(\"\u002F\").summary(\"List products\").responses({ 200: productList }),\n    find: Route.get(\"\u002F:sku\").pathParams(productParams).responses({ 200: product }),\n    create: Route.post(\"\u002F\").body(createProduct).responses({ 201: product }),\n  },\n}) {}\n","src\u002Fproducts\u002Fproduct.api.ts","ts","",[503,521,522,564,602,609,635,655,666,736,790,844,850],{"__ignoreMap":519},[523,524,527,531,535,539,542,545,548,551,554,558,561],"span",{"class":525,"line":526},"line",1,[523,528,530],{"class":529},"s7zQu","import",[523,532,534],{"class":533},"sMK4o"," {",[523,536,538],{"class":537},"sTEyZ"," Contract",[523,540,541],{"class":533},",",[523,543,544],{"class":537}," Route",[523,546,547],{"class":533}," }",[523,549,550],{"class":529}," from",[523,552,553],{"class":533}," \"",[523,555,557],{"class":556},"sfazB","@heximon\u002Fcontract",[523,559,560],{"class":533},"\"",[523,562,563],{"class":533},";\n",[523,565,567,569,571,574,576,579,581,584,586,589,591,593,595,598,600],{"class":525,"line":566},2,[523,568,530],{"class":529},[523,570,534],{"class":533},[523,572,573],{"class":537}," createProduct",[523,575,541],{"class":533},[523,577,578],{"class":537}," product",[523,580,541],{"class":533},[523,582,583],{"class":537}," productList",[523,585,541],{"class":533},[523,587,588],{"class":537}," productParams",[523,590,547],{"class":533},[523,592,550],{"class":529},[523,594,553],{"class":533},[523,596,597],{"class":556},".\u002Fproduct.schema",[523,599,560],{"class":533},[523,601,563],{"class":533},[523,603,605],{"class":525,"line":604},3,[523,606,608],{"emptyLinePlaceholder":607},true,"\n",[523,610,612,615,619,623,626,629,632],{"class":525,"line":611},4,[523,613,614],{"class":529},"export",[523,616,618],{"class":617},"spNyl"," class",[523,620,622],{"class":621},"sBMFI"," ProductsApi",[523,624,625],{"class":617}," extends",[523,627,538],{"class":628},"s2Zo4",[523,630,631],{"class":537},"(",[523,633,634],{"class":533},"{\n",[523,636,638,642,645,647,650,652],{"class":525,"line":637},5,[523,639,641],{"class":640},"swJcz","  prefix",[523,643,644],{"class":533},":",[523,646,553],{"class":533},[523,648,649],{"class":556},"\u002Fapi\u002Fproducts",[523,651,560],{"class":533},[523,653,654],{"class":533},",\n",[523,656,658,661,663],{"class":525,"line":657},6,[523,659,660],{"class":640},"  routes",[523,662,644],{"class":533},[523,664,665],{"class":533}," {\n",[523,667,669,672,674,676,679,682,684,686,689,691,694,696,699,701,703,706,708,710,712,715,717,720,724,726,729,732,734],{"class":525,"line":668},7,[523,670,671],{"class":640},"    list",[523,673,644],{"class":533},[523,675,544],{"class":537},[523,677,678],{"class":533},".",[523,680,681],{"class":628},"get",[523,683,631],{"class":537},[523,685,560],{"class":533},[523,687,688],{"class":556},"\u002F",[523,690,560],{"class":533},[523,692,693],{"class":537},")",[523,695,678],{"class":533},[523,697,698],{"class":628},"summary",[523,700,631],{"class":537},[523,702,560],{"class":533},[523,704,705],{"class":556},"List products",[523,707,560],{"class":533},[523,709,693],{"class":537},[523,711,678],{"class":533},[523,713,714],{"class":628},"responses",[523,716,631],{"class":537},[523,718,719],{"class":533},"{",[523,721,723],{"class":722},"sbssI"," 200",[523,725,644],{"class":533},[523,727,728],{"class":537}," productList ",[523,730,731],{"class":533},"}",[523,733,693],{"class":537},[523,735,654],{"class":533},[523,737,739,742,744,746,748,750,752,754,757,759,761,763,766,769,771,773,775,777,779,781,784,786,788],{"class":525,"line":738},8,[523,740,741],{"class":640},"    find",[523,743,644],{"class":533},[523,745,544],{"class":537},[523,747,678],{"class":533},[523,749,681],{"class":628},[523,751,631],{"class":537},[523,753,560],{"class":533},[523,755,756],{"class":556},"\u002F:sku",[523,758,560],{"class":533},[523,760,693],{"class":537},[523,762,678],{"class":533},[523,764,765],{"class":628},"pathParams",[523,767,768],{"class":537},"(productParams)",[523,770,678],{"class":533},[523,772,714],{"class":628},[523,774,631],{"class":537},[523,776,719],{"class":533},[523,778,723],{"class":722},[523,780,644],{"class":533},[523,782,783],{"class":537}," product ",[523,785,731],{"class":533},[523,787,693],{"class":537},[523,789,654],{"class":533},[523,791,793,796,798,800,802,805,807,809,811,813,815,817,820,823,825,827,829,831,834,836,838,840,842],{"class":525,"line":792},9,[523,794,795],{"class":640},"    create",[523,797,644],{"class":533},[523,799,544],{"class":537},[523,801,678],{"class":533},[523,803,804],{"class":628},"post",[523,806,631],{"class":537},[523,808,560],{"class":533},[523,810,688],{"class":556},[523,812,560],{"class":533},[523,814,693],{"class":537},[523,816,678],{"class":533},[523,818,819],{"class":628},"body",[523,821,822],{"class":537},"(createProduct)",[523,824,678],{"class":533},[523,826,714],{"class":628},[523,828,631],{"class":537},[523,830,719],{"class":533},[523,832,833],{"class":722}," 201",[523,835,644],{"class":533},[523,837,783],{"class":537},[523,839,731],{"class":533},[523,841,693],{"class":537},[523,843,654],{"class":533},[523,845,847],{"class":525,"line":846},10,[523,848,849],{"class":533},"  },\n",[523,851,853,855,858],{"class":525,"line":852},11,[523,854,731],{"class":533},[523,856,857],{"class":537},") ",[523,859,860],{"class":533},"{}\n",[499,862,863,864,867,868,871,872,688,875,878,879,882],{},"That one class is consumed three ways: a backend controller ",[503,865,866],{},"implements Controller\u003CProductsApi>",",\na typed REST client calls it, and the OpenAPI generator reads it. It carries no server or client code, so\nit's safe to import from the frontend — the seam between client and server can't depend on either side.\nBecause it's a class, ",[503,869,870],{},"ProductsApi"," is both a value (its static ",[503,873,874],{},"routes",[503,876,877],{},"prefix",") and a type (no\n",[503,880,881],{},"typeof",").",[884,885,887],"h2",{"id":886},"define-a-contract","Define a contract",[499,889,890,893,894,896,897,899,900,902,903,906,907,909],{},[503,891,892],{},"Contract({...})"," takes a ",[503,895,877],{},", a ",[503,898,874],{}," table, and optional contract-level ",[503,901,714],{},", and returns\na base class you ",[503,904,905],{},"extend",". Each ",[503,908,874],{}," key becomes a controller handler name — name them as you'd name\nmethods.",[513,911,913],{"className":515,"code":912,"filename":517,"language":518,"meta":519,"style":519},"import { Contract, Route } from \"@heximon\u002Fcontract\";\nimport { createProduct, product, productList, productParams } from \".\u002Fproduct.schema\";\n\nexport class ProductsApi extends Contract({\n  prefix: \"\u002Fapi\u002Fproducts\",\n  routes: {\n    list: Route.get(\"\u002F\").summary(\"List products\").responses({ 200: productList }),\n    find: Route.get(\"\u002F:sku\")\n      .pathParams(productParams)\n      .scopes(\"products.read\")\n      .responses({ 200: product }),\n    create: Route.post(\"\u002F\")\n      .body(createProduct)\n      .scopes(\"products.write\")\n      .responses({ 201: product }),\n  },\n}) {}\n",[503,914,915,939,971,975,991,1005,1013,1069,1092,1102,1120,1142,1165,1175,1193,1216,1221],{"__ignoreMap":519},[523,916,917,919,921,923,925,927,929,931,933,935,937],{"class":525,"line":526},[523,918,530],{"class":529},[523,920,534],{"class":533},[523,922,538],{"class":537},[523,924,541],{"class":533},[523,926,544],{"class":537},[523,928,547],{"class":533},[523,930,550],{"class":529},[523,932,553],{"class":533},[523,934,557],{"class":556},[523,936,560],{"class":533},[523,938,563],{"class":533},[523,940,941,943,945,947,949,951,953,955,957,959,961,963,965,967,969],{"class":525,"line":566},[523,942,530],{"class":529},[523,944,534],{"class":533},[523,946,573],{"class":537},[523,948,541],{"class":533},[523,950,578],{"class":537},[523,952,541],{"class":533},[523,954,583],{"class":537},[523,956,541],{"class":533},[523,958,588],{"class":537},[523,960,547],{"class":533},[523,962,550],{"class":529},[523,964,553],{"class":533},[523,966,597],{"class":556},[523,968,560],{"class":533},[523,970,563],{"class":533},[523,972,973],{"class":525,"line":604},[523,974,608],{"emptyLinePlaceholder":607},[523,976,977,979,981,983,985,987,989],{"class":525,"line":611},[523,978,614],{"class":529},[523,980,618],{"class":617},[523,982,622],{"class":621},[523,984,625],{"class":617},[523,986,538],{"class":628},[523,988,631],{"class":537},[523,990,634],{"class":533},[523,992,993,995,997,999,1001,1003],{"class":525,"line":637},[523,994,641],{"class":640},[523,996,644],{"class":533},[523,998,553],{"class":533},[523,1000,649],{"class":556},[523,1002,560],{"class":533},[523,1004,654],{"class":533},[523,1006,1007,1009,1011],{"class":525,"line":657},[523,1008,660],{"class":640},[523,1010,644],{"class":533},[523,1012,665],{"class":533},[523,1014,1015,1017,1019,1021,1023,1025,1027,1029,1031,1033,1035,1037,1039,1041,1043,1045,1047,1049,1051,1053,1055,1057,1059,1061,1063,1065,1067],{"class":525,"line":668},[523,1016,671],{"class":640},[523,1018,644],{"class":533},[523,1020,544],{"class":537},[523,1022,678],{"class":533},[523,1024,681],{"class":628},[523,1026,631],{"class":537},[523,1028,560],{"class":533},[523,1030,688],{"class":556},[523,1032,560],{"class":533},[523,1034,693],{"class":537},[523,1036,678],{"class":533},[523,1038,698],{"class":628},[523,1040,631],{"class":537},[523,1042,560],{"class":533},[523,1044,705],{"class":556},[523,1046,560],{"class":533},[523,1048,693],{"class":537},[523,1050,678],{"class":533},[523,1052,714],{"class":628},[523,1054,631],{"class":537},[523,1056,719],{"class":533},[523,1058,723],{"class":722},[523,1060,644],{"class":533},[523,1062,728],{"class":537},[523,1064,731],{"class":533},[523,1066,693],{"class":537},[523,1068,654],{"class":533},[523,1070,1071,1073,1075,1077,1079,1081,1083,1085,1087,1089],{"class":525,"line":738},[523,1072,741],{"class":640},[523,1074,644],{"class":533},[523,1076,544],{"class":537},[523,1078,678],{"class":533},[523,1080,681],{"class":628},[523,1082,631],{"class":537},[523,1084,560],{"class":533},[523,1086,756],{"class":556},[523,1088,560],{"class":533},[523,1090,1091],{"class":537},")\n",[523,1093,1094,1097,1099],{"class":525,"line":792},[523,1095,1096],{"class":533},"      .",[523,1098,765],{"class":628},[523,1100,1101],{"class":537},"(productParams)\n",[523,1103,1104,1106,1109,1111,1113,1116,1118],{"class":525,"line":846},[523,1105,1096],{"class":533},[523,1107,1108],{"class":628},"scopes",[523,1110,631],{"class":537},[523,1112,560],{"class":533},[523,1114,1115],{"class":556},"products.read",[523,1117,560],{"class":533},[523,1119,1091],{"class":537},[523,1121,1122,1124,1126,1128,1130,1132,1134,1136,1138,1140],{"class":525,"line":852},[523,1123,1096],{"class":533},[523,1125,714],{"class":628},[523,1127,631],{"class":537},[523,1129,719],{"class":533},[523,1131,723],{"class":722},[523,1133,644],{"class":533},[523,1135,783],{"class":537},[523,1137,731],{"class":533},[523,1139,693],{"class":537},[523,1141,654],{"class":533},[523,1143,1145,1147,1149,1151,1153,1155,1157,1159,1161,1163],{"class":525,"line":1144},12,[523,1146,795],{"class":640},[523,1148,644],{"class":533},[523,1150,544],{"class":537},[523,1152,678],{"class":533},[523,1154,804],{"class":628},[523,1156,631],{"class":537},[523,1158,560],{"class":533},[523,1160,688],{"class":556},[523,1162,560],{"class":533},[523,1164,1091],{"class":537},[523,1166,1168,1170,1172],{"class":525,"line":1167},13,[523,1169,1096],{"class":533},[523,1171,819],{"class":628},[523,1173,1174],{"class":537},"(createProduct)\n",[523,1176,1178,1180,1182,1184,1186,1189,1191],{"class":525,"line":1177},14,[523,1179,1096],{"class":533},[523,1181,1108],{"class":628},[523,1183,631],{"class":537},[523,1185,560],{"class":533},[523,1187,1188],{"class":556},"products.write",[523,1190,560],{"class":533},[523,1192,1091],{"class":537},[523,1194,1196,1198,1200,1202,1204,1206,1208,1210,1212,1214],{"class":525,"line":1195},15,[523,1197,1096],{"class":533},[523,1199,714],{"class":628},[523,1201,631],{"class":537},[523,1203,719],{"class":533},[523,1205,833],{"class":722},[523,1207,644],{"class":533},[523,1209,783],{"class":537},[523,1211,731],{"class":533},[523,1213,693],{"class":537},[523,1215,654],{"class":533},[523,1217,1219],{"class":525,"line":1218},16,[523,1220,849],{"class":533},[523,1222,1224,1226,1228],{"class":525,"line":1223},17,[523,1225,731],{"class":533},[523,1227,857],{"class":537},[523,1229,860],{"class":533},[499,1231,1232],{},"Each route reads back as a finished descriptor — plain values the client and OpenAPI generator iterate.",[884,1234,1236],{"id":1235},"build-a-route","Build a route",[499,1238,1239,1242,1243,1246,1247,1246,1250,1246,1253,1246,1256,1246,1259,1262],{},[503,1240,1241],{},"Route.get(path)"," and its sibling verbs (",[503,1244,1245],{},".post",", ",[503,1248,1249],{},".put",[503,1251,1252],{},".patch",[503,1254,1255],{},".delete",[503,1257,1258],{},".head",[503,1260,1261],{},".options",") start a\nbuilder you chain. Each method attaches one piece of the route's shape.",[513,1264,1266],{"className":515,"code":1265,"language":518,"meta":519,"style":519},"import { Route } from \"@heximon\u002Fcontract\";\nimport { createProduct, product, productList, productParams } from \".\u002Fproduct.schema\";\n\nconst list = Route.get(\"\u002F\").summary(\"List products\").responses({ 200: productList });\n\nconst find = Route.get(\"\u002F:sku\")\n  .pathParams(productParams)\n  .scopes(\"products.read\")\n  .responses({ 200: product });\n\nconst create = Route.post(\"\u002F\")\n  .body(createProduct)\n  .scopes(\"products.write\")\n  .responses({ 201: product });\n",[503,1267,1268,1288,1320,1324,1385,1389,1414,1423,1439,1461,1465,1490,1498,1514],{"__ignoreMap":519},[523,1269,1270,1272,1274,1276,1278,1280,1282,1284,1286],{"class":525,"line":526},[523,1271,530],{"class":529},[523,1273,534],{"class":533},[523,1275,544],{"class":537},[523,1277,547],{"class":533},[523,1279,550],{"class":529},[523,1281,553],{"class":533},[523,1283,557],{"class":556},[523,1285,560],{"class":533},[523,1287,563],{"class":533},[523,1289,1290,1292,1294,1296,1298,1300,1302,1304,1306,1308,1310,1312,1314,1316,1318],{"class":525,"line":566},[523,1291,530],{"class":529},[523,1293,534],{"class":533},[523,1295,573],{"class":537},[523,1297,541],{"class":533},[523,1299,578],{"class":537},[523,1301,541],{"class":533},[523,1303,583],{"class":537},[523,1305,541],{"class":533},[523,1307,588],{"class":537},[523,1309,547],{"class":533},[523,1311,550],{"class":529},[523,1313,553],{"class":533},[523,1315,597],{"class":556},[523,1317,560],{"class":533},[523,1319,563],{"class":533},[523,1321,1322],{"class":525,"line":604},[523,1323,608],{"emptyLinePlaceholder":607},[523,1325,1326,1329,1332,1335,1337,1339,1341,1343,1345,1347,1349,1351,1353,1355,1357,1359,1361,1363,1365,1367,1369,1371,1373,1375,1377,1379,1381,1383],{"class":525,"line":611},[523,1327,1328],{"class":617},"const",[523,1330,1331],{"class":537}," list ",[523,1333,1334],{"class":533},"=",[523,1336,544],{"class":537},[523,1338,678],{"class":533},[523,1340,681],{"class":628},[523,1342,631],{"class":537},[523,1344,560],{"class":533},[523,1346,688],{"class":556},[523,1348,560],{"class":533},[523,1350,693],{"class":537},[523,1352,678],{"class":533},[523,1354,698],{"class":628},[523,1356,631],{"class":537},[523,1358,560],{"class":533},[523,1360,705],{"class":556},[523,1362,560],{"class":533},[523,1364,693],{"class":537},[523,1366,678],{"class":533},[523,1368,714],{"class":628},[523,1370,631],{"class":537},[523,1372,719],{"class":533},[523,1374,723],{"class":722},[523,1376,644],{"class":533},[523,1378,728],{"class":537},[523,1380,731],{"class":533},[523,1382,693],{"class":537},[523,1384,563],{"class":533},[523,1386,1387],{"class":525,"line":637},[523,1388,608],{"emptyLinePlaceholder":607},[523,1390,1391,1393,1396,1398,1400,1402,1404,1406,1408,1410,1412],{"class":525,"line":657},[523,1392,1328],{"class":617},[523,1394,1395],{"class":537}," find ",[523,1397,1334],{"class":533},[523,1399,544],{"class":537},[523,1401,678],{"class":533},[523,1403,681],{"class":628},[523,1405,631],{"class":537},[523,1407,560],{"class":533},[523,1409,756],{"class":556},[523,1411,560],{"class":533},[523,1413,1091],{"class":537},[523,1415,1416,1419,1421],{"class":525,"line":668},[523,1417,1418],{"class":533},"  .",[523,1420,765],{"class":628},[523,1422,1101],{"class":537},[523,1424,1425,1427,1429,1431,1433,1435,1437],{"class":525,"line":738},[523,1426,1418],{"class":533},[523,1428,1108],{"class":628},[523,1430,631],{"class":537},[523,1432,560],{"class":533},[523,1434,1115],{"class":556},[523,1436,560],{"class":533},[523,1438,1091],{"class":537},[523,1440,1441,1443,1445,1447,1449,1451,1453,1455,1457,1459],{"class":525,"line":792},[523,1442,1418],{"class":533},[523,1444,714],{"class":628},[523,1446,631],{"class":537},[523,1448,719],{"class":533},[523,1450,723],{"class":722},[523,1452,644],{"class":533},[523,1454,783],{"class":537},[523,1456,731],{"class":533},[523,1458,693],{"class":537},[523,1460,563],{"class":533},[523,1462,1463],{"class":525,"line":846},[523,1464,608],{"emptyLinePlaceholder":607},[523,1466,1467,1469,1472,1474,1476,1478,1480,1482,1484,1486,1488],{"class":525,"line":852},[523,1468,1328],{"class":617},[523,1470,1471],{"class":537}," create ",[523,1473,1334],{"class":533},[523,1475,544],{"class":537},[523,1477,678],{"class":533},[523,1479,804],{"class":628},[523,1481,631],{"class":537},[523,1483,560],{"class":533},[523,1485,688],{"class":556},[523,1487,560],{"class":533},[523,1489,1091],{"class":537},[523,1491,1492,1494,1496],{"class":525,"line":1144},[523,1493,1418],{"class":533},[523,1495,819],{"class":628},[523,1497,1174],{"class":537},[523,1499,1500,1502,1504,1506,1508,1510,1512],{"class":525,"line":1167},[523,1501,1418],{"class":533},[523,1503,1108],{"class":628},[523,1505,631],{"class":537},[523,1507,560],{"class":533},[523,1509,1188],{"class":556},[523,1511,560],{"class":533},[523,1513,1091],{"class":537},[523,1515,1516,1518,1520,1522,1524,1526,1528,1530,1532,1534],{"class":525,"line":1177},[523,1517,1418],{"class":533},[523,1519,714],{"class":628},[523,1521,631],{"class":537},[523,1523,719],{"class":533},[523,1525,833],{"class":722},[523,1527,644],{"class":533},[523,1529,783],{"class":537},[523,1531,731],{"class":533},[523,1533,693],{"class":537},[523,1535,563],{"class":533},[499,1537,1538],{},"Every chaining method widens the route's type, so the contract knows each route's exact inputs and outputs:",[1540,1541,1542,1556],"table",{},[1543,1544,1545],"thead",{},[1546,1547,1548,1553],"tr",{},[1549,1550,1552],"th",{"align":1551},"left","Method",[1549,1554,1555],{"align":1551},"What it declares",[1557,1558,1559,1574,1584,1594,1610,1623,1656,1666,1693,1713,1725,1739],"tbody",{},[1546,1560,1561,1567],{},[1562,1563,1564],"td",{"align":1551},[503,1565,1566],{},".pathParams(schema)",[1562,1568,1569,1570,1573],{"align":1551},"The ",[503,1571,1572],{},":segment"," schema — its output must cover every segment in the path",[1546,1575,1576,1581],{},[1562,1577,1578],{"align":1551},[503,1579,1580],{},".query(schema)",[1562,1582,1583],{"align":1551},"The query-string schema",[1546,1585,1586,1591],{},[1562,1587,1588],{"align":1551},[503,1589,1590],{},".headers(schema)",[1562,1592,1593],{"align":1551},"The request-headers schema",[1546,1595,1596,1601],{},[1562,1597,1598],{"align":1551},[503,1599,1600],{},".body(schema)",[1562,1602,1603,1604,688,1607],{"align":1551},"The request-body schema — unavailable on ",[503,1605,1606],{},"GET",[503,1608,1609],{},"HEAD",[1546,1611,1612,1617],{},[1562,1613,1614],{"align":1551},[503,1615,1616],{},".responses(schemas)",[1562,1618,1619,1620,693],{"align":1551},"Status-keyed response schemas (",[503,1621,1622],{},"{ 200: …, 404: … }",[1546,1624,1625,1637],{},[1562,1626,1627,1630,1631,1630,1634],{"align":1551},[503,1628,1629],{},".responseContentType(type)"," · ",[503,1632,1633],{},".download()",[503,1635,1636],{},".html()",[1562,1638,1639,1640,1643,1644,1648,1649,688,1652,1655],{"align":1551},"The non-JSON ",[508,1641,1642],{},"2xx"," body wire type (binary \u002F text); the ",[1645,1646,1647],"a",{"href":73},"client"," decodes it to a ",[503,1650,1651],{},"Blob",[503,1653,1654],{},"string"," and skips validation, declared errors stay JSON",[1546,1657,1658,1663],{},[1562,1659,1660],{"align":1551},[503,1661,1662],{},".scopes(...names)",[1562,1664,1665],{"align":1551},"Authorization scopes the auth guard enforces",[1546,1667,1668,1673],{},[1562,1669,1670],{"align":1551},[503,1671,1672],{},".cors(options)",[1562,1674,1675,1676,1679,1680,1683,1684,1687,1688,1690,1691,693],{"align":1551},"CORS handling — ",[503,1677,1678],{},"true"," for permissive, or a ",[503,1681,1682],{},"CorsOptions"," object; registers an implicit ",[503,1685,1686],{},"OPTIONS"," row (and ",[503,1689,1609],{}," on ",[503,1692,1606],{},[1546,1694,1695,1700],{},[1562,1696,1697],{"align":1551},[503,1698,1699],{},".cache(options)",[1562,1701,1702,1703,688,1706,688,1709,1712],{"align":1551},"Cache directives for the response — ",[503,1704,1705],{},"maxAge",[503,1707,1708],{},"staleMaxAge",[503,1710,1711],{},"swr","; emitted as cache headers by the HTTP layer",[1546,1714,1715,1720],{},[1562,1716,1717],{"align":1551},[503,1718,1719],{},".summary(text)",[1562,1721,1722,1723,693],{"align":1551},"A short one-liner (OpenAPI ",[503,1724,698],{},[1546,1726,1727,1732],{},[1562,1728,1729],{"align":1551},[503,1730,1731],{},".description(text)",[1562,1733,1734,1735,1738],{"align":1551},"Extended prose (OpenAPI ",[503,1736,1737],{},"description","); Markdown is supported in renderers",[1546,1740,1741,1746],{},[1562,1742,1743],{"align":1551},[503,1744,1745],{},".deprecated()",[1562,1747,1748,1749,1752],{"align":1551},"Mark the route as deprecated — the OpenAPI generator emits ",[503,1750,1751],{},"deprecated: true"," on the operation",[499,1754,1755,1756,1762,1763,1766,1767,1770],{},"The schemas are any ",[1645,1757,1761],{"href":1758,"rel":1759},"https:\u002F\u002Fstandardschema.dev",[1760],"nofollow","Standard Schema"," value — a ",[503,1764,1765],{},"SchemaObject"," from\n",[503,1768,1769],{},"@heximon\u002Fschema",", or a raw Zod \u002F Valibot \u002F ArkType schema. The contract doesn't pin a validator; it\nholds whatever you author for the server and client to check against.",[1772,1773,1775,1778,1779,1781,1782,1784,1785,1788,1789,688,1791,1793,1794,1797,1798,1800,1801,1804],"callout",{"type":1774},"info",[508,1776,1777],{},"Path params and bodies are checked at the type level."," ",[503,1780,1566],{}," requires the schema's output\nto cover every ",[503,1783,1572],{}," in the path, and ",[503,1786,1787],{},".body"," isn't callable on a ",[503,1790,1606],{},[503,1792,1609],{}," route. Forget the ",[503,1795,1796],{},":sku","\nparam or attach a body to a ",[503,1799,1606],{},", and ",[503,1802,1803],{},"pnpm check"," flags it — the contract can't describe an unservable route.",[884,1806,1808],{"id":1807},"author-routes-with-less-ceremony","Author routes with less ceremony",[499,1810,1811],{},"The fluent chain is the common form; two shorthands save repetition.",[499,1813,1814,1817,1818,1821,1822,1246,1824,1246,1827,1246,1829,1246,1832,1246,1834,1246,1836,654,1838,1246,1840,1246,1843,1800,1846,678],{},[503,1815,1816],{},"Route.define(path, { method, ... })"," puts the whole route in one flat object — same descriptor, and ",[503,1819,1820],{},"path","\nstays positional so the path-param check still applies. The flat form accepts all the same metadata fields\nas the fluent chain: ",[503,1823,765],{},[503,1825,1826],{},"query",[503,1828,819],{},[503,1830,1831],{},"headers",[503,1833,714],{},[503,1835,1108],{},[503,1837,698],{},[503,1839,1737],{},[503,1841,1842],{},"cors",[503,1844,1845],{},"cache",[503,1847,1848],{},"deprecated",[513,1850,1852],{"className":515,"code":1851,"language":518,"meta":519,"style":519},"import { Route } from \"@heximon\u002Fcontract\";\nimport { productParams, product } from \".\u002Fproduct.schema\";\n\nconst find = Route.define(\"\u002F:sku\", {\n  method: \"GET\",\n  pathParams: productParams,\n  summary: \"Find a product\",\n  description: \"Returns the product matching the given SKU. Returns 404 when not found.\",\n  cors: { origin: \"*\" },\n  responses: { 200: product },\n});\n",[503,1853,1854,1874,1898,1902,1929,1944,1955,1971,1987,2011,2029],{"__ignoreMap":519},[523,1855,1856,1858,1860,1862,1864,1866,1868,1870,1872],{"class":525,"line":526},[523,1857,530],{"class":529},[523,1859,534],{"class":533},[523,1861,544],{"class":537},[523,1863,547],{"class":533},[523,1865,550],{"class":529},[523,1867,553],{"class":533},[523,1869,557],{"class":556},[523,1871,560],{"class":533},[523,1873,563],{"class":533},[523,1875,1876,1878,1880,1882,1884,1886,1888,1890,1892,1894,1896],{"class":525,"line":566},[523,1877,530],{"class":529},[523,1879,534],{"class":533},[523,1881,588],{"class":537},[523,1883,541],{"class":533},[523,1885,578],{"class":537},[523,1887,547],{"class":533},[523,1889,550],{"class":529},[523,1891,553],{"class":533},[523,1893,597],{"class":556},[523,1895,560],{"class":533},[523,1897,563],{"class":533},[523,1899,1900],{"class":525,"line":604},[523,1901,608],{"emptyLinePlaceholder":607},[523,1903,1904,1906,1908,1910,1912,1914,1917,1919,1921,1923,1925,1927],{"class":525,"line":611},[523,1905,1328],{"class":617},[523,1907,1395],{"class":537},[523,1909,1334],{"class":533},[523,1911,544],{"class":537},[523,1913,678],{"class":533},[523,1915,1916],{"class":628},"define",[523,1918,631],{"class":537},[523,1920,560],{"class":533},[523,1922,756],{"class":556},[523,1924,560],{"class":533},[523,1926,541],{"class":533},[523,1928,665],{"class":533},[523,1930,1931,1934,1936,1938,1940,1942],{"class":525,"line":637},[523,1932,1933],{"class":640},"  method",[523,1935,644],{"class":533},[523,1937,553],{"class":533},[523,1939,1606],{"class":556},[523,1941,560],{"class":533},[523,1943,654],{"class":533},[523,1945,1946,1949,1951,1953],{"class":525,"line":657},[523,1947,1948],{"class":640},"  pathParams",[523,1950,644],{"class":533},[523,1952,588],{"class":537},[523,1954,654],{"class":533},[523,1956,1957,1960,1962,1964,1967,1969],{"class":525,"line":668},[523,1958,1959],{"class":640},"  summary",[523,1961,644],{"class":533},[523,1963,553],{"class":533},[523,1965,1966],{"class":556},"Find a product",[523,1968,560],{"class":533},[523,1970,654],{"class":533},[523,1972,1973,1976,1978,1980,1983,1985],{"class":525,"line":738},[523,1974,1975],{"class":640},"  description",[523,1977,644],{"class":533},[523,1979,553],{"class":533},[523,1981,1982],{"class":556},"Returns the product matching the given SKU. Returns 404 when not found.",[523,1984,560],{"class":533},[523,1986,654],{"class":533},[523,1988,1989,1992,1994,1996,1999,2001,2003,2006,2008],{"class":525,"line":792},[523,1990,1991],{"class":640},"  cors",[523,1993,644],{"class":533},[523,1995,534],{"class":533},[523,1997,1998],{"class":640}," origin",[523,2000,644],{"class":533},[523,2002,553],{"class":533},[523,2004,2005],{"class":556},"*",[523,2007,560],{"class":533},[523,2009,2010],{"class":533}," },\n",[523,2012,2013,2016,2018,2020,2022,2024,2026],{"class":525,"line":846},[523,2014,2015],{"class":640},"  responses",[523,2017,644],{"class":533},[523,2019,534],{"class":533},[523,2021,723],{"class":722},[523,2023,644],{"class":533},[523,2025,783],{"class":537},[523,2027,2028],{"class":533},"},\n",[523,2030,2031,2033,2035],{"class":525,"line":852},[523,2032,731],{"class":533},[523,2034,693],{"class":537},[523,2036,563],{"class":533},[499,2038,2039,2042,2043,1778,2046,2049],{},[503,2040,2041],{},"Route.path(path)"," types a path's ",[503,2044,2045],{},":params",[508,2047,2048],{},"once",", then reuses them across verbs through its verb getters\n— so a resource with several methods on one path declares its params once:",[513,2051,2053],{"className":515,"code":2052,"language":518,"meta":519,"style":519},"import { Route } from \"@heximon\u002Fcontract\";\nimport { productParams, product } from \".\u002Fproduct.schema\";\n\nconst bySku = Route.path(\"\u002F:sku\").pathParams(productParams);\n\nconst find = bySku.get.responses({ 200: product });\nconst remove = bySku.delete.responses({ 204: product });\n",[503,2054,2055,2075,2099,2103,2136,2140,2175],{"__ignoreMap":519},[523,2056,2057,2059,2061,2063,2065,2067,2069,2071,2073],{"class":525,"line":526},[523,2058,530],{"class":529},[523,2060,534],{"class":533},[523,2062,544],{"class":537},[523,2064,547],{"class":533},[523,2066,550],{"class":529},[523,2068,553],{"class":533},[523,2070,557],{"class":556},[523,2072,560],{"class":533},[523,2074,563],{"class":533},[523,2076,2077,2079,2081,2083,2085,2087,2089,2091,2093,2095,2097],{"class":525,"line":566},[523,2078,530],{"class":529},[523,2080,534],{"class":533},[523,2082,588],{"class":537},[523,2084,541],{"class":533},[523,2086,578],{"class":537},[523,2088,547],{"class":533},[523,2090,550],{"class":529},[523,2092,553],{"class":533},[523,2094,597],{"class":556},[523,2096,560],{"class":533},[523,2098,563],{"class":533},[523,2100,2101],{"class":525,"line":604},[523,2102,608],{"emptyLinePlaceholder":607},[523,2104,2105,2107,2110,2112,2114,2116,2118,2120,2122,2124,2126,2128,2130,2132,2134],{"class":525,"line":611},[523,2106,1328],{"class":617},[523,2108,2109],{"class":537}," bySku ",[523,2111,1334],{"class":533},[523,2113,544],{"class":537},[523,2115,678],{"class":533},[523,2117,1820],{"class":628},[523,2119,631],{"class":537},[523,2121,560],{"class":533},[523,2123,756],{"class":556},[523,2125,560],{"class":533},[523,2127,693],{"class":537},[523,2129,678],{"class":533},[523,2131,765],{"class":628},[523,2133,768],{"class":537},[523,2135,563],{"class":533},[523,2137,2138],{"class":525,"line":637},[523,2139,608],{"emptyLinePlaceholder":607},[523,2141,2142,2144,2146,2148,2151,2153,2155,2157,2159,2161,2163,2165,2167,2169,2171,2173],{"class":525,"line":657},[523,2143,1328],{"class":617},[523,2145,1395],{"class":537},[523,2147,1334],{"class":533},[523,2149,2150],{"class":537}," bySku",[523,2152,678],{"class":533},[523,2154,681],{"class":537},[523,2156,678],{"class":533},[523,2158,714],{"class":628},[523,2160,631],{"class":537},[523,2162,719],{"class":533},[523,2164,723],{"class":722},[523,2166,644],{"class":533},[523,2168,783],{"class":537},[523,2170,731],{"class":533},[523,2172,693],{"class":537},[523,2174,563],{"class":533},[523,2176,2177,2179,2182,2184,2186,2188,2191,2193,2195,2197,2199,2202,2204,2206,2208,2210],{"class":525,"line":668},[523,2178,1328],{"class":617},[523,2180,2181],{"class":537}," remove ",[523,2183,1334],{"class":533},[523,2185,2150],{"class":537},[523,2187,678],{"class":533},[523,2189,2190],{"class":537},"delete",[523,2192,678],{"class":533},[523,2194,714],{"class":628},[523,2196,631],{"class":537},[523,2198,719],{"class":533},[523,2200,2201],{"class":722}," 204",[523,2203,644],{"class":533},[523,2205,783],{"class":537},[523,2207,731],{"class":533},[523,2209,693],{"class":537},[523,2211,563],{"class":533},[884,2213,2215],{"id":2214},"share-responses-across-routes","Share responses across routes",[499,2217,2218,2219,2222,2223,2226,2227,2229],{},"Most routes answer the same way on failure — a ",[503,2220,2221],{},"400"," for bad input, a ",[503,2224,2225],{},"401"," for a missing token. Contract-level\n",[503,2228,714],{}," fold into every route, so each route only declares what's unique to it.",[513,2231,2233],{"className":515,"code":2232,"filename":517,"language":518,"meta":519,"style":519},"import { Contract, Route } from \"@heximon\u002Fcontract\";\nimport { SchemaObject } from \"@heximon\u002Fschema\";\nimport * as v from \"valibot\";\n\n\u002F\u002F Error shapes are plain Standard-Schema DTOs, authored exactly like success shapes.\nclass ValidationError extends SchemaObject({ message: v.string() }) {}\nclass UnauthorizedError extends SchemaObject({ message: v.string() }) {}\nclass NotFoundError extends SchemaObject({ message: v.string() }) {}\n\nexport class ProductsApi extends Contract({\n  prefix: \"\u002Fapi\u002Fproducts\",\n  responses: { 400: ValidationError, 401: UnauthorizedError }, \u002F\u002F merged into every route\n  routes: {\n    list: Route.get(\"\u002F\").responses({ 200: productList }),\n    find: Route.get(\"\u002F:sku\").pathParams(productParams).responses({ 200: product, 404: NotFoundError }),\n  },\n}) {}\n\nProductsApi.routes.find.responses?.[404]; \u002F\u002F NotFoundError — the route's own\nProductsApi.routes.find.responses?.[400]; \u002F\u002F ValidationError — the shared default, folded in\n",[503,2234,2235,2259,2280,2305,2309,2315,2352,2385,2418,2422,2438,2452,2483,2491,2533,2591,2595,2603,2608,2644],{"__ignoreMap":519},[523,2236,2237,2239,2241,2243,2245,2247,2249,2251,2253,2255,2257],{"class":525,"line":526},[523,2238,530],{"class":529},[523,2240,534],{"class":533},[523,2242,538],{"class":537},[523,2244,541],{"class":533},[523,2246,544],{"class":537},[523,2248,547],{"class":533},[523,2250,550],{"class":529},[523,2252,553],{"class":533},[523,2254,557],{"class":556},[523,2256,560],{"class":533},[523,2258,563],{"class":533},[523,2260,2261,2263,2265,2268,2270,2272,2274,2276,2278],{"class":525,"line":566},[523,2262,530],{"class":529},[523,2264,534],{"class":533},[523,2266,2267],{"class":537}," SchemaObject",[523,2269,547],{"class":533},[523,2271,550],{"class":529},[523,2273,553],{"class":533},[523,2275,1769],{"class":556},[523,2277,560],{"class":533},[523,2279,563],{"class":533},[523,2281,2282,2284,2287,2290,2293,2296,2298,2301,2303],{"class":525,"line":604},[523,2283,530],{"class":529},[523,2285,2286],{"class":533}," *",[523,2288,2289],{"class":529}," as",[523,2291,2292],{"class":537}," v ",[523,2294,2295],{"class":529},"from",[523,2297,553],{"class":533},[523,2299,2300],{"class":556},"valibot",[523,2302,560],{"class":533},[523,2304,563],{"class":533},[523,2306,2307],{"class":525,"line":611},[523,2308,608],{"emptyLinePlaceholder":607},[523,2310,2311],{"class":525,"line":637},[523,2312,2314],{"class":2313},"sHwdD","\u002F\u002F Error shapes are plain Standard-Schema DTOs, authored exactly like success shapes.\n",[523,2316,2317,2320,2323,2325,2327,2329,2331,2334,2336,2339,2341,2343,2346,2348,2350],{"class":525,"line":657},[523,2318,2319],{"class":617},"class",[523,2321,2322],{"class":621}," ValidationError",[523,2324,625],{"class":617},[523,2326,2267],{"class":628},[523,2328,631],{"class":537},[523,2330,719],{"class":533},[523,2332,2333],{"class":640}," message",[523,2335,644],{"class":533},[523,2337,2338],{"class":537}," v",[523,2340,678],{"class":533},[523,2342,1654],{"class":628},[523,2344,2345],{"class":537},"() ",[523,2347,731],{"class":533},[523,2349,857],{"class":537},[523,2351,860],{"class":533},[523,2353,2354,2356,2359,2361,2363,2365,2367,2369,2371,2373,2375,2377,2379,2381,2383],{"class":525,"line":668},[523,2355,2319],{"class":617},[523,2357,2358],{"class":621}," UnauthorizedError",[523,2360,625],{"class":617},[523,2362,2267],{"class":628},[523,2364,631],{"class":537},[523,2366,719],{"class":533},[523,2368,2333],{"class":640},[523,2370,644],{"class":533},[523,2372,2338],{"class":537},[523,2374,678],{"class":533},[523,2376,1654],{"class":628},[523,2378,2345],{"class":537},[523,2380,731],{"class":533},[523,2382,857],{"class":537},[523,2384,860],{"class":533},[523,2386,2387,2389,2392,2394,2396,2398,2400,2402,2404,2406,2408,2410,2412,2414,2416],{"class":525,"line":738},[523,2388,2319],{"class":617},[523,2390,2391],{"class":621}," NotFoundError",[523,2393,625],{"class":617},[523,2395,2267],{"class":628},[523,2397,631],{"class":537},[523,2399,719],{"class":533},[523,2401,2333],{"class":640},[523,2403,644],{"class":533},[523,2405,2338],{"class":537},[523,2407,678],{"class":533},[523,2409,1654],{"class":628},[523,2411,2345],{"class":537},[523,2413,731],{"class":533},[523,2415,857],{"class":537},[523,2417,860],{"class":533},[523,2419,2420],{"class":525,"line":792},[523,2421,608],{"emptyLinePlaceholder":607},[523,2423,2424,2426,2428,2430,2432,2434,2436],{"class":525,"line":846},[523,2425,614],{"class":529},[523,2427,618],{"class":617},[523,2429,622],{"class":621},[523,2431,625],{"class":617},[523,2433,538],{"class":628},[523,2435,631],{"class":537},[523,2437,634],{"class":533},[523,2439,2440,2442,2444,2446,2448,2450],{"class":525,"line":852},[523,2441,641],{"class":640},[523,2443,644],{"class":533},[523,2445,553],{"class":533},[523,2447,649],{"class":556},[523,2449,560],{"class":533},[523,2451,654],{"class":533},[523,2453,2454,2456,2458,2460,2463,2465,2467,2469,2472,2474,2477,2480],{"class":525,"line":1144},[523,2455,2015],{"class":640},[523,2457,644],{"class":533},[523,2459,534],{"class":533},[523,2461,2462],{"class":722}," 400",[523,2464,644],{"class":533},[523,2466,2322],{"class":537},[523,2468,541],{"class":533},[523,2470,2471],{"class":722}," 401",[523,2473,644],{"class":533},[523,2475,2476],{"class":537}," UnauthorizedError ",[523,2478,2479],{"class":533},"},",[523,2481,2482],{"class":2313}," \u002F\u002F merged into every route\n",[523,2484,2485,2487,2489],{"class":525,"line":1167},[523,2486,660],{"class":640},[523,2488,644],{"class":533},[523,2490,665],{"class":533},[523,2492,2493,2495,2497,2499,2501,2503,2505,2507,2509,2511,2513,2515,2517,2519,2521,2523,2525,2527,2529,2531],{"class":525,"line":1177},[523,2494,671],{"class":640},[523,2496,644],{"class":533},[523,2498,544],{"class":537},[523,2500,678],{"class":533},[523,2502,681],{"class":628},[523,2504,631],{"class":537},[523,2506,560],{"class":533},[523,2508,688],{"class":556},[523,2510,560],{"class":533},[523,2512,693],{"class":537},[523,2514,678],{"class":533},[523,2516,714],{"class":628},[523,2518,631],{"class":537},[523,2520,719],{"class":533},[523,2522,723],{"class":722},[523,2524,644],{"class":533},[523,2526,728],{"class":537},[523,2528,731],{"class":533},[523,2530,693],{"class":537},[523,2532,654],{"class":533},[523,2534,2535,2537,2539,2541,2543,2545,2547,2549,2551,2553,2555,2557,2559,2561,2563,2565,2567,2569,2571,2573,2575,2577,2580,2582,2585,2587,2589],{"class":525,"line":1195},[523,2536,741],{"class":640},[523,2538,644],{"class":533},[523,2540,544],{"class":537},[523,2542,678],{"class":533},[523,2544,681],{"class":628},[523,2546,631],{"class":537},[523,2548,560],{"class":533},[523,2550,756],{"class":556},[523,2552,560],{"class":533},[523,2554,693],{"class":537},[523,2556,678],{"class":533},[523,2558,765],{"class":628},[523,2560,768],{"class":537},[523,2562,678],{"class":533},[523,2564,714],{"class":628},[523,2566,631],{"class":537},[523,2568,719],{"class":533},[523,2570,723],{"class":722},[523,2572,644],{"class":533},[523,2574,578],{"class":537},[523,2576,541],{"class":533},[523,2578,2579],{"class":722}," 404",[523,2581,644],{"class":533},[523,2583,2584],{"class":537}," NotFoundError ",[523,2586,731],{"class":533},[523,2588,693],{"class":537},[523,2590,654],{"class":533},[523,2592,2593],{"class":525,"line":1218},[523,2594,849],{"class":533},[523,2596,2597,2599,2601],{"class":525,"line":1223},[523,2598,731],{"class":533},[523,2600,857],{"class":537},[523,2602,860],{"class":533},[523,2604,2606],{"class":525,"line":2605},18,[523,2607,608],{"emptyLinePlaceholder":607},[523,2609,2611,2613,2615,2617,2619,2622,2624,2626,2629,2632,2635,2638,2641],{"class":525,"line":2610},19,[523,2612,870],{"class":537},[523,2614,678],{"class":533},[523,2616,874],{"class":537},[523,2618,678],{"class":533},[523,2620,2621],{"class":537},"find",[523,2623,678],{"class":533},[523,2625,714],{"class":537},[523,2627,2628],{"class":533},"?.",[523,2630,2631],{"class":537},"[",[523,2633,2634],{"class":722},"404",[523,2636,2637],{"class":537},"]",[523,2639,2640],{"class":533},";",[523,2642,2643],{"class":2313}," \u002F\u002F NotFoundError — the route's own\n",[523,2645,2647,2649,2651,2653,2655,2657,2659,2661,2663,2665,2667,2669,2671],{"class":525,"line":2646},20,[523,2648,870],{"class":537},[523,2650,678],{"class":533},[523,2652,874],{"class":537},[523,2654,678],{"class":533},[523,2656,2621],{"class":537},[523,2658,678],{"class":533},[523,2660,714],{"class":537},[523,2662,2628],{"class":533},[523,2664,2631],{"class":537},[523,2666,2221],{"class":722},[523,2668,2637],{"class":537},[523,2670,2640],{"class":533},[523,2672,2673],{"class":2313}," \u002F\u002F ValidationError — the shared default, folded in\n",[499,2675,2676,2677,2680,2681,2683],{},"A route's own status ",[508,2678,2679],{},"wins on collision"," — a route-specific ",[503,2682,2221],{}," overrides the shared one there, while\nevery other shared status still folds in: terse by default, with per-route control intact.",[884,2685,2687],{"id":2686},"bind-the-contract-on-the-server","Bind the contract on the server",[499,2689,2690,2691,2693,2694,678],{},"A contract-mode controller ",[503,2692,866],{}," — the contract supplies its prefix,\nhandler names, and per-route types. Each handler matches a route key, its action typed off that route with\n",[503,2695,2696],{},"Action\u003CProductsApi, \"key\">",[513,2698,2701],{"className":515,"code":2699,"filename":2700,"language":518,"meta":519,"style":519},"import type { Action, Controller } from \"@heximon\u002Fhttp\";\nimport { ProductsApi } from \".\u002Fproduct.api\";\nimport { ProductsRepository } from \".\u002Fproducts.repository\";\n\nexport class ProductsController implements Controller\u003CProductsApi> {\n  public constructor(private readonly products: ProductsRepository) {}\n\n  public async list(action: Action\u003CProductsApi, \"list\">) {\n    return this.products.list();\n  }\n\n  public async find(action: Action\u003CProductsApi, \"find\">) {\n    const { sku } = await action.request.getValidatedPathParams();\n    return this.products.getBySku(sku);\n  }\n\n  public async create(action: Action\u003CProductsApi, \"create\">) {\n    const body = await action.request.readValidatedBody();\n    return action.respond(201, await this.products.create(body));\n  }\n}\n","src\u002Fproducts\u002Fproducts.controller.ts",[503,2702,2703,2733,2754,2776,2780,2804,2833,2837,2874,2894,2899,2903,2936,2971,2993,2997,3001,3035,3061,3098,3102],{"__ignoreMap":519},[523,2704,2705,2707,2710,2712,2715,2717,2720,2722,2724,2726,2729,2731],{"class":525,"line":526},[523,2706,530],{"class":529},[523,2708,2709],{"class":529}," type",[523,2711,534],{"class":533},[523,2713,2714],{"class":537}," Action",[523,2716,541],{"class":533},[523,2718,2719],{"class":537}," Controller",[523,2721,547],{"class":533},[523,2723,550],{"class":529},[523,2725,553],{"class":533},[523,2727,2728],{"class":556},"@heximon\u002Fhttp",[523,2730,560],{"class":533},[523,2732,563],{"class":533},[523,2734,2735,2737,2739,2741,2743,2745,2747,2750,2752],{"class":525,"line":566},[523,2736,530],{"class":529},[523,2738,534],{"class":533},[523,2740,622],{"class":537},[523,2742,547],{"class":533},[523,2744,550],{"class":529},[523,2746,553],{"class":533},[523,2748,2749],{"class":556},".\u002Fproduct.api",[523,2751,560],{"class":533},[523,2753,563],{"class":533},[523,2755,2756,2758,2760,2763,2765,2767,2769,2772,2774],{"class":525,"line":604},[523,2757,530],{"class":529},[523,2759,534],{"class":533},[523,2761,2762],{"class":537}," ProductsRepository",[523,2764,547],{"class":533},[523,2766,550],{"class":529},[523,2768,553],{"class":533},[523,2770,2771],{"class":556},".\u002Fproducts.repository",[523,2773,560],{"class":533},[523,2775,563],{"class":533},[523,2777,2778],{"class":525,"line":611},[523,2779,608],{"emptyLinePlaceholder":607},[523,2781,2782,2784,2786,2789,2792,2794,2797,2799,2802],{"class":525,"line":637},[523,2783,614],{"class":529},[523,2785,618],{"class":617},[523,2787,2788],{"class":621}," ProductsController",[523,2790,2791],{"class":617}," implements",[523,2793,2719],{"class":621},[523,2795,2796],{"class":533},"\u003C",[523,2798,870],{"class":621},[523,2800,2801],{"class":533},">",[523,2803,665],{"class":533},[523,2805,2806,2809,2812,2814,2817,2820,2824,2826,2828,2830],{"class":525,"line":657},[523,2807,2808],{"class":617},"  public",[523,2810,2811],{"class":617}," constructor",[523,2813,631],{"class":533},[523,2815,2816],{"class":617},"private",[523,2818,2819],{"class":617}," readonly",[523,2821,2823],{"class":2822},"sHdIc"," products",[523,2825,644],{"class":533},[523,2827,2762],{"class":621},[523,2829,693],{"class":533},[523,2831,2832],{"class":533}," {}\n",[523,2834,2835],{"class":525,"line":668},[523,2836,608],{"emptyLinePlaceholder":607},[523,2838,2839,2841,2844,2847,2849,2852,2854,2856,2858,2860,2862,2864,2867,2869,2872],{"class":525,"line":738},[523,2840,2808],{"class":617},[523,2842,2843],{"class":617}," async",[523,2845,2846],{"class":640}," list",[523,2848,631],{"class":533},[523,2850,2851],{"class":2822},"action",[523,2853,644],{"class":533},[523,2855,2714],{"class":621},[523,2857,2796],{"class":533},[523,2859,870],{"class":621},[523,2861,541],{"class":533},[523,2863,553],{"class":533},[523,2865,2866],{"class":556},"list",[523,2868,560],{"class":533},[523,2870,2871],{"class":533},">)",[523,2873,665],{"class":533},[523,2875,2876,2879,2882,2885,2887,2889,2892],{"class":525,"line":792},[523,2877,2878],{"class":529},"    return",[523,2880,2881],{"class":533}," this.",[523,2883,2884],{"class":537},"products",[523,2886,678],{"class":533},[523,2888,2866],{"class":628},[523,2890,2891],{"class":640},"()",[523,2893,563],{"class":533},[523,2895,2896],{"class":525,"line":846},[523,2897,2898],{"class":533},"  }\n",[523,2900,2901],{"class":525,"line":852},[523,2902,608],{"emptyLinePlaceholder":607},[523,2904,2905,2907,2909,2912,2914,2916,2918,2920,2922,2924,2926,2928,2930,2932,2934],{"class":525,"line":1144},[523,2906,2808],{"class":617},[523,2908,2843],{"class":617},[523,2910,2911],{"class":640}," find",[523,2913,631],{"class":533},[523,2915,2851],{"class":2822},[523,2917,644],{"class":533},[523,2919,2714],{"class":621},[523,2921,2796],{"class":533},[523,2923,870],{"class":621},[523,2925,541],{"class":533},[523,2927,553],{"class":533},[523,2929,2621],{"class":556},[523,2931,560],{"class":533},[523,2933,2871],{"class":533},[523,2935,665],{"class":533},[523,2937,2938,2941,2943,2946,2948,2951,2954,2957,2959,2962,2964,2967,2969],{"class":525,"line":1167},[523,2939,2940],{"class":617},"    const",[523,2942,534],{"class":533},[523,2944,2945],{"class":537}," sku",[523,2947,547],{"class":533},[523,2949,2950],{"class":533}," =",[523,2952,2953],{"class":529}," await",[523,2955,2956],{"class":537}," action",[523,2958,678],{"class":533},[523,2960,2961],{"class":537},"request",[523,2963,678],{"class":533},[523,2965,2966],{"class":628},"getValidatedPathParams",[523,2968,2891],{"class":640},[523,2970,563],{"class":533},[523,2972,2973,2975,2977,2979,2981,2984,2986,2989,2991],{"class":525,"line":1177},[523,2974,2878],{"class":529},[523,2976,2881],{"class":533},[523,2978,2884],{"class":537},[523,2980,678],{"class":533},[523,2982,2983],{"class":628},"getBySku",[523,2985,631],{"class":640},[523,2987,2988],{"class":537},"sku",[523,2990,693],{"class":640},[523,2992,563],{"class":533},[523,2994,2995],{"class":525,"line":1195},[523,2996,2898],{"class":533},[523,2998,2999],{"class":525,"line":1218},[523,3000,608],{"emptyLinePlaceholder":607},[523,3002,3003,3005,3007,3010,3012,3014,3016,3018,3020,3022,3024,3026,3029,3031,3033],{"class":525,"line":1223},[523,3004,2808],{"class":617},[523,3006,2843],{"class":617},[523,3008,3009],{"class":640}," create",[523,3011,631],{"class":533},[523,3013,2851],{"class":2822},[523,3015,644],{"class":533},[523,3017,2714],{"class":621},[523,3019,2796],{"class":533},[523,3021,870],{"class":621},[523,3023,541],{"class":533},[523,3025,553],{"class":533},[523,3027,3028],{"class":556},"create",[523,3030,560],{"class":533},[523,3032,2871],{"class":533},[523,3034,665],{"class":533},[523,3036,3037,3039,3042,3044,3046,3048,3050,3052,3054,3057,3059],{"class":525,"line":2605},[523,3038,2940],{"class":617},[523,3040,3041],{"class":537}," body",[523,3043,2950],{"class":533},[523,3045,2953],{"class":529},[523,3047,2956],{"class":537},[523,3049,678],{"class":533},[523,3051,2961],{"class":537},[523,3053,678],{"class":533},[523,3055,3056],{"class":628},"readValidatedBody",[523,3058,2891],{"class":640},[523,3060,563],{"class":533},[523,3062,3063,3065,3067,3069,3072,3074,3077,3079,3081,3083,3085,3087,3089,3091,3093,3096],{"class":525,"line":2610},[523,3064,2878],{"class":529},[523,3066,2956],{"class":537},[523,3068,678],{"class":533},[523,3070,3071],{"class":628},"respond",[523,3073,631],{"class":640},[523,3075,3076],{"class":722},"201",[523,3078,541],{"class":533},[523,3080,2953],{"class":529},[523,3082,2881],{"class":533},[523,3084,2884],{"class":537},[523,3086,678],{"class":533},[523,3088,3028],{"class":628},[523,3090,631],{"class":640},[523,3092,819],{"class":537},[523,3094,3095],{"class":640},"))",[523,3097,563],{"class":533},[523,3099,3100],{"class":525,"line":2646},[523,3101,2898],{"class":533},[523,3103,3105],{"class":525,"line":3104},21,[523,3106,3107],{"class":533},"}\n",[499,3109,3110,3111,3113,3114,3116],{},"Because the types come from the contract, the ",[503,3112,866],{}," clause checks that\nevery route has a handler and that each return type satisfies its ",[503,3115,714],{},". Change a response schema\nand the controller lights up where it no longer matches — spec and implementation can't quietly diverge.",[499,3118,1569,3119,3122,3123,882],{},[1645,3120,3121],{"href":58},"controllers page"," covers both modes in depth, including the config form that adds\ncontroller-level middlewares (",[503,3124,3125],{},"implements Controller\u003C{ contract: ProductsApi; middlewares: [Auth] }>",[884,3127,3129],{"id":3128},"call-it-from-the-same-value","Call it from the same value",[499,3131,3132,3133,3137,3138,3141],{},"The contract that types the server is ",[3134,3135,3136],"em",{},"also"," the client — construct it with a transport and call its\n",[503,3139,3140],{},".client",". The request body, response status, and response shape are all known with nothing to annotate.",[513,3143,3146],{"className":515,"code":3144,"filename":3145,"language":518,"meta":519,"style":519},"import { ClientTransport } from \"@heximon\u002Fclient\";\nimport { ProductsApi } from \".\u002Fproducts\u002Fproduct.api\";\n\nconst api = new ProductsApi(ClientTransport.fetch({ baseUrl: \"https:\u002F\u002Fshop.example.com\" }));\n\nconst product = await api.client.create({\n  body: { sku: \"ABC-1\", name: \"Widget\", priceInCents: 1999 },\n});\n\u002F\u002F    ^? { sku: string; name: string; priceInCents: number } — the 2xx body (throws on non-2xx)\n","client.ts",[503,3147,3148,3170,3191,3195,3239,3243,3268,3314,3322],{"__ignoreMap":519},[523,3149,3150,3152,3154,3157,3159,3161,3163,3166,3168],{"class":525,"line":526},[523,3151,530],{"class":529},[523,3153,534],{"class":533},[523,3155,3156],{"class":537}," ClientTransport",[523,3158,547],{"class":533},[523,3160,550],{"class":529},[523,3162,553],{"class":533},[523,3164,3165],{"class":556},"@heximon\u002Fclient",[523,3167,560],{"class":533},[523,3169,563],{"class":533},[523,3171,3172,3174,3176,3178,3180,3182,3184,3187,3189],{"class":525,"line":566},[523,3173,530],{"class":529},[523,3175,534],{"class":533},[523,3177,622],{"class":537},[523,3179,547],{"class":533},[523,3181,550],{"class":529},[523,3183,553],{"class":533},[523,3185,3186],{"class":556},".\u002Fproducts\u002Fproduct.api",[523,3188,560],{"class":533},[523,3190,563],{"class":533},[523,3192,3193],{"class":525,"line":604},[523,3194,608],{"emptyLinePlaceholder":607},[523,3196,3197,3199,3202,3204,3207,3209,3212,3214,3217,3219,3221,3224,3226,3228,3231,3233,3235,3237],{"class":525,"line":611},[523,3198,1328],{"class":617},[523,3200,3201],{"class":537}," api ",[523,3203,1334],{"class":533},[523,3205,3206],{"class":533}," new",[523,3208,622],{"class":628},[523,3210,3211],{"class":537},"(ClientTransport",[523,3213,678],{"class":533},[523,3215,3216],{"class":628},"fetch",[523,3218,631],{"class":537},[523,3220,719],{"class":533},[523,3222,3223],{"class":640}," baseUrl",[523,3225,644],{"class":533},[523,3227,553],{"class":533},[523,3229,3230],{"class":556},"https:\u002F\u002Fshop.example.com",[523,3232,560],{"class":533},[523,3234,547],{"class":533},[523,3236,3095],{"class":537},[523,3238,563],{"class":533},[523,3240,3241],{"class":525,"line":637},[523,3242,608],{"emptyLinePlaceholder":607},[523,3244,3245,3247,3249,3251,3253,3256,3258,3260,3262,3264,3266],{"class":525,"line":657},[523,3246,1328],{"class":617},[523,3248,783],{"class":537},[523,3250,1334],{"class":533},[523,3252,2953],{"class":529},[523,3254,3255],{"class":537}," api",[523,3257,678],{"class":533},[523,3259,1647],{"class":537},[523,3261,678],{"class":533},[523,3263,3028],{"class":628},[523,3265,631],{"class":537},[523,3267,634],{"class":533},[523,3269,3270,3273,3275,3277,3279,3281,3283,3286,3288,3290,3293,3295,3297,3300,3302,3304,3307,3309,3312],{"class":525,"line":668},[523,3271,3272],{"class":640},"  body",[523,3274,644],{"class":533},[523,3276,534],{"class":533},[523,3278,2945],{"class":640},[523,3280,644],{"class":533},[523,3282,553],{"class":533},[523,3284,3285],{"class":556},"ABC-1",[523,3287,560],{"class":533},[523,3289,541],{"class":533},[523,3291,3292],{"class":640}," name",[523,3294,644],{"class":533},[523,3296,553],{"class":533},[523,3298,3299],{"class":556},"Widget",[523,3301,560],{"class":533},[523,3303,541],{"class":533},[523,3305,3306],{"class":640}," priceInCents",[523,3308,644],{"class":533},[523,3310,3311],{"class":722}," 1999",[523,3313,2010],{"class":533},[523,3315,3316,3318,3320],{"class":525,"line":738},[523,3317,731],{"class":533},[523,3319,693],{"class":537},[523,3321,563],{"class":533},[523,3323,3324],{"class":525,"line":792},[523,3325,3326],{"class":2313},"\u002F\u002F    ^? { sku: string; name: string; priceInCents: number } — the 2xx body (throws on non-2xx)\n",[499,3328,3329,3330,3333,3334,3336],{},"Edit the contract, and every handler and client call that no longer matches surfaces as a type error — the\npoint of one source of truth: the type system, not a code review, catches drift. See the\n",[1645,3331,3332],{"href":73},"REST client"," and ",[1645,3335,199],{"href":200}," pages for the two consumers in full.",[884,3338,3340],{"id":3339},"see-also","See also",[3342,3343,3344,3358,3372,3380,3385,3395],"ul",{},[3345,3346,3347,3349,3350,3353,3354,3357],"li",{},[1645,3348,57],{"href":58}," — bind a contract with ",[503,3351,3352],{},"implements Controller\u003CSomeApi>",",\ntype each handler with ",[503,3355,3356],{},"Action",", and compare the inline route mode.",[3345,3359,3360,3362,3363,3365,3366,654,3368,1800,3370,678],{},[1645,3361,62],{"href":63}," — author the ",[503,3364,1765],{}," DTOs a route references as ",[503,3367,819],{},[503,3369,714],{},[503,3371,765],{},[3345,3373,3374,3376,3377,882],{},[1645,3375,3332],{"href":73}," — call a contract by constructing it with a transport (",[503,3378,3379],{},"new SomeApi(...)",[3345,3381,3382,3384],{},[1645,3383,199],{"href":200}," — generate an OpenAPI document from the same contract at runtime.",[3345,3386,3387,3394],{},[1645,3388,3391],{"href":3389,"rel":3390},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fgap\u002Fopenapi-mcp",[1760],[508,3392,3393],{},"OpenAPI + MCP"," — a products\ncontract bound by a contract-mode controller and turned into a served Swagger \u002F Scalar spec from the one value.",[3345,3396,3397,3402],{},[1645,3398,3401],{"href":3399,"rel":3400},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fflagship",[1760],"the flagship app"," — a\nscoped task contract driving a guarded controller, CQRS handlers, and a typed client end-to-end.",[3404,3405,3406],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}",{"title":519,"searchDepth":566,"depth":566,"links":3408},[3409,3410,3411,3412,3413,3414,3415],{"id":886,"depth":566,"text":887},{"id":1235,"depth":566,"text":1236},{"id":1807,"depth":566,"text":1808},{"id":2214,"depth":566,"text":2215},{"id":2686,"depth":566,"text":2687},{"id":3128,"depth":566,"text":3129},{"id":3339,"depth":566,"text":3340},"Describe an HTTP API once with the Contract class and Route builder, then bind the server, the REST client, and OpenAPI to the same route table — Route.get\u002Fpost, body, responses, pathParams, scopes, shared responses, contract-mode controllers.","md",null,{},{"icon":70},{"title":67,"description":3416},"TJtRfcplcV8awf-5OXPgOfWGGDNuwgP6atoQIZy75aw",[3424,3426],{"title":62,"path":63,"stem":64,"description":3425,"icon":65,"children":-1},"Request bodies, query, path params, and headers are validated automatically at dispatch — the handler receives typed data without calling an accessor. Declare the shape once with SchemaObject and any Standard Schema validator.",{"title":72,"path":73,"stem":74,"description":3427,"icon":75,"children":-1},"Call a shared Contract from the frontend by constructing it with a transport — ClientTransport.fetch, ClientTransport.internal, and ClientTransport.mock, throwing 2xx-body callers, raw() for the full status union, request\u002Fresponse interceptors, and vue-query bindings.",1783300761903]