[{"data":1,"prerenderedAt":5929},["ShallowReactive",2],{"navigation_docs":3,"-docs-essentials-createtestapp":493,"-docs-essentials-createtestapp-surround":5924},[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":116,"body":495,"description":5917,"extension":5918,"links":5919,"meta":5920,"navigation":5921,"path":117,"seo":5922,"stem":118,"__hash__":5923},"docs\u002Fdocs\u002F02.essentials\u002F14.createtestapp.md",{"type":496,"value":497,"toc":5894},"minimark",[498,515,554,559,577,824,837,844,870,910,933,955,965,969,974,1428,1445,1459,1463,1475,1720,1737,1756,1955,1960,1985,2443,2461,2465,2476,2495,2819,2830,2834,2856,3061,3075,3079,3090,3097,3754,3772,3793,3977,4006,4030,4186,4190,4202,4216,4230,4435,4445,4451,4487,4491,4512,4608,4630,4788,4801,4991,5007,5011,5024,5109,5118,5124,5157,5270,5286,5298,5325,5352,5356,5362,5554,5560,5566,5688,5696,5753,5765,5769,5890],[499,500,501,502,506,507,510,511,514],"p",{},"Boot your full app in a single line and drive it from inside a test. ",[503,504,505],"code",{},"createTestApp"," boots a fresh,\nisolated ",[503,508,509],{},"AppHandle"," — reusing the Vite plugin's already-compiled wiring when it can (the fast path), or\ncompiling the app into a unique temp directory otherwise — all automatically cleaned up when the\n",[503,512,513],{},"await using"," block exits.",[499,516,517,518,522,523,526,527,530,531,534,535,538,539,542,543,549,550,553],{},"The harness is ",[519,520,521],"strong",{},"transport-neutral",": HTTP is not assumed, and ",[503,524,525],{},"app.get(Token)","\nresolves any DI token — a ",[503,528,529],{},"CommandBus",", a repository, a service — regardless of which transport your app uses.\nWhen your app does serve HTTP, ",[503,532,533],{},"createTestClient"," (from ",[503,536,537],{},"@heximon\u002Fhttp\u002Ftesting",") drives real ",[503,540,541],{},"Request","s\nthrough the ",[519,544,545,546],{},"same generated ",[503,547,548],{},"fetch"," a production host serves — the full middleware chain, error\nfilters, and per-request ",[503,551,552],{},"Context",", with no port and no socket.",[555,556,558],"h2",{"id":557},"boot-the-app","Boot the app",[499,560,561,562,565,566,569,570,573,574],{},"Under ",[503,563,564],{},"vp test"," the ",[503,567,568],{},"heximon()"," plugin has already compiled your app, so ",[503,571,572],{},"createTestApp()"," reuses that\nwiring directly — ",[519,575,576],{},"no plugins to list, no root to compute:",[578,579,585],"pre",{"className":580,"code":581,"filename":582,"language":583,"meta":584,"style":584},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { createTestApp } from \"@heximon\u002Ftesting\";\nimport { UsersRepository } from \"..\u002Fsrc\u002Fusers\u002Fusers.repository\";\nimport { expect, test } from \"vitest\";\n\ntest(\"createTestApp() resolves a DI token\", async () => {\n  await using app = await createTestApp();\n\n  const repository = await app.get(UsersRepository);\n\n  expect(await repository.list()).toHaveLength(2);\n});\n","test\u002Fusers.test.ts","ts","",[503,586,587,623,646,675,682,714,737,742,773,778,814],{"__ignoreMap":584},[588,589,592,596,600,604,607,610,613,617,620],"span",{"class":590,"line":591},"line",1,[588,593,595],{"class":594},"s7zQu","import",[588,597,599],{"class":598},"sMK4o"," {",[588,601,603],{"class":602},"sTEyZ"," createTestApp",[588,605,606],{"class":598}," }",[588,608,609],{"class":594}," from",[588,611,612],{"class":598}," \"",[588,614,616],{"class":615},"sfazB","@heximon\u002Ftesting",[588,618,619],{"class":598},"\"",[588,621,622],{"class":598},";\n",[588,624,626,628,630,633,635,637,639,642,644],{"class":590,"line":625},2,[588,627,595],{"class":594},[588,629,599],{"class":598},[588,631,632],{"class":602}," UsersRepository",[588,634,606],{"class":598},[588,636,609],{"class":594},[588,638,612],{"class":598},[588,640,641],{"class":615},"..\u002Fsrc\u002Fusers\u002Fusers.repository",[588,643,619],{"class":598},[588,645,622],{"class":598},[588,647,649,651,653,656,659,662,664,666,668,671,673],{"class":590,"line":648},3,[588,650,595],{"class":594},[588,652,599],{"class":598},[588,654,655],{"class":602}," expect",[588,657,658],{"class":598},",",[588,660,661],{"class":602}," test",[588,663,606],{"class":598},[588,665,609],{"class":594},[588,667,612],{"class":598},[588,669,670],{"class":615},"vitest",[588,672,619],{"class":598},[588,674,622],{"class":598},[588,676,678],{"class":590,"line":677},4,[588,679,681],{"emptyLinePlaceholder":680},true,"\n",[588,683,685,689,692,694,697,699,701,705,708,711],{"class":590,"line":684},5,[588,686,688],{"class":687},"s2Zo4","test",[588,690,691],{"class":602},"(",[588,693,619],{"class":598},[588,695,696],{"class":615},"createTestApp() resolves a DI token",[588,698,619],{"class":598},[588,700,658],{"class":598},[588,702,704],{"class":703},"spNyl"," async",[588,706,707],{"class":598}," ()",[588,709,710],{"class":703}," =>",[588,712,713],{"class":598}," {\n",[588,715,717,720,723,726,729,731,735],{"class":590,"line":716},6,[588,718,719],{"class":703},"  await using",[588,721,722],{"class":602}," app",[588,724,725],{"class":598}," =",[588,727,728],{"class":594}," await",[588,730,603],{"class":687},[588,732,734],{"class":733},"swJcz","()",[588,736,622],{"class":598},[588,738,740],{"class":590,"line":739},7,[588,741,681],{"emptyLinePlaceholder":680},[588,743,745,748,751,753,755,757,760,763,765,768,771],{"class":590,"line":744},8,[588,746,747],{"class":703},"  const",[588,749,750],{"class":602}," repository",[588,752,725],{"class":598},[588,754,728],{"class":594},[588,756,722],{"class":602},[588,758,759],{"class":598},".",[588,761,762],{"class":687},"get",[588,764,691],{"class":733},[588,766,767],{"class":602},"UsersRepository",[588,769,770],{"class":733},")",[588,772,622],{"class":598},[588,774,776],{"class":590,"line":775},9,[588,777,681],{"emptyLinePlaceholder":680},[588,779,781,784,786,789,791,793,796,799,801,804,806,810,812],{"class":590,"line":780},10,[588,782,783],{"class":687},"  expect",[588,785,691],{"class":733},[588,787,788],{"class":594},"await",[588,790,750],{"class":602},[588,792,759],{"class":598},[588,794,795],{"class":687},"list",[588,797,798],{"class":733},"())",[588,800,759],{"class":598},[588,802,803],{"class":687},"toHaveLength",[588,805,691],{"class":733},[588,807,809],{"class":808},"sbssI","2",[588,811,770],{"class":733},[588,813,622],{"class":598},[588,815,817,820,822],{"class":590,"line":816},11,[588,818,819],{"class":598},"}",[588,821,770],{"class":602},[588,823,622],{"class":598},[499,825,826,828,829,832,833,836],{},[503,827,513],{}," is the right idiom: when the block exits it calls ",[503,830,831],{},"app[Symbol.asyncDispose]()",", which\nshuts down the app (and removes the temp wiring directory if one was created). No ",[503,834,835],{},"afterAll"," is needed.",[499,838,839,840,843],{},"Each call boots a fresh, non-memoised app — ",[503,841,842],{},"onInit"," runs every time, in-memory databases start empty,\nand no state bleeds between tests.",[499,845,846,847,850,851,853,854,856,857,859,860,863,864,867,868,759],{},"This works with ",[519,848,849],{},"no arguments"," because ",[503,852,572],{}," runs under\n",[503,855,564],{},", where the ",[503,858,568],{}," plugin is the active config and has already compiled your app at\n",[503,861,862],{},"buildStart"," — the harness reuses that in-memory wiring (no recompile, no temp directory), and ",[503,865,866],{},"root","\ndefaults to the current directory, your project root under ",[503,869,564],{},[499,871,872,873,879,880,882,883,886,887,889,890,892,893,892,897,899,900,903,904,909],{},"For this to work, your project needs ",[519,874,875,876],{},"no ",[503,877,878],{},"vitest.config.ts",": ",[503,881,564],{}," then loads ",[503,884,885],{},"vite.config.ts",", where\n",[503,888,568],{}," lives. (Vitest loads ",[503,891,878],{}," ",[894,895,896],"em",{},"instead of",[503,898,885],{}," when both exist, which would\nhide the plugin.) Configure your compiler plugins once there — or in the ",[503,901,902],{},"heximon.config.ts"," config file (see\n",[905,906,908],"a",{"href":907},"#share-the-plugin-list-with-heximonconfigts","Share the plugin list"," below) — and the test never\nrepeats them.",[911,912,914,917,918,921,922,925,926,928,929,932],"callout",{"type":913},"info",[519,915,916],{},"Heximon is a Vite-based framework — run tests under Vitest."," The harness imports your app's own ",[503,919,920],{},".ts","\nsource through a Vite-powered module loader (",[503,923,924],{},".js"," specifiers the compiler rewrites need remapping to\n",[503,927,920],{},"). Vitest is the supported path — a bare ",[503,930,931],{},"node --test",", even with native type-stripping, is not.",[499,934,935,936,939,940,943,944,947,948,951,952,954],{},"Pass options only for what the fast path can't infer: ",[503,937,938],{},"{ root }"," when the test isn't run from the project\nroot (e.g. a monorepo fixture; defaults to ",[503,941,942],{},"process.cwd()","), or ",[503,945,946],{},"{ plugins }"," to ",[519,949,950],{},"force a standalone\nrecompile"," for an app with no ",[503,953,568],{}," config — the harness runs the compiler itself into a temp dir\n(cleaned up on dispose) with exactly those plugins.",[499,956,957,958,961,962,964],{},"Same ",[503,959,960],{},"TestApp",", purely a fallback; otherwise the\nplugin set comes from your ",[503,963,902],{}," file.",[555,966,968],{"id":967},"resolve-di-tokens-directly","Resolve DI tokens directly",[499,970,971,973],{},[503,972,525],{}," is the universal accessor. Any token your app's DI graph exposes — a service, a\nrepository, a bus — is reachable by class identity. Import the class from source; because Vitest dedupes\nmodules, the identity you import is the same one the compiler wired.",[578,975,977],{"className":580,"code":976,"filename":582,"language":583,"meta":584,"style":584},"import { CommandBus, QueryBus } from \"@heximon\u002Fcqrs\";\nimport { createTestApp } from \"@heximon\u002Ftesting\";\nimport { expect, test } from \"vitest\";\nimport { CreateUserCommand } from \"..\u002Fsrc\u002Fusers\u002Fcommands\u002Fcreate-user.command\";\nimport { ListUsersQuery } from \"..\u002Fsrc\u002Fusers\u002Fqueries\u002Flist-users.query\";\nimport { UserId } from \"..\u002Fsrc\u002Fusers\u002Fuser\";\n\ntest(\"createTestApp() dispatches a command and reads it back through a query\", async () => {\n  await using app = await createTestApp();\n\n  const commandBus = await app.get(CommandBus);\n  const queryBus = await app.get(QueryBus);\n  const id = UserId.generate();\n\n  await app.context.run(async () => {\n    await commandBus.execute(new CreateUserCommand(id, \"Alice\", \"alice@example.com\"));\n\n    const users = await queryBus.execute(new ListUsersQuery());\n    expect(users.some((user) => user.id === id)).toBe(true);\n  });\n});\n",[503,978,979,1006,1026,1050,1072,1094,1116,1120,1143,1159,1163,1188,1215,1236,1241,1270,1318,1323,1352,1409,1419],{"__ignoreMap":584},[588,980,981,983,985,988,990,993,995,997,999,1002,1004],{"class":590,"line":591},[588,982,595],{"class":594},[588,984,599],{"class":598},[588,986,987],{"class":602}," CommandBus",[588,989,658],{"class":598},[588,991,992],{"class":602}," QueryBus",[588,994,606],{"class":598},[588,996,609],{"class":594},[588,998,612],{"class":598},[588,1000,1001],{"class":615},"@heximon\u002Fcqrs",[588,1003,619],{"class":598},[588,1005,622],{"class":598},[588,1007,1008,1010,1012,1014,1016,1018,1020,1022,1024],{"class":590,"line":625},[588,1009,595],{"class":594},[588,1011,599],{"class":598},[588,1013,603],{"class":602},[588,1015,606],{"class":598},[588,1017,609],{"class":594},[588,1019,612],{"class":598},[588,1021,616],{"class":615},[588,1023,619],{"class":598},[588,1025,622],{"class":598},[588,1027,1028,1030,1032,1034,1036,1038,1040,1042,1044,1046,1048],{"class":590,"line":648},[588,1029,595],{"class":594},[588,1031,599],{"class":598},[588,1033,655],{"class":602},[588,1035,658],{"class":598},[588,1037,661],{"class":602},[588,1039,606],{"class":598},[588,1041,609],{"class":594},[588,1043,612],{"class":598},[588,1045,670],{"class":615},[588,1047,619],{"class":598},[588,1049,622],{"class":598},[588,1051,1052,1054,1056,1059,1061,1063,1065,1068,1070],{"class":590,"line":677},[588,1053,595],{"class":594},[588,1055,599],{"class":598},[588,1057,1058],{"class":602}," CreateUserCommand",[588,1060,606],{"class":598},[588,1062,609],{"class":594},[588,1064,612],{"class":598},[588,1066,1067],{"class":615},"..\u002Fsrc\u002Fusers\u002Fcommands\u002Fcreate-user.command",[588,1069,619],{"class":598},[588,1071,622],{"class":598},[588,1073,1074,1076,1078,1081,1083,1085,1087,1090,1092],{"class":590,"line":684},[588,1075,595],{"class":594},[588,1077,599],{"class":598},[588,1079,1080],{"class":602}," ListUsersQuery",[588,1082,606],{"class":598},[588,1084,609],{"class":594},[588,1086,612],{"class":598},[588,1088,1089],{"class":615},"..\u002Fsrc\u002Fusers\u002Fqueries\u002Flist-users.query",[588,1091,619],{"class":598},[588,1093,622],{"class":598},[588,1095,1096,1098,1100,1103,1105,1107,1109,1112,1114],{"class":590,"line":716},[588,1097,595],{"class":594},[588,1099,599],{"class":598},[588,1101,1102],{"class":602}," UserId",[588,1104,606],{"class":598},[588,1106,609],{"class":594},[588,1108,612],{"class":598},[588,1110,1111],{"class":615},"..\u002Fsrc\u002Fusers\u002Fuser",[588,1113,619],{"class":598},[588,1115,622],{"class":598},[588,1117,1118],{"class":590,"line":739},[588,1119,681],{"emptyLinePlaceholder":680},[588,1121,1122,1124,1126,1128,1131,1133,1135,1137,1139,1141],{"class":590,"line":744},[588,1123,688],{"class":687},[588,1125,691],{"class":602},[588,1127,619],{"class":598},[588,1129,1130],{"class":615},"createTestApp() dispatches a command and reads it back through a query",[588,1132,619],{"class":598},[588,1134,658],{"class":598},[588,1136,704],{"class":703},[588,1138,707],{"class":598},[588,1140,710],{"class":703},[588,1142,713],{"class":598},[588,1144,1145,1147,1149,1151,1153,1155,1157],{"class":590,"line":775},[588,1146,719],{"class":703},[588,1148,722],{"class":602},[588,1150,725],{"class":598},[588,1152,728],{"class":594},[588,1154,603],{"class":687},[588,1156,734],{"class":733},[588,1158,622],{"class":598},[588,1160,1161],{"class":590,"line":780},[588,1162,681],{"emptyLinePlaceholder":680},[588,1164,1165,1167,1170,1172,1174,1176,1178,1180,1182,1184,1186],{"class":590,"line":816},[588,1166,747],{"class":703},[588,1168,1169],{"class":602}," commandBus",[588,1171,725],{"class":598},[588,1173,728],{"class":594},[588,1175,722],{"class":602},[588,1177,759],{"class":598},[588,1179,762],{"class":687},[588,1181,691],{"class":733},[588,1183,529],{"class":602},[588,1185,770],{"class":733},[588,1187,622],{"class":598},[588,1189,1191,1193,1196,1198,1200,1202,1204,1206,1208,1211,1213],{"class":590,"line":1190},12,[588,1192,747],{"class":703},[588,1194,1195],{"class":602}," queryBus",[588,1197,725],{"class":598},[588,1199,728],{"class":594},[588,1201,722],{"class":602},[588,1203,759],{"class":598},[588,1205,762],{"class":687},[588,1207,691],{"class":733},[588,1209,1210],{"class":602},"QueryBus",[588,1212,770],{"class":733},[588,1214,622],{"class":598},[588,1216,1218,1220,1223,1225,1227,1229,1232,1234],{"class":590,"line":1217},13,[588,1219,747],{"class":703},[588,1221,1222],{"class":602}," id",[588,1224,725],{"class":598},[588,1226,1102],{"class":602},[588,1228,759],{"class":598},[588,1230,1231],{"class":687},"generate",[588,1233,734],{"class":733},[588,1235,622],{"class":598},[588,1237,1239],{"class":590,"line":1238},14,[588,1240,681],{"emptyLinePlaceholder":680},[588,1242,1244,1247,1249,1251,1254,1256,1259,1261,1264,1266,1268],{"class":590,"line":1243},15,[588,1245,1246],{"class":594},"  await",[588,1248,722],{"class":602},[588,1250,759],{"class":598},[588,1252,1253],{"class":602},"context",[588,1255,759],{"class":598},[588,1257,1258],{"class":687},"run",[588,1260,691],{"class":733},[588,1262,1263],{"class":703},"async",[588,1265,707],{"class":598},[588,1267,710],{"class":703},[588,1269,713],{"class":598},[588,1271,1273,1276,1278,1280,1283,1285,1288,1290,1292,1295,1297,1299,1302,1304,1306,1308,1311,1313,1316],{"class":590,"line":1272},16,[588,1274,1275],{"class":594},"    await",[588,1277,1169],{"class":602},[588,1279,759],{"class":598},[588,1281,1282],{"class":687},"execute",[588,1284,691],{"class":733},[588,1286,1287],{"class":598},"new",[588,1289,1058],{"class":687},[588,1291,691],{"class":733},[588,1293,1294],{"class":602},"id",[588,1296,658],{"class":598},[588,1298,612],{"class":598},[588,1300,1301],{"class":615},"Alice",[588,1303,619],{"class":598},[588,1305,658],{"class":598},[588,1307,612],{"class":598},[588,1309,1310],{"class":615},"alice@example.com",[588,1312,619],{"class":598},[588,1314,1315],{"class":733},"))",[588,1317,622],{"class":598},[588,1319,1321],{"class":590,"line":1320},17,[588,1322,681],{"emptyLinePlaceholder":680},[588,1324,1326,1329,1332,1334,1336,1338,1340,1342,1344,1346,1348,1350],{"class":590,"line":1325},18,[588,1327,1328],{"class":703},"    const",[588,1330,1331],{"class":602}," users",[588,1333,725],{"class":598},[588,1335,728],{"class":594},[588,1337,1195],{"class":602},[588,1339,759],{"class":598},[588,1341,1282],{"class":687},[588,1343,691],{"class":733},[588,1345,1287],{"class":598},[588,1347,1080],{"class":687},[588,1349,798],{"class":733},[588,1351,622],{"class":598},[588,1353,1355,1358,1360,1363,1365,1368,1370,1372,1376,1378,1380,1383,1385,1387,1390,1392,1394,1396,1399,1401,1405,1407],{"class":590,"line":1354},19,[588,1356,1357],{"class":687},"    expect",[588,1359,691],{"class":733},[588,1361,1362],{"class":602},"users",[588,1364,759],{"class":598},[588,1366,1367],{"class":687},"some",[588,1369,691],{"class":733},[588,1371,691],{"class":598},[588,1373,1375],{"class":1374},"sHdIc","user",[588,1377,770],{"class":598},[588,1379,710],{"class":703},[588,1381,1382],{"class":602}," user",[588,1384,759],{"class":598},[588,1386,1294],{"class":602},[588,1388,1389],{"class":598}," ===",[588,1391,1222],{"class":602},[588,1393,1315],{"class":733},[588,1395,759],{"class":598},[588,1397,1398],{"class":687},"toBe",[588,1400,691],{"class":733},[588,1402,1404],{"class":1403},"sfNiH","true",[588,1406,770],{"class":733},[588,1408,622],{"class":598},[588,1410,1412,1415,1417],{"class":590,"line":1411},20,[588,1413,1414],{"class":598},"  }",[588,1416,770],{"class":733},[588,1418,622],{"class":598},[588,1420,1422,1424,1426],{"class":590,"line":1421},21,[588,1423,819],{"class":598},[588,1425,770],{"class":602},[588,1427,622],{"class":598},[499,1429,1430,1433,1434,1436,1437,1440,1441,1444],{},[503,1431,1432],{},"app.context.run(fn)"," opens the ambient ",[503,1435,552],{}," frame. Any code that reads from an in-memory\ndatabase, drains a queue, or calls ",[503,1438,1439],{},"waitUntil"," on a ",[503,1442,1443],{},"Task"," needs this frame open — without it you\nget a \"context not available\" error. HTTP requests from a test client open the frame automatically.",[499,1446,1447,1448,1451,1452,1455,1456,759],{},"The same pattern works for event-driven apps (",[503,1449,1450],{},"app.get(EventBus)","), DDD apps (",[503,1453,1454],{},"app.get(DomainEvents)","),\nor any service you've listed in a module's ",[503,1457,1458],{},"providers",[555,1460,1462],{"id":1461},"add-the-http-client","Add the HTTP client",[499,1464,1465,1466,1468,1469,1471,1472,1474],{},"HTTP is one opt-in layer, imported from ",[503,1467,537],{},". Pass the ",[503,1470,960],{}," to\n",[503,1473,533],{}," — it reads the routes and contract registrations off the app's wiring, so no\nmanual extraction is needed.",[578,1476,1478],{"className":580,"code":1477,"filename":582,"language":583,"meta":584,"style":584},"import { createTestClient } from \"@heximon\u002Fhttp\u002Ftesting\";\nimport { createTestApp } from \"@heximon\u002Ftesting\";\nimport { expect, test } from \"vitest\";\n\ntest(\"createTestApp() + createTestClient(app) drive GET \u002Fusers\", async () => {\n  await using app = await createTestApp();\n  const client = createTestClient(app);\n\n  const response = await client.request(new Request(\"http:\u002F\u002Flocalhost\u002Fusers\"));\n\n  expect(response.status).toBe(200);\n  expect(await response.json()).toHaveLength(2);\n});\n",[503,1479,1480,1501,1521,1545,1549,1572,1588,1608,1612,1650,1654,1683,1712],{"__ignoreMap":584},[588,1481,1482,1484,1486,1489,1491,1493,1495,1497,1499],{"class":590,"line":591},[588,1483,595],{"class":594},[588,1485,599],{"class":598},[588,1487,1488],{"class":602}," createTestClient",[588,1490,606],{"class":598},[588,1492,609],{"class":594},[588,1494,612],{"class":598},[588,1496,537],{"class":615},[588,1498,619],{"class":598},[588,1500,622],{"class":598},[588,1502,1503,1505,1507,1509,1511,1513,1515,1517,1519],{"class":590,"line":625},[588,1504,595],{"class":594},[588,1506,599],{"class":598},[588,1508,603],{"class":602},[588,1510,606],{"class":598},[588,1512,609],{"class":594},[588,1514,612],{"class":598},[588,1516,616],{"class":615},[588,1518,619],{"class":598},[588,1520,622],{"class":598},[588,1522,1523,1525,1527,1529,1531,1533,1535,1537,1539,1541,1543],{"class":590,"line":648},[588,1524,595],{"class":594},[588,1526,599],{"class":598},[588,1528,655],{"class":602},[588,1530,658],{"class":598},[588,1532,661],{"class":602},[588,1534,606],{"class":598},[588,1536,609],{"class":594},[588,1538,612],{"class":598},[588,1540,670],{"class":615},[588,1542,619],{"class":598},[588,1544,622],{"class":598},[588,1546,1547],{"class":590,"line":677},[588,1548,681],{"emptyLinePlaceholder":680},[588,1550,1551,1553,1555,1557,1560,1562,1564,1566,1568,1570],{"class":590,"line":684},[588,1552,688],{"class":687},[588,1554,691],{"class":602},[588,1556,619],{"class":598},[588,1558,1559],{"class":615},"createTestApp() + createTestClient(app) drive GET \u002Fusers",[588,1561,619],{"class":598},[588,1563,658],{"class":598},[588,1565,704],{"class":703},[588,1567,707],{"class":598},[588,1569,710],{"class":703},[588,1571,713],{"class":598},[588,1573,1574,1576,1578,1580,1582,1584,1586],{"class":590,"line":716},[588,1575,719],{"class":703},[588,1577,722],{"class":602},[588,1579,725],{"class":598},[588,1581,728],{"class":594},[588,1583,603],{"class":687},[588,1585,734],{"class":733},[588,1587,622],{"class":598},[588,1589,1590,1592,1595,1597,1599,1601,1604,1606],{"class":590,"line":739},[588,1591,747],{"class":703},[588,1593,1594],{"class":602}," client",[588,1596,725],{"class":598},[588,1598,1488],{"class":687},[588,1600,691],{"class":733},[588,1602,1603],{"class":602},"app",[588,1605,770],{"class":733},[588,1607,622],{"class":598},[588,1609,1610],{"class":590,"line":744},[588,1611,681],{"emptyLinePlaceholder":680},[588,1613,1614,1616,1619,1621,1623,1625,1627,1630,1632,1634,1637,1639,1641,1644,1646,1648],{"class":590,"line":775},[588,1615,747],{"class":703},[588,1617,1618],{"class":602}," response",[588,1620,725],{"class":598},[588,1622,728],{"class":594},[588,1624,1594],{"class":602},[588,1626,759],{"class":598},[588,1628,1629],{"class":687},"request",[588,1631,691],{"class":733},[588,1633,1287],{"class":598},[588,1635,1636],{"class":687}," Request",[588,1638,691],{"class":733},[588,1640,619],{"class":598},[588,1642,1643],{"class":615},"http:\u002F\u002Flocalhost\u002Fusers",[588,1645,619],{"class":598},[588,1647,1315],{"class":733},[588,1649,622],{"class":598},[588,1651,1652],{"class":590,"line":780},[588,1653,681],{"emptyLinePlaceholder":680},[588,1655,1656,1658,1660,1663,1665,1668,1670,1672,1674,1676,1679,1681],{"class":590,"line":816},[588,1657,783],{"class":687},[588,1659,691],{"class":733},[588,1661,1662],{"class":602},"response",[588,1664,759],{"class":598},[588,1666,1667],{"class":602},"status",[588,1669,770],{"class":733},[588,1671,759],{"class":598},[588,1673,1398],{"class":687},[588,1675,691],{"class":733},[588,1677,1678],{"class":808},"200",[588,1680,770],{"class":733},[588,1682,622],{"class":598},[588,1684,1685,1687,1689,1691,1693,1695,1698,1700,1702,1704,1706,1708,1710],{"class":590,"line":1190},[588,1686,783],{"class":687},[588,1688,691],{"class":733},[588,1690,788],{"class":594},[588,1692,1618],{"class":602},[588,1694,759],{"class":598},[588,1696,1697],{"class":687},"json",[588,1699,798],{"class":733},[588,1701,759],{"class":598},[588,1703,803],{"class":687},[588,1705,691],{"class":733},[588,1707,809],{"class":808},[588,1709,770],{"class":733},[588,1711,622],{"class":598},[588,1713,1714,1716,1718],{"class":590,"line":1217},[588,1715,819],{"class":598},[588,1717,770],{"class":602},[588,1719,622],{"class":598},[499,1721,1722,1724,1725,1729,1730,1732,1733,1736],{},[503,1723,533],{}," runs the ",[519,1726,545,1727],{},[503,1728,548],{}," a production host serves — every middleware,\nevery error filter, body validation, and the per-request ",[503,1731,552],{}," chain. Nothing about the HTTP layer\nis mocked. If a middleware ordering or an error filter is wrong, the test sees the same ",[503,1734,1735],{},"Response"," a\nbrowser would — there is no second, weakened code path to drift out of sync with production.",[499,1738,1739,1740,1743,1744,1746,1747,1749,1750,1752,1753,1755],{},"When you want the app to live across multiple requests in a test suite (sequential describe blocks,\n",[503,1741,1742],{},"beforeAll","\u002F",[503,1745,835],{},"), hold the ",[503,1748,960],{}," as a variable and call ",[503,1751,831],{}," in\n",[503,1754,835],{},":",[578,1757,1760],{"className":580,"code":1758,"filename":1759,"language":583,"meta":584,"style":584},"import { type TestClient, createTestClient } from \"@heximon\u002Fhttp\u002Ftesting\";\nimport { type TestApp, createTestApp } from \"@heximon\u002Ftesting\";\nimport { afterAll, beforeAll } from \"vitest\";\n\nlet app: TestApp;\nlet client: TestClient;\n\nbeforeAll(async () => {\n  app = await createTestApp();\n  client = createTestClient(app);\n});\n\nafterAll(() => app[Symbol.asyncDispose]());\n","test\u002Fapp.e2e.test.ts",[503,1761,1762,1790,1817,1843,1847,1861,1873,1877,1891,1906,1923,1931,1935],{"__ignoreMap":584},[588,1763,1764,1766,1768,1771,1774,1776,1778,1780,1782,1784,1786,1788],{"class":590,"line":591},[588,1765,595],{"class":594},[588,1767,599],{"class":598},[588,1769,1770],{"class":594}," type",[588,1772,1773],{"class":602}," TestClient",[588,1775,658],{"class":598},[588,1777,1488],{"class":602},[588,1779,606],{"class":598},[588,1781,609],{"class":594},[588,1783,612],{"class":598},[588,1785,537],{"class":615},[588,1787,619],{"class":598},[588,1789,622],{"class":598},[588,1791,1792,1794,1796,1798,1801,1803,1805,1807,1809,1811,1813,1815],{"class":590,"line":625},[588,1793,595],{"class":594},[588,1795,599],{"class":598},[588,1797,1770],{"class":594},[588,1799,1800],{"class":602}," TestApp",[588,1802,658],{"class":598},[588,1804,603],{"class":602},[588,1806,606],{"class":598},[588,1808,609],{"class":594},[588,1810,612],{"class":598},[588,1812,616],{"class":615},[588,1814,619],{"class":598},[588,1816,622],{"class":598},[588,1818,1819,1821,1823,1826,1828,1831,1833,1835,1837,1839,1841],{"class":590,"line":648},[588,1820,595],{"class":594},[588,1822,599],{"class":598},[588,1824,1825],{"class":602}," afterAll",[588,1827,658],{"class":598},[588,1829,1830],{"class":602}," beforeAll",[588,1832,606],{"class":598},[588,1834,609],{"class":594},[588,1836,612],{"class":598},[588,1838,670],{"class":615},[588,1840,619],{"class":598},[588,1842,622],{"class":598},[588,1844,1845],{"class":590,"line":677},[588,1846,681],{"emptyLinePlaceholder":680},[588,1848,1849,1852,1854,1856,1859],{"class":590,"line":684},[588,1850,1851],{"class":703},"let",[588,1853,722],{"class":602},[588,1855,1755],{"class":598},[588,1857,1800],{"class":1858},"sBMFI",[588,1860,622],{"class":598},[588,1862,1863,1865,1867,1869,1871],{"class":590,"line":716},[588,1864,1851],{"class":703},[588,1866,1594],{"class":602},[588,1868,1755],{"class":598},[588,1870,1773],{"class":1858},[588,1872,622],{"class":598},[588,1874,1875],{"class":590,"line":739},[588,1876,681],{"emptyLinePlaceholder":680},[588,1878,1879,1881,1883,1885,1887,1889],{"class":590,"line":744},[588,1880,1742],{"class":687},[588,1882,691],{"class":602},[588,1884,1263],{"class":703},[588,1886,707],{"class":598},[588,1888,710],{"class":703},[588,1890,713],{"class":598},[588,1892,1893,1896,1898,1900,1902,1904],{"class":590,"line":775},[588,1894,1895],{"class":602},"  app",[588,1897,725],{"class":598},[588,1899,728],{"class":594},[588,1901,603],{"class":687},[588,1903,734],{"class":733},[588,1905,622],{"class":598},[588,1907,1908,1911,1913,1915,1917,1919,1921],{"class":590,"line":780},[588,1909,1910],{"class":602},"  client",[588,1912,725],{"class":598},[588,1914,1488],{"class":687},[588,1916,691],{"class":733},[588,1918,1603],{"class":602},[588,1920,770],{"class":733},[588,1922,622],{"class":598},[588,1924,1925,1927,1929],{"class":590,"line":816},[588,1926,819],{"class":598},[588,1928,770],{"class":602},[588,1930,622],{"class":598},[588,1932,1933],{"class":590,"line":1190},[588,1934,681],{"emptyLinePlaceholder":680},[588,1936,1937,1939,1941,1943,1945,1948,1950,1953],{"class":590,"line":1217},[588,1938,835],{"class":687},[588,1940,691],{"class":602},[588,1942,734],{"class":598},[588,1944,710],{"class":703},[588,1946,1947],{"class":602}," app[Symbol",[588,1949,759],{"class":598},[588,1951,1952],{"class":602},"asyncDispose]())",[588,1954,622],{"class":598},[1956,1957,1959],"h3",{"id":1958},"assert-status-then-body","Assert status, then body",[499,1961,1962,1963,1972,1973,1976,1977,1980,1981,1984],{},"Assert the HTTP status before the parsed body — the status is the contract, the body is the detail.\nAgainst the seeded repository in\n",[905,1964,1968,1969,770],{"href":1965,"rel":1966},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fladder\u002FL02-http-validation",[1967],"nofollow","the ladder's HTTP validation example (",[503,1970,1971],{},"L02",",\n",[503,1974,1975],{},"GET \u002Fusers"," returns the two users the repository seeds, and ",[503,1978,1979],{},"GET \u002Fusers\u002F:id"," resolves the typed ",[503,1982,1983],{},":id","\npath parameter to one of them:",[578,1986,1989],{"className":580,"code":1987,"filename":1988,"language":583,"meta":584,"style":584},"import { expect, test } from \"vitest\";\n\ntest(\"GET \u002Fusers lists the seeded users\", async () => {\n  const response = await client.request(new Request(\"http:\u002F\u002Flocalhost\u002Fusers\"));\n\n  expect(response.status).toBe(200);\n  expect(response.headers.get(\"content-type\")).toContain(\"application\u002Fjson\");\n  expect(await response.json()).toEqual([\n    { id: \"1\", name: \"Alice\", email: \"alice@example.com\" },\n    { id: \"2\", name: \"Bob\", email: \"bob@example.com\" },\n  ]);\n});\n\ntest(\"GET \u002Fusers\u002F:id resolves the typed path parameter to a single user\", async () => {\n  const response = await client.request(new Request(\"http:\u002F\u002Flocalhost\u002Fusers\u002F2\"));\n\n  expect(response.status).toBe(200);\n  expect(await response.json()).toEqual({ id: \"2\", name: \"Bob\", email: \"bob@example.com\" });\n});\n","users.test.ts",[503,1990,1991,2015,2019,2042,2076,2080,2106,2152,2176,2221,2263,2270,2278,2282,2305,2340,2344,2370,2435],{"__ignoreMap":584},[588,1992,1993,1995,1997,1999,2001,2003,2005,2007,2009,2011,2013],{"class":590,"line":591},[588,1994,595],{"class":594},[588,1996,599],{"class":598},[588,1998,655],{"class":602},[588,2000,658],{"class":598},[588,2002,661],{"class":602},[588,2004,606],{"class":598},[588,2006,609],{"class":594},[588,2008,612],{"class":598},[588,2010,670],{"class":615},[588,2012,619],{"class":598},[588,2014,622],{"class":598},[588,2016,2017],{"class":590,"line":625},[588,2018,681],{"emptyLinePlaceholder":680},[588,2020,2021,2023,2025,2027,2030,2032,2034,2036,2038,2040],{"class":590,"line":648},[588,2022,688],{"class":687},[588,2024,691],{"class":602},[588,2026,619],{"class":598},[588,2028,2029],{"class":615},"GET \u002Fusers lists the seeded users",[588,2031,619],{"class":598},[588,2033,658],{"class":598},[588,2035,704],{"class":703},[588,2037,707],{"class":598},[588,2039,710],{"class":703},[588,2041,713],{"class":598},[588,2043,2044,2046,2048,2050,2052,2054,2056,2058,2060,2062,2064,2066,2068,2070,2072,2074],{"class":590,"line":677},[588,2045,747],{"class":703},[588,2047,1618],{"class":602},[588,2049,725],{"class":598},[588,2051,728],{"class":594},[588,2053,1594],{"class":602},[588,2055,759],{"class":598},[588,2057,1629],{"class":687},[588,2059,691],{"class":733},[588,2061,1287],{"class":598},[588,2063,1636],{"class":687},[588,2065,691],{"class":733},[588,2067,619],{"class":598},[588,2069,1643],{"class":615},[588,2071,619],{"class":598},[588,2073,1315],{"class":733},[588,2075,622],{"class":598},[588,2077,2078],{"class":590,"line":684},[588,2079,681],{"emptyLinePlaceholder":680},[588,2081,2082,2084,2086,2088,2090,2092,2094,2096,2098,2100,2102,2104],{"class":590,"line":716},[588,2083,783],{"class":687},[588,2085,691],{"class":733},[588,2087,1662],{"class":602},[588,2089,759],{"class":598},[588,2091,1667],{"class":602},[588,2093,770],{"class":733},[588,2095,759],{"class":598},[588,2097,1398],{"class":687},[588,2099,691],{"class":733},[588,2101,1678],{"class":808},[588,2103,770],{"class":733},[588,2105,622],{"class":598},[588,2107,2108,2110,2112,2114,2116,2119,2121,2123,2125,2127,2130,2132,2134,2136,2139,2141,2143,2146,2148,2150],{"class":590,"line":739},[588,2109,783],{"class":687},[588,2111,691],{"class":733},[588,2113,1662],{"class":602},[588,2115,759],{"class":598},[588,2117,2118],{"class":602},"headers",[588,2120,759],{"class":598},[588,2122,762],{"class":687},[588,2124,691],{"class":733},[588,2126,619],{"class":598},[588,2128,2129],{"class":615},"content-type",[588,2131,619],{"class":598},[588,2133,1315],{"class":733},[588,2135,759],{"class":598},[588,2137,2138],{"class":687},"toContain",[588,2140,691],{"class":733},[588,2142,619],{"class":598},[588,2144,2145],{"class":615},"application\u002Fjson",[588,2147,619],{"class":598},[588,2149,770],{"class":733},[588,2151,622],{"class":598},[588,2153,2154,2156,2158,2160,2162,2164,2166,2168,2170,2173],{"class":590,"line":744},[588,2155,783],{"class":687},[588,2157,691],{"class":733},[588,2159,788],{"class":594},[588,2161,1618],{"class":602},[588,2163,759],{"class":598},[588,2165,1697],{"class":687},[588,2167,798],{"class":733},[588,2169,759],{"class":598},[588,2171,2172],{"class":687},"toEqual",[588,2174,2175],{"class":733},"([\n",[588,2177,2178,2181,2183,2185,2187,2190,2192,2194,2197,2199,2201,2203,2205,2207,2210,2212,2214,2216,2218],{"class":590,"line":775},[588,2179,2180],{"class":598},"    {",[588,2182,1222],{"class":733},[588,2184,1755],{"class":598},[588,2186,612],{"class":598},[588,2188,2189],{"class":615},"1",[588,2191,619],{"class":598},[588,2193,658],{"class":598},[588,2195,2196],{"class":733}," name",[588,2198,1755],{"class":598},[588,2200,612],{"class":598},[588,2202,1301],{"class":615},[588,2204,619],{"class":598},[588,2206,658],{"class":598},[588,2208,2209],{"class":733}," email",[588,2211,1755],{"class":598},[588,2213,612],{"class":598},[588,2215,1310],{"class":615},[588,2217,619],{"class":598},[588,2219,2220],{"class":598}," },\n",[588,2222,2223,2225,2227,2229,2231,2233,2235,2237,2239,2241,2243,2246,2248,2250,2252,2254,2256,2259,2261],{"class":590,"line":780},[588,2224,2180],{"class":598},[588,2226,1222],{"class":733},[588,2228,1755],{"class":598},[588,2230,612],{"class":598},[588,2232,809],{"class":615},[588,2234,619],{"class":598},[588,2236,658],{"class":598},[588,2238,2196],{"class":733},[588,2240,1755],{"class":598},[588,2242,612],{"class":598},[588,2244,2245],{"class":615},"Bob",[588,2247,619],{"class":598},[588,2249,658],{"class":598},[588,2251,2209],{"class":733},[588,2253,1755],{"class":598},[588,2255,612],{"class":598},[588,2257,2258],{"class":615},"bob@example.com",[588,2260,619],{"class":598},[588,2262,2220],{"class":598},[588,2264,2265,2268],{"class":590,"line":816},[588,2266,2267],{"class":733},"  ])",[588,2269,622],{"class":598},[588,2271,2272,2274,2276],{"class":590,"line":1190},[588,2273,819],{"class":598},[588,2275,770],{"class":602},[588,2277,622],{"class":598},[588,2279,2280],{"class":590,"line":1217},[588,2281,681],{"emptyLinePlaceholder":680},[588,2283,2284,2286,2288,2290,2293,2295,2297,2299,2301,2303],{"class":590,"line":1238},[588,2285,688],{"class":687},[588,2287,691],{"class":602},[588,2289,619],{"class":598},[588,2291,2292],{"class":615},"GET \u002Fusers\u002F:id resolves the typed path parameter to a single user",[588,2294,619],{"class":598},[588,2296,658],{"class":598},[588,2298,704],{"class":703},[588,2300,707],{"class":598},[588,2302,710],{"class":703},[588,2304,713],{"class":598},[588,2306,2307,2309,2311,2313,2315,2317,2319,2321,2323,2325,2327,2329,2331,2334,2336,2338],{"class":590,"line":1243},[588,2308,747],{"class":703},[588,2310,1618],{"class":602},[588,2312,725],{"class":598},[588,2314,728],{"class":594},[588,2316,1594],{"class":602},[588,2318,759],{"class":598},[588,2320,1629],{"class":687},[588,2322,691],{"class":733},[588,2324,1287],{"class":598},[588,2326,1636],{"class":687},[588,2328,691],{"class":733},[588,2330,619],{"class":598},[588,2332,2333],{"class":615},"http:\u002F\u002Flocalhost\u002Fusers\u002F2",[588,2335,619],{"class":598},[588,2337,1315],{"class":733},[588,2339,622],{"class":598},[588,2341,2342],{"class":590,"line":1272},[588,2343,681],{"emptyLinePlaceholder":680},[588,2345,2346,2348,2350,2352,2354,2356,2358,2360,2362,2364,2366,2368],{"class":590,"line":1320},[588,2347,783],{"class":687},[588,2349,691],{"class":733},[588,2351,1662],{"class":602},[588,2353,759],{"class":598},[588,2355,1667],{"class":602},[588,2357,770],{"class":733},[588,2359,759],{"class":598},[588,2361,1398],{"class":687},[588,2363,691],{"class":733},[588,2365,1678],{"class":808},[588,2367,770],{"class":733},[588,2369,622],{"class":598},[588,2371,2372,2374,2376,2378,2380,2382,2384,2386,2388,2390,2392,2395,2397,2399,2401,2403,2405,2407,2409,2411,2413,2415,2417,2419,2421,2423,2425,2427,2429,2431,2433],{"class":590,"line":1325},[588,2373,783],{"class":687},[588,2375,691],{"class":733},[588,2377,788],{"class":594},[588,2379,1618],{"class":602},[588,2381,759],{"class":598},[588,2383,1697],{"class":687},[588,2385,798],{"class":733},[588,2387,759],{"class":598},[588,2389,2172],{"class":687},[588,2391,691],{"class":733},[588,2393,2394],{"class":598},"{",[588,2396,1222],{"class":733},[588,2398,1755],{"class":598},[588,2400,612],{"class":598},[588,2402,809],{"class":615},[588,2404,619],{"class":598},[588,2406,658],{"class":598},[588,2408,2196],{"class":733},[588,2410,1755],{"class":598},[588,2412,612],{"class":598},[588,2414,2245],{"class":615},[588,2416,619],{"class":598},[588,2418,658],{"class":598},[588,2420,2209],{"class":733},[588,2422,1755],{"class":598},[588,2424,612],{"class":598},[588,2426,2258],{"class":615},[588,2428,619],{"class":598},[588,2430,606],{"class":598},[588,2432,770],{"class":733},[588,2434,622],{"class":598},[588,2436,2437,2439,2441],{"class":590,"line":1354},[588,2438,819],{"class":598},[588,2440,770],{"class":602},[588,2442,622],{"class":598},[499,2444,2445,2446,2448,2449,2452,2453,2456,2457,2460],{},"A small ",[503,2447,541],{}," helper (",[503,2450,2451],{},"json(path)"," \u002F ",[503,2454,2455],{},"postJson(path, body)"," wrapping ",[503,2458,2459],{},"client.request(new Request(...))",")\nkeeps call sites short when you exercise many routes — the examples below assume one.",[1956,2462,2464],{"id":2463},"prove-thrown-errors-map-to-problemjson","Prove thrown errors map to problem+json",[499,2466,2467,2468,2471,2472,2475],{},"Because the ",[519,2469,2470],{},"real"," error formatter runs, a domain error thrown deep in the repository surfaces as the exact\n",[503,2473,2474],{},"problem+json"," it was wired to produce — you assert on the wire format, not on the exception.",[499,2477,2478,2479,2482,2483,2486,2487,2490,2491,2494],{},"The\nrepository throws ",[503,2480,2481],{},"UserNotFoundError extends NotFoundError","; the controller has no custom ",[503,2484,2485],{},"ErrorFilter"," —\nheximon-http's built-in ",[503,2488,2489],{},"ErrorFormatter"," renders it from the error's own status, so an unknown id comes back\nas a ",[503,2492,2493],{},"404"," RFC 9457 document:",[578,2496,2498],{"className":580,"code":2497,"filename":1988,"language":583,"meta":584,"style":584},"test(\"GET \u002Fusers\u002F:id maps a UserNotFoundError to a 404 RFC 9457 problem+json (built-in formatter)\", async () => {\n  const response = await json(\"\u002Fusers\u002F999\");\n\n  expect(response.status).toBe(404);\n  expect(response.headers.get(\"content-type\")).toContain(\"application\u002Fproblem+json\");\n\n  const problem = (await response.json()) as Record\u003Cstring, unknown>;\n\n  \u002F\u002F The built-in formatter fills the RFC 9457 envelope from the thrown error: `status`\u002F`title` come from the\n  \u002F\u002F error's status (a `NotFoundError` → 404 \"Not Found\"), `instance` is the request path, and the human-readable\n  \u002F\u002F message becomes `detail` (carrying the looked-up id).\n  expect(problem.status).toBe(404);\n  expect(problem.title).toBe(\"Not Found\");\n  expect(problem.instance).toBe(\"\u002Fusers\u002F999\");\n  expect(problem.detail).toContain(\"999\");\n});\n",[503,2499,2500,2523,2549,2553,2579,2622,2626,2669,2673,2679,2684,2689,2716,2748,2779,2811],{"__ignoreMap":584},[588,2501,2502,2504,2506,2508,2511,2513,2515,2517,2519,2521],{"class":590,"line":591},[588,2503,688],{"class":687},[588,2505,691],{"class":602},[588,2507,619],{"class":598},[588,2509,2510],{"class":615},"GET \u002Fusers\u002F:id maps a UserNotFoundError to a 404 RFC 9457 problem+json (built-in formatter)",[588,2512,619],{"class":598},[588,2514,658],{"class":598},[588,2516,704],{"class":703},[588,2518,707],{"class":598},[588,2520,710],{"class":703},[588,2522,713],{"class":598},[588,2524,2525,2527,2529,2531,2533,2536,2538,2540,2543,2545,2547],{"class":590,"line":625},[588,2526,747],{"class":703},[588,2528,1618],{"class":602},[588,2530,725],{"class":598},[588,2532,728],{"class":594},[588,2534,2535],{"class":687}," json",[588,2537,691],{"class":733},[588,2539,619],{"class":598},[588,2541,2542],{"class":615},"\u002Fusers\u002F999",[588,2544,619],{"class":598},[588,2546,770],{"class":733},[588,2548,622],{"class":598},[588,2550,2551],{"class":590,"line":648},[588,2552,681],{"emptyLinePlaceholder":680},[588,2554,2555,2557,2559,2561,2563,2565,2567,2569,2571,2573,2575,2577],{"class":590,"line":677},[588,2556,783],{"class":687},[588,2558,691],{"class":733},[588,2560,1662],{"class":602},[588,2562,759],{"class":598},[588,2564,1667],{"class":602},[588,2566,770],{"class":733},[588,2568,759],{"class":598},[588,2570,1398],{"class":687},[588,2572,691],{"class":733},[588,2574,2493],{"class":808},[588,2576,770],{"class":733},[588,2578,622],{"class":598},[588,2580,2581,2583,2585,2587,2589,2591,2593,2595,2597,2599,2601,2603,2605,2607,2609,2611,2613,2616,2618,2620],{"class":590,"line":684},[588,2582,783],{"class":687},[588,2584,691],{"class":733},[588,2586,1662],{"class":602},[588,2588,759],{"class":598},[588,2590,2118],{"class":602},[588,2592,759],{"class":598},[588,2594,762],{"class":687},[588,2596,691],{"class":733},[588,2598,619],{"class":598},[588,2600,2129],{"class":615},[588,2602,619],{"class":598},[588,2604,1315],{"class":733},[588,2606,759],{"class":598},[588,2608,2138],{"class":687},[588,2610,691],{"class":733},[588,2612,619],{"class":598},[588,2614,2615],{"class":615},"application\u002Fproblem+json",[588,2617,619],{"class":598},[588,2619,770],{"class":733},[588,2621,622],{"class":598},[588,2623,2624],{"class":590,"line":716},[588,2625,681],{"emptyLinePlaceholder":680},[588,2627,2628,2630,2633,2635,2638,2640,2642,2644,2646,2649,2652,2655,2658,2661,2663,2666],{"class":590,"line":739},[588,2629,747],{"class":703},[588,2631,2632],{"class":602}," problem",[588,2634,725],{"class":598},[588,2636,2637],{"class":733}," (",[588,2639,788],{"class":594},[588,2641,1618],{"class":602},[588,2643,759],{"class":598},[588,2645,1697],{"class":687},[588,2647,2648],{"class":733},"()) ",[588,2650,2651],{"class":594},"as",[588,2653,2654],{"class":1858}," Record",[588,2656,2657],{"class":598},"\u003C",[588,2659,2660],{"class":1858},"string",[588,2662,658],{"class":598},[588,2664,2665],{"class":1858}," unknown",[588,2667,2668],{"class":598},">;\n",[588,2670,2671],{"class":590,"line":744},[588,2672,681],{"emptyLinePlaceholder":680},[588,2674,2675],{"class":590,"line":775},[588,2676,2678],{"class":2677},"sHwdD","  \u002F\u002F The built-in formatter fills the RFC 9457 envelope from the thrown error: `status`\u002F`title` come from the\n",[588,2680,2681],{"class":590,"line":780},[588,2682,2683],{"class":2677},"  \u002F\u002F error's status (a `NotFoundError` → 404 \"Not Found\"), `instance` is the request path, and the human-readable\n",[588,2685,2686],{"class":590,"line":816},[588,2687,2688],{"class":2677},"  \u002F\u002F message becomes `detail` (carrying the looked-up id).\n",[588,2690,2691,2693,2695,2698,2700,2702,2704,2706,2708,2710,2712,2714],{"class":590,"line":1190},[588,2692,783],{"class":687},[588,2694,691],{"class":733},[588,2696,2697],{"class":602},"problem",[588,2699,759],{"class":598},[588,2701,1667],{"class":602},[588,2703,770],{"class":733},[588,2705,759],{"class":598},[588,2707,1398],{"class":687},[588,2709,691],{"class":733},[588,2711,2493],{"class":808},[588,2713,770],{"class":733},[588,2715,622],{"class":598},[588,2717,2718,2720,2722,2724,2726,2729,2731,2733,2735,2737,2739,2742,2744,2746],{"class":590,"line":1217},[588,2719,783],{"class":687},[588,2721,691],{"class":733},[588,2723,2697],{"class":602},[588,2725,759],{"class":598},[588,2727,2728],{"class":602},"title",[588,2730,770],{"class":733},[588,2732,759],{"class":598},[588,2734,1398],{"class":687},[588,2736,691],{"class":733},[588,2738,619],{"class":598},[588,2740,2741],{"class":615},"Not Found",[588,2743,619],{"class":598},[588,2745,770],{"class":733},[588,2747,622],{"class":598},[588,2749,2750,2752,2754,2756,2758,2761,2763,2765,2767,2769,2771,2773,2775,2777],{"class":590,"line":1238},[588,2751,783],{"class":687},[588,2753,691],{"class":733},[588,2755,2697],{"class":602},[588,2757,759],{"class":598},[588,2759,2760],{"class":602},"instance",[588,2762,770],{"class":733},[588,2764,759],{"class":598},[588,2766,1398],{"class":687},[588,2768,691],{"class":733},[588,2770,619],{"class":598},[588,2772,2542],{"class":615},[588,2774,619],{"class":598},[588,2776,770],{"class":733},[588,2778,622],{"class":598},[588,2780,2781,2783,2785,2787,2789,2792,2794,2796,2798,2800,2802,2805,2807,2809],{"class":590,"line":1243},[588,2782,783],{"class":687},[588,2784,691],{"class":733},[588,2786,2697],{"class":602},[588,2788,759],{"class":598},[588,2790,2791],{"class":602},"detail",[588,2793,770],{"class":733},[588,2795,759],{"class":598},[588,2797,2138],{"class":687},[588,2799,691],{"class":733},[588,2801,619],{"class":598},[588,2803,2804],{"class":615},"999",[588,2806,619],{"class":598},[588,2808,770],{"class":733},[588,2810,622],{"class":598},[588,2812,2813,2815,2817],{"class":590,"line":1272},[588,2814,819],{"class":598},[588,2816,770],{"class":602},[588,2818,622],{"class":598},[499,2820,2821,2822,2825,2826,2829],{},"The same repository throws ",[503,2823,2824],{},"EmailAlreadyInUseError extends ConflictError"," on a duplicate email — same\npattern, different status (",[503,2827,2828],{},"409"," \"Conflict\"), proven through the live chain with no custom filter.",[1956,2831,2833],{"id":2832},"test-contract-mode-controllers","Test contract-mode controllers",[499,2835,2836,2837,2840,2841,2844,2845,2848,2849,2851,2852,2855],{},"A contract-mode controller (",[503,2838,2839],{},"implements Controller\u003CSomeApi>",") registers its routes at boot rather than\nfrom the static table. When you build the client from the lower-level ",[503,2842,2843],{},"routes"," + ",[503,2846,2847],{},"createApp"," exports\ndirectly (rather than from a ",[503,2850,960],{},"), pass the generated ",[503,2853,2854],{},"contractRegistrations"," as a third argument\nand the contract routes resolve exactly as they do in production:",[578,2857,2860],{"className":580,"code":2858,"filename":2859,"language":583,"meta":584,"style":584},"import { createTestClient } from \"@heximon\u002Fhttp\u002Ftesting\";\nimport { createApp } from \"..\u002F.heximon\u002Fapps\u002Fmain.wiring.js\";\nimport { contractRegistrations } from \"..\u002F.heximon\u002Fcontracts.js\";\nimport { routes } from \"..\u002F.heximon\u002Frouter.js\";\n\nconst app = await createApp();\nconst client = createTestClient(routes, app, contractRegistrations);\n\nconst response = await client.request(new Request(\"http:\u002F\u002Ftest\u002Fapi\u002Fproducts\"));\nexpect(response.status).toBe(200);\n","products.test.ts",[503,2861,2862,2882,2904,2926,2948,2952,2971,2996,3000,3036],{"__ignoreMap":584},[588,2863,2864,2866,2868,2870,2872,2874,2876,2878,2880],{"class":590,"line":591},[588,2865,595],{"class":594},[588,2867,599],{"class":598},[588,2869,1488],{"class":602},[588,2871,606],{"class":598},[588,2873,609],{"class":594},[588,2875,612],{"class":598},[588,2877,537],{"class":615},[588,2879,619],{"class":598},[588,2881,622],{"class":598},[588,2883,2884,2886,2888,2891,2893,2895,2897,2900,2902],{"class":590,"line":625},[588,2885,595],{"class":594},[588,2887,599],{"class":598},[588,2889,2890],{"class":602}," createApp",[588,2892,606],{"class":598},[588,2894,609],{"class":594},[588,2896,612],{"class":598},[588,2898,2899],{"class":615},"..\u002F.heximon\u002Fapps\u002Fmain.wiring.js",[588,2901,619],{"class":598},[588,2903,622],{"class":598},[588,2905,2906,2908,2910,2913,2915,2917,2919,2922,2924],{"class":590,"line":648},[588,2907,595],{"class":594},[588,2909,599],{"class":598},[588,2911,2912],{"class":602}," contractRegistrations",[588,2914,606],{"class":598},[588,2916,609],{"class":594},[588,2918,612],{"class":598},[588,2920,2921],{"class":615},"..\u002F.heximon\u002Fcontracts.js",[588,2923,619],{"class":598},[588,2925,622],{"class":598},[588,2927,2928,2930,2932,2935,2937,2939,2941,2944,2946],{"class":590,"line":677},[588,2929,595],{"class":594},[588,2931,599],{"class":598},[588,2933,2934],{"class":602}," routes",[588,2936,606],{"class":598},[588,2938,609],{"class":594},[588,2940,612],{"class":598},[588,2942,2943],{"class":615},"..\u002F.heximon\u002Frouter.js",[588,2945,619],{"class":598},[588,2947,622],{"class":598},[588,2949,2950],{"class":590,"line":684},[588,2951,681],{"emptyLinePlaceholder":680},[588,2953,2954,2957,2960,2963,2965,2967,2969],{"class":590,"line":716},[588,2955,2956],{"class":703},"const",[588,2958,2959],{"class":602}," app ",[588,2961,2962],{"class":598},"=",[588,2964,728],{"class":594},[588,2966,2890],{"class":687},[588,2968,734],{"class":602},[588,2970,622],{"class":598},[588,2972,2973,2975,2978,2980,2982,2985,2987,2989,2991,2994],{"class":590,"line":739},[588,2974,2956],{"class":703},[588,2976,2977],{"class":602}," client ",[588,2979,2962],{"class":598},[588,2981,1488],{"class":687},[588,2983,2984],{"class":602},"(routes",[588,2986,658],{"class":598},[588,2988,722],{"class":602},[588,2990,658],{"class":598},[588,2992,2993],{"class":602}," contractRegistrations)",[588,2995,622],{"class":598},[588,2997,2998],{"class":590,"line":744},[588,2999,681],{"emptyLinePlaceholder":680},[588,3001,3002,3004,3007,3009,3011,3013,3015,3017,3019,3021,3023,3025,3027,3030,3032,3034],{"class":590,"line":775},[588,3003,2956],{"class":703},[588,3005,3006],{"class":602}," response ",[588,3008,2962],{"class":598},[588,3010,728],{"class":594},[588,3012,1594],{"class":602},[588,3014,759],{"class":598},[588,3016,1629],{"class":687},[588,3018,691],{"class":602},[588,3020,1287],{"class":598},[588,3022,1636],{"class":687},[588,3024,691],{"class":602},[588,3026,619],{"class":598},[588,3028,3029],{"class":615},"http:\u002F\u002Ftest\u002Fapi\u002Fproducts",[588,3031,619],{"class":598},[588,3033,1315],{"class":602},[588,3035,622],{"class":598},[588,3037,3038,3041,3044,3046,3049,3051,3053,3055,3057,3059],{"class":590,"line":780},[588,3039,3040],{"class":687},"expect",[588,3042,3043],{"class":602},"(response",[588,3045,759],{"class":598},[588,3047,3048],{"class":602},"status)",[588,3050,759],{"class":598},[588,3052,1398],{"class":687},[588,3054,691],{"class":602},[588,3056,1678],{"class":808},[588,3058,770],{"class":602},[588,3060,622],{"class":598},[499,3062,3063,3066,3067,3069,3070,3072,3073,759],{},[503,3064,3065],{},"createTestClient(app)"," (the one-argument form over a ",[503,3068,960],{},") reads ",[503,3071,2854],{}," off the\napp automatically — pass it explicitly only when you're driving the generated wiring by hand instead of\nthrough ",[503,3074,505],{},[555,3076,3078],{"id":3077},"swap-real-dependencies-for-fakes","Swap real dependencies for fakes",[499,3080,3081,892,3084,3086,3087,3089],{},[519,3082,3083],{},"An override replaces a DI token everywhere it is injected.",[503,3085,505],{}," compiles in a dedicated\ntest wiring mode, so an override reaches every injection site of the token — same-module construction,\ncross-module constructor inputs, dispatched handlers, and direct ",[503,3088,525],{},". The real provider is\nnever constructed when an override is active. The mental model is simple: the fake stands in for the real\nprovider at every site.",[499,3091,3092,3093,3096],{},"A controller is one such site — resolved at dispatch via ",[503,3094,3095],{},"app.get(UsersController)"," — which makes it an\neasy seam to replace in a test. Two isolated apps, each with a different controller fake, see only their\nown override:",[578,3098,3101],{"className":580,"code":3099,"filename":3100,"language":583,"meta":584,"style":584},"import { createTestClient } from \"@heximon\u002Fhttp\u002Ftesting\";\nimport { createTestApp } from \"@heximon\u002Ftesting\";\nimport { expect, test } from \"vitest\";\nimport { UsersController } from \"..\u002Fsrc\u002Fusers\u002Fusers.controller\";\n\ntest(\"two isolated apps with different controller overrides do not cross-talk\", async () => {\n  class FakeUsersController {\n    constructor(private readonly roster: { id: string; name: string }[]) {}\n    public async list(): Promise\u003C{ id: string; name: string }[]> {\n      return this.roster;\n    }\n  }\n\n  await using appA = await createTestApp({\n    overrides: [{ provide: UsersController, useValue: new FakeUsersController([{ id: \"a1\", name: \"Anna\" }]) }],\n  });\n  await using appB = await createTestApp({\n    overrides: [{ provide: UsersController, useValue: new FakeUsersController([{ id: \"b1\", name: \"Bence\" }]) }],\n  });\n\n  const clientA = createTestClient(appA);\n  const clientB = createTestClient(appB);\n\n  expect(await (await clientA.request(new Request(\"http:\u002F\u002Flocalhost\u002Fusers\"))).json()).toEqual([\n    { id: \"a1\", name: \"Anna\" },\n  ]);\n  expect(await (await clientB.request(new Request(\"http:\u002F\u002Flocalhost\u002Fusers\"))).json()).toEqual([\n    { id: \"b1\", name: \"Bence\" },\n  ]);\n});\n","test\u002Fmulti-app-isolation.test.ts",[503,3102,3103,3123,3143,3167,3189,3193,3216,3226,3272,3314,3327,3332,3337,3341,3359,3431,3439,3456,3520,3528,3532,3552,3573,3578,3626,3655,3662,3709,3738,3745],{"__ignoreMap":584},[588,3104,3105,3107,3109,3111,3113,3115,3117,3119,3121],{"class":590,"line":591},[588,3106,595],{"class":594},[588,3108,599],{"class":598},[588,3110,1488],{"class":602},[588,3112,606],{"class":598},[588,3114,609],{"class":594},[588,3116,612],{"class":598},[588,3118,537],{"class":615},[588,3120,619],{"class":598},[588,3122,622],{"class":598},[588,3124,3125,3127,3129,3131,3133,3135,3137,3139,3141],{"class":590,"line":625},[588,3126,595],{"class":594},[588,3128,599],{"class":598},[588,3130,603],{"class":602},[588,3132,606],{"class":598},[588,3134,609],{"class":594},[588,3136,612],{"class":598},[588,3138,616],{"class":615},[588,3140,619],{"class":598},[588,3142,622],{"class":598},[588,3144,3145,3147,3149,3151,3153,3155,3157,3159,3161,3163,3165],{"class":590,"line":648},[588,3146,595],{"class":594},[588,3148,599],{"class":598},[588,3150,655],{"class":602},[588,3152,658],{"class":598},[588,3154,661],{"class":602},[588,3156,606],{"class":598},[588,3158,609],{"class":594},[588,3160,612],{"class":598},[588,3162,670],{"class":615},[588,3164,619],{"class":598},[588,3166,622],{"class":598},[588,3168,3169,3171,3173,3176,3178,3180,3182,3185,3187],{"class":590,"line":677},[588,3170,595],{"class":594},[588,3172,599],{"class":598},[588,3174,3175],{"class":602}," UsersController",[588,3177,606],{"class":598},[588,3179,609],{"class":594},[588,3181,612],{"class":598},[588,3183,3184],{"class":615},"..\u002Fsrc\u002Fusers\u002Fusers.controller",[588,3186,619],{"class":598},[588,3188,622],{"class":598},[588,3190,3191],{"class":590,"line":684},[588,3192,681],{"emptyLinePlaceholder":680},[588,3194,3195,3197,3199,3201,3204,3206,3208,3210,3212,3214],{"class":590,"line":716},[588,3196,688],{"class":687},[588,3198,691],{"class":602},[588,3200,619],{"class":598},[588,3202,3203],{"class":615},"two isolated apps with different controller overrides do not cross-talk",[588,3205,619],{"class":598},[588,3207,658],{"class":598},[588,3209,704],{"class":703},[588,3211,707],{"class":598},[588,3213,710],{"class":703},[588,3215,713],{"class":598},[588,3217,3218,3221,3224],{"class":590,"line":739},[588,3219,3220],{"class":703},"  class",[588,3222,3223],{"class":1858}," FakeUsersController",[588,3225,713],{"class":598},[588,3227,3228,3231,3233,3236,3239,3242,3244,3246,3248,3250,3253,3256,3258,3260,3262,3264,3267,3269],{"class":590,"line":744},[588,3229,3230],{"class":703},"    constructor",[588,3232,691],{"class":598},[588,3234,3235],{"class":703},"private",[588,3237,3238],{"class":703}," readonly",[588,3240,3241],{"class":1374}," roster",[588,3243,1755],{"class":598},[588,3245,599],{"class":598},[588,3247,1222],{"class":733},[588,3249,1755],{"class":598},[588,3251,3252],{"class":1858}," string",[588,3254,3255],{"class":598},";",[588,3257,2196],{"class":733},[588,3259,1755],{"class":598},[588,3261,3252],{"class":1858},[588,3263,606],{"class":598},[588,3265,3266],{"class":733},"[]",[588,3268,770],{"class":598},[588,3270,3271],{"class":598}," {}\n",[588,3273,3274,3277,3279,3282,3285,3288,3291,3293,3295,3297,3299,3301,3303,3305,3307,3309,3312],{"class":590,"line":775},[588,3275,3276],{"class":703},"    public",[588,3278,704],{"class":703},[588,3280,3281],{"class":733}," list",[588,3283,3284],{"class":598},"():",[588,3286,3287],{"class":1858}," Promise",[588,3289,3290],{"class":598},"\u003C{",[588,3292,1222],{"class":733},[588,3294,1755],{"class":598},[588,3296,3252],{"class":1858},[588,3298,3255],{"class":598},[588,3300,2196],{"class":733},[588,3302,1755],{"class":598},[588,3304,3252],{"class":1858},[588,3306,606],{"class":598},[588,3308,3266],{"class":733},[588,3310,3311],{"class":598},">",[588,3313,713],{"class":598},[588,3315,3316,3319,3322,3325],{"class":590,"line":780},[588,3317,3318],{"class":594},"      return",[588,3320,3321],{"class":598}," this.",[588,3323,3324],{"class":602},"roster",[588,3326,622],{"class":598},[588,3328,3329],{"class":590,"line":816},[588,3330,3331],{"class":598},"    }\n",[588,3333,3334],{"class":590,"line":1190},[588,3335,3336],{"class":598},"  }\n",[588,3338,3339],{"class":590,"line":1217},[588,3340,681],{"emptyLinePlaceholder":680},[588,3342,3343,3345,3348,3350,3352,3354,3356],{"class":590,"line":1238},[588,3344,719],{"class":703},[588,3346,3347],{"class":602}," appA",[588,3349,725],{"class":598},[588,3351,728],{"class":594},[588,3353,603],{"class":687},[588,3355,691],{"class":733},[588,3357,3358],{"class":598},"{\n",[588,3360,3361,3364,3366,3369,3371,3374,3376,3378,3380,3383,3385,3388,3390,3393,3395,3397,3399,3401,3404,3406,3408,3410,3412,3414,3417,3419,3421,3424,3426,3429],{"class":590,"line":1243},[588,3362,3363],{"class":733},"    overrides",[588,3365,1755],{"class":598},[588,3367,3368],{"class":733}," [",[588,3370,2394],{"class":598},[588,3372,3373],{"class":733}," provide",[588,3375,1755],{"class":598},[588,3377,3175],{"class":602},[588,3379,658],{"class":598},[588,3381,3382],{"class":733}," useValue",[588,3384,1755],{"class":598},[588,3386,3387],{"class":598}," new",[588,3389,3223],{"class":687},[588,3391,3392],{"class":733},"([",[588,3394,2394],{"class":598},[588,3396,1222],{"class":733},[588,3398,1755],{"class":598},[588,3400,612],{"class":598},[588,3402,3403],{"class":615},"a1",[588,3405,619],{"class":598},[588,3407,658],{"class":598},[588,3409,2196],{"class":733},[588,3411,1755],{"class":598},[588,3413,612],{"class":598},[588,3415,3416],{"class":615},"Anna",[588,3418,619],{"class":598},[588,3420,606],{"class":598},[588,3422,3423],{"class":733},"]) ",[588,3425,819],{"class":598},[588,3427,3428],{"class":733},"]",[588,3430,1972],{"class":598},[588,3432,3433,3435,3437],{"class":590,"line":1272},[588,3434,1414],{"class":598},[588,3436,770],{"class":733},[588,3438,622],{"class":598},[588,3440,3441,3443,3446,3448,3450,3452,3454],{"class":590,"line":1320},[588,3442,719],{"class":703},[588,3444,3445],{"class":602}," appB",[588,3447,725],{"class":598},[588,3449,728],{"class":594},[588,3451,603],{"class":687},[588,3453,691],{"class":733},[588,3455,3358],{"class":598},[588,3457,3458,3460,3462,3464,3466,3468,3470,3472,3474,3476,3478,3480,3482,3484,3486,3488,3490,3492,3495,3497,3499,3501,3503,3505,3508,3510,3512,3514,3516,3518],{"class":590,"line":1325},[588,3459,3363],{"class":733},[588,3461,1755],{"class":598},[588,3463,3368],{"class":733},[588,3465,2394],{"class":598},[588,3467,3373],{"class":733},[588,3469,1755],{"class":598},[588,3471,3175],{"class":602},[588,3473,658],{"class":598},[588,3475,3382],{"class":733},[588,3477,1755],{"class":598},[588,3479,3387],{"class":598},[588,3481,3223],{"class":687},[588,3483,3392],{"class":733},[588,3485,2394],{"class":598},[588,3487,1222],{"class":733},[588,3489,1755],{"class":598},[588,3491,612],{"class":598},[588,3493,3494],{"class":615},"b1",[588,3496,619],{"class":598},[588,3498,658],{"class":598},[588,3500,2196],{"class":733},[588,3502,1755],{"class":598},[588,3504,612],{"class":598},[588,3506,3507],{"class":615},"Bence",[588,3509,619],{"class":598},[588,3511,606],{"class":598},[588,3513,3423],{"class":733},[588,3515,819],{"class":598},[588,3517,3428],{"class":733},[588,3519,1972],{"class":598},[588,3521,3522,3524,3526],{"class":590,"line":1354},[588,3523,1414],{"class":598},[588,3525,770],{"class":733},[588,3527,622],{"class":598},[588,3529,3530],{"class":590,"line":1411},[588,3531,681],{"emptyLinePlaceholder":680},[588,3533,3534,3536,3539,3541,3543,3545,3548,3550],{"class":590,"line":1421},[588,3535,747],{"class":703},[588,3537,3538],{"class":602}," clientA",[588,3540,725],{"class":598},[588,3542,1488],{"class":687},[588,3544,691],{"class":733},[588,3546,3547],{"class":602},"appA",[588,3549,770],{"class":733},[588,3551,622],{"class":598},[588,3553,3555,3557,3560,3562,3564,3566,3569,3571],{"class":590,"line":3554},22,[588,3556,747],{"class":703},[588,3558,3559],{"class":602}," clientB",[588,3561,725],{"class":598},[588,3563,1488],{"class":687},[588,3565,691],{"class":733},[588,3567,3568],{"class":602},"appB",[588,3570,770],{"class":733},[588,3572,622],{"class":598},[588,3574,3576],{"class":590,"line":3575},23,[588,3577,681],{"emptyLinePlaceholder":680},[588,3579,3581,3583,3585,3587,3589,3591,3593,3595,3597,3599,3601,3603,3605,3607,3609,3611,3614,3616,3618,3620,3622,3624],{"class":590,"line":3580},24,[588,3582,783],{"class":687},[588,3584,691],{"class":733},[588,3586,788],{"class":594},[588,3588,2637],{"class":733},[588,3590,788],{"class":594},[588,3592,3538],{"class":602},[588,3594,759],{"class":598},[588,3596,1629],{"class":687},[588,3598,691],{"class":733},[588,3600,1287],{"class":598},[588,3602,1636],{"class":687},[588,3604,691],{"class":733},[588,3606,619],{"class":598},[588,3608,1643],{"class":615},[588,3610,619],{"class":598},[588,3612,3613],{"class":733},")))",[588,3615,759],{"class":598},[588,3617,1697],{"class":687},[588,3619,798],{"class":733},[588,3621,759],{"class":598},[588,3623,2172],{"class":687},[588,3625,2175],{"class":733},[588,3627,3629,3631,3633,3635,3637,3639,3641,3643,3645,3647,3649,3651,3653],{"class":590,"line":3628},25,[588,3630,2180],{"class":598},[588,3632,1222],{"class":733},[588,3634,1755],{"class":598},[588,3636,612],{"class":598},[588,3638,3403],{"class":615},[588,3640,619],{"class":598},[588,3642,658],{"class":598},[588,3644,2196],{"class":733},[588,3646,1755],{"class":598},[588,3648,612],{"class":598},[588,3650,3416],{"class":615},[588,3652,619],{"class":598},[588,3654,2220],{"class":598},[588,3656,3658,3660],{"class":590,"line":3657},26,[588,3659,2267],{"class":733},[588,3661,622],{"class":598},[588,3663,3665,3667,3669,3671,3673,3675,3677,3679,3681,3683,3685,3687,3689,3691,3693,3695,3697,3699,3701,3703,3705,3707],{"class":590,"line":3664},27,[588,3666,783],{"class":687},[588,3668,691],{"class":733},[588,3670,788],{"class":594},[588,3672,2637],{"class":733},[588,3674,788],{"class":594},[588,3676,3559],{"class":602},[588,3678,759],{"class":598},[588,3680,1629],{"class":687},[588,3682,691],{"class":733},[588,3684,1287],{"class":598},[588,3686,1636],{"class":687},[588,3688,691],{"class":733},[588,3690,619],{"class":598},[588,3692,1643],{"class":615},[588,3694,619],{"class":598},[588,3696,3613],{"class":733},[588,3698,759],{"class":598},[588,3700,1697],{"class":687},[588,3702,798],{"class":733},[588,3704,759],{"class":598},[588,3706,2172],{"class":687},[588,3708,2175],{"class":733},[588,3710,3712,3714,3716,3718,3720,3722,3724,3726,3728,3730,3732,3734,3736],{"class":590,"line":3711},28,[588,3713,2180],{"class":598},[588,3715,1222],{"class":733},[588,3717,1755],{"class":598},[588,3719,612],{"class":598},[588,3721,3494],{"class":615},[588,3723,619],{"class":598},[588,3725,658],{"class":598},[588,3727,2196],{"class":733},[588,3729,1755],{"class":598},[588,3731,612],{"class":598},[588,3733,3507],{"class":615},[588,3735,619],{"class":598},[588,3737,2220],{"class":598},[588,3739,3741,3743],{"class":590,"line":3740},29,[588,3742,2267],{"class":733},[588,3744,622],{"class":598},[588,3746,3748,3750,3752],{"class":590,"line":3747},30,[588,3749,819],{"class":598},[588,3751,770],{"class":602},[588,3753,622],{"class":598},[499,3755,3756,3757,3760,3761,3764,3765,3768,3769,3771],{},"Each override is ",[503,3758,3759],{},"{ provide: Token, useValue }"," (a ready-made instance), ",[503,3762,3763],{},"{ provide: Token, useClass }","\n(a no-arg class the graph constructs once, shared across all consumers within that app), or\n",[503,3766,3767],{},"{ provide: Token, useFactory }"," (a factory given the request ",[503,3770,552],{},", built once and memoized — for a\nfake that needs the ambient context, like a database). The token is the class you would inject — the same\nclass identity you import from source.",[499,3773,3774,3777,3778,3781,3782,3785,3786,3788,3789,3792],{},[519,3775,3776],{},"A same-module constructor dependency is reachable too."," When ",[503,3779,3780],{},"Service(dep: Helper)"," and ",[503,3783,3784],{},"Helper"," live\nin the same module, an override of ",[503,3787,3784],{}," still reaches ",[503,3790,3791],{},"Service","'s constructor — test mode re-keys\nevery construction site through the override, not just the cross-module ones:",[578,3794,3797],{"className":580,"code":3795,"filename":3796,"language":583,"meta":584,"style":584},"import { createTestApp } from \"@heximon\u002Ftesting\";\nimport { FakeHelper, Helper } from \"..\u002Fsrc\u002Fhelper\";\nimport { Service } from \"..\u002Fsrc\u002Fservice\";\n\nawait using app = await createTestApp({\n  overrides: [{ provide: Helper, useClass: FakeHelper }],\n});\n\nconst service = await app.get(Service);\nexpect(service.dep).toBeInstanceOf(FakeHelper);\n","test\u002Fservice.test.ts",[503,3798,3799,3819,3846,3868,3872,3888,3921,3929,3933,3955],{"__ignoreMap":584},[588,3800,3801,3803,3805,3807,3809,3811,3813,3815,3817],{"class":590,"line":591},[588,3802,595],{"class":594},[588,3804,599],{"class":598},[588,3806,603],{"class":602},[588,3808,606],{"class":598},[588,3810,609],{"class":594},[588,3812,612],{"class":598},[588,3814,616],{"class":615},[588,3816,619],{"class":598},[588,3818,622],{"class":598},[588,3820,3821,3823,3825,3828,3830,3833,3835,3837,3839,3842,3844],{"class":590,"line":625},[588,3822,595],{"class":594},[588,3824,599],{"class":598},[588,3826,3827],{"class":602}," FakeHelper",[588,3829,658],{"class":598},[588,3831,3832],{"class":602}," Helper",[588,3834,606],{"class":598},[588,3836,609],{"class":594},[588,3838,612],{"class":598},[588,3840,3841],{"class":615},"..\u002Fsrc\u002Fhelper",[588,3843,619],{"class":598},[588,3845,622],{"class":598},[588,3847,3848,3850,3852,3855,3857,3859,3861,3864,3866],{"class":590,"line":648},[588,3849,595],{"class":594},[588,3851,599],{"class":598},[588,3853,3854],{"class":602}," Service",[588,3856,606],{"class":598},[588,3858,609],{"class":594},[588,3860,612],{"class":598},[588,3862,3863],{"class":615},"..\u002Fsrc\u002Fservice",[588,3865,619],{"class":598},[588,3867,622],{"class":598},[588,3869,3870],{"class":590,"line":677},[588,3871,681],{"emptyLinePlaceholder":680},[588,3873,3874,3876,3878,3880,3882,3884,3886],{"class":590,"line":684},[588,3875,513],{"class":703},[588,3877,2959],{"class":602},[588,3879,2962],{"class":598},[588,3881,728],{"class":594},[588,3883,603],{"class":687},[588,3885,691],{"class":602},[588,3887,3358],{"class":598},[588,3889,3890,3893,3895,3897,3899,3901,3903,3905,3907,3910,3912,3915,3917,3919],{"class":590,"line":716},[588,3891,3892],{"class":733},"  overrides",[588,3894,1755],{"class":598},[588,3896,3368],{"class":602},[588,3898,2394],{"class":598},[588,3900,3373],{"class":733},[588,3902,1755],{"class":598},[588,3904,3832],{"class":602},[588,3906,658],{"class":598},[588,3908,3909],{"class":733}," useClass",[588,3911,1755],{"class":598},[588,3913,3914],{"class":602}," FakeHelper ",[588,3916,819],{"class":598},[588,3918,3428],{"class":602},[588,3920,1972],{"class":598},[588,3922,3923,3925,3927],{"class":590,"line":739},[588,3924,819],{"class":598},[588,3926,770],{"class":602},[588,3928,622],{"class":598},[588,3930,3931],{"class":590,"line":744},[588,3932,681],{"emptyLinePlaceholder":680},[588,3934,3935,3937,3940,3942,3944,3946,3948,3950,3953],{"class":590,"line":775},[588,3936,2956],{"class":703},[588,3938,3939],{"class":602}," service ",[588,3941,2962],{"class":598},[588,3943,728],{"class":594},[588,3945,722],{"class":602},[588,3947,759],{"class":598},[588,3949,762],{"class":687},[588,3951,3952],{"class":602},"(Service)",[588,3954,622],{"class":598},[588,3956,3957,3959,3962,3964,3967,3969,3972,3975],{"class":590,"line":780},[588,3958,3040],{"class":687},[588,3960,3961],{"class":602},"(service",[588,3963,759],{"class":598},[588,3965,3966],{"class":602},"dep)",[588,3968,759],{"class":598},[588,3970,3971],{"class":687},"toBeInstanceOf",[588,3973,3974],{"class":602},"(FakeHelper)",[588,3976,622],{"class":598},[499,3978,3979,3982,3983,3986,3987,3781,3990,3993,3994,3997,3998,4001,4002,4005],{},[519,3980,3981],{},"One boundary is out of reach: a precompiled package's internals."," An imported ",[519,3984,3985],{},"precompiled"," package (a library-mode boundary) is overridable\nonly at its declared seams — its ",[503,3988,3989],{},"requires",[503,3991,3992],{},"exports"," — never its internals, which were wired at that\npackage's own build time. A genuinely internal ",[503,3995,3996],{},"new EmailClient(config)"," where ",[503,3999,4000],{},"EmailClient"," is ",[519,4003,4004],{},"not"," a\nDI token also has nothing for an override to key on; declare it as a token (or a constructor parameter)\nand the override takes effect.",[499,4007,4008,4013,4014,1743,4017,4020,4021,4023,4024,4026,4027,4029],{},[519,4009,4010,4012],{},[503,4011,505],{}," returns a distinct, fully isolated handle each call",", so a suite that boots several\napps in one process — one per tenant, or a fresh app per test — sees no cross-talk: the two apps above\nhave their own registries, and ",[503,4015,4016],{},"clientA",[503,4018,4019],{},"clientB"," see only their own controller override. Contract\nroutes are app-scoped the same way — keyed to the handle passed to ",[503,4022,533],{}," — so give each app\nonly its own ",[503,4025,2854],{}," and a route registered on one app ",[503,4028,2493],{},"s on the other:",[578,4031,4034],{"className":580,"code":4032,"filename":4033,"language":583,"meta":584,"style":584},"const clientA = createTestClient(routes, appA, [alphaRegistration]);\nconst clientB = createTestClient(routes, appB, [betaRegistration]);\n\nexpect((await clientA.request(new Request(\"http:\u002F\u002Ftest\u002Falpha\u002Fping\"))).status).toBe(200);\nexpect((await clientA.request(new Request(\"http:\u002F\u002Ftest\u002Fbeta\u002Fping\"))).status).toBe(404); \u002F\u002F no leak\n","contracts-isolation.test.ts",[503,4035,4036,4060,4084,4088,4136],{"__ignoreMap":584},[588,4037,4038,4040,4043,4045,4047,4049,4051,4053,4055,4058],{"class":590,"line":591},[588,4039,2956],{"class":703},[588,4041,4042],{"class":602}," clientA ",[588,4044,2962],{"class":598},[588,4046,1488],{"class":687},[588,4048,2984],{"class":602},[588,4050,658],{"class":598},[588,4052,3347],{"class":602},[588,4054,658],{"class":598},[588,4056,4057],{"class":602}," [alphaRegistration])",[588,4059,622],{"class":598},[588,4061,4062,4064,4067,4069,4071,4073,4075,4077,4079,4082],{"class":590,"line":625},[588,4063,2956],{"class":703},[588,4065,4066],{"class":602}," clientB ",[588,4068,2962],{"class":598},[588,4070,1488],{"class":687},[588,4072,2984],{"class":602},[588,4074,658],{"class":598},[588,4076,3445],{"class":602},[588,4078,658],{"class":598},[588,4080,4081],{"class":602}," [betaRegistration])",[588,4083,622],{"class":598},[588,4085,4086],{"class":590,"line":648},[588,4087,681],{"emptyLinePlaceholder":680},[588,4089,4090,4092,4095,4097,4099,4101,4103,4105,4107,4109,4111,4113,4116,4118,4120,4122,4124,4126,4128,4130,4132,4134],{"class":590,"line":677},[588,4091,3040],{"class":687},[588,4093,4094],{"class":602},"((",[588,4096,788],{"class":594},[588,4098,3538],{"class":602},[588,4100,759],{"class":598},[588,4102,1629],{"class":687},[588,4104,691],{"class":602},[588,4106,1287],{"class":598},[588,4108,1636],{"class":687},[588,4110,691],{"class":602},[588,4112,619],{"class":598},[588,4114,4115],{"class":615},"http:\u002F\u002Ftest\u002Falpha\u002Fping",[588,4117,619],{"class":598},[588,4119,3613],{"class":602},[588,4121,759],{"class":598},[588,4123,3048],{"class":602},[588,4125,759],{"class":598},[588,4127,1398],{"class":687},[588,4129,691],{"class":602},[588,4131,1678],{"class":808},[588,4133,770],{"class":602},[588,4135,622],{"class":598},[588,4137,4138,4140,4142,4144,4146,4148,4150,4152,4154,4156,4158,4160,4163,4165,4167,4169,4171,4173,4175,4177,4179,4181,4183],{"class":590,"line":684},[588,4139,3040],{"class":687},[588,4141,4094],{"class":602},[588,4143,788],{"class":594},[588,4145,3538],{"class":602},[588,4147,759],{"class":598},[588,4149,1629],{"class":687},[588,4151,691],{"class":602},[588,4153,1287],{"class":598},[588,4155,1636],{"class":687},[588,4157,691],{"class":602},[588,4159,619],{"class":598},[588,4161,4162],{"class":615},"http:\u002F\u002Ftest\u002Fbeta\u002Fping",[588,4164,619],{"class":598},[588,4166,3613],{"class":602},[588,4168,759],{"class":598},[588,4170,3048],{"class":602},[588,4172,759],{"class":598},[588,4174,1398],{"class":687},[588,4176,691],{"class":602},[588,4178,2493],{"class":808},[588,4180,770],{"class":602},[588,4182,3255],{"class":598},[588,4184,4185],{"class":2677}," \u002F\u002F no leak\n",[555,4187,4189],{"id":4188},"isolate-the-database-between-tests","Isolate the database between tests",[499,4191,4192,4194,4195,4198,4199,4201],{},[503,4193,505],{}," produces a ",[519,4196,4197],{},"fresh DI graph per call"," — every provider is constructed anew, ",[503,4200,842],{},"\nruns again, and no in-process state is shared between calls.",[499,4203,4204,4205,4208,4209,4212,4213,4215],{},"However, the DI graph and the database are\ndifferent things: the database in the Drizzle examples is configured as ",[503,4206,4207],{},"file::memory:?cache=shared"," (a\nlibsql connection string), and that connection is ",[519,4210,4211],{},"process-global"," — two ",[503,4214,572],{}," calls within\nthe same test file share the same in-memory tables.",[499,4217,4218,4219,4222,4223,4226,4227,4229],{},"You ",[519,4220,4221],{},"can"," swap the database token itself with a ",[503,4224,4225],{},"useFactory"," override — the factory is given the request\n",[503,4228,552],{},", so a fake that needs the ambient context can be expressed, and the fake reaches every\nconstructor-injected consumer (a repository, a service):",[578,4231,4234],{"className":580,"code":4232,"filename":4233,"language":583,"meta":584,"style":584},"import { createTestApp } from \"@heximon\u002Ftesting\";\nimport { Database, FakeDatabase } from \"..\u002Fsrc\u002Fdatabase\";\nimport { WidgetRepository } from \"..\u002Fsrc\u002Fwidget.repository\";\n\nawait using app = await createTestApp({\n  overrides: [{ provide: Database, useFactory: () => new FakeDatabase() }],\n});\n\n\u002F\u002F `WidgetRepository(database: Database)` is constructor-injected; the override reaches that constructor.\nconst repository = await app.get(WidgetRepository);\nexpect(repository.databaseLabel()).toBe(\"fake-db\");\n","test\u002Fdatabase-swap.test.ts",[503,4235,4236,4256,4283,4305,4309,4325,4365,4373,4377,4382,4404],{"__ignoreMap":584},[588,4237,4238,4240,4242,4244,4246,4248,4250,4252,4254],{"class":590,"line":591},[588,4239,595],{"class":594},[588,4241,599],{"class":598},[588,4243,603],{"class":602},[588,4245,606],{"class":598},[588,4247,609],{"class":594},[588,4249,612],{"class":598},[588,4251,616],{"class":615},[588,4253,619],{"class":598},[588,4255,622],{"class":598},[588,4257,4258,4260,4262,4265,4267,4270,4272,4274,4276,4279,4281],{"class":590,"line":625},[588,4259,595],{"class":594},[588,4261,599],{"class":598},[588,4263,4264],{"class":602}," Database",[588,4266,658],{"class":598},[588,4268,4269],{"class":602}," FakeDatabase",[588,4271,606],{"class":598},[588,4273,609],{"class":594},[588,4275,612],{"class":598},[588,4277,4278],{"class":615},"..\u002Fsrc\u002Fdatabase",[588,4280,619],{"class":598},[588,4282,622],{"class":598},[588,4284,4285,4287,4289,4292,4294,4296,4298,4301,4303],{"class":590,"line":648},[588,4286,595],{"class":594},[588,4288,599],{"class":598},[588,4290,4291],{"class":602}," WidgetRepository",[588,4293,606],{"class":598},[588,4295,609],{"class":594},[588,4297,612],{"class":598},[588,4299,4300],{"class":615},"..\u002Fsrc\u002Fwidget.repository",[588,4302,619],{"class":598},[588,4304,622],{"class":598},[588,4306,4307],{"class":590,"line":677},[588,4308,681],{"emptyLinePlaceholder":680},[588,4310,4311,4313,4315,4317,4319,4321,4323],{"class":590,"line":684},[588,4312,513],{"class":703},[588,4314,2959],{"class":602},[588,4316,2962],{"class":598},[588,4318,728],{"class":594},[588,4320,603],{"class":687},[588,4322,691],{"class":602},[588,4324,3358],{"class":598},[588,4326,4327,4329,4331,4333,4335,4337,4339,4341,4343,4346,4348,4350,4352,4354,4356,4359,4361,4363],{"class":590,"line":716},[588,4328,3892],{"class":733},[588,4330,1755],{"class":598},[588,4332,3368],{"class":602},[588,4334,2394],{"class":598},[588,4336,3373],{"class":733},[588,4338,1755],{"class":598},[588,4340,4264],{"class":602},[588,4342,658],{"class":598},[588,4344,4345],{"class":687}," useFactory",[588,4347,1755],{"class":598},[588,4349,707],{"class":598},[588,4351,710],{"class":703},[588,4353,3387],{"class":598},[588,4355,4269],{"class":687},[588,4357,4358],{"class":602},"() ",[588,4360,819],{"class":598},[588,4362,3428],{"class":602},[588,4364,1972],{"class":598},[588,4366,4367,4369,4371],{"class":590,"line":739},[588,4368,819],{"class":598},[588,4370,770],{"class":602},[588,4372,622],{"class":598},[588,4374,4375],{"class":590,"line":744},[588,4376,681],{"emptyLinePlaceholder":680},[588,4378,4379],{"class":590,"line":775},[588,4380,4381],{"class":2677},"\u002F\u002F `WidgetRepository(database: Database)` is constructor-injected; the override reaches that constructor.\n",[588,4383,4384,4386,4389,4391,4393,4395,4397,4399,4402],{"class":590,"line":780},[588,4385,2956],{"class":703},[588,4387,4388],{"class":602}," repository ",[588,4390,2962],{"class":598},[588,4392,728],{"class":594},[588,4394,722],{"class":602},[588,4396,759],{"class":598},[588,4398,762],{"class":687},[588,4400,4401],{"class":602},"(WidgetRepository)",[588,4403,622],{"class":598},[588,4405,4406,4408,4411,4413,4416,4418,4420,4422,4424,4426,4429,4431,4433],{"class":590,"line":816},[588,4407,3040],{"class":687},[588,4409,4410],{"class":602},"(repository",[588,4412,759],{"class":598},[588,4414,4415],{"class":687},"databaseLabel",[588,4417,798],{"class":602},[588,4419,759],{"class":598},[588,4421,1398],{"class":687},[588,4423,691],{"class":602},[588,4425,619],{"class":598},[588,4427,4428],{"class":615},"fake-db",[588,4430,619],{"class":598},[588,4432,770],{"class":602},[588,4434,622],{"class":598},[499,4436,4437,4438,4441,4442,4444],{},"That swaps which database the app holds. The remaining process-global concern is the shared in-memory\n",[894,4439,4440],{},"connection"," when two apps in the same file use the real ",[503,4443,4207],{}," database — they see\nthe same tables.",[499,4446,4447,4450],{},[519,4448,4449],{},"In practice this is rarely a problem."," Vitest runs each test file in its own worker (projects mode), so\ndifferent test files do not share the database. Within a single file, use one of these patterns:",[4452,4453,4454,4465,4481],"ul",{},[4455,4456,4457,4460,4461,4464],"li",{},[519,4458,4459],{},"Fresh data per test."," Generate unique ids (e.g. ",[503,4462,4463],{},"uuid.v7()",") and assert only on the data each test\nwrites. Tests then coexist in the same tables without conflict.",[4455,4466,4467,4472,4473,4475,4476,1743,4478,4480],{},[519,4468,4469,759],{},[503,4470,4471],{},"describe.sequential"," Group tests that depend on a shared execution order into a\n",[503,4474,4471],{}," block and use one ",[503,4477,1742],{},[503,4479,835],{}," pair for the whole block (as in the\nDrizzle example).",[4455,4482,4483,4486],{},[519,4484,4485],{},"Separate files."," If two suites truly must not see each other's rows, put them in separate test files\nand Vitest's per-file isolation takes care of the rest.",[555,4488,4490],{"id":4489},"test-cross-service-fan-out-with-auto-discovery","Test cross-service fan-out with auto-discovery",[499,4492,4493,4494,4497,4498,4500,4501,4504,4505,4507,4508,4511],{},"A service that opts into cross-service integration events declares a ",[503,4495,4496],{},"crossService"," block in its\n",[503,4499,902],{}," — the scan ",[503,4502,4503],{},"vp build"," runs to discover which sibling services subscribe to which\nevents. ",[503,4506,505],{}," runs that ",[519,4509,4510],{},"same discovery scan"," against disk before compiling, so testing two\nindependently-deployed services together needs no hand-built topology — boot each service's root and let\nthe scan find the other:",[578,4513,4516],{"className":580,"code":4514,"filename":4515,"language":583,"meta":584,"style":584},"export default defineHeximonConfig({\n  plugins: [new IntegrationEventsPlugin(), new HttpPlugin()],\n  service: \"orders\",\n  crossService: { workspaceRoot: \"..\" },\n});\n","services\u002Forders\u002Fheximon.config.ts",[503,4517,4518,4533,4561,4577,4600],{"__ignoreMap":584},[588,4519,4520,4523,4526,4529,4531],{"class":590,"line":591},[588,4521,4522],{"class":594},"export",[588,4524,4525],{"class":594}," default",[588,4527,4528],{"class":687}," defineHeximonConfig",[588,4530,691],{"class":602},[588,4532,3358],{"class":598},[588,4534,4535,4538,4540,4542,4544,4547,4549,4551,4553,4556,4559],{"class":590,"line":625},[588,4536,4537],{"class":733},"  plugins",[588,4539,1755],{"class":598},[588,4541,3368],{"class":602},[588,4543,1287],{"class":598},[588,4545,4546],{"class":687}," IntegrationEventsPlugin",[588,4548,734],{"class":602},[588,4550,658],{"class":598},[588,4552,3387],{"class":598},[588,4554,4555],{"class":687}," HttpPlugin",[588,4557,4558],{"class":602},"()]",[588,4560,1972],{"class":598},[588,4562,4563,4566,4568,4570,4573,4575],{"class":590,"line":648},[588,4564,4565],{"class":733},"  service",[588,4567,1755],{"class":598},[588,4569,612],{"class":598},[588,4571,4572],{"class":615},"orders",[588,4574,619],{"class":598},[588,4576,1972],{"class":598},[588,4578,4579,4582,4584,4586,4589,4591,4593,4596,4598],{"class":590,"line":677},[588,4580,4581],{"class":733},"  crossService",[588,4583,1755],{"class":598},[588,4585,599],{"class":598},[588,4587,4588],{"class":733}," workspaceRoot",[588,4590,1755],{"class":598},[588,4592,612],{"class":598},[588,4594,4595],{"class":615},"..",[588,4597,619],{"class":598},[588,4599,2220],{"class":598},[588,4601,4602,4604,4606],{"class":590,"line":684},[588,4603,819],{"class":598},[588,4605,770],{"class":602},[588,4607,622],{"class":598},[499,4609,4610,4613,4614,4617,4618,4621,4622,4625,4626,4629],{},[503,4611,4612],{},"workspaceRoot"," points the scan at the sibling-services root. Without it the scan walks up to the\nnearest ",[503,4615,4616],{},"pnpm-workspace.yaml"," — in a nested ",[503,4619,4620],{},"services\u002F*"," layout like this one that lands on the outer\nworkspace, not ",[503,4623,4624],{},"services\u002F",". Services sitting at the workspace's own top level can omit the knob\nentirely (",[503,4627,4628],{},"crossService: {}",").",[578,4631,4634],{"className":580,"code":4632,"filename":4633,"language":583,"meta":584,"style":584},"\u002F\u002F Boot the SUBSCRIBER first so its consumer's poll loop is already draining when the producer publishes.\nconst billing = await createTestApp({\n  root: billingRoot,\n  plugins: [new IntegrationEventsPlugin(), new HttpPlugin()],\n  eagerInit: true,\n});\n\nconst orders = await createTestApp({\n  root: ordersRoot,\n  plugins: [new IntegrationEventsPlugin(), new HttpPlugin()],\n  eagerInit: true,\n});\n","test\u002Fcross-service.e2e.test.ts",[503,4635,4636,4641,4658,4670,4694,4706,4714,4718,4735,4746,4770,4780],{"__ignoreMap":584},[588,4637,4638],{"class":590,"line":591},[588,4639,4640],{"class":2677},"\u002F\u002F Boot the SUBSCRIBER first so its consumer's poll loop is already draining when the producer publishes.\n",[588,4642,4643,4645,4648,4650,4652,4654,4656],{"class":590,"line":625},[588,4644,2956],{"class":703},[588,4646,4647],{"class":602}," billing ",[588,4649,2962],{"class":598},[588,4651,728],{"class":594},[588,4653,603],{"class":687},[588,4655,691],{"class":602},[588,4657,3358],{"class":598},[588,4659,4660,4663,4665,4668],{"class":590,"line":648},[588,4661,4662],{"class":733},"  root",[588,4664,1755],{"class":598},[588,4666,4667],{"class":602}," billingRoot",[588,4669,1972],{"class":598},[588,4671,4672,4674,4676,4678,4680,4682,4684,4686,4688,4690,4692],{"class":590,"line":677},[588,4673,4537],{"class":733},[588,4675,1755],{"class":598},[588,4677,3368],{"class":602},[588,4679,1287],{"class":598},[588,4681,4546],{"class":687},[588,4683,734],{"class":602},[588,4685,658],{"class":598},[588,4687,3387],{"class":598},[588,4689,4555],{"class":687},[588,4691,4558],{"class":602},[588,4693,1972],{"class":598},[588,4695,4696,4699,4701,4704],{"class":590,"line":684},[588,4697,4698],{"class":733},"  eagerInit",[588,4700,1755],{"class":598},[588,4702,4703],{"class":1403}," true",[588,4705,1972],{"class":598},[588,4707,4708,4710,4712],{"class":590,"line":716},[588,4709,819],{"class":598},[588,4711,770],{"class":602},[588,4713,622],{"class":598},[588,4715,4716],{"class":590,"line":739},[588,4717,681],{"emptyLinePlaceholder":680},[588,4719,4720,4722,4725,4727,4729,4731,4733],{"class":590,"line":744},[588,4721,2956],{"class":703},[588,4723,4724],{"class":602}," orders ",[588,4726,2962],{"class":598},[588,4728,728],{"class":594},[588,4730,603],{"class":687},[588,4732,691],{"class":602},[588,4734,3358],{"class":598},[588,4736,4737,4739,4741,4744],{"class":590,"line":775},[588,4738,4662],{"class":733},[588,4740,1755],{"class":598},[588,4742,4743],{"class":602}," ordersRoot",[588,4745,1972],{"class":598},[588,4747,4748,4750,4752,4754,4756,4758,4760,4762,4764,4766,4768],{"class":590,"line":780},[588,4749,4537],{"class":733},[588,4751,1755],{"class":598},[588,4753,3368],{"class":602},[588,4755,1287],{"class":598},[588,4757,4546],{"class":687},[588,4759,734],{"class":602},[588,4761,658],{"class":598},[588,4763,3387],{"class":598},[588,4765,4555],{"class":687},[588,4767,4558],{"class":602},[588,4769,1972],{"class":598},[588,4771,4772,4774,4776,4778],{"class":590,"line":816},[588,4773,4698],{"class":733},[588,4775,1755],{"class":598},[588,4777,4703],{"class":1403},[588,4779,1972],{"class":598},[588,4781,4782,4784,4786],{"class":590,"line":1190},[588,4783,819],{"class":598},[588,4785,770],{"class":602},[588,4787,622],{"class":598},[499,4789,4790,4791,4793,4794,4797,4798,4800],{},"Placing an order on ",[503,4792,4572],{}," fans one row into ",[503,4795,4796],{},"billing","'s own queue — the exact production distributor\nwiring the workspace scan discovered — and ",[503,4799,4796],{},"'s compiler-emitted consumer drains it into its handler:",[578,4802,4804],{"className":580,"code":4803,"filename":4633,"language":583,"meta":584,"style":584},"const response = await createTestClient(orders).request(\n  new Request(\"http:\u002F\u002Ftest\u002Forders\", { method: \"POST\" }),\n);\nconst placed = (await response.json()) as { orderId: string };\n\n\u002F\u002F billing's compiler-emitted subscriber consumer drains its queue and dispatches to OnOrderPlaced.\nawait expect\n  .poll(() => log.received, { timeout: 5_000 })\n  .toEqual([{ orderId: placed.orderId }]);\n",[503,4805,4806,4828,4866,4872,4907,4911,4916,4923,4962],{"__ignoreMap":584},[588,4807,4808,4810,4812,4814,4816,4818,4821,4823,4825],{"class":590,"line":591},[588,4809,2956],{"class":703},[588,4811,3006],{"class":602},[588,4813,2962],{"class":598},[588,4815,728],{"class":594},[588,4817,1488],{"class":687},[588,4819,4820],{"class":602},"(orders)",[588,4822,759],{"class":598},[588,4824,1629],{"class":687},[588,4826,4827],{"class":602},"(\n",[588,4829,4830,4833,4835,4837,4839,4842,4844,4846,4848,4851,4853,4855,4858,4860,4862,4864],{"class":590,"line":625},[588,4831,4832],{"class":598},"  new",[588,4834,1636],{"class":687},[588,4836,691],{"class":602},[588,4838,619],{"class":598},[588,4840,4841],{"class":615},"http:\u002F\u002Ftest\u002Forders",[588,4843,619],{"class":598},[588,4845,658],{"class":598},[588,4847,599],{"class":598},[588,4849,4850],{"class":733}," method",[588,4852,1755],{"class":598},[588,4854,612],{"class":598},[588,4856,4857],{"class":615},"POST",[588,4859,619],{"class":598},[588,4861,606],{"class":598},[588,4863,770],{"class":602},[588,4865,1972],{"class":598},[588,4867,4868,4870],{"class":590,"line":648},[588,4869,770],{"class":602},[588,4871,622],{"class":598},[588,4873,4874,4876,4879,4881,4883,4885,4887,4889,4891,4893,4895,4897,4900,4902,4904],{"class":590,"line":677},[588,4875,2956],{"class":703},[588,4877,4878],{"class":602}," placed ",[588,4880,2962],{"class":598},[588,4882,2637],{"class":602},[588,4884,788],{"class":594},[588,4886,1618],{"class":602},[588,4888,759],{"class":598},[588,4890,1697],{"class":687},[588,4892,2648],{"class":602},[588,4894,2651],{"class":594},[588,4896,599],{"class":598},[588,4898,4899],{"class":733}," orderId",[588,4901,1755],{"class":598},[588,4903,3252],{"class":1858},[588,4905,4906],{"class":598}," };\n",[588,4908,4909],{"class":590,"line":684},[588,4910,681],{"emptyLinePlaceholder":680},[588,4912,4913],{"class":590,"line":716},[588,4914,4915],{"class":2677},"\u002F\u002F billing's compiler-emitted subscriber consumer drains its queue and dispatches to OnOrderPlaced.\n",[588,4917,4918,4920],{"class":590,"line":739},[588,4919,788],{"class":594},[588,4921,4922],{"class":602}," expect\n",[588,4924,4925,4928,4931,4933,4935,4937,4940,4942,4945,4947,4949,4952,4954,4957,4959],{"class":590,"line":744},[588,4926,4927],{"class":598},"  .",[588,4929,4930],{"class":687},"poll",[588,4932,691],{"class":602},[588,4934,734],{"class":598},[588,4936,710],{"class":703},[588,4938,4939],{"class":602}," log",[588,4941,759],{"class":598},[588,4943,4944],{"class":602},"received",[588,4946,658],{"class":598},[588,4948,599],{"class":598},[588,4950,4951],{"class":733}," timeout",[588,4953,1755],{"class":598},[588,4955,4956],{"class":808}," 5_000",[588,4958,606],{"class":598},[588,4960,4961],{"class":602},")\n",[588,4963,4964,4966,4968,4970,4972,4974,4976,4979,4981,4984,4986,4989],{"class":590,"line":775},[588,4965,4927],{"class":598},[588,4967,2172],{"class":687},[588,4969,3392],{"class":602},[588,4971,2394],{"class":598},[588,4973,4899],{"class":733},[588,4975,1755],{"class":598},[588,4977,4978],{"class":602}," placed",[588,4980,759],{"class":598},[588,4982,4983],{"class":602},"orderId ",[588,4985,819],{"class":598},[588,4987,4988],{"class":602},"])",[588,4990,622],{"class":598},[499,4992,4993,4994,4997,4998,5001,5002,5004,5005,759],{},"Pass ",[503,4995,4996],{},"workspaceSubscribers"," only to ",[519,4999,5000],{},"override"," the disk scan — a unit test that wants a synthetic\ntopology without laying out a real workspace, or a topology you want pinned. Omit it and let each\nservice's own ",[503,5003,4496],{}," declaration drive the discovery, exactly like a real ",[503,5006,4503],{},[555,5008,5010],{"id":5009},"surface-eager-construction-errors","Surface eager construction errors",[499,5012,5013,5014,5016,5017,5020,5021,5023],{},"By default, providers are constructed lazily — the first ",[503,5015,525],{}," call triggers construction.\nSet ",[503,5018,5019],{},"eagerInit: true"," to force upfront construction of every module and provider. Any misconfigured\ndependency or broken ",[503,5022,842],{}," surfaces at setup time rather than buried inside a later assertion:",[578,5025,5028],{"className":580,"code":5026,"filename":5027,"language":583,"meta":584,"style":584},"test(\"app boots with no construction errors\", async () => {\n  await using app = await createTestApp({ eagerInit: true });\n  expect(app).toBeDefined();\n});\n","test\u002Fsanity.test.ts",[503,5029,5030,5053,5082,5101],{"__ignoreMap":584},[588,5031,5032,5034,5036,5038,5041,5043,5045,5047,5049,5051],{"class":590,"line":591},[588,5033,688],{"class":687},[588,5035,691],{"class":602},[588,5037,619],{"class":598},[588,5039,5040],{"class":615},"app boots with no construction errors",[588,5042,619],{"class":598},[588,5044,658],{"class":598},[588,5046,704],{"class":703},[588,5048,707],{"class":598},[588,5050,710],{"class":703},[588,5052,713],{"class":598},[588,5054,5055,5057,5059,5061,5063,5065,5067,5069,5072,5074,5076,5078,5080],{"class":590,"line":625},[588,5056,719],{"class":703},[588,5058,722],{"class":602},[588,5060,725],{"class":598},[588,5062,728],{"class":594},[588,5064,603],{"class":687},[588,5066,691],{"class":733},[588,5068,2394],{"class":598},[588,5070,5071],{"class":733}," eagerInit",[588,5073,1755],{"class":598},[588,5075,4703],{"class":1403},[588,5077,606],{"class":598},[588,5079,770],{"class":733},[588,5081,622],{"class":598},[588,5083,5084,5086,5088,5090,5092,5094,5097,5099],{"class":590,"line":648},[588,5085,783],{"class":687},[588,5087,691],{"class":733},[588,5089,1603],{"class":602},[588,5091,770],{"class":733},[588,5093,759],{"class":598},[588,5095,5096],{"class":687},"toBeDefined",[588,5098,734],{"class":733},[588,5100,622],{"class":598},[588,5102,5103,5105,5107],{"class":590,"line":677},[588,5104,819],{"class":598},[588,5106,770],{"class":602},[588,5108,622],{"class":598},[499,5110,5111,5114,5115,5117],{},[503,5112,5113],{},"eagerInit()"," is also exposed as a method on the ",[503,5116,960],{}," if you need to call it manually after boot.",[555,5119,5121,5122],{"id":5120},"share-the-plugin-list-with-heximonconfigts","Share the plugin list with ",[503,5123,902],{},[499,5125,5126,5128,5129,5132,5133,5136,5137,5139,5140,5143,5144,5146,5147,5150,5151,892,5153,5156],{},[503,5127,505],{},"'s ",[503,5130,5131],{},"plugins"," option accepts the same ",[503,5134,5135],{},"CompilerPlugin[]"," you pass to the ",[503,5138,568],{},"\nVite plugin. To declare the list ",[519,5141,5142],{},"once",", put it in a ",[503,5145,902],{}," file at your project\nroot. All three hosts — the Vite plugin, the Nitro module, and the Nuxt module — ",[519,5148,5149],{},"auto-load it",", and\n",[503,5152,505],{},[519,5154,5155],{},"auto-loads it"," too. No explicit import or reference is needed in the host config.",[578,5158,5160],{"className":580,"code":5159,"filename":902,"language":583,"meta":584,"style":584},"import { defineHeximonConfig } from \"@heximon\u002Fbuild\";\nimport { CqrsPlugin } from \"@heximon\u002Fcqrs\u002Fcompiler\";\nimport { HttpPlugin } from \"@heximon\u002Fhttp\u002Fcompiler\";\n\nexport default defineHeximonConfig({ plugins: [new HttpPlugin(), new CqrsPlugin()] });\n",[503,5161,5162,5183,5205,5226,5230],{"__ignoreMap":584},[588,5163,5164,5166,5168,5170,5172,5174,5176,5179,5181],{"class":590,"line":591},[588,5165,595],{"class":594},[588,5167,599],{"class":598},[588,5169,4528],{"class":602},[588,5171,606],{"class":598},[588,5173,609],{"class":594},[588,5175,612],{"class":598},[588,5177,5178],{"class":615},"@heximon\u002Fbuild",[588,5180,619],{"class":598},[588,5182,622],{"class":598},[588,5184,5185,5187,5189,5192,5194,5196,5198,5201,5203],{"class":590,"line":625},[588,5186,595],{"class":594},[588,5188,599],{"class":598},[588,5190,5191],{"class":602}," CqrsPlugin",[588,5193,606],{"class":598},[588,5195,609],{"class":594},[588,5197,612],{"class":598},[588,5199,5200],{"class":615},"@heximon\u002Fcqrs\u002Fcompiler",[588,5202,619],{"class":598},[588,5204,622],{"class":598},[588,5206,5207,5209,5211,5213,5215,5217,5219,5222,5224],{"class":590,"line":648},[588,5208,595],{"class":594},[588,5210,599],{"class":598},[588,5212,4555],{"class":602},[588,5214,606],{"class":598},[588,5216,609],{"class":594},[588,5218,612],{"class":598},[588,5220,5221],{"class":615},"@heximon\u002Fhttp\u002Fcompiler",[588,5223,619],{"class":598},[588,5225,622],{"class":598},[588,5227,5228],{"class":590,"line":677},[588,5229,681],{"emptyLinePlaceholder":680},[588,5231,5232,5234,5236,5238,5240,5242,5245,5247,5249,5251,5253,5255,5257,5259,5261,5264,5266,5268],{"class":590,"line":684},[588,5233,4522],{"class":594},[588,5235,4525],{"class":594},[588,5237,4528],{"class":687},[588,5239,691],{"class":602},[588,5241,2394],{"class":598},[588,5243,5244],{"class":733}," plugins",[588,5246,1755],{"class":598},[588,5248,3368],{"class":602},[588,5250,1287],{"class":598},[588,5252,4555],{"class":687},[588,5254,734],{"class":602},[588,5256,658],{"class":598},[588,5258,3387],{"class":598},[588,5260,5191],{"class":687},[588,5262,5263],{"class":602},"()] ",[588,5265,819],{"class":598},[588,5267,770],{"class":602},[588,5269,622],{"class":598},[499,5271,5272,5273,5275,5276,5279,5280,5282,5283,5285],{},"The ",[503,5274,885],{}," from ",[905,5277,558],{"href":5278},"#boot-the-app"," above needs no change — ",[503,5281,568],{}," auto-loads this\nfile from the project root, and ",[503,5284,572],{}," reads the same file, so neither the host config nor\nthe test repeats the plugin list.",[499,5287,5272,5288,5290,5291,5294,5295,5297],{},[503,5289,902],{}," file is the ",[519,5292,5293],{},"single source of truth"," for the plugin set — the Vite plugin,\nthe Nitro module, the Nuxt module, and ",[503,5296,505],{}," all read it identically, so there's nothing to\nreconcile between layers.",[499,5299,5300,5301,5304,5305,5307,5308,5310,5311,5313,5314,5316,5317,5320,5321,5324],{},"Host-intrinsic plugins (like ",[503,5302,5303],{},"NitroPlugin",", which requires HTTP) are added on\ntop and deduped by class identity. An explicit ",[503,5306,5131],{}," option passed to ",[503,5309,505],{}," always wins\nover the config file; with neither present, the plugin set is ",[503,5312,3266],{}," — transport-neutral core, HTTP never\nassumed. So list the plugins your app needs once, in ",[503,5315,902],{}," (a CQRS app → ",[503,5318,5319],{},"new CqrsPlugin()",",\nan HTTP app → ",[503,5322,5323],{},"new HttpPlugin()","), rather than repeating them in every test.",[499,5326,5327,5328,5331,5332,5335,5336,5339,5340,5343,5344,5347,5348,5351],{},"The shared loader is ",[503,5329,5330],{},"ConfigLoader.load(rootDir)",", exported from ",[503,5333,5334],{},"@heximon\u002Fcompiler\u002Fproject",". It is backed\nby ",[519,5337,5338],{},"c12"," (which uses jiti), so it loads the TypeScript config file at build time and under test runners\nalike. It recognises ",[503,5341,5342],{},"heximon.config.{ts,mjs,js,json,...}"," (plus c12's ",[503,5345,5346],{},".local","\u002Fenv layers) and\nreturns ",[503,5349,5350],{},"undefined"," when no config file is present.",[555,5353,5355],{"id":5354},"api-reference","API reference",[1956,5357,5359],{"id":5358},"createtestappoptions",[503,5360,5361],{},"createTestApp(options?)",[5363,5364,5365,5385],"table",{},[5366,5367,5368],"thead",{},[5369,5370,5371,5376,5379,5382],"tr",{},[5372,5373,5375],"th",{"align":5374},"left","Option",[5372,5377,5378],{"align":5374},"Type",[5372,5380,5381],{"align":5374},"Default",[5372,5383,5384],{"align":5374},"Description",[5386,5387,5388,5409,5427,5457,5484,5504,5532],"tbody",{},[5369,5389,5390,5395,5399,5403],{},[5391,5392,5393],"td",{"align":5374},[503,5394,866],{},[5391,5396,5397],{"align":5374},[503,5398,2660],{},[5391,5400,5401],{"align":5374},[503,5402,942],{},[5391,5404,5405,5406,759],{"align":5374},"Project root containing ",[503,5407,5408],{},"src\u002F",[5369,5410,5411,5415,5419,5422],{},[5391,5412,5413],{"align":5374},[503,5414,5131],{},[5391,5416,5417],{"align":5374},[503,5418,5135],{},[5391,5420,5421],{"align":5374},"from config file",[5391,5423,5424,5425,759],{"align":5374},"Compiler plugins for the standalone compile. Passing this forces the standalone compile; omit it to use the fast path + ",[503,5426,902],{},[5369,5428,5429,5434,5439,5443],{},[5391,5430,5431],{"align":5374},[503,5432,5433],{},"overrides",[5391,5435,5436],{"align":5374},[503,5437,5438],{},"ProviderOverride[]",[5391,5440,5441],{"align":5374},[503,5442,3266],{},[5391,5444,5445,5446,5449,5450,5453,5454,759],{"align":5374},"Provider fakes (replace a DI token at every injection site) for the lifetime of this app. Each is ",[503,5447,5448],{},"{ provide, useValue }",", ",[503,5451,5452],{},"{ provide, useClass }",", or ",[503,5455,5456],{},"{ provide, useFactory }",[5369,5458,5459,5464,5469,5474],{},[5391,5460,5461],{"align":5374},[503,5462,5463],{},"bindings",[5391,5465,5466],{"align":5374},[503,5467,5468],{},"Record\u003Cstring, unknown>",[5391,5470,5471],{"align":5374},[503,5472,5473],{},"{}",[5391,5475,5476,5477,5480,5481,5483],{"align":5374},"Runtime bindings seeded into the app — the host seam (e.g. ",[503,5478,5479],{},"{ InternalClient: new H3FetchClient(...) }"," for an app whose controllers call their own contract routes; see example gap\u002Fopenapi-mcp). Distinct from ",[503,5482,5433],{},": bindings are ambient values keyed by name, not DI token replacements.",[5369,5485,5486,5491,5496,5501],{},[5391,5487,5488],{"align":5374},[503,5489,5490],{},"eagerInit",[5391,5492,5493],{"align":5374},[503,5494,5495],{},"boolean",[5391,5497,5498],{"align":5374},[503,5499,5500],{},"false",[5391,5502,5503],{"align":5374},"Construct every provider at setup time.",[5369,5505,5506,5510,5515,5518],{},[5391,5507,5508],{"align":5374},[503,5509,4996],{},[5391,5511,5512],{"align":5374},[503,5513,5514],{},"WorkspaceSubscriptionTopology",[5391,5516,5517],{"align":5374},"auto-discovered",[5391,5519,5520,5521,5523,5524,5449,5526,5528,5529,5531],{"align":5374},"The cross-service integration-event topology. When the app declares ",[503,5522,4496],{}," in ",[503,5525,902],{},[503,5527,505],{}," auto-discovers sibling services + subscriptions from disk — the same scan ",[503,5530,4503],{}," runs. Supply this only to override that scan with a synthetic topology.",[5369,5533,5534,5539,5544,5546],{},[5391,5535,5536],{"align":5374},[503,5537,5538],{},"platform",[5391,5540,5541],{"align":5374},[503,5542,5543],{},"PlatformStrategy",[5391,5545,5421],{"align":5374},[5391,5547,5548,5549,5128,5551,5553],{"align":5374},"The deploy strategy to compile with (the in-process equivalent of ",[503,5550,902],{},[503,5552,5538],{}," line), so a test exercises the same capability legs (OTel, durable timers, workflow engine) the app deploys with.",[499,5555,5556,5557,759],{},"Returns ",[503,5558,5559],{},"TestApp = AppHandle & AsyncDisposable & { context, eagerInit(), routes?, contractRegistrations? }",[1956,5561,5563,5565],{"id":5562},"testapp-members",[503,5564,960],{}," members",[5363,5567,5568,5577],{},[5366,5569,5570],{},[5369,5571,5572,5575],{},[5372,5573,5574],{"align":5374},"Member",[5372,5576,5384],{"align":5374},[5386,5578,5579,5589,5602,5626,5635,5650,5663,5675],{},[5369,5580,5581,5586],{},[5391,5582,5583],{"align":5374},[503,5584,5585],{},"get(Token)",[5391,5587,5588],{"align":5374},"Resolve a DI token. Returns the same instance the generated wiring constructed.",[5369,5590,5591,5596],{},[5391,5592,5593],{"align":5374},[503,5594,5595],{},"context.run(fn)",[5391,5597,5598,5599,5601],{"align":5374},"Open the ambient ",[503,5600,552],{}," frame for code that needs it (repositories, buses, tasks).",[5369,5603,5604,5609],{},[5391,5605,5606],{"align":5374},[503,5607,5608],{},"context.drain(options?)",[5391,5610,5611,5612,5615,5616,5618,5619,5622,5623,5625],{"align":5374},"Wait until every in-flight ",[503,5613,5614],{},"Context.run"," frame — and any ",[503,5617,1439],{}," work it deferred — has settled. Resolves immediately when nothing is in flight; an optional ",[503,5620,5621],{},"{ timeoutMs }"," caps the wait. Useful in a test that fires a request and needs its background ",[503,5624,1439],{}," work done before asserting, without wiring the generated graceful-shutdown sequence yourself.",[5369,5627,5628,5632],{},[5391,5629,5630],{"align":5374},[503,5631,5113],{},[5391,5633,5634],{"align":5374},"Force upfront construction of every module and provider.",[5369,5636,5637,5641],{},[5391,5638,5639],{"align":5374},[503,5640,2843],{},[5391,5642,5643,5644,5647,5648,759],{"align":5374},"Opaque HTTP route definitions (present only when ",[503,5645,5646],{},"HttpPlugin"," was active). Consumed by ",[503,5649,533],{},[5369,5651,5652,5656],{},[5391,5653,5654],{"align":5374},[503,5655,2854],{},[5391,5657,5658,5659,5647,5661,759],{"align":5374},"Opaque HTTP contract registrations (present only when ",[503,5660,5646],{},[503,5662,533],{},[5369,5664,5665,5670],{},[5391,5666,5667],{"align":5374},[503,5668,5669],{},"[Symbol.asyncDispose]()",[5391,5671,5672,5673,759],{"align":5374},"Shut down the app and remove the temp wiring directory. Called automatically by ",[503,5674,513],{},[5369,5676,5677,5682],{},[5391,5678,5679],{"align":5374},[503,5680,5681],{},"shutdown()",[5391,5683,5684,5685,5687],{"align":5374},"Shut down the app explicitly (same as the ",[503,5686,509],{}," method).",[1956,5689,5691,2452,5693],{"id":5690},"createtestclientapp-createtestclientroutes-app-contractregistrations",[503,5692,3065],{},[503,5694,5695],{},"createTestClient(routes, app, contractRegistrations?)",[5363,5697,5698,5708],{},[5366,5699,5700],{},[5369,5701,5702,5705],{},[5372,5703,5704],{"align":5374},"Form",[5372,5706,5707],{"align":5374},"When to use",[5386,5709,5710,5727],{},[5369,5711,5712,5716],{},[5391,5713,5714],{"align":5374},[503,5715,3065],{},[5391,5717,5718,5719,5721,5722,2844,5724,5726],{"align":5374},"The default — pass a ",[503,5720,960],{}," and it reads ",[503,5723,2843],{},[503,5725,2854],{}," off it automatically.",[5369,5728,5729,5733],{},[5391,5730,5731],{"align":5374},[503,5732,5695],{},[5391,5734,5735,5736,5275,5738,5449,5741,5743,5744,5746,5747,5275,5749,5752],{"align":5374},"Driving the generated wiring directly (",[503,5737,2843],{},[503,5739,5740],{},"router.js",[503,5742,2847],{}," from the app's wiring file) without ",[503,5745,505],{}," — pass ",[503,5748,2854],{},[503,5750,5751],{},"contracts.js"," only when the app serves contract-mode controllers.",[499,5754,5755,5757,5758,5760,5761,5764],{},[503,5756,533],{}," assembles the server ",[519,5759,5142],{}," per client, then hands you ",[503,5762,5763],{},"request(req)",". Reuse the one\nclient across every request in a test — building a client per request rebuilds the route table for no\nreason.",[555,5766,5768],{"id":5767},"see-also","See also",[4452,5770,5771,5777,5793,5802,5815,5825,5833,5847,5869],{},[4455,5772,5773,5776],{},[905,5774,5775],{"href":112},"Testing"," — the decision ladder: unit-test a provider with fakes, dispatch over\nthe real bus, or boot the full app — start there when you're deciding which shape a new test needs.",[4455,5778,5779,5781,5782,5449,5785,5788,5789,5792],{},[905,5780,57],{"href":58}," — the ",[503,5783,5784],{},"Controller",[503,5786,5787],{},"Middleware",", and ",[503,5790,5791],{},"HttpAction"," surface the transport exercises.",[4455,5794,5795,5781,5797,2452,5799,5801],{},[905,5796,233],{"href":234},[503,5798,529],{},[503,5800,1210],{}," you dispatch through in transport-neutral tests.",[4455,5803,5804,5806,5807,3781,5809,5811,5812,5814],{},[905,5805,53],{"href":54}," — how ",[503,5808,1458],{},[503,5810,3992],{}," define what ",[503,5813,525],{}," can resolve.",[4455,5816,5817,5820,5821,5824],{},[905,5818,5819],{"href":127},"Lifecycle"," — ",[503,5822,5823],{},"Context.drain()"," in full, and the generated graceful-shutdown sequence it backs in production.",[4455,5826,5827,5781,5830,5832],{},[905,5828,5829],{"href":244},"Integration events",[503,5831,4496],{}," config block, the outbox, and the four cross-service fan-out legs a workspace-topology test exercises.",[4455,5834,5835,5841,5842,1743,5844,5846],{},[905,5836,5838],{"href":1965,"rel":5837},[1967],[519,5839,5840],{},"HTTP validation"," — two feature modules, middleware, validation, and the built-in error formatter, with a test that drives every route in-process and proves the ",[503,5843,2493],{},[503,5845,2828],{}," problem+json mapping.",[4455,5848,5849,5856,5857,3781,5859,5861,5862,5865,5866,759],{},[905,5850,5853],{"href":5851,"rel":5852},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fladder\u002FL06-ddd",[1967],[519,5854,5855],{},"DDD with Drizzle"," — a full compile → DI → Drizzle\u002Flibsql → HTTP test using ",[503,5858,505],{},[503,5860,3065],{},", including an ",[503,5863,5864],{},"app.context.run(...)"," block that proves optimistic concurrency raises ",[503,5867,5868],{},"ConcurrencyError",[4455,5870,5871,5878,5879,2844,5881,5883,5884,5886,5887,5889],{},[905,5872,5875],{"href":5873,"rel":5874},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fgap\u002Fcross-service-transports\u002Ffanout",[1967],[519,5876,5877],{},"Cross-service fan-out"," — two independently-rooted services (",[503,5880,4572],{},[503,5882,4796],{},") whose ",[503,5885,505],{}," calls auto-discover the workspace topology from each service's own ",[503,5888,4496],{}," declaration.",[5891,5892,5893],"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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":584,"searchDepth":625,"depth":625,"links":5895},[5896,5897,5898,5903,5904,5905,5906,5907,5909,5916],{"id":557,"depth":625,"text":558},{"id":967,"depth":625,"text":968},{"id":1461,"depth":625,"text":1462,"children":5899},[5900,5901,5902],{"id":1958,"depth":648,"text":1959},{"id":2463,"depth":648,"text":2464},{"id":2832,"depth":648,"text":2833},{"id":3077,"depth":625,"text":3078},{"id":4188,"depth":625,"text":4189},{"id":4489,"depth":625,"text":4490},{"id":5009,"depth":625,"text":5010},{"id":5120,"depth":625,"text":5908},"Share the plugin list with heximon.config.ts",{"id":5354,"depth":625,"text":5355,"children":5910},[5911,5912,5914],{"id":5358,"depth":648,"text":5361},{"id":5562,"depth":648,"text":5913},"TestApp members",{"id":5690,"depth":648,"text":5915},"createTestClient(app) \u002F createTestClient(routes, app, contractRegistrations?)",{"id":5767,"depth":625,"text":5768},"createTestApp, TestApp, TestAppOptions, createTestClient, eagerInit, context.run, provider overrides, database isolation, contract-mode registration, multi-app isolation, heximon.config.ts plugin precedence","md",null,{},{"icon":119},{"title":116,"description":5917},"YJrhddXDZA9H3pKs3sAyuvIKRwCxUWF95RbYbAiV3FM",[5925,5927],{"title":111,"path":112,"stem":113,"description":5926,"icon":114,"children":-1},"Unit-test providers and handlers as plain classes with constructor-injected fakes, then reach for createTestApp and createTestClient when you need the real compiled wiring — routes, middleware, validation, error filters, and bus dispatch.",{"title":121,"path":122,"stem":123,"description":5928,"icon":124,"children":-1},"Logger, child fields, Logger.configure, LoggerReporter pretty and json, log levels, HEXIMON_DEBUG, shipping logs to drains, opt-in wide events, and the startup summary lines.",1783300761903]