[{"data":1,"prerenderedAt":5481},["ShallowReactive",2],{"navigation_docs":3,"-docs-recipes-crud-api":493,"-docs-recipes-crud-api-surround":5476},[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":453,"body":495,"description":5469,"extension":5470,"links":5471,"meta":5472,"navigation":5473,"path":454,"seo":5474,"stem":455,"__hash__":5475},"docs\u002Fdocs\u002F09.recipes\u002F07.crud-api.md",{"type":496,"value":497,"toc":5458},"minimark",[498,522,527,537,898,1104,1111,1216,1431,1435,1465,1640,1664,1668,1682,2949,2967,2971,2982,4023,4026,4030,4048,4218,4221,4319,4323,4338,5246,5261,5265,5284,5302,5320,5324,5341,5352,5358,5365,5369,5454],[499,500,501,502,506,507,517,518,521],"p",{},"A ",[503,504,505],"code",{},"Task"," resource with list, find, create, update, and delete — typed from the request body to the\ndatabase row, and copy-paste ready. You validate bodies with zod, persist through a plain repository over\nDrizzle, and prove the round-trip with a test — no decorators, the compiler reads each class from the\ninterface it implements and each dependency from a constructor parameter. It's the runnable\n",[508,509,513,516],"a",{"href":510,"rel":511},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fstarters\u002Ftree\u002Fmain\u002Fdatabase-zod",[512],"nofollow",[503,514,515],{},"database-zod"," starter"," (",[503,519,520],{},"heximon create --template database --validator zod",").",[523,524,526],"h2",{"id":525},"wire-the-database","Wire the database",[499,528,529,530,533,534,536],{},"The table is stock Drizzle, and one config object is read by two consumers — the Heximon runtime, which\nbuilds the database from it, and the stock ",[503,531,532],{},"drizzle-kit"," CLI, which generates migrations against the same\ninstance. ",[508,535,77],{"href":78}," builds this shape up one step at a time; here it is\nend to end:",[538,539,545],"pre",{"className":540,"code":541,"filename":542,"language":543,"meta":544,"style":544},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { defineRelations } from \"drizzle-orm\";\nimport { integer, sqliteTable, text } from \"drizzle-orm\u002Fsqlite-core\";\n\n\u002F\u002F The `done` flag is stored as a SQLite integer (0\u002F1) — SQLite has no native boolean; the repository\n\u002F\u002F maps it to\u002Ffrom JS booleans.\nexport const tasks = sqliteTable(\"tasks\", {\n  id: integer(\"id\").primaryKey({ autoIncrement: true }),\n  title: text(\"title\").notNull(),\n  done: integer(\"done\").notNull().default(0),\n});\n\n\u002F\u002F One canonical schema map both consumers read: the runtime ORM and the stock drizzle-kit CLI.\nexport const schema = { tasks };\n\n\u002F\u002F No relations yet (a single standalone table) — declared so the relational-query surface is well-formed.\nexport const relations = defineRelations(schema);\n\nexport type TaskRow = typeof tasks.$inferSelect;\n","src\u002Fdatabase\u002Fschema.ts","ts","",[503,546,547,583,617,624,631,637,671,722,753,795,805,810,816,835,840,846,865,870],{"__ignoreMap":544},[548,549,552,556,560,564,567,570,573,577,580],"span",{"class":550,"line":551},"line",1,[548,553,555],{"class":554},"s7zQu","import",[548,557,559],{"class":558},"sMK4o"," {",[548,561,563],{"class":562},"sTEyZ"," defineRelations",[548,565,566],{"class":558}," }",[548,568,569],{"class":554}," from",[548,571,572],{"class":558}," \"",[548,574,576],{"class":575},"sfazB","drizzle-orm",[548,578,579],{"class":558},"\"",[548,581,582],{"class":558},";\n",[548,584,586,588,590,593,596,599,601,604,606,608,610,613,615],{"class":550,"line":585},2,[548,587,555],{"class":554},[548,589,559],{"class":558},[548,591,592],{"class":562}," integer",[548,594,595],{"class":558},",",[548,597,598],{"class":562}," sqliteTable",[548,600,595],{"class":558},[548,602,603],{"class":562}," text",[548,605,566],{"class":558},[548,607,569],{"class":554},[548,609,572],{"class":558},[548,611,612],{"class":575},"drizzle-orm\u002Fsqlite-core",[548,614,579],{"class":558},[548,616,582],{"class":558},[548,618,620],{"class":550,"line":619},3,[548,621,623],{"emptyLinePlaceholder":622},true,"\n",[548,625,627],{"class":550,"line":626},4,[548,628,630],{"class":629},"sHwdD","\u002F\u002F The `done` flag is stored as a SQLite integer (0\u002F1) — SQLite has no native boolean; the repository\n",[548,632,634],{"class":550,"line":633},5,[548,635,636],{"class":629},"\u002F\u002F maps it to\u002Ffrom JS booleans.\n",[548,638,640,643,647,650,653,656,659,661,664,666,668],{"class":550,"line":639},6,[548,641,642],{"class":554},"export",[548,644,646],{"class":645},"spNyl"," const",[548,648,649],{"class":562}," tasks ",[548,651,652],{"class":558},"=",[548,654,598],{"class":655},"s2Zo4",[548,657,658],{"class":562},"(",[548,660,579],{"class":558},[548,662,663],{"class":575},"tasks",[548,665,579],{"class":558},[548,667,595],{"class":558},[548,669,670],{"class":558}," {\n",[548,672,674,678,681,683,685,687,690,692,695,698,701,703,706,709,711,715,717,719],{"class":550,"line":673},7,[548,675,677],{"class":676},"swJcz","  id",[548,679,680],{"class":558},":",[548,682,592],{"class":655},[548,684,658],{"class":562},[548,686,579],{"class":558},[548,688,689],{"class":575},"id",[548,691,579],{"class":558},[548,693,694],{"class":562},")",[548,696,697],{"class":558},".",[548,699,700],{"class":655},"primaryKey",[548,702,658],{"class":562},[548,704,705],{"class":558},"{",[548,707,708],{"class":676}," autoIncrement",[548,710,680],{"class":558},[548,712,714],{"class":713},"sfNiH"," true",[548,716,566],{"class":558},[548,718,694],{"class":562},[548,720,721],{"class":558},",\n",[548,723,725,728,730,732,734,736,739,741,743,745,748,751],{"class":550,"line":724},8,[548,726,727],{"class":676},"  title",[548,729,680],{"class":558},[548,731,603],{"class":655},[548,733,658],{"class":562},[548,735,579],{"class":558},[548,737,738],{"class":575},"title",[548,740,579],{"class":558},[548,742,694],{"class":562},[548,744,697],{"class":558},[548,746,747],{"class":655},"notNull",[548,749,750],{"class":562},"()",[548,752,721],{"class":558},[548,754,756,759,761,763,765,767,770,772,774,776,778,780,782,785,787,791,793],{"class":550,"line":755},9,[548,757,758],{"class":676},"  done",[548,760,680],{"class":558},[548,762,592],{"class":655},[548,764,658],{"class":562},[548,766,579],{"class":558},[548,768,769],{"class":575},"done",[548,771,579],{"class":558},[548,773,694],{"class":562},[548,775,697],{"class":558},[548,777,747],{"class":655},[548,779,750],{"class":562},[548,781,697],{"class":558},[548,783,784],{"class":655},"default",[548,786,658],{"class":562},[548,788,790],{"class":789},"sbssI","0",[548,792,694],{"class":562},[548,794,721],{"class":558},[548,796,798,801,803],{"class":550,"line":797},10,[548,799,800],{"class":558},"}",[548,802,694],{"class":562},[548,804,582],{"class":558},[548,806,808],{"class":550,"line":807},11,[548,809,623],{"emptyLinePlaceholder":622},[548,811,813],{"class":550,"line":812},12,[548,814,815],{"class":629},"\u002F\u002F One canonical schema map both consumers read: the runtime ORM and the stock drizzle-kit CLI.\n",[548,817,819,821,823,826,828,830,832],{"class":550,"line":818},13,[548,820,642],{"class":554},[548,822,646],{"class":645},[548,824,825],{"class":562}," schema ",[548,827,652],{"class":558},[548,829,559],{"class":558},[548,831,649],{"class":562},[548,833,834],{"class":558},"};\n",[548,836,838],{"class":550,"line":837},14,[548,839,623],{"emptyLinePlaceholder":622},[548,841,843],{"class":550,"line":842},15,[548,844,845],{"class":629},"\u002F\u002F No relations yet (a single standalone table) — declared so the relational-query surface is well-formed.\n",[548,847,849,851,853,856,858,860,863],{"class":550,"line":848},16,[548,850,642],{"class":554},[548,852,646],{"class":645},[548,854,855],{"class":562}," relations ",[548,857,652],{"class":558},[548,859,563],{"class":655},[548,861,862],{"class":562},"(schema)",[548,864,582],{"class":558},[548,866,868],{"class":550,"line":867},17,[548,869,623],{"emptyLinePlaceholder":622},[548,871,873,875,878,882,885,888,891,893,896],{"class":550,"line":872},18,[548,874,642],{"class":554},[548,876,877],{"class":645}," type",[548,879,881],{"class":880},"sBMFI"," TaskRow",[548,883,884],{"class":558}," =",[548,886,887],{"class":558}," typeof",[548,889,890],{"class":562}," tasks",[548,892,697],{"class":558},[548,894,895],{"class":562},"$inferSelect",[548,897,582],{"class":558},[538,899,902],{"className":540,"code":900,"filename":901,"language":543,"meta":544,"style":544},"import { DrizzleLibSQLConfig } from \"@heximon\u002Fdrizzle\u002Flibsql\u002Fconfig\";\nimport { relations, schema } from \".\u002Fschema\";\n\n\u002F\u002F `url: \":memory:\"` is an in-process SQLite database (fresh on every boot). Swap it for `file:.\u002Fapp.db`\n\u002F\u002F to persist between runs, or a `libsql:\u002F\u002F…` Turso URL (plus an authToken) for a hosted database.\nexport const databaseConfig = new DrizzleLibSQLConfig(schema, relations, {\n  dialect: \"sqlite\",\n  schema: \".\u002Fsrc\u002Fdatabase\u002Fschema.ts\",\n  out: \".\u002Fmigrations\",\n  url: \":memory:\",\n});\n\nexport type DatabaseSchema = typeof schema;\nexport type DatabaseRelations = typeof relations;\n","src\u002Fdatabase\u002Fdatabase.config.ts",[503,903,904,926,953,957,962,967,994,1010,1026,1042,1058,1066,1070,1087],{"__ignoreMap":544},[548,905,906,908,910,913,915,917,919,922,924],{"class":550,"line":551},[548,907,555],{"class":554},[548,909,559],{"class":558},[548,911,912],{"class":562}," DrizzleLibSQLConfig",[548,914,566],{"class":558},[548,916,569],{"class":554},[548,918,572],{"class":558},[548,920,921],{"class":575},"@heximon\u002Fdrizzle\u002Flibsql\u002Fconfig",[548,923,579],{"class":558},[548,925,582],{"class":558},[548,927,928,930,932,935,937,940,942,944,946,949,951],{"class":550,"line":585},[548,929,555],{"class":554},[548,931,559],{"class":558},[548,933,934],{"class":562}," relations",[548,936,595],{"class":558},[548,938,939],{"class":562}," schema",[548,941,566],{"class":558},[548,943,569],{"class":554},[548,945,572],{"class":558},[548,947,948],{"class":575},".\u002Fschema",[548,950,579],{"class":558},[548,952,582],{"class":558},[548,954,955],{"class":550,"line":619},[548,956,623],{"emptyLinePlaceholder":622},[548,958,959],{"class":550,"line":626},[548,960,961],{"class":629},"\u002F\u002F `url: \":memory:\"` is an in-process SQLite database (fresh on every boot). Swap it for `file:.\u002Fapp.db`\n",[548,963,964],{"class":550,"line":633},[548,965,966],{"class":629},"\u002F\u002F to persist between runs, or a `libsql:\u002F\u002F…` Turso URL (plus an authToken) for a hosted database.\n",[548,968,969,971,973,976,978,981,983,986,988,990,992],{"class":550,"line":639},[548,970,642],{"class":554},[548,972,646],{"class":645},[548,974,975],{"class":562}," databaseConfig ",[548,977,652],{"class":558},[548,979,980],{"class":558}," new",[548,982,912],{"class":655},[548,984,985],{"class":562},"(schema",[548,987,595],{"class":558},[548,989,934],{"class":562},[548,991,595],{"class":558},[548,993,670],{"class":558},[548,995,996,999,1001,1003,1006,1008],{"class":550,"line":673},[548,997,998],{"class":676},"  dialect",[548,1000,680],{"class":558},[548,1002,572],{"class":558},[548,1004,1005],{"class":575},"sqlite",[548,1007,579],{"class":558},[548,1009,721],{"class":558},[548,1011,1012,1015,1017,1019,1022,1024],{"class":550,"line":724},[548,1013,1014],{"class":676},"  schema",[548,1016,680],{"class":558},[548,1018,572],{"class":558},[548,1020,1021],{"class":575},".\u002Fsrc\u002Fdatabase\u002Fschema.ts",[548,1023,579],{"class":558},[548,1025,721],{"class":558},[548,1027,1028,1031,1033,1035,1038,1040],{"class":550,"line":755},[548,1029,1030],{"class":676},"  out",[548,1032,680],{"class":558},[548,1034,572],{"class":558},[548,1036,1037],{"class":575},".\u002Fmigrations",[548,1039,579],{"class":558},[548,1041,721],{"class":558},[548,1043,1044,1047,1049,1051,1054,1056],{"class":550,"line":797},[548,1045,1046],{"class":676},"  url",[548,1048,680],{"class":558},[548,1050,572],{"class":558},[548,1052,1053],{"class":575},":memory:",[548,1055,579],{"class":558},[548,1057,721],{"class":558},[548,1059,1060,1062,1064],{"class":550,"line":807},[548,1061,800],{"class":558},[548,1063,694],{"class":562},[548,1065,582],{"class":558},[548,1067,1068],{"class":550,"line":812},[548,1069,623],{"emptyLinePlaceholder":622},[548,1071,1072,1074,1076,1079,1081,1083,1085],{"class":550,"line":818},[548,1073,642],{"class":554},[548,1075,877],{"class":645},[548,1077,1078],{"class":880}," DatabaseSchema",[548,1080,884],{"class":558},[548,1082,887],{"class":558},[548,1084,939],{"class":562},[548,1086,582],{"class":558},[548,1088,1089,1091,1093,1096,1098,1100,1102],{"class":550,"line":837},[548,1090,642],{"class":554},[548,1092,877],{"class":645},[548,1094,1095],{"class":880}," DatabaseRelations",[548,1097,884],{"class":558},[548,1099,887],{"class":558},[548,1101,934],{"class":562},[548,1103,582],{"class":558},[499,1105,1106,1107,1110],{},"Dependency injection resolves by class identity, and generic type arguments are erased once resolution\nhappens — so the generic ",[503,1108,1109],{},"DrizzleLibSQLDatabase\u003CSchema, Relations>"," can't be a token: every\nparameterization would collapse onto the same class. A named, otherwise-empty subclass fixes the schema and\nrelations types once, giving you one concrete class every consumer can inject:",[538,1112,1115],{"className":540,"code":1113,"filename":1114,"language":543,"meta":544,"style":544},"import { DrizzleLibSQLDatabase } from \"@heximon\u002Fdrizzle\u002Flibsql\";\nimport type { DatabaseRelations, DatabaseSchema } from \".\u002Fdatabase.config\";\n\n\u002F\u002F The app's concrete database — a NAMED subclass typed against this app's schema, and the DI token every\n\u002F\u002F consumer injects (class identity is the only token; the generic base's type arguments are erased). The\n\u002F\u002F body is empty: it inherits the `(config, context)` constructor unchanged.\nexport class AppDatabase extends DrizzleLibSQLDatabase\u003CDatabaseSchema, DatabaseRelations> {}\n","src\u002Fdatabase\u002Fapp-database.ts",[503,1116,1117,1139,1166,1170,1175,1180,1185],{"__ignoreMap":544},[548,1118,1119,1121,1123,1126,1128,1130,1132,1135,1137],{"class":550,"line":551},[548,1120,555],{"class":554},[548,1122,559],{"class":558},[548,1124,1125],{"class":562}," DrizzleLibSQLDatabase",[548,1127,566],{"class":558},[548,1129,569],{"class":554},[548,1131,572],{"class":558},[548,1133,1134],{"class":575},"@heximon\u002Fdrizzle\u002Flibsql",[548,1136,579],{"class":558},[548,1138,582],{"class":558},[548,1140,1141,1143,1145,1147,1149,1151,1153,1155,1157,1159,1162,1164],{"class":550,"line":585},[548,1142,555],{"class":554},[548,1144,877],{"class":554},[548,1146,559],{"class":558},[548,1148,1095],{"class":562},[548,1150,595],{"class":558},[548,1152,1078],{"class":562},[548,1154,566],{"class":558},[548,1156,569],{"class":554},[548,1158,572],{"class":558},[548,1160,1161],{"class":575},".\u002Fdatabase.config",[548,1163,579],{"class":558},[548,1165,582],{"class":558},[548,1167,1168],{"class":550,"line":619},[548,1169,623],{"emptyLinePlaceholder":622},[548,1171,1172],{"class":550,"line":626},[548,1173,1174],{"class":629},"\u002F\u002F The app's concrete database — a NAMED subclass typed against this app's schema, and the DI token every\n",[548,1176,1177],{"class":550,"line":633},[548,1178,1179],{"class":629},"\u002F\u002F consumer injects (class identity is the only token; the generic base's type arguments are erased). The\n",[548,1181,1182],{"class":550,"line":639},[548,1183,1184],{"class":629},"\u002F\u002F body is empty: it inherits the `(config, context)` constructor unchanged.\n",[548,1186,1187,1189,1192,1195,1198,1200,1203,1206,1208,1210,1213],{"class":550,"line":673},[548,1188,642],{"class":554},[548,1190,1191],{"class":645}," class",[548,1193,1194],{"class":880}," AppDatabase",[548,1196,1197],{"class":645}," extends",[548,1199,1125],{"class":880},[548,1201,1202],{"class":558},"\u003C",[548,1204,1205],{"class":880},"DatabaseSchema",[548,1207,595],{"class":558},[548,1209,1095],{"class":880},[548,1211,1212],{"class":558},">",[548,1214,1215],{"class":558}," {}\n",[538,1217,1220],{"className":540,"code":1218,"filename":1219,"language":543,"meta":544,"style":544},"import { type Context, Module } from \"@heximon\u002Fruntime\";\nimport { AppDatabase } from \".\u002Fapp-database\";\nimport { databaseConfig } from \".\u002Fdatabase.config\";\n\n\u002F\u002F Owns the single AppDatabase connection and exports it so any importing module can inject it by class\n\u002F\u002F identity. There is no Drizzle compiler plugin — the database is an ordinary `useFactory` provider whose\n\u002F\u002F one parameter (`Context`) resolves by its type, like any constructor dependency. The config is a\n\u002F\u002F closed-over value, never a DI token.\nexport class DatabaseModule extends Module({\n  providers: [\n    {\n      provide: AppDatabase,\n      useFactory: (context: Context) => new AppDatabase(databaseConfig, context),\n    },\n  ],\n  exports: [AppDatabase],\n}) {}\n","src\u002Fdatabase\u002Fdatabase.module.ts",[503,1221,1222,1251,1272,1293,1297,1302,1307,1312,1317,1335,1345,1350,1361,1397,1402,1409,1421],{"__ignoreMap":544},[548,1223,1224,1226,1228,1230,1233,1235,1238,1240,1242,1244,1247,1249],{"class":550,"line":551},[548,1225,555],{"class":554},[548,1227,559],{"class":558},[548,1229,877],{"class":554},[548,1231,1232],{"class":562}," Context",[548,1234,595],{"class":558},[548,1236,1237],{"class":562}," Module",[548,1239,566],{"class":558},[548,1241,569],{"class":554},[548,1243,572],{"class":558},[548,1245,1246],{"class":575},"@heximon\u002Fruntime",[548,1248,579],{"class":558},[548,1250,582],{"class":558},[548,1252,1253,1255,1257,1259,1261,1263,1265,1268,1270],{"class":550,"line":585},[548,1254,555],{"class":554},[548,1256,559],{"class":558},[548,1258,1194],{"class":562},[548,1260,566],{"class":558},[548,1262,569],{"class":554},[548,1264,572],{"class":558},[548,1266,1267],{"class":575},".\u002Fapp-database",[548,1269,579],{"class":558},[548,1271,582],{"class":558},[548,1273,1274,1276,1278,1281,1283,1285,1287,1289,1291],{"class":550,"line":619},[548,1275,555],{"class":554},[548,1277,559],{"class":558},[548,1279,1280],{"class":562}," databaseConfig",[548,1282,566],{"class":558},[548,1284,569],{"class":554},[548,1286,572],{"class":558},[548,1288,1161],{"class":575},[548,1290,579],{"class":558},[548,1292,582],{"class":558},[548,1294,1295],{"class":550,"line":626},[548,1296,623],{"emptyLinePlaceholder":622},[548,1298,1299],{"class":550,"line":633},[548,1300,1301],{"class":629},"\u002F\u002F Owns the single AppDatabase connection and exports it so any importing module can inject it by class\n",[548,1303,1304],{"class":550,"line":639},[548,1305,1306],{"class":629},"\u002F\u002F identity. There is no Drizzle compiler plugin — the database is an ordinary `useFactory` provider whose\n",[548,1308,1309],{"class":550,"line":673},[548,1310,1311],{"class":629},"\u002F\u002F one parameter (`Context`) resolves by its type, like any constructor dependency. The config is a\n",[548,1313,1314],{"class":550,"line":724},[548,1315,1316],{"class":629},"\u002F\u002F closed-over value, never a DI token.\n",[548,1318,1319,1321,1323,1326,1328,1330,1332],{"class":550,"line":755},[548,1320,642],{"class":554},[548,1322,1191],{"class":645},[548,1324,1325],{"class":880}," DatabaseModule",[548,1327,1197],{"class":645},[548,1329,1237],{"class":655},[548,1331,658],{"class":562},[548,1333,1334],{"class":558},"{\n",[548,1336,1337,1340,1342],{"class":550,"line":797},[548,1338,1339],{"class":676},"  providers",[548,1341,680],{"class":558},[548,1343,1344],{"class":562}," [\n",[548,1346,1347],{"class":550,"line":807},[548,1348,1349],{"class":558},"    {\n",[548,1351,1352,1355,1357,1359],{"class":550,"line":812},[548,1353,1354],{"class":676},"      provide",[548,1356,680],{"class":558},[548,1358,1194],{"class":562},[548,1360,721],{"class":558},[548,1362,1363,1366,1368,1370,1374,1376,1378,1380,1383,1385,1387,1390,1392,1395],{"class":550,"line":818},[548,1364,1365],{"class":655},"      useFactory",[548,1367,680],{"class":558},[548,1369,517],{"class":558},[548,1371,1373],{"class":1372},"sHdIc","context",[548,1375,680],{"class":558},[548,1377,1232],{"class":880},[548,1379,694],{"class":558},[548,1381,1382],{"class":645}," =>",[548,1384,980],{"class":558},[548,1386,1194],{"class":655},[548,1388,1389],{"class":562},"(databaseConfig",[548,1391,595],{"class":558},[548,1393,1394],{"class":562}," context)",[548,1396,721],{"class":558},[548,1398,1399],{"class":550,"line":837},[548,1400,1401],{"class":558},"    },\n",[548,1403,1404,1407],{"class":550,"line":842},[548,1405,1406],{"class":562},"  ]",[548,1408,721],{"class":558},[548,1410,1411,1414,1416,1419],{"class":550,"line":848},[548,1412,1413],{"class":676},"  exports",[548,1415,680],{"class":558},[548,1417,1418],{"class":562}," [AppDatabase]",[548,1420,721],{"class":558},[548,1422,1423,1425,1428],{"class":550,"line":867},[548,1424,800],{"class":558},[548,1426,1427],{"class":562},") ",[548,1429,1430],{"class":558},"{}\n",[523,1432,1434],{"id":1433},"author-the-request-shapes-with-zod","Author the request shapes with zod",[499,1436,1437,1438,1441,1442,1447,1448,1451,1452,1455,1456,1460,1461,1464],{},"A route's ",[503,1439,1440],{},"body"," can be any ",[508,1443,1446],{"href":1444,"rel":1445},"https:\u002F\u002Fstandardschema.dev",[512],"Standard Schema"," — zod, valibot, or a hand-rolled\nvalidator all work unchanged. Wrapping the fields in ",[503,1449,1450],{},"@heximon\u002Fschema","'s ",[503,1453,1454],{},"SchemaObject"," gives you a class\nthat is ",[1457,1458,1459],"strong",{},"both"," the runtime validator and the static type, so a route references it bare (no ",[503,1462,1463],{},"typeof","):",[538,1466,1469],{"className":540,"code":1467,"filename":1468,"language":543,"meta":544,"style":544},"import { SchemaObject } from \"@heximon\u002Fschema\";\nimport { z } from \"zod\";\n\n\u002F\u002F A `SchemaObject` class is both a value (the validator wired into the route) and a type (the handler's\n\u002F\u002F parsed body), so it drops straight into a `{ body: … }` slot. A declared body that fails validation is\n\u002F\u002F rejected with an RFC 9457 `400` before the handler runs.\nexport class CreateTask extends SchemaObject({\n  title: z.string().trim().min(1),\n}) {}\n\nexport class SetDone extends SchemaObject({\n  done: z.boolean(),\n}) {}\n","src\u002Ftasks\u002Ftask.schema.ts",[503,1470,1471,1492,1514,1518,1523,1528,1533,1550,1586,1594,1598,1615,1632],{"__ignoreMap":544},[548,1472,1473,1475,1477,1480,1482,1484,1486,1488,1490],{"class":550,"line":551},[548,1474,555],{"class":554},[548,1476,559],{"class":558},[548,1478,1479],{"class":562}," SchemaObject",[548,1481,566],{"class":558},[548,1483,569],{"class":554},[548,1485,572],{"class":558},[548,1487,1450],{"class":575},[548,1489,579],{"class":558},[548,1491,582],{"class":558},[548,1493,1494,1496,1498,1501,1503,1505,1507,1510,1512],{"class":550,"line":585},[548,1495,555],{"class":554},[548,1497,559],{"class":558},[548,1499,1500],{"class":562}," z",[548,1502,566],{"class":558},[548,1504,569],{"class":554},[548,1506,572],{"class":558},[548,1508,1509],{"class":575},"zod",[548,1511,579],{"class":558},[548,1513,582],{"class":558},[548,1515,1516],{"class":550,"line":619},[548,1517,623],{"emptyLinePlaceholder":622},[548,1519,1520],{"class":550,"line":626},[548,1521,1522],{"class":629},"\u002F\u002F A `SchemaObject` class is both a value (the validator wired into the route) and a type (the handler's\n",[548,1524,1525],{"class":550,"line":633},[548,1526,1527],{"class":629},"\u002F\u002F parsed body), so it drops straight into a `{ body: … }` slot. A declared body that fails validation is\n",[548,1529,1530],{"class":550,"line":639},[548,1531,1532],{"class":629},"\u002F\u002F rejected with an RFC 9457 `400` before the handler runs.\n",[548,1534,1535,1537,1539,1542,1544,1546,1548],{"class":550,"line":673},[548,1536,642],{"class":554},[548,1538,1191],{"class":645},[548,1540,1541],{"class":880}," CreateTask",[548,1543,1197],{"class":645},[548,1545,1479],{"class":655},[548,1547,658],{"class":562},[548,1549,1334],{"class":558},[548,1551,1552,1554,1556,1558,1560,1563,1565,1567,1570,1572,1574,1577,1579,1582,1584],{"class":550,"line":724},[548,1553,727],{"class":676},[548,1555,680],{"class":558},[548,1557,1500],{"class":562},[548,1559,697],{"class":558},[548,1561,1562],{"class":655},"string",[548,1564,750],{"class":562},[548,1566,697],{"class":558},[548,1568,1569],{"class":655},"trim",[548,1571,750],{"class":562},[548,1573,697],{"class":558},[548,1575,1576],{"class":655},"min",[548,1578,658],{"class":562},[548,1580,1581],{"class":789},"1",[548,1583,694],{"class":562},[548,1585,721],{"class":558},[548,1587,1588,1590,1592],{"class":550,"line":755},[548,1589,800],{"class":558},[548,1591,1427],{"class":562},[548,1593,1430],{"class":558},[548,1595,1596],{"class":550,"line":797},[548,1597,623],{"emptyLinePlaceholder":622},[548,1599,1600,1602,1604,1607,1609,1611,1613],{"class":550,"line":807},[548,1601,642],{"class":554},[548,1603,1191],{"class":645},[548,1605,1606],{"class":880}," SetDone",[548,1608,1197],{"class":645},[548,1610,1479],{"class":655},[548,1612,658],{"class":562},[548,1614,1334],{"class":558},[548,1616,1617,1619,1621,1623,1625,1628,1630],{"class":550,"line":812},[548,1618,758],{"class":676},[548,1620,680],{"class":558},[548,1622,1500],{"class":562},[548,1624,697],{"class":558},[548,1626,1627],{"class":655},"boolean",[548,1629,750],{"class":562},[548,1631,721],{"class":558},[548,1633,1634,1636,1638],{"class":550,"line":818},[548,1635,800],{"class":558},[548,1637,1427],{"class":562},[548,1639,1430],{"class":558},[499,1641,1642,1643,1646,1647,1649,1650,1653,1654,1653,1657,1653,1660,1663],{},"zod is the docs default; the fields can be any validator. See ",[508,1644,1645],{"href":63},"Validation"," for\n",[503,1648,1454],{},", ",[503,1651,1652],{},"partial","\u002F",[503,1655,1656],{},"pick",[503,1658,1659],{},"omit",[503,1661,1662],{},"extend",", and bringing your own validator.",[523,1665,1667],{"id":1666},"write-the-repository","Write the repository",[499,1669,1670,1671,1674,1675,1678,1679,680],{},"A repository is a plain class that injects ",[503,1672,1673],{},"AppDatabase"," by constructor parameter, exactly like injecting\nany other provider. It runs typed queries through ",[503,1676,1677],{},"getOrm()",", and — because the in-memory database starts\nempty on every boot — creates its own table in ",[503,1680,1681],{},"onInit",[538,1683,1686],{"className":540,"code":1684,"filename":1685,"language":543,"meta":544,"style":544},"import { type OnInit } from \"@heximon\u002Fruntime\";\nimport { eq, sql } from \"drizzle-orm\";\nimport { AppDatabase } from \"..\u002Fdatabase\u002Fapp-database\";\nimport { tasks, type TaskRow } from \"..\u002Fdatabase\u002Fschema\";\n\n\u002F** A task as the rest of the app sees it — `done` is a real boolean (the row stores it as 0\u002F1). *\u002F\nexport interface Task {\n  readonly id: number;\n  readonly title: string;\n  readonly done: boolean;\n}\n\n\u002F\u002F The data-access service: depends on the single shared AppDatabase (resolved by class identity) and runs\n\u002F\u002F all persistence through the typed Drizzle ORM. The in-memory database starts empty on every boot, so the\n\u002F\u002F table is created in onInit — a file-backed or remote database would use a migration instead.\nexport class TasksRepository implements OnInit {\n  public constructor(private readonly database: AppDatabase) {}\n\n  public async onInit(): Promise\u003Cvoid> {\n    await this.database.getOrm().run(sql`\n      CREATE TABLE IF NOT EXISTS tasks (\n        id    INTEGER PRIMARY KEY AUTOINCREMENT,\n        title TEXT NOT NULL,\n        done  INTEGER NOT NULL DEFAULT 0\n      )\n    `);\n  }\n\n  public async list(): Promise\u003CTask[]> {\n    const rows = await this.database.getOrm().select().from(tasks).orderBy(tasks.id);\n\n    return rows.map((row) => TasksRepository.toTask(row));\n  }\n\n  public async findById(id: number): Promise\u003CTask | undefined> {\n    const rows = await this.database.getOrm().select().from(tasks).where(eq(tasks.id, id)).limit(1);\n    const row = rows[0];\n\n    return row === undefined ? undefined : TasksRepository.toTask(row);\n  }\n\n  public async create(title: string): Promise\u003CTask> {\n    const [row] = await this.database.getOrm().insert(tasks).values({ title, done: 0 }).returning();\n\n    if (row === undefined) {\n      throw new Error(\"Insert returned no row.\");\n    }\n\n    return TasksRepository.toTask(row);\n  }\n\n  public async setDone(id: number, done: boolean): Promise\u003CTask | undefined> {\n    const [row] = await this.database\n      .getOrm()\n      .update(tasks)\n      .set({ done: done ? 1 : 0 })\n      .where(eq(tasks.id, id))\n      .returning();\n\n    return row === undefined ? undefined : TasksRepository.toTask(row);\n  }\n\n  public async remove(id: number): Promise\u003Cboolean> {\n    const deleted = await this.database.getOrm().delete(tasks).where(eq(tasks.id, id)).returning();\n\n    return deleted.length > 0;\n  }\n\n  private static toTask(row: TaskRow): Task {\n    return { id: row.id, title: row.title, done: row.done === 1 };\n  }\n}\n","src\u002Ftasks\u002Ftasks.repository.ts",[503,1687,1688,1711,1737,1758,1785,1789,1794,1806,1821,1835,1849,1854,1858,1863,1868,1873,1889,1916,1920,1946,1978,1984,1990,1996,2002,2008,2018,2024,2029,2054,2113,2118,2158,2163,2168,2204,2278,2300,2305,2339,2344,2349,2379,2449,2454,2472,2496,2502,2507,2526,2531,2536,2578,2598,2609,2624,2655,2681,2692,2697,2728,2733,2738,2768,2831,2836,2855,2860,2865,2891,2939,2944],{"__ignoreMap":544},[548,1689,1690,1692,1694,1696,1699,1701,1703,1705,1707,1709],{"class":550,"line":551},[548,1691,555],{"class":554},[548,1693,559],{"class":558},[548,1695,877],{"class":554},[548,1697,1698],{"class":562}," OnInit",[548,1700,566],{"class":558},[548,1702,569],{"class":554},[548,1704,572],{"class":558},[548,1706,1246],{"class":575},[548,1708,579],{"class":558},[548,1710,582],{"class":558},[548,1712,1713,1715,1717,1720,1722,1725,1727,1729,1731,1733,1735],{"class":550,"line":585},[548,1714,555],{"class":554},[548,1716,559],{"class":558},[548,1718,1719],{"class":562}," eq",[548,1721,595],{"class":558},[548,1723,1724],{"class":562}," sql",[548,1726,566],{"class":558},[548,1728,569],{"class":554},[548,1730,572],{"class":558},[548,1732,576],{"class":575},[548,1734,579],{"class":558},[548,1736,582],{"class":558},[548,1738,1739,1741,1743,1745,1747,1749,1751,1754,1756],{"class":550,"line":619},[548,1740,555],{"class":554},[548,1742,559],{"class":558},[548,1744,1194],{"class":562},[548,1746,566],{"class":558},[548,1748,569],{"class":554},[548,1750,572],{"class":558},[548,1752,1753],{"class":575},"..\u002Fdatabase\u002Fapp-database",[548,1755,579],{"class":558},[548,1757,582],{"class":558},[548,1759,1760,1762,1764,1766,1768,1770,1772,1774,1776,1778,1781,1783],{"class":550,"line":626},[548,1761,555],{"class":554},[548,1763,559],{"class":558},[548,1765,890],{"class":562},[548,1767,595],{"class":558},[548,1769,877],{"class":554},[548,1771,881],{"class":562},[548,1773,566],{"class":558},[548,1775,569],{"class":554},[548,1777,572],{"class":558},[548,1779,1780],{"class":575},"..\u002Fdatabase\u002Fschema",[548,1782,579],{"class":558},[548,1784,582],{"class":558},[548,1786,1787],{"class":550,"line":633},[548,1788,623],{"emptyLinePlaceholder":622},[548,1790,1791],{"class":550,"line":639},[548,1792,1793],{"class":629},"\u002F** A task as the rest of the app sees it — `done` is a real boolean (the row stores it as 0\u002F1). *\u002F\n",[548,1795,1796,1798,1801,1804],{"class":550,"line":673},[548,1797,642],{"class":554},[548,1799,1800],{"class":645}," interface",[548,1802,1803],{"class":880}," Task",[548,1805,670],{"class":558},[548,1807,1808,1811,1814,1816,1819],{"class":550,"line":724},[548,1809,1810],{"class":645},"  readonly",[548,1812,1813],{"class":676}," id",[548,1815,680],{"class":558},[548,1817,1818],{"class":880}," number",[548,1820,582],{"class":558},[548,1822,1823,1825,1828,1830,1833],{"class":550,"line":755},[548,1824,1810],{"class":645},[548,1826,1827],{"class":676}," title",[548,1829,680],{"class":558},[548,1831,1832],{"class":880}," string",[548,1834,582],{"class":558},[548,1836,1837,1839,1842,1844,1847],{"class":550,"line":797},[548,1838,1810],{"class":645},[548,1840,1841],{"class":676}," done",[548,1843,680],{"class":558},[548,1845,1846],{"class":880}," boolean",[548,1848,582],{"class":558},[548,1850,1851],{"class":550,"line":807},[548,1852,1853],{"class":558},"}\n",[548,1855,1856],{"class":550,"line":812},[548,1857,623],{"emptyLinePlaceholder":622},[548,1859,1860],{"class":550,"line":818},[548,1861,1862],{"class":629},"\u002F\u002F The data-access service: depends on the single shared AppDatabase (resolved by class identity) and runs\n",[548,1864,1865],{"class":550,"line":837},[548,1866,1867],{"class":629},"\u002F\u002F all persistence through the typed Drizzle ORM. The in-memory database starts empty on every boot, so the\n",[548,1869,1870],{"class":550,"line":842},[548,1871,1872],{"class":629},"\u002F\u002F table is created in onInit — a file-backed or remote database would use a migration instead.\n",[548,1874,1875,1877,1879,1882,1885,1887],{"class":550,"line":848},[548,1876,642],{"class":554},[548,1878,1191],{"class":645},[548,1880,1881],{"class":880}," TasksRepository",[548,1883,1884],{"class":645}," implements",[548,1886,1698],{"class":880},[548,1888,670],{"class":558},[548,1890,1891,1894,1897,1899,1902,1905,1908,1910,1912,1914],{"class":550,"line":867},[548,1892,1893],{"class":645},"  public",[548,1895,1896],{"class":645}," constructor",[548,1898,658],{"class":558},[548,1900,1901],{"class":645},"private",[548,1903,1904],{"class":645}," readonly",[548,1906,1907],{"class":1372}," database",[548,1909,680],{"class":558},[548,1911,1194],{"class":880},[548,1913,694],{"class":558},[548,1915,1215],{"class":558},[548,1917,1918],{"class":550,"line":872},[548,1919,623],{"emptyLinePlaceholder":622},[548,1921,1923,1925,1928,1931,1934,1937,1939,1942,1944],{"class":550,"line":1922},19,[548,1924,1893],{"class":645},[548,1926,1927],{"class":645}," async",[548,1929,1930],{"class":676}," onInit",[548,1932,1933],{"class":558},"():",[548,1935,1936],{"class":880}," Promise",[548,1938,1202],{"class":558},[548,1940,1941],{"class":880},"void",[548,1943,1212],{"class":558},[548,1945,670],{"class":558},[548,1947,1949,1952,1955,1958,1960,1963,1965,1967,1970,1972,1975],{"class":550,"line":1948},20,[548,1950,1951],{"class":554},"    await",[548,1953,1954],{"class":558}," this.",[548,1956,1957],{"class":562},"database",[548,1959,697],{"class":558},[548,1961,1962],{"class":655},"getOrm",[548,1964,750],{"class":676},[548,1966,697],{"class":558},[548,1968,1969],{"class":655},"run",[548,1971,658],{"class":676},[548,1973,1974],{"class":655},"sql",[548,1976,1977],{"class":558},"`\n",[548,1979,1981],{"class":550,"line":1980},21,[548,1982,1983],{"class":575},"      CREATE TABLE IF NOT EXISTS tasks (\n",[548,1985,1987],{"class":550,"line":1986},22,[548,1988,1989],{"class":575},"        id    INTEGER PRIMARY KEY AUTOINCREMENT,\n",[548,1991,1993],{"class":550,"line":1992},23,[548,1994,1995],{"class":575},"        title TEXT NOT NULL,\n",[548,1997,1999],{"class":550,"line":1998},24,[548,2000,2001],{"class":575},"        done  INTEGER NOT NULL DEFAULT 0\n",[548,2003,2005],{"class":550,"line":2004},25,[548,2006,2007],{"class":575},"      )\n",[548,2009,2011,2014,2016],{"class":550,"line":2010},26,[548,2012,2013],{"class":558},"    `",[548,2015,694],{"class":676},[548,2017,582],{"class":558},[548,2019,2021],{"class":550,"line":2020},27,[548,2022,2023],{"class":558},"  }\n",[548,2025,2027],{"class":550,"line":2026},28,[548,2028,623],{"emptyLinePlaceholder":622},[548,2030,2032,2034,2036,2039,2041,2043,2045,2047,2050,2052],{"class":550,"line":2031},29,[548,2033,1893],{"class":645},[548,2035,1927],{"class":645},[548,2037,2038],{"class":676}," list",[548,2040,1933],{"class":558},[548,2042,1936],{"class":880},[548,2044,1202],{"class":558},[548,2046,505],{"class":880},[548,2048,2049],{"class":562},"[]",[548,2051,1212],{"class":558},[548,2053,670],{"class":558},[548,2055,2057,2060,2063,2065,2068,2070,2072,2074,2076,2078,2080,2083,2085,2087,2090,2092,2094,2096,2098,2101,2103,2105,2107,2109,2111],{"class":550,"line":2056},30,[548,2058,2059],{"class":645},"    const",[548,2061,2062],{"class":562}," rows",[548,2064,884],{"class":558},[548,2066,2067],{"class":554}," await",[548,2069,1954],{"class":558},[548,2071,1957],{"class":562},[548,2073,697],{"class":558},[548,2075,1962],{"class":655},[548,2077,750],{"class":676},[548,2079,697],{"class":558},[548,2081,2082],{"class":655},"select",[548,2084,750],{"class":676},[548,2086,697],{"class":558},[548,2088,2089],{"class":655},"from",[548,2091,658],{"class":676},[548,2093,663],{"class":562},[548,2095,694],{"class":676},[548,2097,697],{"class":558},[548,2099,2100],{"class":655},"orderBy",[548,2102,658],{"class":676},[548,2104,663],{"class":562},[548,2106,697],{"class":558},[548,2108,689],{"class":562},[548,2110,694],{"class":676},[548,2112,582],{"class":558},[548,2114,2116],{"class":550,"line":2115},31,[548,2117,623],{"emptyLinePlaceholder":622},[548,2119,2121,2124,2126,2128,2131,2133,2135,2138,2140,2142,2144,2146,2149,2151,2153,2156],{"class":550,"line":2120},32,[548,2122,2123],{"class":554},"    return",[548,2125,2062],{"class":562},[548,2127,697],{"class":558},[548,2129,2130],{"class":655},"map",[548,2132,658],{"class":676},[548,2134,658],{"class":558},[548,2136,2137],{"class":1372},"row",[548,2139,694],{"class":558},[548,2141,1382],{"class":645},[548,2143,1881],{"class":562},[548,2145,697],{"class":558},[548,2147,2148],{"class":655},"toTask",[548,2150,658],{"class":676},[548,2152,2137],{"class":562},[548,2154,2155],{"class":676},"))",[548,2157,582],{"class":558},[548,2159,2161],{"class":550,"line":2160},33,[548,2162,2023],{"class":558},[548,2164,2166],{"class":550,"line":2165},34,[548,2167,623],{"emptyLinePlaceholder":622},[548,2169,2171,2173,2175,2178,2180,2182,2184,2186,2188,2190,2192,2194,2197,2200,2202],{"class":550,"line":2170},35,[548,2172,1893],{"class":645},[548,2174,1927],{"class":645},[548,2176,2177],{"class":676}," findById",[548,2179,658],{"class":558},[548,2181,689],{"class":1372},[548,2183,680],{"class":558},[548,2185,1818],{"class":880},[548,2187,1464],{"class":558},[548,2189,1936],{"class":880},[548,2191,1202],{"class":558},[548,2193,505],{"class":880},[548,2195,2196],{"class":558}," |",[548,2198,2199],{"class":880}," undefined",[548,2201,1212],{"class":558},[548,2203,670],{"class":558},[548,2205,2207,2209,2211,2213,2215,2217,2219,2221,2223,2225,2227,2229,2231,2233,2235,2237,2239,2241,2243,2246,2248,2251,2253,2255,2257,2259,2261,2263,2265,2267,2270,2272,2274,2276],{"class":550,"line":2206},36,[548,2208,2059],{"class":645},[548,2210,2062],{"class":562},[548,2212,884],{"class":558},[548,2214,2067],{"class":554},[548,2216,1954],{"class":558},[548,2218,1957],{"class":562},[548,2220,697],{"class":558},[548,2222,1962],{"class":655},[548,2224,750],{"class":676},[548,2226,697],{"class":558},[548,2228,2082],{"class":655},[548,2230,750],{"class":676},[548,2232,697],{"class":558},[548,2234,2089],{"class":655},[548,2236,658],{"class":676},[548,2238,663],{"class":562},[548,2240,694],{"class":676},[548,2242,697],{"class":558},[548,2244,2245],{"class":655},"where",[548,2247,658],{"class":676},[548,2249,2250],{"class":655},"eq",[548,2252,658],{"class":676},[548,2254,663],{"class":562},[548,2256,697],{"class":558},[548,2258,689],{"class":562},[548,2260,595],{"class":558},[548,2262,1813],{"class":562},[548,2264,2155],{"class":676},[548,2266,697],{"class":558},[548,2268,2269],{"class":655},"limit",[548,2271,658],{"class":676},[548,2273,1581],{"class":789},[548,2275,694],{"class":676},[548,2277,582],{"class":558},[548,2279,2281,2283,2286,2288,2290,2293,2295,2298],{"class":550,"line":2280},37,[548,2282,2059],{"class":645},[548,2284,2285],{"class":562}," row",[548,2287,884],{"class":558},[548,2289,2062],{"class":562},[548,2291,2292],{"class":676},"[",[548,2294,790],{"class":789},[548,2296,2297],{"class":676},"]",[548,2299,582],{"class":558},[548,2301,2303],{"class":550,"line":2302},38,[548,2304,623],{"emptyLinePlaceholder":622},[548,2306,2308,2310,2312,2315,2317,2320,2322,2325,2327,2329,2331,2333,2335,2337],{"class":550,"line":2307},39,[548,2309,2123],{"class":554},[548,2311,2285],{"class":562},[548,2313,2314],{"class":558}," ===",[548,2316,2199],{"class":558},[548,2318,2319],{"class":558}," ?",[548,2321,2199],{"class":558},[548,2323,2324],{"class":558}," :",[548,2326,1881],{"class":562},[548,2328,697],{"class":558},[548,2330,2148],{"class":655},[548,2332,658],{"class":676},[548,2334,2137],{"class":562},[548,2336,694],{"class":676},[548,2338,582],{"class":558},[548,2340,2342],{"class":550,"line":2341},40,[548,2343,2023],{"class":558},[548,2345,2347],{"class":550,"line":2346},41,[548,2348,623],{"emptyLinePlaceholder":622},[548,2350,2352,2354,2356,2359,2361,2363,2365,2367,2369,2371,2373,2375,2377],{"class":550,"line":2351},42,[548,2353,1893],{"class":645},[548,2355,1927],{"class":645},[548,2357,2358],{"class":676}," create",[548,2360,658],{"class":558},[548,2362,738],{"class":1372},[548,2364,680],{"class":558},[548,2366,1832],{"class":880},[548,2368,1464],{"class":558},[548,2370,1936],{"class":880},[548,2372,1202],{"class":558},[548,2374,505],{"class":880},[548,2376,1212],{"class":558},[548,2378,670],{"class":558},[548,2380,2382,2384,2387,2389,2391,2393,2395,2397,2399,2401,2403,2405,2407,2410,2412,2414,2416,2418,2421,2423,2425,2427,2429,2431,2433,2436,2438,2440,2442,2445,2447],{"class":550,"line":2381},43,[548,2383,2059],{"class":645},[548,2385,2386],{"class":558}," [",[548,2388,2137],{"class":562},[548,2390,2297],{"class":558},[548,2392,884],{"class":558},[548,2394,2067],{"class":554},[548,2396,1954],{"class":558},[548,2398,1957],{"class":562},[548,2400,697],{"class":558},[548,2402,1962],{"class":655},[548,2404,750],{"class":676},[548,2406,697],{"class":558},[548,2408,2409],{"class":655},"insert",[548,2411,658],{"class":676},[548,2413,663],{"class":562},[548,2415,694],{"class":676},[548,2417,697],{"class":558},[548,2419,2420],{"class":655},"values",[548,2422,658],{"class":676},[548,2424,705],{"class":558},[548,2426,1827],{"class":562},[548,2428,595],{"class":558},[548,2430,1841],{"class":676},[548,2432,680],{"class":558},[548,2434,2435],{"class":789}," 0",[548,2437,566],{"class":558},[548,2439,694],{"class":676},[548,2441,697],{"class":558},[548,2443,2444],{"class":655},"returning",[548,2446,750],{"class":676},[548,2448,582],{"class":558},[548,2450,2452],{"class":550,"line":2451},44,[548,2453,623],{"emptyLinePlaceholder":622},[548,2455,2457,2460,2462,2464,2466,2468,2470],{"class":550,"line":2456},45,[548,2458,2459],{"class":554},"    if",[548,2461,517],{"class":676},[548,2463,2137],{"class":562},[548,2465,2314],{"class":558},[548,2467,2199],{"class":558},[548,2469,1427],{"class":676},[548,2471,1334],{"class":558},[548,2473,2475,2478,2480,2483,2485,2487,2490,2492,2494],{"class":550,"line":2474},46,[548,2476,2477],{"class":554},"      throw",[548,2479,980],{"class":558},[548,2481,2482],{"class":655}," Error",[548,2484,658],{"class":676},[548,2486,579],{"class":558},[548,2488,2489],{"class":575},"Insert returned no row.",[548,2491,579],{"class":558},[548,2493,694],{"class":676},[548,2495,582],{"class":558},[548,2497,2499],{"class":550,"line":2498},47,[548,2500,2501],{"class":558},"    }\n",[548,2503,2505],{"class":550,"line":2504},48,[548,2506,623],{"emptyLinePlaceholder":622},[548,2508,2510,2512,2514,2516,2518,2520,2522,2524],{"class":550,"line":2509},49,[548,2511,2123],{"class":554},[548,2513,1881],{"class":562},[548,2515,697],{"class":558},[548,2517,2148],{"class":655},[548,2519,658],{"class":676},[548,2521,2137],{"class":562},[548,2523,694],{"class":676},[548,2525,582],{"class":558},[548,2527,2529],{"class":550,"line":2528},50,[548,2530,2023],{"class":558},[548,2532,2534],{"class":550,"line":2533},51,[548,2535,623],{"emptyLinePlaceholder":622},[548,2537,2539,2541,2543,2546,2548,2550,2552,2554,2556,2558,2560,2562,2564,2566,2568,2570,2572,2574,2576],{"class":550,"line":2538},52,[548,2540,1893],{"class":645},[548,2542,1927],{"class":645},[548,2544,2545],{"class":676}," setDone",[548,2547,658],{"class":558},[548,2549,689],{"class":1372},[548,2551,680],{"class":558},[548,2553,1818],{"class":880},[548,2555,595],{"class":558},[548,2557,1841],{"class":1372},[548,2559,680],{"class":558},[548,2561,1846],{"class":880},[548,2563,1464],{"class":558},[548,2565,1936],{"class":880},[548,2567,1202],{"class":558},[548,2569,505],{"class":880},[548,2571,2196],{"class":558},[548,2573,2199],{"class":880},[548,2575,1212],{"class":558},[548,2577,670],{"class":558},[548,2579,2581,2583,2585,2587,2589,2591,2593,2595],{"class":550,"line":2580},53,[548,2582,2059],{"class":645},[548,2584,2386],{"class":558},[548,2586,2137],{"class":562},[548,2588,2297],{"class":558},[548,2590,884],{"class":558},[548,2592,2067],{"class":554},[548,2594,1954],{"class":558},[548,2596,2597],{"class":562},"database\n",[548,2599,2601,2604,2606],{"class":550,"line":2600},54,[548,2602,2603],{"class":558},"      .",[548,2605,1962],{"class":655},[548,2607,2608],{"class":676},"()\n",[548,2610,2612,2614,2617,2619,2621],{"class":550,"line":2611},55,[548,2613,2603],{"class":558},[548,2615,2616],{"class":655},"update",[548,2618,658],{"class":676},[548,2620,663],{"class":562},[548,2622,2623],{"class":676},")\n",[548,2625,2627,2629,2632,2634,2636,2638,2640,2642,2644,2647,2649,2651,2653],{"class":550,"line":2626},56,[548,2628,2603],{"class":558},[548,2630,2631],{"class":655},"set",[548,2633,658],{"class":676},[548,2635,705],{"class":558},[548,2637,1841],{"class":676},[548,2639,680],{"class":558},[548,2641,1841],{"class":562},[548,2643,2319],{"class":558},[548,2645,2646],{"class":789}," 1",[548,2648,2324],{"class":558},[548,2650,2435],{"class":789},[548,2652,566],{"class":558},[548,2654,2623],{"class":676},[548,2656,2658,2660,2662,2664,2666,2668,2670,2672,2674,2676,2678],{"class":550,"line":2657},57,[548,2659,2603],{"class":558},[548,2661,2245],{"class":655},[548,2663,658],{"class":676},[548,2665,2250],{"class":655},[548,2667,658],{"class":676},[548,2669,663],{"class":562},[548,2671,697],{"class":558},[548,2673,689],{"class":562},[548,2675,595],{"class":558},[548,2677,1813],{"class":562},[548,2679,2680],{"class":676},"))\n",[548,2682,2684,2686,2688,2690],{"class":550,"line":2683},58,[548,2685,2603],{"class":558},[548,2687,2444],{"class":655},[548,2689,750],{"class":676},[548,2691,582],{"class":558},[548,2693,2695],{"class":550,"line":2694},59,[548,2696,623],{"emptyLinePlaceholder":622},[548,2698,2700,2702,2704,2706,2708,2710,2712,2714,2716,2718,2720,2722,2724,2726],{"class":550,"line":2699},60,[548,2701,2123],{"class":554},[548,2703,2285],{"class":562},[548,2705,2314],{"class":558},[548,2707,2199],{"class":558},[548,2709,2319],{"class":558},[548,2711,2199],{"class":558},[548,2713,2324],{"class":558},[548,2715,1881],{"class":562},[548,2717,697],{"class":558},[548,2719,2148],{"class":655},[548,2721,658],{"class":676},[548,2723,2137],{"class":562},[548,2725,694],{"class":676},[548,2727,582],{"class":558},[548,2729,2731],{"class":550,"line":2730},61,[548,2732,2023],{"class":558},[548,2734,2736],{"class":550,"line":2735},62,[548,2737,623],{"emptyLinePlaceholder":622},[548,2739,2741,2743,2745,2748,2750,2752,2754,2756,2758,2760,2762,2764,2766],{"class":550,"line":2740},63,[548,2742,1893],{"class":645},[548,2744,1927],{"class":645},[548,2746,2747],{"class":676}," remove",[548,2749,658],{"class":558},[548,2751,689],{"class":1372},[548,2753,680],{"class":558},[548,2755,1818],{"class":880},[548,2757,1464],{"class":558},[548,2759,1936],{"class":880},[548,2761,1202],{"class":558},[548,2763,1627],{"class":880},[548,2765,1212],{"class":558},[548,2767,670],{"class":558},[548,2769,2771,2773,2776,2778,2780,2782,2784,2786,2788,2790,2792,2795,2797,2799,2801,2803,2805,2807,2809,2811,2813,2815,2817,2819,2821,2823,2825,2827,2829],{"class":550,"line":2770},64,[548,2772,2059],{"class":645},[548,2774,2775],{"class":562}," deleted",[548,2777,884],{"class":558},[548,2779,2067],{"class":554},[548,2781,1954],{"class":558},[548,2783,1957],{"class":562},[548,2785,697],{"class":558},[548,2787,1962],{"class":655},[548,2789,750],{"class":676},[548,2791,697],{"class":558},[548,2793,2794],{"class":655},"delete",[548,2796,658],{"class":676},[548,2798,663],{"class":562},[548,2800,694],{"class":676},[548,2802,697],{"class":558},[548,2804,2245],{"class":655},[548,2806,658],{"class":676},[548,2808,2250],{"class":655},[548,2810,658],{"class":676},[548,2812,663],{"class":562},[548,2814,697],{"class":558},[548,2816,689],{"class":562},[548,2818,595],{"class":558},[548,2820,1813],{"class":562},[548,2822,2155],{"class":676},[548,2824,697],{"class":558},[548,2826,2444],{"class":655},[548,2828,750],{"class":676},[548,2830,582],{"class":558},[548,2832,2834],{"class":550,"line":2833},65,[548,2835,623],{"emptyLinePlaceholder":622},[548,2837,2839,2841,2843,2845,2848,2851,2853],{"class":550,"line":2838},66,[548,2840,2123],{"class":554},[548,2842,2775],{"class":562},[548,2844,697],{"class":558},[548,2846,2847],{"class":562},"length",[548,2849,2850],{"class":558}," >",[548,2852,2435],{"class":789},[548,2854,582],{"class":558},[548,2856,2858],{"class":550,"line":2857},67,[548,2859,2023],{"class":558},[548,2861,2863],{"class":550,"line":2862},68,[548,2864,623],{"emptyLinePlaceholder":622},[548,2866,2868,2871,2874,2877,2879,2881,2883,2885,2887,2889],{"class":550,"line":2867},69,[548,2869,2870],{"class":645},"  private",[548,2872,2873],{"class":645}," static",[548,2875,2876],{"class":676}," toTask",[548,2878,658],{"class":558},[548,2880,2137],{"class":1372},[548,2882,680],{"class":558},[548,2884,881],{"class":880},[548,2886,1464],{"class":558},[548,2888,1803],{"class":880},[548,2890,670],{"class":558},[548,2892,2894,2896,2898,2900,2902,2904,2906,2908,2910,2912,2914,2916,2918,2920,2922,2924,2926,2928,2930,2932,2934,2936],{"class":550,"line":2893},70,[548,2895,2123],{"class":554},[548,2897,559],{"class":558},[548,2899,1813],{"class":676},[548,2901,680],{"class":558},[548,2903,2285],{"class":562},[548,2905,697],{"class":558},[548,2907,689],{"class":562},[548,2909,595],{"class":558},[548,2911,1827],{"class":676},[548,2913,680],{"class":558},[548,2915,2285],{"class":562},[548,2917,697],{"class":558},[548,2919,738],{"class":562},[548,2921,595],{"class":558},[548,2923,1841],{"class":676},[548,2925,680],{"class":558},[548,2927,2285],{"class":562},[548,2929,697],{"class":558},[548,2931,769],{"class":562},[548,2933,2314],{"class":558},[548,2935,2646],{"class":789},[548,2937,2938],{"class":558}," };\n",[548,2940,2942],{"class":550,"line":2941},71,[548,2943,2023],{"class":558},[548,2945,2947],{"class":550,"line":2946},72,[548,2948,1853],{"class":558},[499,2950,2951,2953,2954,2957,2958,2961,2962,2964,2965,697],{},[503,2952,1681],{}," runs once, in dependency order, the first time something resolves ",[503,2955,2956],{},"TasksRepository"," — in\npractice, the first request that hits ",[503,2959,2960],{},"\u002Ftasks"," — and completes before any repository method runs. A\nfile-backed or hosted database wouldn't boot-create a table this way; see\n",[508,2963,92],{"href":93}," once you're off ",[503,2966,1053],{},[523,2968,2970],{"id":2969},"bind-the-controller","Bind the controller",[499,2972,2973,2974,2977,2978,2981],{},"Routes are declared by each handler's action parameter ",[1457,2975,2976],{},"type"," — no route config, no decorators.\nDeclared bodies are validated before the handler runs; ",[503,2979,2980],{},"readValidatedBody()"," returns the parsed, typed\nresult, so a handler only ever sees a well-formed body.",[538,2983,2986],{"className":540,"code":2984,"filename":2985,"language":543,"meta":544,"style":544},"import type { Controller, Delete, Get, Patch, Post } from \"@heximon\u002Fhttp\";\nimport { CreateTask, SetDone } from \".\u002Ftask.schema\";\nimport { type Task, TasksRepository } from \".\u002Ftasks.repository\";\n\ninterface ErrorBody {\n  readonly error: string;\n}\n\n\u002F\u002F Routes are declared by each handler's action parameter type — the compiler reads `Get\u003C\"\u002F\">`,\n\u002F\u002F `Post\u003C\"\u002F\", { body }>`, … off the signatures and builds the route table. Declared bodies are validated\n\u002F\u002F before the handler runs; `readValidatedBody()` returns the parsed, typed result.\nexport class TasksController implements Controller\u003C\"\u002Ftasks\"> {\n  public constructor(private readonly tasks: TasksRepository) {}\n\n  public async list(_action: Get\u003C\"\u002F\">): Promise\u003CTask[]> {\n    return this.tasks.list();\n  }\n\n  public async get(action: Get\u003C\"\u002F:id\">): Promise\u003CTask | ErrorBody> {\n    const id = Number(action.request.pathParams.id);\n    const task = await this.tasks.findById(id);\n\n    if (task === undefined) {\n      action.response.status = 404;\n\n      return { error: `No task with id ${id}.` };\n    }\n\n    return task;\n  }\n\n  public async create(action: Post\u003C\"\u002F\", { body: CreateTask }>): Promise\u003CTask> {\n    const body = await action.request.readValidatedBody();\n    action.response.status = 201;\n\n    return this.tasks.create(body.title);\n  }\n\n  public async setDone(action: Patch\u003C\"\u002F:id\", { body: SetDone }>): Promise\u003CTask | ErrorBody> {\n    const id = Number(action.request.pathParams.id);\n    const body = await action.request.readValidatedBody();\n    const updated = await this.tasks.setDone(id, body.done);\n\n    if (updated === undefined) {\n      action.response.status = 404;\n\n      return { error: `No task with id ${id}.` };\n    }\n\n    return updated;\n  }\n\n  public async remove(action: Delete\u003C\"\u002F:id\">): Promise\u003C{ deleted: number } | ErrorBody> {\n    const id = Number(action.request.pathParams.id);\n    const removed = await this.tasks.remove(id);\n\n    if (!removed) {\n      action.response.status = 404;\n\n      return { error: `No task with id ${id}.` };\n    }\n\n    return { deleted: id };\n  }\n}\n","src\u002Ftasks\u002Ftasks.controller.ts",[503,2987,2988,3032,3057,3084,3088,3098,3111,3115,3119,3124,3129,3134,3159,3181,3185,3225,3242,3246,3250,3293,3326,3354,3358,3375,3397,3401,3432,3436,3440,3448,3452,3456,3504,3530,3550,3554,3579,3583,3587,3637,3667,3691,3727,3731,3748,3766,3770,3796,3800,3804,3812,3816,3820,3867,3897,3925,3929,3945,3963,3967,3993,3997,4001,4015,4019],{"__ignoreMap":544},[548,2989,2990,2992,2994,2996,2999,3001,3004,3006,3009,3011,3014,3016,3019,3021,3023,3025,3028,3030],{"class":550,"line":551},[548,2991,555],{"class":554},[548,2993,877],{"class":554},[548,2995,559],{"class":558},[548,2997,2998],{"class":562}," Controller",[548,3000,595],{"class":558},[548,3002,3003],{"class":562}," Delete",[548,3005,595],{"class":558},[548,3007,3008],{"class":562}," Get",[548,3010,595],{"class":558},[548,3012,3013],{"class":562}," Patch",[548,3015,595],{"class":558},[548,3017,3018],{"class":562}," Post",[548,3020,566],{"class":558},[548,3022,569],{"class":554},[548,3024,572],{"class":558},[548,3026,3027],{"class":575},"@heximon\u002Fhttp",[548,3029,579],{"class":558},[548,3031,582],{"class":558},[548,3033,3034,3036,3038,3040,3042,3044,3046,3048,3050,3053,3055],{"class":550,"line":585},[548,3035,555],{"class":554},[548,3037,559],{"class":558},[548,3039,1541],{"class":562},[548,3041,595],{"class":558},[548,3043,1606],{"class":562},[548,3045,566],{"class":558},[548,3047,569],{"class":554},[548,3049,572],{"class":558},[548,3051,3052],{"class":575},".\u002Ftask.schema",[548,3054,579],{"class":558},[548,3056,582],{"class":558},[548,3058,3059,3061,3063,3065,3067,3069,3071,3073,3075,3077,3080,3082],{"class":550,"line":619},[548,3060,555],{"class":554},[548,3062,559],{"class":558},[548,3064,877],{"class":554},[548,3066,1803],{"class":562},[548,3068,595],{"class":558},[548,3070,1881],{"class":562},[548,3072,566],{"class":558},[548,3074,569],{"class":554},[548,3076,572],{"class":558},[548,3078,3079],{"class":575},".\u002Ftasks.repository",[548,3081,579],{"class":558},[548,3083,582],{"class":558},[548,3085,3086],{"class":550,"line":626},[548,3087,623],{"emptyLinePlaceholder":622},[548,3089,3090,3093,3096],{"class":550,"line":633},[548,3091,3092],{"class":645},"interface",[548,3094,3095],{"class":880}," ErrorBody",[548,3097,670],{"class":558},[548,3099,3100,3102,3105,3107,3109],{"class":550,"line":639},[548,3101,1810],{"class":645},[548,3103,3104],{"class":676}," error",[548,3106,680],{"class":558},[548,3108,1832],{"class":880},[548,3110,582],{"class":558},[548,3112,3113],{"class":550,"line":673},[548,3114,1853],{"class":558},[548,3116,3117],{"class":550,"line":724},[548,3118,623],{"emptyLinePlaceholder":622},[548,3120,3121],{"class":550,"line":755},[548,3122,3123],{"class":629},"\u002F\u002F Routes are declared by each handler's action parameter type — the compiler reads `Get\u003C\"\u002F\">`,\n",[548,3125,3126],{"class":550,"line":797},[548,3127,3128],{"class":629},"\u002F\u002F `Post\u003C\"\u002F\", { body }>`, … off the signatures and builds the route table. Declared bodies are validated\n",[548,3130,3131],{"class":550,"line":807},[548,3132,3133],{"class":629},"\u002F\u002F before the handler runs; `readValidatedBody()` returns the parsed, typed result.\n",[548,3135,3136,3138,3140,3143,3145,3147,3149,3151,3153,3155,3157],{"class":550,"line":812},[548,3137,642],{"class":554},[548,3139,1191],{"class":645},[548,3141,3142],{"class":880}," TasksController",[548,3144,1884],{"class":645},[548,3146,2998],{"class":880},[548,3148,1202],{"class":558},[548,3150,579],{"class":558},[548,3152,2960],{"class":575},[548,3154,579],{"class":558},[548,3156,1212],{"class":558},[548,3158,670],{"class":558},[548,3160,3161,3163,3165,3167,3169,3171,3173,3175,3177,3179],{"class":550,"line":818},[548,3162,1893],{"class":645},[548,3164,1896],{"class":645},[548,3166,658],{"class":558},[548,3168,1901],{"class":645},[548,3170,1904],{"class":645},[548,3172,890],{"class":1372},[548,3174,680],{"class":558},[548,3176,1881],{"class":880},[548,3178,694],{"class":558},[548,3180,1215],{"class":558},[548,3182,3183],{"class":550,"line":837},[548,3184,623],{"emptyLinePlaceholder":622},[548,3186,3187,3189,3191,3193,3195,3198,3200,3202,3204,3206,3208,3210,3213,3215,3217,3219,3221,3223],{"class":550,"line":842},[548,3188,1893],{"class":645},[548,3190,1927],{"class":645},[548,3192,2038],{"class":676},[548,3194,658],{"class":558},[548,3196,3197],{"class":1372},"_action",[548,3199,680],{"class":558},[548,3201,3008],{"class":880},[548,3203,1202],{"class":558},[548,3205,579],{"class":558},[548,3207,1653],{"class":575},[548,3209,579],{"class":558},[548,3211,3212],{"class":558},">):",[548,3214,1936],{"class":880},[548,3216,1202],{"class":558},[548,3218,505],{"class":880},[548,3220,2049],{"class":562},[548,3222,1212],{"class":558},[548,3224,670],{"class":558},[548,3226,3227,3229,3231,3233,3235,3238,3240],{"class":550,"line":848},[548,3228,2123],{"class":554},[548,3230,1954],{"class":558},[548,3232,663],{"class":562},[548,3234,697],{"class":558},[548,3236,3237],{"class":655},"list",[548,3239,750],{"class":676},[548,3241,582],{"class":558},[548,3243,3244],{"class":550,"line":867},[548,3245,2023],{"class":558},[548,3247,3248],{"class":550,"line":872},[548,3249,623],{"emptyLinePlaceholder":622},[548,3251,3252,3254,3256,3259,3261,3264,3266,3268,3270,3272,3275,3277,3279,3281,3283,3285,3287,3289,3291],{"class":550,"line":1922},[548,3253,1893],{"class":645},[548,3255,1927],{"class":645},[548,3257,3258],{"class":676}," get",[548,3260,658],{"class":558},[548,3262,3263],{"class":1372},"action",[548,3265,680],{"class":558},[548,3267,3008],{"class":880},[548,3269,1202],{"class":558},[548,3271,579],{"class":558},[548,3273,3274],{"class":575},"\u002F:id",[548,3276,579],{"class":558},[548,3278,3212],{"class":558},[548,3280,1936],{"class":880},[548,3282,1202],{"class":558},[548,3284,505],{"class":880},[548,3286,2196],{"class":558},[548,3288,3095],{"class":880},[548,3290,1212],{"class":558},[548,3292,670],{"class":558},[548,3294,3295,3297,3299,3301,3304,3306,3308,3310,3313,3315,3318,3320,3322,3324],{"class":550,"line":1948},[548,3296,2059],{"class":645},[548,3298,1813],{"class":562},[548,3300,884],{"class":558},[548,3302,3303],{"class":655}," Number",[548,3305,658],{"class":676},[548,3307,3263],{"class":562},[548,3309,697],{"class":558},[548,3311,3312],{"class":562},"request",[548,3314,697],{"class":558},[548,3316,3317],{"class":562},"pathParams",[548,3319,697],{"class":558},[548,3321,689],{"class":562},[548,3323,694],{"class":676},[548,3325,582],{"class":558},[548,3327,3328,3330,3333,3335,3337,3339,3341,3343,3346,3348,3350,3352],{"class":550,"line":1980},[548,3329,2059],{"class":645},[548,3331,3332],{"class":562}," task",[548,3334,884],{"class":558},[548,3336,2067],{"class":554},[548,3338,1954],{"class":558},[548,3340,663],{"class":562},[548,3342,697],{"class":558},[548,3344,3345],{"class":655},"findById",[548,3347,658],{"class":676},[548,3349,689],{"class":562},[548,3351,694],{"class":676},[548,3353,582],{"class":558},[548,3355,3356],{"class":550,"line":1986},[548,3357,623],{"emptyLinePlaceholder":622},[548,3359,3360,3362,3364,3367,3369,3371,3373],{"class":550,"line":1992},[548,3361,2459],{"class":554},[548,3363,517],{"class":676},[548,3365,3366],{"class":562},"task",[548,3368,2314],{"class":558},[548,3370,2199],{"class":558},[548,3372,1427],{"class":676},[548,3374,1334],{"class":558},[548,3376,3377,3380,3382,3385,3387,3390,3392,3395],{"class":550,"line":1998},[548,3378,3379],{"class":562},"      action",[548,3381,697],{"class":558},[548,3383,3384],{"class":562},"response",[548,3386,697],{"class":558},[548,3388,3389],{"class":562},"status",[548,3391,884],{"class":558},[548,3393,3394],{"class":789}," 404",[548,3396,582],{"class":558},[548,3398,3399],{"class":550,"line":2004},[548,3400,623],{"emptyLinePlaceholder":622},[548,3402,3403,3406,3408,3410,3412,3415,3418,3421,3423,3425,3427,3430],{"class":550,"line":2010},[548,3404,3405],{"class":554},"      return",[548,3407,559],{"class":558},[548,3409,3104],{"class":676},[548,3411,680],{"class":558},[548,3413,3414],{"class":558}," `",[548,3416,3417],{"class":575},"No task with id ",[548,3419,3420],{"class":558},"${",[548,3422,689],{"class":562},[548,3424,800],{"class":558},[548,3426,697],{"class":575},[548,3428,3429],{"class":558},"`",[548,3431,2938],{"class":558},[548,3433,3434],{"class":550,"line":2020},[548,3435,2501],{"class":558},[548,3437,3438],{"class":550,"line":2026},[548,3439,623],{"emptyLinePlaceholder":622},[548,3441,3442,3444,3446],{"class":550,"line":2031},[548,3443,2123],{"class":554},[548,3445,3332],{"class":562},[548,3447,582],{"class":558},[548,3449,3450],{"class":550,"line":2056},[548,3451,2023],{"class":558},[548,3453,3454],{"class":550,"line":2115},[548,3455,623],{"emptyLinePlaceholder":622},[548,3457,3458,3460,3462,3464,3466,3468,3470,3472,3474,3476,3478,3480,3482,3484,3487,3489,3491,3494,3496,3498,3500,3502],{"class":550,"line":2120},[548,3459,1893],{"class":645},[548,3461,1927],{"class":645},[548,3463,2358],{"class":676},[548,3465,658],{"class":558},[548,3467,3263],{"class":1372},[548,3469,680],{"class":558},[548,3471,3018],{"class":880},[548,3473,1202],{"class":558},[548,3475,579],{"class":558},[548,3477,1653],{"class":575},[548,3479,579],{"class":558},[548,3481,595],{"class":558},[548,3483,559],{"class":558},[548,3485,3486],{"class":676}," body",[548,3488,680],{"class":558},[548,3490,1541],{"class":880},[548,3492,3493],{"class":558}," }>):",[548,3495,1936],{"class":880},[548,3497,1202],{"class":558},[548,3499,505],{"class":880},[548,3501,1212],{"class":558},[548,3503,670],{"class":558},[548,3505,3506,3508,3510,3512,3514,3517,3519,3521,3523,3526,3528],{"class":550,"line":2160},[548,3507,2059],{"class":645},[548,3509,3486],{"class":562},[548,3511,884],{"class":558},[548,3513,2067],{"class":554},[548,3515,3516],{"class":562}," action",[548,3518,697],{"class":558},[548,3520,3312],{"class":562},[548,3522,697],{"class":558},[548,3524,3525],{"class":655},"readValidatedBody",[548,3527,750],{"class":676},[548,3529,582],{"class":558},[548,3531,3532,3535,3537,3539,3541,3543,3545,3548],{"class":550,"line":2165},[548,3533,3534],{"class":562},"    action",[548,3536,697],{"class":558},[548,3538,3384],{"class":562},[548,3540,697],{"class":558},[548,3542,3389],{"class":562},[548,3544,884],{"class":558},[548,3546,3547],{"class":789}," 201",[548,3549,582],{"class":558},[548,3551,3552],{"class":550,"line":2170},[548,3553,623],{"emptyLinePlaceholder":622},[548,3555,3556,3558,3560,3562,3564,3567,3569,3571,3573,3575,3577],{"class":550,"line":2206},[548,3557,2123],{"class":554},[548,3559,1954],{"class":558},[548,3561,663],{"class":562},[548,3563,697],{"class":558},[548,3565,3566],{"class":655},"create",[548,3568,658],{"class":676},[548,3570,1440],{"class":562},[548,3572,697],{"class":558},[548,3574,738],{"class":562},[548,3576,694],{"class":676},[548,3578,582],{"class":558},[548,3580,3581],{"class":550,"line":2280},[548,3582,2023],{"class":558},[548,3584,3585],{"class":550,"line":2302},[548,3586,623],{"emptyLinePlaceholder":622},[548,3588,3589,3591,3593,3595,3597,3599,3601,3603,3605,3607,3609,3611,3613,3615,3617,3619,3621,3623,3625,3627,3629,3631,3633,3635],{"class":550,"line":2307},[548,3590,1893],{"class":645},[548,3592,1927],{"class":645},[548,3594,2545],{"class":676},[548,3596,658],{"class":558},[548,3598,3263],{"class":1372},[548,3600,680],{"class":558},[548,3602,3013],{"class":880},[548,3604,1202],{"class":558},[548,3606,579],{"class":558},[548,3608,3274],{"class":575},[548,3610,579],{"class":558},[548,3612,595],{"class":558},[548,3614,559],{"class":558},[548,3616,3486],{"class":676},[548,3618,680],{"class":558},[548,3620,1606],{"class":880},[548,3622,3493],{"class":558},[548,3624,1936],{"class":880},[548,3626,1202],{"class":558},[548,3628,505],{"class":880},[548,3630,2196],{"class":558},[548,3632,3095],{"class":880},[548,3634,1212],{"class":558},[548,3636,670],{"class":558},[548,3638,3639,3641,3643,3645,3647,3649,3651,3653,3655,3657,3659,3661,3663,3665],{"class":550,"line":2341},[548,3640,2059],{"class":645},[548,3642,1813],{"class":562},[548,3644,884],{"class":558},[548,3646,3303],{"class":655},[548,3648,658],{"class":676},[548,3650,3263],{"class":562},[548,3652,697],{"class":558},[548,3654,3312],{"class":562},[548,3656,697],{"class":558},[548,3658,3317],{"class":562},[548,3660,697],{"class":558},[548,3662,689],{"class":562},[548,3664,694],{"class":676},[548,3666,582],{"class":558},[548,3668,3669,3671,3673,3675,3677,3679,3681,3683,3685,3687,3689],{"class":550,"line":2346},[548,3670,2059],{"class":645},[548,3672,3486],{"class":562},[548,3674,884],{"class":558},[548,3676,2067],{"class":554},[548,3678,3516],{"class":562},[548,3680,697],{"class":558},[548,3682,3312],{"class":562},[548,3684,697],{"class":558},[548,3686,3525],{"class":655},[548,3688,750],{"class":676},[548,3690,582],{"class":558},[548,3692,3693,3695,3698,3700,3702,3704,3706,3708,3711,3713,3715,3717,3719,3721,3723,3725],{"class":550,"line":2351},[548,3694,2059],{"class":645},[548,3696,3697],{"class":562}," updated",[548,3699,884],{"class":558},[548,3701,2067],{"class":554},[548,3703,1954],{"class":558},[548,3705,663],{"class":562},[548,3707,697],{"class":558},[548,3709,3710],{"class":655},"setDone",[548,3712,658],{"class":676},[548,3714,689],{"class":562},[548,3716,595],{"class":558},[548,3718,3486],{"class":562},[548,3720,697],{"class":558},[548,3722,769],{"class":562},[548,3724,694],{"class":676},[548,3726,582],{"class":558},[548,3728,3729],{"class":550,"line":2381},[548,3730,623],{"emptyLinePlaceholder":622},[548,3732,3733,3735,3737,3740,3742,3744,3746],{"class":550,"line":2451},[548,3734,2459],{"class":554},[548,3736,517],{"class":676},[548,3738,3739],{"class":562},"updated",[548,3741,2314],{"class":558},[548,3743,2199],{"class":558},[548,3745,1427],{"class":676},[548,3747,1334],{"class":558},[548,3749,3750,3752,3754,3756,3758,3760,3762,3764],{"class":550,"line":2456},[548,3751,3379],{"class":562},[548,3753,697],{"class":558},[548,3755,3384],{"class":562},[548,3757,697],{"class":558},[548,3759,3389],{"class":562},[548,3761,884],{"class":558},[548,3763,3394],{"class":789},[548,3765,582],{"class":558},[548,3767,3768],{"class":550,"line":2474},[548,3769,623],{"emptyLinePlaceholder":622},[548,3771,3772,3774,3776,3778,3780,3782,3784,3786,3788,3790,3792,3794],{"class":550,"line":2498},[548,3773,3405],{"class":554},[548,3775,559],{"class":558},[548,3777,3104],{"class":676},[548,3779,680],{"class":558},[548,3781,3414],{"class":558},[548,3783,3417],{"class":575},[548,3785,3420],{"class":558},[548,3787,689],{"class":562},[548,3789,800],{"class":558},[548,3791,697],{"class":575},[548,3793,3429],{"class":558},[548,3795,2938],{"class":558},[548,3797,3798],{"class":550,"line":2504},[548,3799,2501],{"class":558},[548,3801,3802],{"class":550,"line":2509},[548,3803,623],{"emptyLinePlaceholder":622},[548,3805,3806,3808,3810],{"class":550,"line":2528},[548,3807,2123],{"class":554},[548,3809,3697],{"class":562},[548,3811,582],{"class":558},[548,3813,3814],{"class":550,"line":2533},[548,3815,2023],{"class":558},[548,3817,3818],{"class":550,"line":2538},[548,3819,623],{"emptyLinePlaceholder":622},[548,3821,3822,3824,3826,3828,3830,3832,3834,3836,3838,3840,3842,3844,3846,3848,3851,3853,3855,3857,3859,3861,3863,3865],{"class":550,"line":2580},[548,3823,1893],{"class":645},[548,3825,1927],{"class":645},[548,3827,2747],{"class":676},[548,3829,658],{"class":558},[548,3831,3263],{"class":1372},[548,3833,680],{"class":558},[548,3835,3003],{"class":880},[548,3837,1202],{"class":558},[548,3839,579],{"class":558},[548,3841,3274],{"class":575},[548,3843,579],{"class":558},[548,3845,3212],{"class":558},[548,3847,1936],{"class":880},[548,3849,3850],{"class":558},"\u003C{",[548,3852,2775],{"class":676},[548,3854,680],{"class":558},[548,3856,1818],{"class":880},[548,3858,566],{"class":558},[548,3860,2196],{"class":558},[548,3862,3095],{"class":880},[548,3864,1212],{"class":558},[548,3866,670],{"class":558},[548,3868,3869,3871,3873,3875,3877,3879,3881,3883,3885,3887,3889,3891,3893,3895],{"class":550,"line":2600},[548,3870,2059],{"class":645},[548,3872,1813],{"class":562},[548,3874,884],{"class":558},[548,3876,3303],{"class":655},[548,3878,658],{"class":676},[548,3880,3263],{"class":562},[548,3882,697],{"class":558},[548,3884,3312],{"class":562},[548,3886,697],{"class":558},[548,3888,3317],{"class":562},[548,3890,697],{"class":558},[548,3892,689],{"class":562},[548,3894,694],{"class":676},[548,3896,582],{"class":558},[548,3898,3899,3901,3904,3906,3908,3910,3912,3914,3917,3919,3921,3923],{"class":550,"line":2611},[548,3900,2059],{"class":645},[548,3902,3903],{"class":562}," removed",[548,3905,884],{"class":558},[548,3907,2067],{"class":554},[548,3909,1954],{"class":558},[548,3911,663],{"class":562},[548,3913,697],{"class":558},[548,3915,3916],{"class":655},"remove",[548,3918,658],{"class":676},[548,3920,689],{"class":562},[548,3922,694],{"class":676},[548,3924,582],{"class":558},[548,3926,3927],{"class":550,"line":2626},[548,3928,623],{"emptyLinePlaceholder":622},[548,3930,3931,3933,3935,3938,3941,3943],{"class":550,"line":2657},[548,3932,2459],{"class":554},[548,3934,517],{"class":676},[548,3936,3937],{"class":558},"!",[548,3939,3940],{"class":562},"removed",[548,3942,1427],{"class":676},[548,3944,1334],{"class":558},[548,3946,3947,3949,3951,3953,3955,3957,3959,3961],{"class":550,"line":2683},[548,3948,3379],{"class":562},[548,3950,697],{"class":558},[548,3952,3384],{"class":562},[548,3954,697],{"class":558},[548,3956,3389],{"class":562},[548,3958,884],{"class":558},[548,3960,3394],{"class":789},[548,3962,582],{"class":558},[548,3964,3965],{"class":550,"line":2694},[548,3966,623],{"emptyLinePlaceholder":622},[548,3968,3969,3971,3973,3975,3977,3979,3981,3983,3985,3987,3989,3991],{"class":550,"line":2699},[548,3970,3405],{"class":554},[548,3972,559],{"class":558},[548,3974,3104],{"class":676},[548,3976,680],{"class":558},[548,3978,3414],{"class":558},[548,3980,3417],{"class":575},[548,3982,3420],{"class":558},[548,3984,689],{"class":562},[548,3986,800],{"class":558},[548,3988,697],{"class":575},[548,3990,3429],{"class":558},[548,3992,2938],{"class":558},[548,3994,3995],{"class":550,"line":2730},[548,3996,2501],{"class":558},[548,3998,3999],{"class":550,"line":2735},[548,4000,623],{"emptyLinePlaceholder":622},[548,4002,4003,4005,4007,4009,4011,4013],{"class":550,"line":2740},[548,4004,2123],{"class":554},[548,4006,559],{"class":558},[548,4008,2775],{"class":676},[548,4010,680],{"class":558},[548,4012,1813],{"class":562},[548,4014,2938],{"class":558},[548,4016,4017],{"class":550,"line":2770},[548,4018,2023],{"class":558},[548,4020,4021],{"class":550,"line":2833},[548,4022,1853],{"class":558},[499,4024,4025],{},"The controller stays thin on purpose: read the validated input, call the repository, shape the response.",[523,4027,4029],{"id":4028},"wire-the-module","Wire the module",[499,4031,4032,4033,4036,4037,4039,4040,4043,4044,4047],{},"The feature module imports ",[503,4034,4035],{},"DatabaseModule"," so the repository can inject ",[503,4038,1673],{},", lists the\nrepository as a plain provider, and declares the controller under the ",[503,4041,4042],{},"http"," namespace. That config is the\nonly place the compiler looks — a typo'd sub-key like ",[503,4045,4046],{},"controllerz"," is a native TypeScript excess-property\nerror, not a silent miss.",[538,4049,4052],{"className":540,"code":4050,"filename":4051,"language":543,"meta":544,"style":544},"import { Module } from \"@heximon\u002Fruntime\";\nimport { DatabaseModule } from \"..\u002Fdatabase\u002Fdatabase.module\";\nimport { TasksController } from \".\u002Ftasks.controller\";\nimport { TasksRepository } from \".\u002Ftasks.repository\";\n\nexport class TasksModule extends Module({\n  imports: [DatabaseModule],\n  providers: [TasksRepository],\n  http: { controllers: [TasksController] },\n  exports: [TasksRepository],\n}) {}\n","src\u002Ftasks\u002Ftasks.module.ts",[503,4053,4054,4074,4095,4116,4136,4140,4157,4169,4180,4200,4210],{"__ignoreMap":544},[548,4055,4056,4058,4060,4062,4064,4066,4068,4070,4072],{"class":550,"line":551},[548,4057,555],{"class":554},[548,4059,559],{"class":558},[548,4061,1237],{"class":562},[548,4063,566],{"class":558},[548,4065,569],{"class":554},[548,4067,572],{"class":558},[548,4069,1246],{"class":575},[548,4071,579],{"class":558},[548,4073,582],{"class":558},[548,4075,4076,4078,4080,4082,4084,4086,4088,4091,4093],{"class":550,"line":585},[548,4077,555],{"class":554},[548,4079,559],{"class":558},[548,4081,1325],{"class":562},[548,4083,566],{"class":558},[548,4085,569],{"class":554},[548,4087,572],{"class":558},[548,4089,4090],{"class":575},"..\u002Fdatabase\u002Fdatabase.module",[548,4092,579],{"class":558},[548,4094,582],{"class":558},[548,4096,4097,4099,4101,4103,4105,4107,4109,4112,4114],{"class":550,"line":619},[548,4098,555],{"class":554},[548,4100,559],{"class":558},[548,4102,3142],{"class":562},[548,4104,566],{"class":558},[548,4106,569],{"class":554},[548,4108,572],{"class":558},[548,4110,4111],{"class":575},".\u002Ftasks.controller",[548,4113,579],{"class":558},[548,4115,582],{"class":558},[548,4117,4118,4120,4122,4124,4126,4128,4130,4132,4134],{"class":550,"line":626},[548,4119,555],{"class":554},[548,4121,559],{"class":558},[548,4123,1881],{"class":562},[548,4125,566],{"class":558},[548,4127,569],{"class":554},[548,4129,572],{"class":558},[548,4131,3079],{"class":575},[548,4133,579],{"class":558},[548,4135,582],{"class":558},[548,4137,4138],{"class":550,"line":633},[548,4139,623],{"emptyLinePlaceholder":622},[548,4141,4142,4144,4146,4149,4151,4153,4155],{"class":550,"line":639},[548,4143,642],{"class":554},[548,4145,1191],{"class":645},[548,4147,4148],{"class":880}," TasksModule",[548,4150,1197],{"class":645},[548,4152,1237],{"class":655},[548,4154,658],{"class":562},[548,4156,1334],{"class":558},[548,4158,4159,4162,4164,4167],{"class":550,"line":673},[548,4160,4161],{"class":676},"  imports",[548,4163,680],{"class":558},[548,4165,4166],{"class":562}," [DatabaseModule]",[548,4168,721],{"class":558},[548,4170,4171,4173,4175,4178],{"class":550,"line":724},[548,4172,1339],{"class":676},[548,4174,680],{"class":558},[548,4176,4177],{"class":562}," [TasksRepository]",[548,4179,721],{"class":558},[548,4181,4182,4185,4187,4189,4192,4194,4197],{"class":550,"line":755},[548,4183,4184],{"class":676},"  http",[548,4186,680],{"class":558},[548,4188,559],{"class":558},[548,4190,4191],{"class":676}," controllers",[548,4193,680],{"class":558},[548,4195,4196],{"class":562}," [TasksController] ",[548,4198,4199],{"class":558},"},\n",[548,4201,4202,4204,4206,4208],{"class":550,"line":797},[548,4203,1413],{"class":676},[548,4205,680],{"class":558},[548,4207,4177],{"class":562},[548,4209,721],{"class":558},[548,4211,4212,4214,4216],{"class":550,"line":807},[548,4213,800],{"class":558},[548,4215,1427],{"class":562},[548,4217,1430],{"class":558},[499,4219,4220],{},"The only compiler plugin this app registers is the HTTP one — the database needs none:",[538,4222,4225],{"className":540,"code":4223,"filename":4224,"language":543,"meta":544,"style":544},"import { defineHeximonConfig } from \"@heximon\u002Fbuild\";\nimport { HttpPlugin } from \"@heximon\u002Fhttp\u002Fcompiler\";\n\n\u002F\u002F The capability manifest: one compiler plugin per capability. The entire HTTP layer is the one plugin\n\u002F\u002F below; everything you add later (events, CQRS, queues, …) is one more entry in the same list.\nexport default defineHeximonConfig({ plugins: [new HttpPlugin()] });\n","heximon.config.ts",[503,4226,4227,4249,4271,4275,4280,4285],{"__ignoreMap":544},[548,4228,4229,4231,4233,4236,4238,4240,4242,4245,4247],{"class":550,"line":551},[548,4230,555],{"class":554},[548,4232,559],{"class":558},[548,4234,4235],{"class":562}," defineHeximonConfig",[548,4237,566],{"class":558},[548,4239,569],{"class":554},[548,4241,572],{"class":558},[548,4243,4244],{"class":575},"@heximon\u002Fbuild",[548,4246,579],{"class":558},[548,4248,582],{"class":558},[548,4250,4251,4253,4255,4258,4260,4262,4264,4267,4269],{"class":550,"line":585},[548,4252,555],{"class":554},[548,4254,559],{"class":558},[548,4256,4257],{"class":562}," HttpPlugin",[548,4259,566],{"class":558},[548,4261,569],{"class":554},[548,4263,572],{"class":558},[548,4265,4266],{"class":575},"@heximon\u002Fhttp\u002Fcompiler",[548,4268,579],{"class":558},[548,4270,582],{"class":558},[548,4272,4273],{"class":550,"line":619},[548,4274,623],{"emptyLinePlaceholder":622},[548,4276,4277],{"class":550,"line":626},[548,4278,4279],{"class":629},"\u002F\u002F The capability manifest: one compiler plugin per capability. The entire HTTP layer is the one plugin\n",[548,4281,4282],{"class":550,"line":633},[548,4283,4284],{"class":629},"\u002F\u002F below; everything you add later (events, CQRS, queues, …) is one more entry in the same list.\n",[548,4286,4287,4289,4292,4294,4296,4298,4301,4303,4305,4308,4310,4313,4315,4317],{"class":550,"line":639},[548,4288,642],{"class":554},[548,4290,4291],{"class":554}," default",[548,4293,4235],{"class":655},[548,4295,658],{"class":562},[548,4297,705],{"class":558},[548,4299,4300],{"class":676}," plugins",[548,4302,680],{"class":558},[548,4304,2386],{"class":562},[548,4306,4307],{"class":558},"new",[548,4309,4257],{"class":655},[548,4311,4312],{"class":562},"()] ",[548,4314,800],{"class":558},[548,4316,694],{"class":562},[548,4318,582],{"class":558},[523,4320,4322],{"id":4321},"test-the-round-trip","Test the round-trip",[499,4324,4325,4326,4329,4330,4333,4334,4337],{},"Compile and boot the generated server in-process with ",[503,4327,4328],{},"createTestApp",", then drive the endpoints through\n",[503,4331,4332],{},"createTestClient"," — the exact pipeline ",[503,4335,4336],{},"pnpm dev"," runs, with no network and a fresh isolated app per call.",[538,4339,4342],{"className":540,"code":4340,"filename":4341,"language":543,"meta":544,"style":544},"import { createTestClient } from \"@heximon\u002Fhttp\u002Ftesting\";\nimport { createTestApp, type TestApp } from \"@heximon\u002Ftesting\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { afterAll, beforeAll, expect, test } from \"vitest\";\n\n\u002F\u002F An in-process end-to-end test: createTestApp compiles src\u002F (the exact pipeline `pnpm dev` runs) and\n\u002F\u002F boots a fresh isolated app; createTestClient drives real requests through the generated routes.\nconst root = join(dirname(fileURLToPath(import.meta.url)), \"..\");\n\nlet app: TestApp;\n\nbeforeAll(async () => {\n  app = await createTestApp({ root });\n});\n\nafterAll(() => app[Symbol.asyncDispose]());\n\ntest(\"creates a task and reads it back\", async () => {\n  const client = createTestClient(app);\n\n  const created = await client.request(\n    new Request(\"http:\u002F\u002Flocalhost\u002Ftasks\", {\n      method: \"POST\",\n      headers: { \"content-type\": \"application\u002Fjson\" },\n      body: JSON.stringify({ title: \"Write docs\" }),\n    }),\n  );\n  expect(created.status).toBe(201);\n  const task = (await created.json()) as { id: number; title: string; done: boolean };\n  expect(task.title).toBe(\"Write docs\");\n  expect(task.done).toBe(false);\n\n  const list = await client.request(new Request(\"http:\u002F\u002Flocalhost\u002Ftasks\"));\n  expect(await list.json()).toEqual([task]);\n});\n\ntest(\"rejects a create without a title\", async () => {\n  const client = createTestClient(app);\n\n  const response = await client.request(\n    new Request(\"http:\u002F\u002Flocalhost\u002Ftasks\", {\n      method: \"POST\",\n      headers: { \"content-type\": \"application\u002Fjson\" },\n      body: JSON.stringify({}),\n    }),\n  );\n\n  expect(response.status).toBe(400);\n});\n","test\u002Ftasks.test.ts",[503,4343,4344,4366,4395,4422,4444,4481,4485,4490,4495,4544,4548,4562,4566,4583,4607,4615,4619,4640,4644,4668,4689,4693,4713,4734,4750,4778,4814,4823,4830,4860,4913,4943,4970,4974,5008,5040,5048,5052,5075,5093,5097,5116,5134,5148,5172,5193,5201,5207,5211,5238],{"__ignoreMap":544},[548,4345,4346,4348,4350,4353,4355,4357,4359,4362,4364],{"class":550,"line":551},[548,4347,555],{"class":554},[548,4349,559],{"class":558},[548,4351,4352],{"class":562}," createTestClient",[548,4354,566],{"class":558},[548,4356,569],{"class":554},[548,4358,572],{"class":558},[548,4360,4361],{"class":575},"@heximon\u002Fhttp\u002Ftesting",[548,4363,579],{"class":558},[548,4365,582],{"class":558},[548,4367,4368,4370,4372,4375,4377,4379,4382,4384,4386,4388,4391,4393],{"class":550,"line":585},[548,4369,555],{"class":554},[548,4371,559],{"class":558},[548,4373,4374],{"class":562}," createTestApp",[548,4376,595],{"class":558},[548,4378,877],{"class":554},[548,4380,4381],{"class":562}," TestApp",[548,4383,566],{"class":558},[548,4385,569],{"class":554},[548,4387,572],{"class":558},[548,4389,4390],{"class":575},"@heximon\u002Ftesting",[548,4392,579],{"class":558},[548,4394,582],{"class":558},[548,4396,4397,4399,4401,4404,4406,4409,4411,4413,4415,4418,4420],{"class":550,"line":619},[548,4398,555],{"class":554},[548,4400,559],{"class":558},[548,4402,4403],{"class":562}," dirname",[548,4405,595],{"class":558},[548,4407,4408],{"class":562}," join",[548,4410,566],{"class":558},[548,4412,569],{"class":554},[548,4414,572],{"class":558},[548,4416,4417],{"class":575},"node:path",[548,4419,579],{"class":558},[548,4421,582],{"class":558},[548,4423,4424,4426,4428,4431,4433,4435,4437,4440,4442],{"class":550,"line":626},[548,4425,555],{"class":554},[548,4427,559],{"class":558},[548,4429,4430],{"class":562}," fileURLToPath",[548,4432,566],{"class":558},[548,4434,569],{"class":554},[548,4436,572],{"class":558},[548,4438,4439],{"class":575},"node:url",[548,4441,579],{"class":558},[548,4443,582],{"class":558},[548,4445,4446,4448,4450,4453,4455,4458,4460,4463,4465,4468,4470,4472,4474,4477,4479],{"class":550,"line":633},[548,4447,555],{"class":554},[548,4449,559],{"class":558},[548,4451,4452],{"class":562}," afterAll",[548,4454,595],{"class":558},[548,4456,4457],{"class":562}," beforeAll",[548,4459,595],{"class":558},[548,4461,4462],{"class":562}," expect",[548,4464,595],{"class":558},[548,4466,4467],{"class":562}," test",[548,4469,566],{"class":558},[548,4471,569],{"class":554},[548,4473,572],{"class":558},[548,4475,4476],{"class":575},"vitest",[548,4478,579],{"class":558},[548,4480,582],{"class":558},[548,4482,4483],{"class":550,"line":639},[548,4484,623],{"emptyLinePlaceholder":622},[548,4486,4487],{"class":550,"line":673},[548,4488,4489],{"class":629},"\u002F\u002F An in-process end-to-end test: createTestApp compiles src\u002F (the exact pipeline `pnpm dev` runs) and\n",[548,4491,4492],{"class":550,"line":724},[548,4493,4494],{"class":629},"\u002F\u002F boots a fresh isolated app; createTestClient drives real requests through the generated routes.\n",[548,4496,4497,4500,4503,4505,4507,4509,4512,4514,4517,4519,4521,4523,4526,4528,4531,4533,4535,4538,4540,4542],{"class":550,"line":755},[548,4498,4499],{"class":645},"const",[548,4501,4502],{"class":562}," root ",[548,4504,652],{"class":558},[548,4506,4408],{"class":655},[548,4508,658],{"class":562},[548,4510,4511],{"class":655},"dirname",[548,4513,658],{"class":562},[548,4515,4516],{"class":655},"fileURLToPath",[548,4518,658],{"class":562},[548,4520,555],{"class":554},[548,4522,697],{"class":558},[548,4524,4525],{"class":562},"meta",[548,4527,697],{"class":558},[548,4529,4530],{"class":562},"url))",[548,4532,595],{"class":558},[548,4534,572],{"class":558},[548,4536,4537],{"class":575},"..",[548,4539,579],{"class":558},[548,4541,694],{"class":562},[548,4543,582],{"class":558},[548,4545,4546],{"class":550,"line":797},[548,4547,623],{"emptyLinePlaceholder":622},[548,4549,4550,4553,4556,4558,4560],{"class":550,"line":807},[548,4551,4552],{"class":645},"let",[548,4554,4555],{"class":562}," app",[548,4557,680],{"class":558},[548,4559,4381],{"class":880},[548,4561,582],{"class":558},[548,4563,4564],{"class":550,"line":812},[548,4565,623],{"emptyLinePlaceholder":622},[548,4567,4568,4571,4573,4576,4579,4581],{"class":550,"line":818},[548,4569,4570],{"class":655},"beforeAll",[548,4572,658],{"class":562},[548,4574,4575],{"class":645},"async",[548,4577,4578],{"class":558}," ()",[548,4580,1382],{"class":645},[548,4582,670],{"class":558},[548,4584,4585,4588,4590,4592,4594,4596,4598,4601,4603,4605],{"class":550,"line":837},[548,4586,4587],{"class":562},"  app",[548,4589,884],{"class":558},[548,4591,2067],{"class":554},[548,4593,4374],{"class":655},[548,4595,658],{"class":676},[548,4597,705],{"class":558},[548,4599,4600],{"class":562}," root",[548,4602,566],{"class":558},[548,4604,694],{"class":676},[548,4606,582],{"class":558},[548,4608,4609,4611,4613],{"class":550,"line":842},[548,4610,800],{"class":558},[548,4612,694],{"class":562},[548,4614,582],{"class":558},[548,4616,4617],{"class":550,"line":848},[548,4618,623],{"emptyLinePlaceholder":622},[548,4620,4621,4624,4626,4628,4630,4633,4635,4638],{"class":550,"line":867},[548,4622,4623],{"class":655},"afterAll",[548,4625,658],{"class":562},[548,4627,750],{"class":558},[548,4629,1382],{"class":645},[548,4631,4632],{"class":562}," app[Symbol",[548,4634,697],{"class":558},[548,4636,4637],{"class":562},"asyncDispose]())",[548,4639,582],{"class":558},[548,4641,4642],{"class":550,"line":872},[548,4643,623],{"emptyLinePlaceholder":622},[548,4645,4646,4649,4651,4653,4656,4658,4660,4662,4664,4666],{"class":550,"line":1922},[548,4647,4648],{"class":655},"test",[548,4650,658],{"class":562},[548,4652,579],{"class":558},[548,4654,4655],{"class":575},"creates a task and reads it back",[548,4657,579],{"class":558},[548,4659,595],{"class":558},[548,4661,1927],{"class":645},[548,4663,4578],{"class":558},[548,4665,1382],{"class":645},[548,4667,670],{"class":558},[548,4669,4670,4673,4676,4678,4680,4682,4685,4687],{"class":550,"line":1948},[548,4671,4672],{"class":645},"  const",[548,4674,4675],{"class":562}," client",[548,4677,884],{"class":558},[548,4679,4352],{"class":655},[548,4681,658],{"class":676},[548,4683,4684],{"class":562},"app",[548,4686,694],{"class":676},[548,4688,582],{"class":558},[548,4690,4691],{"class":550,"line":1980},[548,4692,623],{"emptyLinePlaceholder":622},[548,4694,4695,4697,4700,4702,4704,4706,4708,4710],{"class":550,"line":1986},[548,4696,4672],{"class":645},[548,4698,4699],{"class":562}," created",[548,4701,884],{"class":558},[548,4703,2067],{"class":554},[548,4705,4675],{"class":562},[548,4707,697],{"class":558},[548,4709,3312],{"class":655},[548,4711,4712],{"class":676},"(\n",[548,4714,4715,4718,4721,4723,4725,4728,4730,4732],{"class":550,"line":1992},[548,4716,4717],{"class":558},"    new",[548,4719,4720],{"class":655}," Request",[548,4722,658],{"class":676},[548,4724,579],{"class":558},[548,4726,4727],{"class":575},"http:\u002F\u002Flocalhost\u002Ftasks",[548,4729,579],{"class":558},[548,4731,595],{"class":558},[548,4733,670],{"class":558},[548,4735,4736,4739,4741,4743,4746,4748],{"class":550,"line":1998},[548,4737,4738],{"class":676},"      method",[548,4740,680],{"class":558},[548,4742,572],{"class":558},[548,4744,4745],{"class":575},"POST",[548,4747,579],{"class":558},[548,4749,721],{"class":558},[548,4751,4752,4755,4757,4759,4761,4764,4766,4768,4770,4773,4775],{"class":550,"line":2004},[548,4753,4754],{"class":676},"      headers",[548,4756,680],{"class":558},[548,4758,559],{"class":558},[548,4760,572],{"class":558},[548,4762,4763],{"class":676},"content-type",[548,4765,579],{"class":558},[548,4767,680],{"class":558},[548,4769,572],{"class":558},[548,4771,4772],{"class":575},"application\u002Fjson",[548,4774,579],{"class":558},[548,4776,4777],{"class":558}," },\n",[548,4779,4780,4783,4785,4788,4790,4793,4795,4797,4799,4801,4803,4806,4808,4810,4812],{"class":550,"line":2010},[548,4781,4782],{"class":676},"      body",[548,4784,680],{"class":558},[548,4786,4787],{"class":562}," JSON",[548,4789,697],{"class":558},[548,4791,4792],{"class":655},"stringify",[548,4794,658],{"class":676},[548,4796,705],{"class":558},[548,4798,1827],{"class":676},[548,4800,680],{"class":558},[548,4802,572],{"class":558},[548,4804,4805],{"class":575},"Write docs",[548,4807,579],{"class":558},[548,4809,566],{"class":558},[548,4811,694],{"class":676},[548,4813,721],{"class":558},[548,4815,4816,4819,4821],{"class":550,"line":2020},[548,4817,4818],{"class":558},"    }",[548,4820,694],{"class":676},[548,4822,721],{"class":558},[548,4824,4825,4828],{"class":550,"line":2026},[548,4826,4827],{"class":676},"  )",[548,4829,582],{"class":558},[548,4831,4832,4835,4837,4840,4842,4844,4846,4848,4851,4853,4856,4858],{"class":550,"line":2031},[548,4833,4834],{"class":655},"  expect",[548,4836,658],{"class":676},[548,4838,4839],{"class":562},"created",[548,4841,697],{"class":558},[548,4843,3389],{"class":562},[548,4845,694],{"class":676},[548,4847,697],{"class":558},[548,4849,4850],{"class":655},"toBe",[548,4852,658],{"class":676},[548,4854,4855],{"class":789},"201",[548,4857,694],{"class":676},[548,4859,582],{"class":558},[548,4861,4862,4864,4866,4868,4870,4873,4875,4877,4880,4883,4886,4888,4890,4892,4894,4897,4899,4901,4903,4905,4907,4909,4911],{"class":550,"line":2056},[548,4863,4672],{"class":645},[548,4865,3332],{"class":562},[548,4867,884],{"class":558},[548,4869,517],{"class":676},[548,4871,4872],{"class":554},"await",[548,4874,4699],{"class":562},[548,4876,697],{"class":558},[548,4878,4879],{"class":655},"json",[548,4881,4882],{"class":676},"()) ",[548,4884,4885],{"class":554},"as",[548,4887,559],{"class":558},[548,4889,1813],{"class":676},[548,4891,680],{"class":558},[548,4893,1818],{"class":880},[548,4895,4896],{"class":558},";",[548,4898,1827],{"class":676},[548,4900,680],{"class":558},[548,4902,1832],{"class":880},[548,4904,4896],{"class":558},[548,4906,1841],{"class":676},[548,4908,680],{"class":558},[548,4910,1846],{"class":880},[548,4912,2938],{"class":558},[548,4914,4915,4917,4919,4921,4923,4925,4927,4929,4931,4933,4935,4937,4939,4941],{"class":550,"line":2115},[548,4916,4834],{"class":655},[548,4918,658],{"class":676},[548,4920,3366],{"class":562},[548,4922,697],{"class":558},[548,4924,738],{"class":562},[548,4926,694],{"class":676},[548,4928,697],{"class":558},[548,4930,4850],{"class":655},[548,4932,658],{"class":676},[548,4934,579],{"class":558},[548,4936,4805],{"class":575},[548,4938,579],{"class":558},[548,4940,694],{"class":676},[548,4942,582],{"class":558},[548,4944,4945,4947,4949,4951,4953,4955,4957,4959,4961,4963,4966,4968],{"class":550,"line":2120},[548,4946,4834],{"class":655},[548,4948,658],{"class":676},[548,4950,3366],{"class":562},[548,4952,697],{"class":558},[548,4954,769],{"class":562},[548,4956,694],{"class":676},[548,4958,697],{"class":558},[548,4960,4850],{"class":655},[548,4962,658],{"class":676},[548,4964,4965],{"class":713},"false",[548,4967,694],{"class":676},[548,4969,582],{"class":558},[548,4971,4972],{"class":550,"line":2160},[548,4973,623],{"emptyLinePlaceholder":622},[548,4975,4976,4978,4980,4982,4984,4986,4988,4990,4992,4994,4996,4998,5000,5002,5004,5006],{"class":550,"line":2165},[548,4977,4672],{"class":645},[548,4979,2038],{"class":562},[548,4981,884],{"class":558},[548,4983,2067],{"class":554},[548,4985,4675],{"class":562},[548,4987,697],{"class":558},[548,4989,3312],{"class":655},[548,4991,658],{"class":676},[548,4993,4307],{"class":558},[548,4995,4720],{"class":655},[548,4997,658],{"class":676},[548,4999,579],{"class":558},[548,5001,4727],{"class":575},[548,5003,579],{"class":558},[548,5005,2155],{"class":676},[548,5007,582],{"class":558},[548,5009,5010,5012,5014,5016,5018,5020,5022,5025,5027,5030,5033,5035,5038],{"class":550,"line":2170},[548,5011,4834],{"class":655},[548,5013,658],{"class":676},[548,5015,4872],{"class":554},[548,5017,2038],{"class":562},[548,5019,697],{"class":558},[548,5021,4879],{"class":655},[548,5023,5024],{"class":676},"())",[548,5026,697],{"class":558},[548,5028,5029],{"class":655},"toEqual",[548,5031,5032],{"class":676},"([",[548,5034,3366],{"class":562},[548,5036,5037],{"class":676},"])",[548,5039,582],{"class":558},[548,5041,5042,5044,5046],{"class":550,"line":2206},[548,5043,800],{"class":558},[548,5045,694],{"class":562},[548,5047,582],{"class":558},[548,5049,5050],{"class":550,"line":2280},[548,5051,623],{"emptyLinePlaceholder":622},[548,5053,5054,5056,5058,5060,5063,5065,5067,5069,5071,5073],{"class":550,"line":2302},[548,5055,4648],{"class":655},[548,5057,658],{"class":562},[548,5059,579],{"class":558},[548,5061,5062],{"class":575},"rejects a create without a title",[548,5064,579],{"class":558},[548,5066,595],{"class":558},[548,5068,1927],{"class":645},[548,5070,4578],{"class":558},[548,5072,1382],{"class":645},[548,5074,670],{"class":558},[548,5076,5077,5079,5081,5083,5085,5087,5089,5091],{"class":550,"line":2307},[548,5078,4672],{"class":645},[548,5080,4675],{"class":562},[548,5082,884],{"class":558},[548,5084,4352],{"class":655},[548,5086,658],{"class":676},[548,5088,4684],{"class":562},[548,5090,694],{"class":676},[548,5092,582],{"class":558},[548,5094,5095],{"class":550,"line":2341},[548,5096,623],{"emptyLinePlaceholder":622},[548,5098,5099,5101,5104,5106,5108,5110,5112,5114],{"class":550,"line":2346},[548,5100,4672],{"class":645},[548,5102,5103],{"class":562}," response",[548,5105,884],{"class":558},[548,5107,2067],{"class":554},[548,5109,4675],{"class":562},[548,5111,697],{"class":558},[548,5113,3312],{"class":655},[548,5115,4712],{"class":676},[548,5117,5118,5120,5122,5124,5126,5128,5130,5132],{"class":550,"line":2351},[548,5119,4717],{"class":558},[548,5121,4720],{"class":655},[548,5123,658],{"class":676},[548,5125,579],{"class":558},[548,5127,4727],{"class":575},[548,5129,579],{"class":558},[548,5131,595],{"class":558},[548,5133,670],{"class":558},[548,5135,5136,5138,5140,5142,5144,5146],{"class":550,"line":2381},[548,5137,4738],{"class":676},[548,5139,680],{"class":558},[548,5141,572],{"class":558},[548,5143,4745],{"class":575},[548,5145,579],{"class":558},[548,5147,721],{"class":558},[548,5149,5150,5152,5154,5156,5158,5160,5162,5164,5166,5168,5170],{"class":550,"line":2451},[548,5151,4754],{"class":676},[548,5153,680],{"class":558},[548,5155,559],{"class":558},[548,5157,572],{"class":558},[548,5159,4763],{"class":676},[548,5161,579],{"class":558},[548,5163,680],{"class":558},[548,5165,572],{"class":558},[548,5167,4772],{"class":575},[548,5169,579],{"class":558},[548,5171,4777],{"class":558},[548,5173,5174,5176,5178,5180,5182,5184,5186,5189,5191],{"class":550,"line":2456},[548,5175,4782],{"class":676},[548,5177,680],{"class":558},[548,5179,4787],{"class":562},[548,5181,697],{"class":558},[548,5183,4792],{"class":655},[548,5185,658],{"class":676},[548,5187,5188],{"class":558},"{}",[548,5190,694],{"class":676},[548,5192,721],{"class":558},[548,5194,5195,5197,5199],{"class":550,"line":2474},[548,5196,4818],{"class":558},[548,5198,694],{"class":676},[548,5200,721],{"class":558},[548,5202,5203,5205],{"class":550,"line":2498},[548,5204,4827],{"class":676},[548,5206,582],{"class":558},[548,5208,5209],{"class":550,"line":2504},[548,5210,623],{"emptyLinePlaceholder":622},[548,5212,5213,5215,5217,5219,5221,5223,5225,5227,5229,5231,5234,5236],{"class":550,"line":2509},[548,5214,4834],{"class":655},[548,5216,658],{"class":676},[548,5218,3384],{"class":562},[548,5220,697],{"class":558},[548,5222,3389],{"class":562},[548,5224,694],{"class":676},[548,5226,697],{"class":558},[548,5228,4850],{"class":655},[548,5230,658],{"class":676},[548,5232,5233],{"class":789},"400",[548,5235,694],{"class":676},[548,5237,582],{"class":558},[548,5239,5240,5242,5244],{"class":550,"line":2528},[548,5241,800],{"class":558},[548,5243,694],{"class":562},[548,5245,582],{"class":558},[499,5247,5248,5254,5255,5257,5258,5260],{},[508,5249,5251,5252,516],{"href":510,"rel":5250},[512],"the ",[503,5253,515],{},"'s\n",[503,5256,4341],{}," runs this exact flow, plus the missing-title ",[503,5259,5233],{}," case above.",[523,5262,5264],{"id":5263},"pitfalls","Pitfalls",[499,5266,5267,5273,5274,5277,5278,5280,5281,5283],{},[1457,5268,5269,5270,697],{},"Putting a CRUD handler in ",[503,5271,5272],{},"providers"," Concept classes are discovered under their plugin's namespace: a\ncontroller goes under ",[503,5275,5276],{},"http: { controllers }",", while only plain injectables — the repository — belong in\n",[503,5279,5272],{},". List a controller in ",[503,5282,5272],{}," and it's never wired as a route.",[499,5285,5286,5293,5294,5296,5297,5299,5300,697],{},[1457,5287,5288,5289,5292],{},"Booting ",[503,5290,5291],{},"CREATE TABLE IF NOT EXISTS"," against a persistent database."," That's fine for the ",[503,5295,1053],{},"\ndatabase this recipe uses, which starts empty every boot. Once you swap in a file-backed or hosted URL, a\nsecond boot runs against a database that already has the table — and a real schema change needs a real\nmigration, not an ",[503,5298,1681],{}," side effect. See ",[508,5301,92],{"href":93},[499,5303,5304,5309,5310,5313,5314,5316,5317,5319],{},[1457,5305,5306,5307,697],{},"Forgetting ",[503,5308,2980],{}," Reading ",[503,5311,5312],{},"action.request.json()"," directly skips the route's declared\n",[503,5315,1440],{}," schema — an invalid payload reaches your handler instead of failing with a ",[503,5318,5233],{}," before it runs.",[523,5321,5323],{"id":5322},"why-this-works","Why this works",[499,5325,5326,5327,5330,5331,5333,5334,5336,5337,5340],{},"Every piece you wrote is a plain class, and the compiler reads three things from your source: the interface\neach class implements (so ",[503,5328,5329],{},"TasksController"," is a controller), the constructor parameter types (so the\ncontroller gets a ",[503,5332,2956],{}," and the repository an ",[503,5335,1673],{},"), and the module config. From that\nit generates plain JavaScript that constructs everything directly — roughly\n",[503,5338,5339],{},"new TasksController(new TasksRepository(database))",", no runtime container, no reflection. Startup is instant.",[499,5342,5343,5344,5349,5350,521],{},"The full feature is a runnable starter:\n",[508,5345,5347],{"href":510,"rel":5346},[512],[503,5348,515],{},"\n(",[503,5351,520],{},[499,5353,5354,5355,697],{},"Domain rules accumulating — an invariant that has to hold no matter who calls in, or a value object like a\nvalidated email? The DDD variant of this recipe is ",[508,5356,5357],{"href":471},"Model a DDD aggregate",[499,5359,5360,5361,5364],{},"When this feature grows up — a shared contract with a typed client, CQRS command\u002Fquery handlers, an\naggregate repository over Drizzle, and validated pagination — ",[508,5362,5363],{"href":490},"Build a production CRUD\nAPI"," walks the full best-practice chain over the same kind of resource.",[523,5366,5368],{"id":5367},"see-also","See also",[5370,5371,5372,5382,5391,5412,5418,5423,5441],"ul",{},[5373,5374,5375,5377,5378,5381],"li",{},[508,5376,57],{"href":58}," — both controller modes (inline, and contract mode — where the contract\nbinds via ",[503,5379,5380],{},"Controller","'s type argument), middleware, responses, and how routes are declared by parameter\ntype, in depth.",[5373,5383,5384,5386,5387,5390],{},[508,5385,77],{"href":78}," — this same schema → config → named database → ",[503,5388,5389],{},"useFactory"," shape,\nbuilt up one step at a time.",[5373,5392,5393,5395,5396,5398,5399,5402,5403,1653,5405,1653,5407,1653,5409,5411],{},[508,5394,1645],{"href":63}," — ",[503,5397,1454],{}," \u002F ",[503,5400,5401],{},"SchemaArray",", the ",[503,5404,1652],{},[503,5406,1656],{},[503,5408,1659],{},[503,5410,1662],{},"\nderivations, and bringing your own validator.",[5373,5413,5414,5417],{},[508,5415,5416],{"href":83},"Drizzle Persistence"," — repositories, value-object columns, transactions, and the three\ndialects.",[5373,5419,5420,5422],{},[508,5421,5357],{"href":471}," — when domain rules earn an aggregate root, value\nobjects, and optimistic-concurrency saves instead of a plain repository.",[5373,5424,5425,5428,5429],{},[508,5426,5427],{"href":490},"Build a production CRUD API"," — the same resource as a shared contract\n",[5370,5430,5431],{},[5373,5432,5433,5434,1653,5437,5440],{},"typed client, CQRS handlers, a Drizzle aggregate repository, and ",[503,5435,5436],{},"QuerySchema",[503,5438,5439],{},"PaginatedResponseSchema","\npagination.",[5373,5442,5443,5448,5449,5451,5452,697],{},[508,5444,5251,5446,516],{"href":510,"rel":5445},[512],[503,5447,515],{},"\n— this exact feature as a runnable app (",[503,5450,520],{},"), plus a test that\ndrives the endpoints and proves the validation ",[503,5453,5233],{},[5455,5456,5457],"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 .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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}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 .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":544,"searchDepth":585,"depth":585,"links":5459},[5460,5461,5462,5463,5464,5465,5466,5467,5468],{"id":525,"depth":585,"text":526},{"id":1433,"depth":585,"text":1434},{"id":1666,"depth":585,"text":1667},{"id":2969,"depth":585,"text":2970},{"id":4028,"depth":585,"text":4029},{"id":4321,"depth":585,"text":4322},{"id":5263,"depth":585,"text":5264},{"id":5322,"depth":585,"text":5323},{"id":5367,"depth":585,"text":5368},"A typed CRUD feature end-to-end — a zod-validated body, an inline-route Controller, a plain repository over Drizzle, boot-time table creation, and an in-process test.","md",null,{},{"icon":80},{"title":453,"description":5469},"TbBExRM_Y0a95IDVsFVGGlqePNCvUbIi6JN2vQhGE1Y",[5477,5479],{"title":449,"path":450,"stem":451,"description":5478,"icon":178,"children":-1},"Expose liveness and readiness over an app-owned controller with an injected HealthRegistry, and run a nightly report on a build-time-validated cron with ScheduledHandler.",{"title":457,"path":458,"stem":459,"description":5480,"icon":100,"children":-1},"Protect routes end-to-end with IdentityKeyPair, JWTFactory, JWTVerifier, PasswordHashingAlgorithm, AuthContext, JWTAuthMiddleware, and scope guards — register, login, and a scope-guarded endpoint.",1783300761903]