[{"data":1,"prerenderedAt":3528},["ShallowReactive",2],{"navigation_docs":3,"-docs-getting-started-quick-start":493,"-docs-getting-started-quick-start-surround":3523},[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":21,"body":495,"description":3516,"extension":3517,"links":3518,"meta":3519,"navigation":3520,"path":22,"seo":3521,"stem":23,"__hash__":3522},"docs\u002Fdocs\u002F01.getting-started\u002F03.quick-start.md",{"type":496,"value":497,"toc":3501},"minimark",[498,502,517,522,532,536,543,1026,1030,1054,1381,1390,1394,1408,1555,1562,1650,1654,1715,1750,1757,1761,1772,1897,2207,2252,2256,2259,2603,2620,2630,2634,2645,2650,2961,2965,2975,3254,3266,3270,3287,3458,3464,3468,3497],[499,500,501],"p",{},"Build the smallest real Heximon app: a provider, a controller that injects it, and a module that ties them\ntogether. The compiler reads these three files, builds the wiring, and serves it — you never write a\nbootstrap or a server file.",[503,504,506,507,511,512,516],"callout",{"type":505},"info","Want the finished shape in one command instead of typing it? ",[508,509,510],"code",{},"pnpm create heximon my-app"," scaffolds\nthe same app for you — see ",[513,514,515],"a",{"href":367},"Create a new app",". This tutorial builds it by hand on\npurpose, so you see every file and what it does.",[518,519,521],"h2",{"id":520},"what-youll-build","What you'll build",[499,523,524,527,528,531],{},[508,525,526],{},"GET \u002Fusers"," returns a list of users, and ",[508,529,530],{},"GET \u002Fusers\u002F:id"," returns one by id — served from an injected\nrepository.",[518,533,535],{"id":534},"create-a-provider","Create a provider",[499,537,538,539,542],{},"A provider is any plain class. There's no decorator to add — a class becomes injectable simply by being\nlisted in a module's ",[508,540,541],{},"providers",", and its constructor parameters are its dependencies.",[544,545,551],"pre",{"className":546,"code":547,"filename":548,"language":549,"meta":550,"style":550},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","export interface User {\n  id: string;\n  name: string;\n}\n\nexport class UsersRepository {\n  private readonly users: User[] = [\n    { id: \"1\", name: \"Alice\" },\n    { id: \"2\", name: \"Bob\" },\n  ];\n\n  public async list(): Promise\u003CUser[]> {\n    return this.users;\n  }\n\n  public async findById(id: string): Promise\u003CUser | undefined> {\n    return this.users.find((user) => user.id === id);\n  }\n\n  public async create(input: { name: string }): Promise\u003CUser> {\n    const user = { id: String(this.users.length + 1), name: input.name };\n    this.users.push(user);\n    return user;\n  }\n}\n","src\u002Fusers\u002Fusers.repository.ts","ts","",[508,552,553,574,590,602,608,615,628,654,693,724,732,737,769,783,789,794,834,879,884,889,928,986,1007,1016,1021],{"__ignoreMap":550},[554,555,558,562,566,570],"span",{"class":556,"line":557},"line",1,[554,559,561],{"class":560},"s7zQu","export",[554,563,565],{"class":564},"spNyl"," interface",[554,567,569],{"class":568},"sBMFI"," User",[554,571,573],{"class":572},"sMK4o"," {\n",[554,575,577,581,584,587],{"class":556,"line":576},2,[554,578,580],{"class":579},"swJcz","  id",[554,582,583],{"class":572},":",[554,585,586],{"class":568}," string",[554,588,589],{"class":572},";\n",[554,591,593,596,598,600],{"class":556,"line":592},3,[554,594,595],{"class":579},"  name",[554,597,583],{"class":572},[554,599,586],{"class":568},[554,601,589],{"class":572},[554,603,605],{"class":556,"line":604},4,[554,606,607],{"class":572},"}\n",[554,609,611],{"class":556,"line":610},5,[554,612,614],{"emptyLinePlaceholder":613},true,"\n",[554,616,618,620,623,626],{"class":556,"line":617},6,[554,619,561],{"class":560},[554,621,622],{"class":564}," class",[554,624,625],{"class":568}," UsersRepository",[554,627,573],{"class":572},[554,629,631,634,637,640,642,644,648,651],{"class":556,"line":630},7,[554,632,633],{"class":564},"  private",[554,635,636],{"class":564}," readonly",[554,638,639],{"class":579}," users",[554,641,583],{"class":572},[554,643,569],{"class":568},[554,645,647],{"class":646},"sTEyZ","[] ",[554,649,650],{"class":572},"=",[554,652,653],{"class":646}," [\n",[554,655,657,660,663,665,668,672,675,678,681,683,685,688,690],{"class":556,"line":656},8,[554,658,659],{"class":572},"    {",[554,661,662],{"class":579}," id",[554,664,583],{"class":572},[554,666,667],{"class":572}," \"",[554,669,671],{"class":670},"sfazB","1",[554,673,674],{"class":572},"\"",[554,676,677],{"class":572},",",[554,679,680],{"class":579}," name",[554,682,583],{"class":572},[554,684,667],{"class":572},[554,686,687],{"class":670},"Alice",[554,689,674],{"class":572},[554,691,692],{"class":572}," },\n",[554,694,696,698,700,702,704,707,709,711,713,715,717,720,722],{"class":556,"line":695},9,[554,697,659],{"class":572},[554,699,662],{"class":579},[554,701,583],{"class":572},[554,703,667],{"class":572},[554,705,706],{"class":670},"2",[554,708,674],{"class":572},[554,710,677],{"class":572},[554,712,680],{"class":579},[554,714,583],{"class":572},[554,716,667],{"class":572},[554,718,719],{"class":670},"Bob",[554,721,674],{"class":572},[554,723,692],{"class":572},[554,725,727,730],{"class":556,"line":726},10,[554,728,729],{"class":646},"  ]",[554,731,589],{"class":572},[554,733,735],{"class":556,"line":734},11,[554,736,614],{"emptyLinePlaceholder":613},[554,738,740,743,746,749,752,755,758,761,764,767],{"class":556,"line":739},12,[554,741,742],{"class":564},"  public",[554,744,745],{"class":564}," async",[554,747,748],{"class":579}," list",[554,750,751],{"class":572},"():",[554,753,754],{"class":568}," Promise",[554,756,757],{"class":572},"\u003C",[554,759,760],{"class":568},"User",[554,762,763],{"class":646},"[]",[554,765,766],{"class":572},">",[554,768,573],{"class":572},[554,770,772,775,778,781],{"class":556,"line":771},13,[554,773,774],{"class":560},"    return",[554,776,777],{"class":572}," this.",[554,779,780],{"class":646},"users",[554,782,589],{"class":572},[554,784,786],{"class":556,"line":785},14,[554,787,788],{"class":572},"  }\n",[554,790,792],{"class":556,"line":791},15,[554,793,614],{"emptyLinePlaceholder":613},[554,795,797,799,801,804,807,811,813,815,818,820,822,824,827,830,832],{"class":556,"line":796},16,[554,798,742],{"class":564},[554,800,745],{"class":564},[554,802,803],{"class":579}," findById",[554,805,806],{"class":572},"(",[554,808,810],{"class":809},"sHdIc","id",[554,812,583],{"class":572},[554,814,586],{"class":568},[554,816,817],{"class":572},"):",[554,819,754],{"class":568},[554,821,757],{"class":572},[554,823,760],{"class":568},[554,825,826],{"class":572}," |",[554,828,829],{"class":568}," undefined",[554,831,766],{"class":572},[554,833,573],{"class":572},[554,835,837,839,841,843,846,850,852,854,857,860,863,866,868,870,873,875,877],{"class":556,"line":836},17,[554,838,774],{"class":560},[554,840,777],{"class":572},[554,842,780],{"class":646},[554,844,845],{"class":572},".",[554,847,849],{"class":848},"s2Zo4","find",[554,851,806],{"class":579},[554,853,806],{"class":572},[554,855,856],{"class":809},"user",[554,858,859],{"class":572},")",[554,861,862],{"class":564}," =>",[554,864,865],{"class":646}," user",[554,867,845],{"class":572},[554,869,810],{"class":646},[554,871,872],{"class":572}," ===",[554,874,662],{"class":646},[554,876,859],{"class":579},[554,878,589],{"class":572},[554,880,882],{"class":556,"line":881},18,[554,883,788],{"class":572},[554,885,887],{"class":556,"line":886},19,[554,888,614],{"emptyLinePlaceholder":613},[554,890,892,894,896,899,901,904,906,909,911,913,915,918,920,922,924,926],{"class":556,"line":891},20,[554,893,742],{"class":564},[554,895,745],{"class":564},[554,897,898],{"class":579}," create",[554,900,806],{"class":572},[554,902,903],{"class":809},"input",[554,905,583],{"class":572},[554,907,908],{"class":572}," {",[554,910,680],{"class":579},[554,912,583],{"class":572},[554,914,586],{"class":568},[554,916,917],{"class":572}," }):",[554,919,754],{"class":568},[554,921,757],{"class":572},[554,923,760],{"class":568},[554,925,766],{"class":572},[554,927,573],{"class":572},[554,929,931,934,936,939,941,943,945,948,950,953,955,957,960,963,967,969,971,973,975,978,980,983],{"class":556,"line":930},21,[554,932,933],{"class":564},"    const",[554,935,865],{"class":646},[554,937,938],{"class":572}," =",[554,940,908],{"class":572},[554,942,662],{"class":579},[554,944,583],{"class":572},[554,946,947],{"class":848}," String",[554,949,806],{"class":579},[554,951,952],{"class":572},"this.",[554,954,780],{"class":646},[554,956,845],{"class":572},[554,958,959],{"class":646},"length",[554,961,962],{"class":572}," +",[554,964,966],{"class":965},"sbssI"," 1",[554,968,859],{"class":579},[554,970,677],{"class":572},[554,972,680],{"class":579},[554,974,583],{"class":572},[554,976,977],{"class":646}," input",[554,979,845],{"class":572},[554,981,982],{"class":646},"name",[554,984,985],{"class":572}," };\n",[554,987,989,992,994,996,999,1001,1003,1005],{"class":556,"line":988},22,[554,990,991],{"class":572},"    this.",[554,993,780],{"class":646},[554,995,845],{"class":572},[554,997,998],{"class":848},"push",[554,1000,806],{"class":579},[554,1002,856],{"class":646},[554,1004,859],{"class":579},[554,1006,589],{"class":572},[554,1008,1010,1012,1014],{"class":556,"line":1009},23,[554,1011,774],{"class":560},[554,1013,865],{"class":646},[554,1015,589],{"class":572},[554,1017,1019],{"class":556,"line":1018},24,[554,1020,788],{"class":572},[554,1022,1024],{"class":556,"line":1023},25,[554,1025,607],{"class":572},[518,1027,1029],{"id":1028},"create-a-controller","Create a controller",[499,1031,1032,1033,1036,1037,1040,1041,1045,1046,1049,1050,1053],{},"A controller declares ",[508,1034,1035],{},"implements Controller\u003C\"\u002Fprefix\">"," — ",[508,1038,1039],{},"Controller"," is a marker whose type argument\ncarries the prefix, so a type-only import is all it takes. Each route is declared by its handler's ",[1042,1043,1044],"strong",{},"action\nparameter type"," (",[508,1047,1048],{},"Get\u003C\"\u002F:id\">",") — never in a separate route-config list. The ",[508,1051,1052],{},"UsersRepository"," arrives\nthrough the constructor, and the compiler resolves it by class identity.",[544,1055,1058],{"className":546,"code":1056,"filename":1057,"language":549,"meta":550,"style":550},"import type { Controller, Get } from \"@heximon\u002Fhttp\";\nimport { type User, UsersRepository } from \".\u002Fusers.repository\";\n\nexport class UsersController implements Controller\u003C\"\u002Fusers\"> {\n  constructor(private readonly users: UsersRepository) {}\n\n  \u002F\u002F GET \u002Fusers\n  public async list(_action: Get\u003C\"\u002F\">): Promise\u003CUser[]> {\n    return this.users.list();\n  }\n\n  \u002F\u002F GET \u002Fusers\u002F:id — `pathParams.id` is typed as a string from the \"\u002F:id\" literal\n  public async get(action: Get\u003C\"\u002F:id\">): Promise\u003CUser | { error: string }> {\n    const user = await this.users.findById(action.request.pathParams.id);\n    return user ?? { error: \"User not found\" };\n  }\n}\n","src\u002Fusers\u002Fusers.controller.ts",[508,1059,1060,1093,1120,1124,1151,1174,1178,1184,1225,1243,1247,1251,1256,1307,1349,1373,1377],{"__ignoreMap":550},[554,1061,1062,1065,1068,1070,1073,1075,1078,1081,1084,1086,1089,1091],{"class":556,"line":557},[554,1063,1064],{"class":560},"import",[554,1066,1067],{"class":560}," type",[554,1069,908],{"class":572},[554,1071,1072],{"class":646}," Controller",[554,1074,677],{"class":572},[554,1076,1077],{"class":646}," Get",[554,1079,1080],{"class":572}," }",[554,1082,1083],{"class":560}," from",[554,1085,667],{"class":572},[554,1087,1088],{"class":670},"@heximon\u002Fhttp",[554,1090,674],{"class":572},[554,1092,589],{"class":572},[554,1094,1095,1097,1099,1101,1103,1105,1107,1109,1111,1113,1116,1118],{"class":556,"line":576},[554,1096,1064],{"class":560},[554,1098,908],{"class":572},[554,1100,1067],{"class":560},[554,1102,569],{"class":646},[554,1104,677],{"class":572},[554,1106,625],{"class":646},[554,1108,1080],{"class":572},[554,1110,1083],{"class":560},[554,1112,667],{"class":572},[554,1114,1115],{"class":670},".\u002Fusers.repository",[554,1117,674],{"class":572},[554,1119,589],{"class":572},[554,1121,1122],{"class":556,"line":592},[554,1123,614],{"emptyLinePlaceholder":613},[554,1125,1126,1128,1130,1133,1136,1138,1140,1142,1145,1147,1149],{"class":556,"line":604},[554,1127,561],{"class":560},[554,1129,622],{"class":564},[554,1131,1132],{"class":568}," UsersController",[554,1134,1135],{"class":564}," implements",[554,1137,1072],{"class":568},[554,1139,757],{"class":572},[554,1141,674],{"class":572},[554,1143,1144],{"class":670},"\u002Fusers",[554,1146,674],{"class":572},[554,1148,766],{"class":572},[554,1150,573],{"class":572},[554,1152,1153,1156,1158,1161,1163,1165,1167,1169,1171],{"class":556,"line":610},[554,1154,1155],{"class":564},"  constructor",[554,1157,806],{"class":572},[554,1159,1160],{"class":564},"private",[554,1162,636],{"class":564},[554,1164,639],{"class":809},[554,1166,583],{"class":572},[554,1168,625],{"class":568},[554,1170,859],{"class":572},[554,1172,1173],{"class":572}," {}\n",[554,1175,1176],{"class":556,"line":617},[554,1177,614],{"emptyLinePlaceholder":613},[554,1179,1180],{"class":556,"line":630},[554,1181,1183],{"class":1182},"sHwdD","  \u002F\u002F GET \u002Fusers\n",[554,1185,1186,1188,1190,1192,1194,1197,1199,1201,1203,1205,1208,1210,1213,1215,1217,1219,1221,1223],{"class":556,"line":656},[554,1187,742],{"class":564},[554,1189,745],{"class":564},[554,1191,748],{"class":579},[554,1193,806],{"class":572},[554,1195,1196],{"class":809},"_action",[554,1198,583],{"class":572},[554,1200,1077],{"class":568},[554,1202,757],{"class":572},[554,1204,674],{"class":572},[554,1206,1207],{"class":670},"\u002F",[554,1209,674],{"class":572},[554,1211,1212],{"class":572},">):",[554,1214,754],{"class":568},[554,1216,757],{"class":572},[554,1218,760],{"class":568},[554,1220,763],{"class":646},[554,1222,766],{"class":572},[554,1224,573],{"class":572},[554,1226,1227,1229,1231,1233,1235,1238,1241],{"class":556,"line":695},[554,1228,774],{"class":560},[554,1230,777],{"class":572},[554,1232,780],{"class":646},[554,1234,845],{"class":572},[554,1236,1237],{"class":848},"list",[554,1239,1240],{"class":579},"()",[554,1242,589],{"class":572},[554,1244,1245],{"class":556,"line":726},[554,1246,788],{"class":572},[554,1248,1249],{"class":556,"line":734},[554,1250,614],{"emptyLinePlaceholder":613},[554,1252,1253],{"class":556,"line":739},[554,1254,1255],{"class":1182},"  \u002F\u002F GET \u002Fusers\u002F:id — `pathParams.id` is typed as a string from the \"\u002F:id\" literal\n",[554,1257,1258,1260,1262,1265,1267,1270,1272,1274,1276,1278,1281,1283,1285,1287,1289,1291,1293,1295,1298,1300,1302,1305],{"class":556,"line":771},[554,1259,742],{"class":564},[554,1261,745],{"class":564},[554,1263,1264],{"class":579}," get",[554,1266,806],{"class":572},[554,1268,1269],{"class":809},"action",[554,1271,583],{"class":572},[554,1273,1077],{"class":568},[554,1275,757],{"class":572},[554,1277,674],{"class":572},[554,1279,1280],{"class":670},"\u002F:id",[554,1282,674],{"class":572},[554,1284,1212],{"class":572},[554,1286,754],{"class":568},[554,1288,757],{"class":572},[554,1290,760],{"class":568},[554,1292,826],{"class":572},[554,1294,908],{"class":572},[554,1296,1297],{"class":579}," error",[554,1299,583],{"class":572},[554,1301,586],{"class":568},[554,1303,1304],{"class":572}," }>",[554,1306,573],{"class":572},[554,1308,1309,1311,1313,1315,1318,1320,1322,1324,1327,1329,1331,1333,1336,1338,1341,1343,1345,1347],{"class":556,"line":785},[554,1310,933],{"class":564},[554,1312,865],{"class":646},[554,1314,938],{"class":572},[554,1316,1317],{"class":560}," await",[554,1319,777],{"class":572},[554,1321,780],{"class":646},[554,1323,845],{"class":572},[554,1325,1326],{"class":848},"findById",[554,1328,806],{"class":579},[554,1330,1269],{"class":646},[554,1332,845],{"class":572},[554,1334,1335],{"class":646},"request",[554,1337,845],{"class":572},[554,1339,1340],{"class":646},"pathParams",[554,1342,845],{"class":572},[554,1344,810],{"class":646},[554,1346,859],{"class":579},[554,1348,589],{"class":572},[554,1350,1351,1353,1355,1358,1360,1362,1364,1366,1369,1371],{"class":556,"line":791},[554,1352,774],{"class":560},[554,1354,865],{"class":646},[554,1356,1357],{"class":572}," ??",[554,1359,908],{"class":572},[554,1361,1297],{"class":579},[554,1363,583],{"class":572},[554,1365,667],{"class":572},[554,1367,1368],{"class":670},"User not found",[554,1370,674],{"class":572},[554,1372,985],{"class":572},[554,1374,1375],{"class":556,"line":796},[554,1376,788],{"class":572},[554,1378,1379],{"class":556,"line":836},[554,1380,607],{"class":572},[499,1382,1383,1384,1386,1387,1389],{},"Delete ",[508,1385,1052],{}," from the module's ",[508,1388,541],{}," list below and save — your editor puts an error\nright on that entry, naming the unmet dependency, before you even run the compiler.",[518,1391,1393],{"id":1392},"create-a-module","Create a module",[499,1395,1396,1397,1400,1401,1403,1404,1407],{},"A module ",[508,1398,1399],{},"extends Module({...})",". It lists plain ",[508,1402,541],{}," and names the controller under the HTTP\nplugin's namespace, ",[508,1405,1406],{},"http: { controllers }",". This config is the only place the compiler looks to find\nyour concepts.",[544,1409,1412],{"className":546,"code":1410,"filename":1411,"language":549,"meta":550,"style":550},"import { Module } from \"@heximon\u002Fruntime\";\nimport { UsersController } from \".\u002Fusers.controller\";\nimport { UsersRepository } from \".\u002Fusers.repository\";\n\nexport class UsersModule extends Module({\n  providers: [UsersRepository],\n  http: { controllers: [UsersController] },\n  exports: [UsersRepository],\n}) {}\n","src\u002Fusers\u002Fusers.module.ts",[508,1413,1414,1436,1457,1477,1481,1500,1513,1533,1544],{"__ignoreMap":550},[554,1415,1416,1418,1420,1423,1425,1427,1429,1432,1434],{"class":556,"line":557},[554,1417,1064],{"class":560},[554,1419,908],{"class":572},[554,1421,1422],{"class":646}," Module",[554,1424,1080],{"class":572},[554,1426,1083],{"class":560},[554,1428,667],{"class":572},[554,1430,1431],{"class":670},"@heximon\u002Fruntime",[554,1433,674],{"class":572},[554,1435,589],{"class":572},[554,1437,1438,1440,1442,1444,1446,1448,1450,1453,1455],{"class":556,"line":576},[554,1439,1064],{"class":560},[554,1441,908],{"class":572},[554,1443,1132],{"class":646},[554,1445,1080],{"class":572},[554,1447,1083],{"class":560},[554,1449,667],{"class":572},[554,1451,1452],{"class":670},".\u002Fusers.controller",[554,1454,674],{"class":572},[554,1456,589],{"class":572},[554,1458,1459,1461,1463,1465,1467,1469,1471,1473,1475],{"class":556,"line":592},[554,1460,1064],{"class":560},[554,1462,908],{"class":572},[554,1464,625],{"class":646},[554,1466,1080],{"class":572},[554,1468,1083],{"class":560},[554,1470,667],{"class":572},[554,1472,1115],{"class":670},[554,1474,674],{"class":572},[554,1476,589],{"class":572},[554,1478,1479],{"class":556,"line":604},[554,1480,614],{"emptyLinePlaceholder":613},[554,1482,1483,1485,1487,1490,1493,1495,1497],{"class":556,"line":610},[554,1484,561],{"class":560},[554,1486,622],{"class":564},[554,1488,1489],{"class":568}," UsersModule",[554,1491,1492],{"class":564}," extends",[554,1494,1422],{"class":848},[554,1496,806],{"class":646},[554,1498,1499],{"class":572},"{\n",[554,1501,1502,1505,1507,1510],{"class":556,"line":617},[554,1503,1504],{"class":579},"  providers",[554,1506,583],{"class":572},[554,1508,1509],{"class":646}," [UsersRepository]",[554,1511,1512],{"class":572},",\n",[554,1514,1515,1518,1520,1522,1525,1527,1530],{"class":556,"line":630},[554,1516,1517],{"class":579},"  http",[554,1519,583],{"class":572},[554,1521,908],{"class":572},[554,1523,1524],{"class":579}," controllers",[554,1526,583],{"class":572},[554,1528,1529],{"class":646}," [UsersController] ",[554,1531,1532],{"class":572},"},\n",[554,1534,1535,1538,1540,1542],{"class":556,"line":656},[554,1536,1537],{"class":579},"  exports",[554,1539,583],{"class":572},[554,1541,1509],{"class":646},[554,1543,1512],{"class":572},[554,1545,1546,1549,1552],{"class":556,"line":695},[554,1547,1548],{"class":572},"}",[554,1550,1551],{"class":646},") ",[554,1553,1554],{"class":572},"{}\n",[499,1556,1557,1558,1561],{},"A root module composes feature modules with ",[508,1559,1560],{},"imports"," — the single root module (the one no other module\nimports) is auto-discovered as your app:",[544,1563,1566],{"className":546,"code":1564,"filename":1565,"language":549,"meta":550,"style":550},"import { Module } from \"@heximon\u002Fruntime\";\nimport { UsersModule } from \".\u002Fusers\u002Fusers.module\";\n\nexport class AppModule extends Module({\n  imports: [UsersModule],\n}) {}\n","src\u002Fapp.module.ts",[508,1567,1568,1588,1609,1613,1630,1642],{"__ignoreMap":550},[554,1569,1570,1572,1574,1576,1578,1580,1582,1584,1586],{"class":556,"line":557},[554,1571,1064],{"class":560},[554,1573,908],{"class":572},[554,1575,1422],{"class":646},[554,1577,1080],{"class":572},[554,1579,1083],{"class":560},[554,1581,667],{"class":572},[554,1583,1431],{"class":670},[554,1585,674],{"class":572},[554,1587,589],{"class":572},[554,1589,1590,1592,1594,1596,1598,1600,1602,1605,1607],{"class":556,"line":576},[554,1591,1064],{"class":560},[554,1593,908],{"class":572},[554,1595,1489],{"class":646},[554,1597,1080],{"class":572},[554,1599,1083],{"class":560},[554,1601,667],{"class":572},[554,1603,1604],{"class":670},".\u002Fusers\u002Fusers.module",[554,1606,674],{"class":572},[554,1608,589],{"class":572},[554,1610,1611],{"class":556,"line":592},[554,1612,614],{"emptyLinePlaceholder":613},[554,1614,1615,1617,1619,1622,1624,1626,1628],{"class":556,"line":604},[554,1616,561],{"class":560},[554,1618,622],{"class":564},[554,1620,1621],{"class":568}," AppModule",[554,1623,1492],{"class":564},[554,1625,1422],{"class":848},[554,1627,806],{"class":646},[554,1629,1499],{"class":572},[554,1631,1632,1635,1637,1640],{"class":556,"line":610},[554,1633,1634],{"class":579},"  imports",[554,1636,583],{"class":572},[554,1638,1639],{"class":646}," [UsersModule]",[554,1641,1512],{"class":572},[554,1643,1644,1646,1648],{"class":556,"line":617},[554,1645,1548],{"class":572},[554,1647,1551],{"class":646},[554,1649,1554],{"class":572},[518,1651,1653],{"id":1652},"run-it","Run it",[1655,1656,1657,1672,1687,1701],"code-group",{},[544,1658,1663],{"className":1659,"code":1660,"filename":1661,"language":1662,"meta":550,"style":550},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","pnpm dev\n","pnpm","bash",[508,1664,1665],{"__ignoreMap":550},[554,1666,1667,1669],{"class":556,"line":557},[554,1668,1661],{"class":568},[554,1670,1671],{"class":670}," dev\n",[544,1673,1676],{"className":1659,"code":1674,"filename":1675,"language":1662,"meta":550,"style":550},"npm run dev\n","npm",[508,1677,1678],{"__ignoreMap":550},[554,1679,1680,1682,1685],{"class":556,"line":557},[554,1681,1675],{"class":568},[554,1683,1684],{"class":670}," run",[554,1686,1671],{"class":670},[544,1688,1691],{"className":1659,"code":1689,"filename":1690,"language":1662,"meta":550,"style":550},"yarn run dev\n","yarn",[508,1692,1693],{"__ignoreMap":550},[554,1694,1695,1697,1699],{"class":556,"line":557},[554,1696,1690],{"class":568},[554,1698,1684],{"class":670},[554,1700,1671],{"class":670},[544,1702,1705],{"className":1659,"code":1703,"filename":1704,"language":1662,"meta":550,"style":550},"bun run dev\n","bun",[508,1706,1707],{"__ignoreMap":550},[554,1708,1709,1711,1713],{"class":556,"line":557},[554,1710,1704],{"class":568},[554,1712,1684],{"class":670},[554,1714,1671],{"class":670},[544,1716,1719],{"className":1659,"code":1717,"filename":1718,"language":1662,"meta":550,"style":550},"curl http:\u002F\u002Flocalhost:3000\u002Fusers\n# → [{ \"id\": \"1\", \"name\": \"Alice\" }, { \"id\": \"2\", \"name\": \"Bob\" }]\n\ncurl http:\u002F\u002Flocalhost:3000\u002Fusers\u002F2\n# → { \"id\": \"2\", \"name\": \"Bob\" }\n","terminal",[508,1720,1721,1729,1734,1738,1745],{"__ignoreMap":550},[554,1722,1723,1726],{"class":556,"line":557},[554,1724,1725],{"class":568},"curl",[554,1727,1728],{"class":670}," http:\u002F\u002Flocalhost:3000\u002Fusers\n",[554,1730,1731],{"class":556,"line":576},[554,1732,1733],{"class":1182},"# → [{ \"id\": \"1\", \"name\": \"Alice\" }, { \"id\": \"2\", \"name\": \"Bob\" }]\n",[554,1735,1736],{"class":556,"line":592},[554,1737,614],{"emptyLinePlaceholder":613},[554,1739,1740,1742],{"class":556,"line":604},[554,1741,1725],{"class":568},[554,1743,1744],{"class":670}," http:\u002F\u002Flocalhost:3000\u002Fusers\u002F2\n",[554,1746,1747],{"class":556,"line":610},[554,1748,1749],{"class":1182},"# → { \"id\": \"2\", \"name\": \"Bob\" }\n",[499,1751,1752,1753,1756],{},"The dev server compiles ",[508,1754,1755],{},"src\u002F"," to wiring in memory, serves the generated app, and recompiles on every\nsource change — no entry file, no bootstrap, nothing to restart.",[518,1758,1760],{"id":1759},"validate-a-request","Validate a request",[499,1762,1763,1764,1767,1768,1771],{},"Author a DTO as a ",[508,1765,1766],{},"SchemaObject"," class and reference it directly in the route's schema slot. The compiler\nturns that one declaration into both the static parameter type and the runtime validator — an invalid\nbody is rejected with a ",[508,1769,1770],{},"400 application\u002Fproblem+json"," before your handler runs.",[544,1773,1776],{"className":546,"code":1774,"filename":1775,"language":549,"meta":550,"style":550},"import { SchemaObject } from \"@heximon\u002Fschema\";\nimport { z } from \"zod\";\n\nexport class CreateUser extends SchemaObject({\n  name: z.string().min(1),\n  email: z.email(),\n}) {}\n","src\u002Fusers\u002Fuser.schema.ts",[508,1777,1778,1800,1822,1826,1843,1871,1889],{"__ignoreMap":550},[554,1779,1780,1782,1784,1787,1789,1791,1793,1796,1798],{"class":556,"line":557},[554,1781,1064],{"class":560},[554,1783,908],{"class":572},[554,1785,1786],{"class":646}," SchemaObject",[554,1788,1080],{"class":572},[554,1790,1083],{"class":560},[554,1792,667],{"class":572},[554,1794,1795],{"class":670},"@heximon\u002Fschema",[554,1797,674],{"class":572},[554,1799,589],{"class":572},[554,1801,1802,1804,1806,1809,1811,1813,1815,1818,1820],{"class":556,"line":576},[554,1803,1064],{"class":560},[554,1805,908],{"class":572},[554,1807,1808],{"class":646}," z",[554,1810,1080],{"class":572},[554,1812,1083],{"class":560},[554,1814,667],{"class":572},[554,1816,1817],{"class":670},"zod",[554,1819,674],{"class":572},[554,1821,589],{"class":572},[554,1823,1824],{"class":556,"line":592},[554,1825,614],{"emptyLinePlaceholder":613},[554,1827,1828,1830,1832,1835,1837,1839,1841],{"class":556,"line":604},[554,1829,561],{"class":560},[554,1831,622],{"class":564},[554,1833,1834],{"class":568}," CreateUser",[554,1836,1492],{"class":564},[554,1838,1786],{"class":848},[554,1840,806],{"class":646},[554,1842,1499],{"class":572},[554,1844,1845,1847,1849,1851,1853,1856,1858,1860,1863,1865,1867,1869],{"class":556,"line":610},[554,1846,595],{"class":579},[554,1848,583],{"class":572},[554,1850,1808],{"class":646},[554,1852,845],{"class":572},[554,1854,1855],{"class":848},"string",[554,1857,1240],{"class":646},[554,1859,845],{"class":572},[554,1861,1862],{"class":848},"min",[554,1864,806],{"class":646},[554,1866,671],{"class":965},[554,1868,859],{"class":646},[554,1870,1512],{"class":572},[554,1872,1873,1876,1878,1880,1882,1885,1887],{"class":556,"line":617},[554,1874,1875],{"class":579},"  email",[554,1877,583],{"class":572},[554,1879,1808],{"class":646},[554,1881,845],{"class":572},[554,1883,1884],{"class":848},"email",[554,1886,1240],{"class":646},[554,1888,1512],{"class":572},[554,1890,1891,1893,1895],{"class":556,"line":630},[554,1892,1548],{"class":572},[554,1894,1551],{"class":646},[554,1896,1554],{"class":572},[544,1898,1900],{"className":546,"code":1899,"filename":1057,"language":549,"meta":550,"style":550},"import type { Controller, Get, Post } from \"@heximon\u002Fhttp\";\nimport { CreateUser } from \".\u002Fuser.schema\";\nimport { type User, UsersRepository } from \".\u002Fusers.repository\";\n\nexport class UsersController implements Controller\u003C\"\u002Fusers\"> {\n  constructor(private readonly users: UsersRepository) {}\n\n  public async list(_action: Get\u003C\"\u002F\">): Promise\u003CUser[]> {\n    return this.users.list();\n  }\n\n  \u002F\u002F POST \u002Fusers — body validated against `CreateUser` before the handler runs\n  public async create(action: Post\u003C\"\u002F\", { body: CreateUser }>): Promise\u003CUser> {\n    const body = await action.request.readValidatedBody(); \u002F\u002F invalid → built-in 400\n    return this.users.create(body);\n  }\n}\n",[508,1901,1902,1933,1954,1980,1984,2008,2028,2032,2070,2086,2090,2094,2099,2147,2177,2199,2203],{"__ignoreMap":550},[554,1903,1904,1906,1908,1910,1912,1914,1916,1918,1921,1923,1925,1927,1929,1931],{"class":556,"line":557},[554,1905,1064],{"class":560},[554,1907,1067],{"class":560},[554,1909,908],{"class":572},[554,1911,1072],{"class":646},[554,1913,677],{"class":572},[554,1915,1077],{"class":646},[554,1917,677],{"class":572},[554,1919,1920],{"class":646}," Post",[554,1922,1080],{"class":572},[554,1924,1083],{"class":560},[554,1926,667],{"class":572},[554,1928,1088],{"class":670},[554,1930,674],{"class":572},[554,1932,589],{"class":572},[554,1934,1935,1937,1939,1941,1943,1945,1947,1950,1952],{"class":556,"line":576},[554,1936,1064],{"class":560},[554,1938,908],{"class":572},[554,1940,1834],{"class":646},[554,1942,1080],{"class":572},[554,1944,1083],{"class":560},[554,1946,667],{"class":572},[554,1948,1949],{"class":670},".\u002Fuser.schema",[554,1951,674],{"class":572},[554,1953,589],{"class":572},[554,1955,1956,1958,1960,1962,1964,1966,1968,1970,1972,1974,1976,1978],{"class":556,"line":592},[554,1957,1064],{"class":560},[554,1959,908],{"class":572},[554,1961,1067],{"class":560},[554,1963,569],{"class":646},[554,1965,677],{"class":572},[554,1967,625],{"class":646},[554,1969,1080],{"class":572},[554,1971,1083],{"class":560},[554,1973,667],{"class":572},[554,1975,1115],{"class":670},[554,1977,674],{"class":572},[554,1979,589],{"class":572},[554,1981,1982],{"class":556,"line":604},[554,1983,614],{"emptyLinePlaceholder":613},[554,1985,1986,1988,1990,1992,1994,1996,1998,2000,2002,2004,2006],{"class":556,"line":610},[554,1987,561],{"class":560},[554,1989,622],{"class":564},[554,1991,1132],{"class":568},[554,1993,1135],{"class":564},[554,1995,1072],{"class":568},[554,1997,757],{"class":572},[554,1999,674],{"class":572},[554,2001,1144],{"class":670},[554,2003,674],{"class":572},[554,2005,766],{"class":572},[554,2007,573],{"class":572},[554,2009,2010,2012,2014,2016,2018,2020,2022,2024,2026],{"class":556,"line":617},[554,2011,1155],{"class":564},[554,2013,806],{"class":572},[554,2015,1160],{"class":564},[554,2017,636],{"class":564},[554,2019,639],{"class":809},[554,2021,583],{"class":572},[554,2023,625],{"class":568},[554,2025,859],{"class":572},[554,2027,1173],{"class":572},[554,2029,2030],{"class":556,"line":630},[554,2031,614],{"emptyLinePlaceholder":613},[554,2033,2034,2036,2038,2040,2042,2044,2046,2048,2050,2052,2054,2056,2058,2060,2062,2064,2066,2068],{"class":556,"line":656},[554,2035,742],{"class":564},[554,2037,745],{"class":564},[554,2039,748],{"class":579},[554,2041,806],{"class":572},[554,2043,1196],{"class":809},[554,2045,583],{"class":572},[554,2047,1077],{"class":568},[554,2049,757],{"class":572},[554,2051,674],{"class":572},[554,2053,1207],{"class":670},[554,2055,674],{"class":572},[554,2057,1212],{"class":572},[554,2059,754],{"class":568},[554,2061,757],{"class":572},[554,2063,760],{"class":568},[554,2065,763],{"class":646},[554,2067,766],{"class":572},[554,2069,573],{"class":572},[554,2071,2072,2074,2076,2078,2080,2082,2084],{"class":556,"line":695},[554,2073,774],{"class":560},[554,2075,777],{"class":572},[554,2077,780],{"class":646},[554,2079,845],{"class":572},[554,2081,1237],{"class":848},[554,2083,1240],{"class":579},[554,2085,589],{"class":572},[554,2087,2088],{"class":556,"line":726},[554,2089,788],{"class":572},[554,2091,2092],{"class":556,"line":734},[554,2093,614],{"emptyLinePlaceholder":613},[554,2095,2096],{"class":556,"line":739},[554,2097,2098],{"class":1182},"  \u002F\u002F POST \u002Fusers — body validated against `CreateUser` before the handler runs\n",[554,2100,2101,2103,2105,2107,2109,2111,2113,2115,2117,2119,2121,2123,2125,2127,2130,2132,2134,2137,2139,2141,2143,2145],{"class":556,"line":771},[554,2102,742],{"class":564},[554,2104,745],{"class":564},[554,2106,898],{"class":579},[554,2108,806],{"class":572},[554,2110,1269],{"class":809},[554,2112,583],{"class":572},[554,2114,1920],{"class":568},[554,2116,757],{"class":572},[554,2118,674],{"class":572},[554,2120,1207],{"class":670},[554,2122,674],{"class":572},[554,2124,677],{"class":572},[554,2126,908],{"class":572},[554,2128,2129],{"class":579}," body",[554,2131,583],{"class":572},[554,2133,1834],{"class":568},[554,2135,2136],{"class":572}," }>):",[554,2138,754],{"class":568},[554,2140,757],{"class":572},[554,2142,760],{"class":568},[554,2144,766],{"class":572},[554,2146,573],{"class":572},[554,2148,2149,2151,2153,2155,2157,2160,2162,2164,2166,2169,2171,2174],{"class":556,"line":785},[554,2150,933],{"class":564},[554,2152,2129],{"class":646},[554,2154,938],{"class":572},[554,2156,1317],{"class":560},[554,2158,2159],{"class":646}," action",[554,2161,845],{"class":572},[554,2163,1335],{"class":646},[554,2165,845],{"class":572},[554,2167,2168],{"class":848},"readValidatedBody",[554,2170,1240],{"class":579},[554,2172,2173],{"class":572},";",[554,2175,2176],{"class":1182}," \u002F\u002F invalid → built-in 400\n",[554,2178,2179,2181,2183,2185,2187,2190,2192,2195,2197],{"class":556,"line":791},[554,2180,774],{"class":560},[554,2182,777],{"class":572},[554,2184,780],{"class":646},[554,2186,845],{"class":572},[554,2188,2189],{"class":848},"create",[554,2191,806],{"class":579},[554,2193,2194],{"class":646},"body",[554,2196,859],{"class":579},[554,2198,589],{"class":572},[554,2200,2201],{"class":556,"line":796},[554,2202,788],{"class":572},[554,2204,2205],{"class":556,"line":836},[554,2206,607],{"class":572},[544,2208,2210],{"className":1659,"code":2209,"filename":1718,"language":1662,"meta":550,"style":550},"curl -X POST http:\u002F\u002Flocalhost:3000\u002Fusers -H \"content-type: application\u002Fjson\" -d '{\"name\": \"\"}'\n# → 400 application\u002Fproblem+json — \"name\" is empty, \"email\" is missing\n",[508,2211,2212,2247],{"__ignoreMap":550},[554,2213,2214,2216,2219,2222,2225,2228,2230,2233,2235,2238,2241,2244],{"class":556,"line":557},[554,2215,1725],{"class":568},[554,2217,2218],{"class":670}," -X",[554,2220,2221],{"class":670}," POST",[554,2223,2224],{"class":670}," http:\u002F\u002Flocalhost:3000\u002Fusers",[554,2226,2227],{"class":670}," -H",[554,2229,667],{"class":572},[554,2231,2232],{"class":670},"content-type: application\u002Fjson",[554,2234,674],{"class":572},[554,2236,2237],{"class":670}," -d",[554,2239,2240],{"class":572}," '",[554,2242,2243],{"class":670},"{\"name\": \"\"}",[554,2245,2246],{"class":572},"'\n",[554,2248,2249],{"class":556,"line":576},[554,2250,2251],{"class":1182},"# → 400 application\u002Fproblem+json — \"name\" is empty, \"email\" is missing\n",[518,2253,2255],{"id":2254},"write-your-first-test","Write your first test",[499,2257,2258],{},"A provider is a plain class, so it's a plain constructor call in a test — no compiler, no running server.",[544,2260,2263],{"className":546,"code":2261,"filename":2262,"language":549,"meta":550,"style":550},"import { expect, test } from \"vitest\";\nimport { UsersRepository } from \"..\u002Fsrc\u002Fusers\u002Fusers.repository\";\n\ntest(\"UsersRepository lists seeded users\", async () => {\n  const repo = new UsersRepository();\n  const users = await repo.list();\n  expect(users).toHaveLength(2);\n  expect(users[0]?.name).toBe(\"Alice\");\n});\n\ntest(\"UsersRepository finds a user by id\", async () => {\n  const repo = new UsersRepository();\n  expect(await repo.findById(\"2\")).toEqual({ id: \"2\", name: \"Bob\" });\n  expect(await repo.findById(\"999\")).toBeUndefined();\n});\n","test\u002Fusers.test.ts",[508,2264,2265,2292,2313,2317,2342,2361,2381,2405,2446,2454,2458,2481,2497,2561,2595],{"__ignoreMap":550},[554,2266,2267,2269,2271,2274,2276,2279,2281,2283,2285,2288,2290],{"class":556,"line":557},[554,2268,1064],{"class":560},[554,2270,908],{"class":572},[554,2272,2273],{"class":646}," expect",[554,2275,677],{"class":572},[554,2277,2278],{"class":646}," test",[554,2280,1080],{"class":572},[554,2282,1083],{"class":560},[554,2284,667],{"class":572},[554,2286,2287],{"class":670},"vitest",[554,2289,674],{"class":572},[554,2291,589],{"class":572},[554,2293,2294,2296,2298,2300,2302,2304,2306,2309,2311],{"class":556,"line":576},[554,2295,1064],{"class":560},[554,2297,908],{"class":572},[554,2299,625],{"class":646},[554,2301,1080],{"class":572},[554,2303,1083],{"class":560},[554,2305,667],{"class":572},[554,2307,2308],{"class":670},"..\u002Fsrc\u002Fusers\u002Fusers.repository",[554,2310,674],{"class":572},[554,2312,589],{"class":572},[554,2314,2315],{"class":556,"line":592},[554,2316,614],{"emptyLinePlaceholder":613},[554,2318,2319,2322,2324,2326,2329,2331,2333,2335,2338,2340],{"class":556,"line":604},[554,2320,2321],{"class":848},"test",[554,2323,806],{"class":646},[554,2325,674],{"class":572},[554,2327,2328],{"class":670},"UsersRepository lists seeded users",[554,2330,674],{"class":572},[554,2332,677],{"class":572},[554,2334,745],{"class":564},[554,2336,2337],{"class":572}," ()",[554,2339,862],{"class":564},[554,2341,573],{"class":572},[554,2343,2344,2347,2350,2352,2355,2357,2359],{"class":556,"line":610},[554,2345,2346],{"class":564},"  const",[554,2348,2349],{"class":646}," repo",[554,2351,938],{"class":572},[554,2353,2354],{"class":572}," new",[554,2356,625],{"class":848},[554,2358,1240],{"class":579},[554,2360,589],{"class":572},[554,2362,2363,2365,2367,2369,2371,2373,2375,2377,2379],{"class":556,"line":617},[554,2364,2346],{"class":564},[554,2366,639],{"class":646},[554,2368,938],{"class":572},[554,2370,1317],{"class":560},[554,2372,2349],{"class":646},[554,2374,845],{"class":572},[554,2376,1237],{"class":848},[554,2378,1240],{"class":579},[554,2380,589],{"class":572},[554,2382,2383,2386,2388,2390,2392,2394,2397,2399,2401,2403],{"class":556,"line":630},[554,2384,2385],{"class":848},"  expect",[554,2387,806],{"class":579},[554,2389,780],{"class":646},[554,2391,859],{"class":579},[554,2393,845],{"class":572},[554,2395,2396],{"class":848},"toHaveLength",[554,2398,806],{"class":579},[554,2400,706],{"class":965},[554,2402,859],{"class":579},[554,2404,589],{"class":572},[554,2406,2407,2409,2411,2413,2416,2419,2422,2425,2427,2429,2431,2434,2436,2438,2440,2442,2444],{"class":556,"line":656},[554,2408,2385],{"class":848},[554,2410,806],{"class":579},[554,2412,780],{"class":646},[554,2414,2415],{"class":579},"[",[554,2417,2418],{"class":965},"0",[554,2420,2421],{"class":579},"]",[554,2423,2424],{"class":572},"?.",[554,2426,982],{"class":646},[554,2428,859],{"class":579},[554,2430,845],{"class":572},[554,2432,2433],{"class":848},"toBe",[554,2435,806],{"class":579},[554,2437,674],{"class":572},[554,2439,687],{"class":670},[554,2441,674],{"class":572},[554,2443,859],{"class":579},[554,2445,589],{"class":572},[554,2447,2448,2450,2452],{"class":556,"line":695},[554,2449,1548],{"class":572},[554,2451,859],{"class":646},[554,2453,589],{"class":572},[554,2455,2456],{"class":556,"line":726},[554,2457,614],{"emptyLinePlaceholder":613},[554,2459,2460,2462,2464,2466,2469,2471,2473,2475,2477,2479],{"class":556,"line":734},[554,2461,2321],{"class":848},[554,2463,806],{"class":646},[554,2465,674],{"class":572},[554,2467,2468],{"class":670},"UsersRepository finds a user by id",[554,2470,674],{"class":572},[554,2472,677],{"class":572},[554,2474,745],{"class":564},[554,2476,2337],{"class":572},[554,2478,862],{"class":564},[554,2480,573],{"class":572},[554,2482,2483,2485,2487,2489,2491,2493,2495],{"class":556,"line":739},[554,2484,2346],{"class":564},[554,2486,2349],{"class":646},[554,2488,938],{"class":572},[554,2490,2354],{"class":572},[554,2492,625],{"class":848},[554,2494,1240],{"class":579},[554,2496,589],{"class":572},[554,2498,2499,2501,2503,2506,2508,2510,2512,2514,2516,2518,2520,2523,2525,2528,2530,2533,2535,2537,2539,2541,2543,2545,2547,2549,2551,2553,2555,2557,2559],{"class":556,"line":771},[554,2500,2385],{"class":848},[554,2502,806],{"class":579},[554,2504,2505],{"class":560},"await",[554,2507,2349],{"class":646},[554,2509,845],{"class":572},[554,2511,1326],{"class":848},[554,2513,806],{"class":579},[554,2515,674],{"class":572},[554,2517,706],{"class":670},[554,2519,674],{"class":572},[554,2521,2522],{"class":579},"))",[554,2524,845],{"class":572},[554,2526,2527],{"class":848},"toEqual",[554,2529,806],{"class":579},[554,2531,2532],{"class":572},"{",[554,2534,662],{"class":579},[554,2536,583],{"class":572},[554,2538,667],{"class":572},[554,2540,706],{"class":670},[554,2542,674],{"class":572},[554,2544,677],{"class":572},[554,2546,680],{"class":579},[554,2548,583],{"class":572},[554,2550,667],{"class":572},[554,2552,719],{"class":670},[554,2554,674],{"class":572},[554,2556,1080],{"class":572},[554,2558,859],{"class":579},[554,2560,589],{"class":572},[554,2562,2563,2565,2567,2569,2571,2573,2575,2577,2579,2582,2584,2586,2588,2591,2593],{"class":556,"line":785},[554,2564,2385],{"class":848},[554,2566,806],{"class":579},[554,2568,2505],{"class":560},[554,2570,2349],{"class":646},[554,2572,845],{"class":572},[554,2574,1326],{"class":848},[554,2576,806],{"class":579},[554,2578,674],{"class":572},[554,2580,2581],{"class":670},"999",[554,2583,674],{"class":572},[554,2585,2522],{"class":579},[554,2587,845],{"class":572},[554,2589,2590],{"class":848},"toBeUndefined",[554,2592,1240],{"class":579},[554,2594,589],{"class":572},[554,2596,2597,2599,2601],{"class":556,"line":791},[554,2598,1548],{"class":572},[554,2600,859],{"class":646},[554,2602,589],{"class":572},[544,2604,2606],{"className":1659,"code":2605,"filename":1718,"language":1662,"meta":550,"style":550},"vitest --run\n# ✓ test\u002Fusers.test.ts (2 tests)\n",[508,2607,2608,2615],{"__ignoreMap":550},[554,2609,2610,2612],{"class":556,"line":557},[554,2611,2287],{"class":568},[554,2613,2614],{"class":670}," --run\n",[554,2616,2617],{"class":556,"line":576},[554,2618,2619],{"class":1182},"# ✓ test\u002Fusers.test.ts (2 tests)\n",[499,2621,2622,2623,2626,2627,845],{},"A controller takes the same shape — construct it with a fake repository and call its methods directly.\nThe full story, including in-process HTTP tests via ",[508,2624,2625],{},"createTestApp",", is on ",[513,2628,2629],{"href":112},"Testing",[518,2631,2633],{"id":2632},"make-it-type-safe-with-a-contract","Make it type-safe with a contract",[499,2635,2636,2637,2640,2641,2644],{},"The controller above works, but a client has no way to know the shape of a response without duplicating\nit. A ",[508,2638,2639],{},"Contract"," lets you ",[1042,2642,2643],{},"define the API once"," and bind both the server and a client to the same value.",[2646,2647,2649],"h3",{"id":2648},"define-the-contract","Define the contract",[544,2651,2654],{"className":546,"code":2652,"filename":2653,"language":549,"meta":550,"style":550},"import { Contract, Route } from \"@heximon\u002Fcontract\";\nimport { z } from \"zod\";\nimport { CreateUser } from \".\u002Fuser.schema\";\n\nconst user = z.object({ id: z.string(), name: z.string() });\n\nexport class UsersApi extends Contract({\n  prefix: \"\u002Fusers\",\n  routes: {\n    list: Route.get(\"\u002F\").summary(\"List users\").responses({ 200: z.array(user) }),\n    create: Route.post(\"\u002F\").body(CreateUser).responses({ 201: user }),\n  },\n}) {}\n","src\u002Fusers\u002Fusers.api.ts",[508,2655,2656,2683,2703,2723,2727,2781,2785,2802,2817,2826,2896,2948,2953],{"__ignoreMap":550},[554,2657,2658,2660,2662,2665,2667,2670,2672,2674,2676,2679,2681],{"class":556,"line":557},[554,2659,1064],{"class":560},[554,2661,908],{"class":572},[554,2663,2664],{"class":646}," Contract",[554,2666,677],{"class":572},[554,2668,2669],{"class":646}," Route",[554,2671,1080],{"class":572},[554,2673,1083],{"class":560},[554,2675,667],{"class":572},[554,2677,2678],{"class":670},"@heximon\u002Fcontract",[554,2680,674],{"class":572},[554,2682,589],{"class":572},[554,2684,2685,2687,2689,2691,2693,2695,2697,2699,2701],{"class":556,"line":576},[554,2686,1064],{"class":560},[554,2688,908],{"class":572},[554,2690,1808],{"class":646},[554,2692,1080],{"class":572},[554,2694,1083],{"class":560},[554,2696,667],{"class":572},[554,2698,1817],{"class":670},[554,2700,674],{"class":572},[554,2702,589],{"class":572},[554,2704,2705,2707,2709,2711,2713,2715,2717,2719,2721],{"class":556,"line":592},[554,2706,1064],{"class":560},[554,2708,908],{"class":572},[554,2710,1834],{"class":646},[554,2712,1080],{"class":572},[554,2714,1083],{"class":560},[554,2716,667],{"class":572},[554,2718,1949],{"class":670},[554,2720,674],{"class":572},[554,2722,589],{"class":572},[554,2724,2725],{"class":556,"line":604},[554,2726,614],{"emptyLinePlaceholder":613},[554,2728,2729,2732,2735,2737,2739,2741,2744,2746,2748,2750,2752,2754,2756,2758,2760,2762,2764,2766,2768,2770,2772,2775,2777,2779],{"class":556,"line":610},[554,2730,2731],{"class":564},"const",[554,2733,2734],{"class":646}," user ",[554,2736,650],{"class":572},[554,2738,1808],{"class":646},[554,2740,845],{"class":572},[554,2742,2743],{"class":848},"object",[554,2745,806],{"class":646},[554,2747,2532],{"class":572},[554,2749,662],{"class":579},[554,2751,583],{"class":572},[554,2753,1808],{"class":646},[554,2755,845],{"class":572},[554,2757,1855],{"class":848},[554,2759,1240],{"class":646},[554,2761,677],{"class":572},[554,2763,680],{"class":579},[554,2765,583],{"class":572},[554,2767,1808],{"class":646},[554,2769,845],{"class":572},[554,2771,1855],{"class":848},[554,2773,2774],{"class":646},"() ",[554,2776,1548],{"class":572},[554,2778,859],{"class":646},[554,2780,589],{"class":572},[554,2782,2783],{"class":556,"line":617},[554,2784,614],{"emptyLinePlaceholder":613},[554,2786,2787,2789,2791,2794,2796,2798,2800],{"class":556,"line":630},[554,2788,561],{"class":560},[554,2790,622],{"class":564},[554,2792,2793],{"class":568}," UsersApi",[554,2795,1492],{"class":564},[554,2797,2664],{"class":848},[554,2799,806],{"class":646},[554,2801,1499],{"class":572},[554,2803,2804,2807,2809,2811,2813,2815],{"class":556,"line":656},[554,2805,2806],{"class":579},"  prefix",[554,2808,583],{"class":572},[554,2810,667],{"class":572},[554,2812,1144],{"class":670},[554,2814,674],{"class":572},[554,2816,1512],{"class":572},[554,2818,2819,2822,2824],{"class":556,"line":695},[554,2820,2821],{"class":579},"  routes",[554,2823,583],{"class":572},[554,2825,573],{"class":572},[554,2827,2828,2831,2833,2835,2837,2840,2842,2844,2846,2848,2850,2852,2855,2857,2859,2862,2864,2866,2868,2871,2873,2875,2878,2880,2882,2884,2887,2890,2892,2894],{"class":556,"line":726},[554,2829,2830],{"class":579},"    list",[554,2832,583],{"class":572},[554,2834,2669],{"class":646},[554,2836,845],{"class":572},[554,2838,2839],{"class":848},"get",[554,2841,806],{"class":646},[554,2843,674],{"class":572},[554,2845,1207],{"class":670},[554,2847,674],{"class":572},[554,2849,859],{"class":646},[554,2851,845],{"class":572},[554,2853,2854],{"class":848},"summary",[554,2856,806],{"class":646},[554,2858,674],{"class":572},[554,2860,2861],{"class":670},"List users",[554,2863,674],{"class":572},[554,2865,859],{"class":646},[554,2867,845],{"class":572},[554,2869,2870],{"class":848},"responses",[554,2872,806],{"class":646},[554,2874,2532],{"class":572},[554,2876,2877],{"class":965}," 200",[554,2879,583],{"class":572},[554,2881,1808],{"class":646},[554,2883,845],{"class":572},[554,2885,2886],{"class":848},"array",[554,2888,2889],{"class":646},"(user) ",[554,2891,1548],{"class":572},[554,2893,859],{"class":646},[554,2895,1512],{"class":572},[554,2897,2898,2901,2903,2905,2907,2910,2912,2914,2916,2918,2920,2922,2924,2927,2929,2931,2933,2935,2938,2940,2942,2944,2946],{"class":556,"line":734},[554,2899,2900],{"class":579},"    create",[554,2902,583],{"class":572},[554,2904,2669],{"class":646},[554,2906,845],{"class":572},[554,2908,2909],{"class":848},"post",[554,2911,806],{"class":646},[554,2913,674],{"class":572},[554,2915,1207],{"class":670},[554,2917,674],{"class":572},[554,2919,859],{"class":646},[554,2921,845],{"class":572},[554,2923,2194],{"class":848},[554,2925,2926],{"class":646},"(CreateUser)",[554,2928,845],{"class":572},[554,2930,2870],{"class":848},[554,2932,806],{"class":646},[554,2934,2532],{"class":572},[554,2936,2937],{"class":965}," 201",[554,2939,583],{"class":572},[554,2941,2734],{"class":646},[554,2943,1548],{"class":572},[554,2945,859],{"class":646},[554,2947,1512],{"class":572},[554,2949,2950],{"class":556,"line":739},[554,2951,2952],{"class":572},"  },\n",[554,2954,2955,2957,2959],{"class":556,"line":771},[554,2956,1548],{"class":572},[554,2958,1551],{"class":646},[554,2960,1554],{"class":572},[2646,2962,2964],{"id":2963},"bind-the-contract-to-the-controller","Bind the contract to the controller",[499,2966,2967,2968,2971,2972,845],{},"A contract-mode controller names the contract as the type argument — ",[508,2969,2970],{},"implements Controller\u003CUsersApi>"," —\nand the contract carries its own prefix. Handler method names match the route keys, and each action is\ntyped off its route with ",[508,2973,2974],{},"Action\u003CUsersApi, \"key\">",[544,2976,2978],{"className":546,"code":2977,"filename":1057,"language":549,"meta":550,"style":550},"import type { Action, Controller } from \"@heximon\u002Fhttp\";\nimport { UsersApi } from \".\u002Fusers.api\";\nimport { UsersRepository } from \".\u002Fusers.repository\";\n\nexport class UsersController implements Controller\u003CUsersApi> {\n  constructor(private readonly users: UsersRepository) {}\n\n  public async list(action: Action\u003CUsersApi, \"list\">) {\n    return this.users.list();\n  }\n\n  public async create(action: Action\u003CUsersApi, \"create\">) {\n    const body = await action.request.readValidatedBody();\n    return action.respond(201, await this.users.create(body));\n  }\n}\n",[508,2979,2980,3007,3028,3048,3052,3073,3093,3097,3130,3146,3150,3154,3186,3210,3246,3250],{"__ignoreMap":550},[554,2981,2982,2984,2986,2988,2991,2993,2995,2997,2999,3001,3003,3005],{"class":556,"line":557},[554,2983,1064],{"class":560},[554,2985,1067],{"class":560},[554,2987,908],{"class":572},[554,2989,2990],{"class":646}," Action",[554,2992,677],{"class":572},[554,2994,1072],{"class":646},[554,2996,1080],{"class":572},[554,2998,1083],{"class":560},[554,3000,667],{"class":572},[554,3002,1088],{"class":670},[554,3004,674],{"class":572},[554,3006,589],{"class":572},[554,3008,3009,3011,3013,3015,3017,3019,3021,3024,3026],{"class":556,"line":576},[554,3010,1064],{"class":560},[554,3012,908],{"class":572},[554,3014,2793],{"class":646},[554,3016,1080],{"class":572},[554,3018,1083],{"class":560},[554,3020,667],{"class":572},[554,3022,3023],{"class":670},".\u002Fusers.api",[554,3025,674],{"class":572},[554,3027,589],{"class":572},[554,3029,3030,3032,3034,3036,3038,3040,3042,3044,3046],{"class":556,"line":592},[554,3031,1064],{"class":560},[554,3033,908],{"class":572},[554,3035,625],{"class":646},[554,3037,1080],{"class":572},[554,3039,1083],{"class":560},[554,3041,667],{"class":572},[554,3043,1115],{"class":670},[554,3045,674],{"class":572},[554,3047,589],{"class":572},[554,3049,3050],{"class":556,"line":604},[554,3051,614],{"emptyLinePlaceholder":613},[554,3053,3054,3056,3058,3060,3062,3064,3066,3069,3071],{"class":556,"line":610},[554,3055,561],{"class":560},[554,3057,622],{"class":564},[554,3059,1132],{"class":568},[554,3061,1135],{"class":564},[554,3063,1072],{"class":568},[554,3065,757],{"class":572},[554,3067,3068],{"class":568},"UsersApi",[554,3070,766],{"class":572},[554,3072,573],{"class":572},[554,3074,3075,3077,3079,3081,3083,3085,3087,3089,3091],{"class":556,"line":617},[554,3076,1155],{"class":564},[554,3078,806],{"class":572},[554,3080,1160],{"class":564},[554,3082,636],{"class":564},[554,3084,639],{"class":809},[554,3086,583],{"class":572},[554,3088,625],{"class":568},[554,3090,859],{"class":572},[554,3092,1173],{"class":572},[554,3094,3095],{"class":556,"line":630},[554,3096,614],{"emptyLinePlaceholder":613},[554,3098,3099,3101,3103,3105,3107,3109,3111,3113,3115,3117,3119,3121,3123,3125,3128],{"class":556,"line":656},[554,3100,742],{"class":564},[554,3102,745],{"class":564},[554,3104,748],{"class":579},[554,3106,806],{"class":572},[554,3108,1269],{"class":809},[554,3110,583],{"class":572},[554,3112,2990],{"class":568},[554,3114,757],{"class":572},[554,3116,3068],{"class":568},[554,3118,677],{"class":572},[554,3120,667],{"class":572},[554,3122,1237],{"class":670},[554,3124,674],{"class":572},[554,3126,3127],{"class":572},">)",[554,3129,573],{"class":572},[554,3131,3132,3134,3136,3138,3140,3142,3144],{"class":556,"line":695},[554,3133,774],{"class":560},[554,3135,777],{"class":572},[554,3137,780],{"class":646},[554,3139,845],{"class":572},[554,3141,1237],{"class":848},[554,3143,1240],{"class":579},[554,3145,589],{"class":572},[554,3147,3148],{"class":556,"line":726},[554,3149,788],{"class":572},[554,3151,3152],{"class":556,"line":734},[554,3153,614],{"emptyLinePlaceholder":613},[554,3155,3156,3158,3160,3162,3164,3166,3168,3170,3172,3174,3176,3178,3180,3182,3184],{"class":556,"line":739},[554,3157,742],{"class":564},[554,3159,745],{"class":564},[554,3161,898],{"class":579},[554,3163,806],{"class":572},[554,3165,1269],{"class":809},[554,3167,583],{"class":572},[554,3169,2990],{"class":568},[554,3171,757],{"class":572},[554,3173,3068],{"class":568},[554,3175,677],{"class":572},[554,3177,667],{"class":572},[554,3179,2189],{"class":670},[554,3181,674],{"class":572},[554,3183,3127],{"class":572},[554,3185,573],{"class":572},[554,3187,3188,3190,3192,3194,3196,3198,3200,3202,3204,3206,3208],{"class":556,"line":771},[554,3189,933],{"class":564},[554,3191,2129],{"class":646},[554,3193,938],{"class":572},[554,3195,1317],{"class":560},[554,3197,2159],{"class":646},[554,3199,845],{"class":572},[554,3201,1335],{"class":646},[554,3203,845],{"class":572},[554,3205,2168],{"class":848},[554,3207,1240],{"class":579},[554,3209,589],{"class":572},[554,3211,3212,3214,3216,3218,3221,3223,3226,3228,3230,3232,3234,3236,3238,3240,3242,3244],{"class":556,"line":785},[554,3213,774],{"class":560},[554,3215,2159],{"class":646},[554,3217,845],{"class":572},[554,3219,3220],{"class":848},"respond",[554,3222,806],{"class":579},[554,3224,3225],{"class":965},"201",[554,3227,677],{"class":572},[554,3229,1317],{"class":560},[554,3231,777],{"class":572},[554,3233,780],{"class":646},[554,3235,845],{"class":572},[554,3237,2189],{"class":848},[554,3239,806],{"class":579},[554,3241,2194],{"class":646},[554,3243,2522],{"class":579},[554,3245,589],{"class":572},[554,3247,3248],{"class":556,"line":791},[554,3249,788],{"class":572},[554,3251,3252],{"class":556,"line":796},[554,3253,607],{"class":572},[499,3255,3256,3257,3259,3260,3262,3263,3265],{},"The ",[508,3258,2970],{}," clause checks that every contract route has a matching handler, and\nthat each handler's return type satisfies the route's ",[508,3261,2870],{}," schemas — delete the ",[508,3264,2189],{}," method and\nthe class itself fails to compile.",[2646,3267,3269],{"id":3268},"call-it-with-type-safety","Call it with type safety",[499,3271,3256,3272,3275,3276,3278,3279,3283,3284,583],{},[1042,3273,3274],{},"same"," ",[508,3277,3068],{}," class drives a fully typed client — from tests, another service, or a browser.\nThe contract ",[3280,3281,3282],"em",{},"is"," the client: construct it with a transport, then call routes through ",[508,3285,3286],{},".client",[544,3288,3291],{"className":546,"code":3289,"filename":3290,"language":549,"meta":550,"style":550},"import { ClientTransport } from \"@heximon\u002Fclient\";\nimport { UsersApi } from \".\u002Fusers\u002Fusers.api\";\n\nconst api = new UsersApi(ClientTransport.fetch({ baseUrl: \"http:\u002F\u002Flocalhost:3000\" }));\n\nconst created = await api.client.create({ body: { name: \"Carol\", email: \"carol@example.com\" } });\n\u002F\u002F    ^? body: { id: string; name: string } — the 2xx body union; throws ContractError on a non-2xx\n","client.ts",[508,3292,3293,3315,3336,3340,3383,3387,3453],{"__ignoreMap":550},[554,3294,3295,3297,3299,3302,3304,3306,3308,3311,3313],{"class":556,"line":557},[554,3296,1064],{"class":560},[554,3298,908],{"class":572},[554,3300,3301],{"class":646}," ClientTransport",[554,3303,1080],{"class":572},[554,3305,1083],{"class":560},[554,3307,667],{"class":572},[554,3309,3310],{"class":670},"@heximon\u002Fclient",[554,3312,674],{"class":572},[554,3314,589],{"class":572},[554,3316,3317,3319,3321,3323,3325,3327,3329,3332,3334],{"class":556,"line":576},[554,3318,1064],{"class":560},[554,3320,908],{"class":572},[554,3322,2793],{"class":646},[554,3324,1080],{"class":572},[554,3326,1083],{"class":560},[554,3328,667],{"class":572},[554,3330,3331],{"class":670},".\u002Fusers\u002Fusers.api",[554,3333,674],{"class":572},[554,3335,589],{"class":572},[554,3337,3338],{"class":556,"line":592},[554,3339,614],{"emptyLinePlaceholder":613},[554,3341,3342,3344,3347,3349,3351,3353,3356,3358,3361,3363,3365,3368,3370,3372,3375,3377,3379,3381],{"class":556,"line":604},[554,3343,2731],{"class":564},[554,3345,3346],{"class":646}," api ",[554,3348,650],{"class":572},[554,3350,2354],{"class":572},[554,3352,2793],{"class":848},[554,3354,3355],{"class":646},"(ClientTransport",[554,3357,845],{"class":572},[554,3359,3360],{"class":848},"fetch",[554,3362,806],{"class":646},[554,3364,2532],{"class":572},[554,3366,3367],{"class":579}," baseUrl",[554,3369,583],{"class":572},[554,3371,667],{"class":572},[554,3373,3374],{"class":670},"http:\u002F\u002Flocalhost:3000",[554,3376,674],{"class":572},[554,3378,1080],{"class":572},[554,3380,2522],{"class":646},[554,3382,589],{"class":572},[554,3384,3385],{"class":556,"line":610},[554,3386,614],{"emptyLinePlaceholder":613},[554,3388,3389,3391,3394,3396,3398,3401,3403,3406,3408,3410,3412,3414,3416,3418,3420,3422,3424,3426,3429,3431,3433,3436,3438,3440,3443,3445,3447,3449,3451],{"class":556,"line":617},[554,3390,2731],{"class":564},[554,3392,3393],{"class":646}," created ",[554,3395,650],{"class":572},[554,3397,1317],{"class":560},[554,3399,3400],{"class":646}," api",[554,3402,845],{"class":572},[554,3404,3405],{"class":646},"client",[554,3407,845],{"class":572},[554,3409,2189],{"class":848},[554,3411,806],{"class":646},[554,3413,2532],{"class":572},[554,3415,2129],{"class":579},[554,3417,583],{"class":572},[554,3419,908],{"class":572},[554,3421,680],{"class":579},[554,3423,583],{"class":572},[554,3425,667],{"class":572},[554,3427,3428],{"class":670},"Carol",[554,3430,674],{"class":572},[554,3432,677],{"class":572},[554,3434,3435],{"class":579}," email",[554,3437,583],{"class":572},[554,3439,667],{"class":572},[554,3441,3442],{"class":670},"carol@example.com",[554,3444,674],{"class":572},[554,3446,1080],{"class":572},[554,3448,1080],{"class":572},[554,3450,859],{"class":646},[554,3452,589],{"class":572},[554,3454,3455],{"class":556,"line":630},[554,3456,3457],{"class":1182},"\u002F\u002F    ^? body: { id: string; name: string } — the 2xx body union; throws ContractError on a non-2xx\n",[499,3459,3460,3461,3463],{},"Rename a field on ",[508,3462,3068],{}," and every server handler and client call that touches it turns red — you fix\nthem at compile time, not in production.",[518,3465,3467],{"id":3466},"where-to-go-from-here","Where to go from here",[3469,3470,3471,3480,3489],"ul",{},[3472,3473,3474,1036,3477,3479],"li",{},[1042,3475,3476],{},"Build out your API",[513,3478,67],{"href":68}," covers path params, query schemas, multipart\nbodies, and per-route middleware.",[3472,3481,3482,1036,3485,3488],{},[1042,3483,3484],{},"Make it a real product",[513,3486,3487],{"href":37},"Where next?"," maps the goal you have next\n(a database, auth, background jobs, real-time) to the page and package that gets you there.",[3472,3490,3491,1036,3494,3496],{},[1042,3492,3493],{},"Ship it",[513,3495,293],{"href":299}," covers Node, Cloudflare, Vercel, Netlify, AWS Lambda, and\nDeno Deploy from the same compiled output.",[3498,3499,3500],"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 .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 .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 .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}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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}",{"title":550,"searchDepth":576,"depth":576,"links":3502},[3503,3504,3505,3506,3507,3508,3509,3510,3515],{"id":520,"depth":576,"text":521},{"id":534,"depth":576,"text":535},{"id":1028,"depth":576,"text":1029},{"id":1392,"depth":576,"text":1393},{"id":1652,"depth":576,"text":1653},{"id":1759,"depth":576,"text":1760},{"id":2254,"depth":576,"text":2255},{"id":2632,"depth":576,"text":2633,"children":3511},[3512,3513,3514],{"id":2648,"depth":592,"text":2649},{"id":2963,"depth":592,"text":2964},{"id":3268,"depth":592,"text":3269},{"id":3466,"depth":576,"text":3467},"Build your first Heximon app in three files — a provider, a controller, and a module, wired by the compiler and served by Vite.","md",null,{},{"icon":24},{"title":21,"description":3516},"NtX8_qE_bUma7xB3QMGC6_88c_4P-tR4SOuB0uyrLjA",[3524,3526],{"title":16,"path":17,"stem":18,"description":3525,"icon":19,"children":-1},"Install @heximon\u002Fruntime, @heximon\u002Fhttp, and @heximon\u002Fbuild; register the heximon() Vite plugin and the HttpPlugin in heximon.config.ts; set strict ESM tsconfig options; and add the vp dev, check, and pack scripts.",{"title":26,"path":27,"stem":28,"description":3527,"icon":29,"children":-1},"The six terms a Heximon app is built from — module, provider, constructor injection, controller, the build step, and the config line — each with a link to its dedicated page.",1783300759753]