[{"data":1,"prerenderedAt":3228},["ShallowReactive",2],{"navigation_docs":3,"-docs-architecture-integration-events":493,"-docs-architecture-integration-events-surround":3223},[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":243,"body":495,"description":3216,"extension":3217,"links":3218,"meta":3219,"navigation":3220,"path":244,"seo":3221,"stem":245,"__hash__":3222},"docs\u002Fdocs\u002F04.architecture\u002F05.integration-events.md",{"type":496,"value":497,"toc":3205},"minimark",[498,520,525,532,696,700,715,1166,1177,1317,1321,1344,1554,1562,1700,1733,1737,1862,1866,1877,1930,1962,1972,2161,2189,2628,2641,2707,2735,2740,2767,3074,3092,3096,3138,3148,3152,3201],[499,500,501,502,506,507,510,511,514,515,519],"p",{},"When an event has to reach ",[503,504,505],"strong",{},"another bounded context or another deployed service"," — without blocking the\nrequest that produced it — reach for an integration event. The producer publishes and returns immediately; a\nconsumer runs later, off the request path, wherever the ",[508,509,151],"a",{"href":152}," transport delivers it. The\nmodel is ",[503,512,513],{},"one class, one event",": declare a typed producer for each cross-context fact, inject it by class\nidentity, and call ",[516,517,518],"code",{},"publish(data)",". A shared payload type keeps producer and consumer in lockstep — drift\nbetween them is a compile error, not a runtime surprise.",[521,522,524],"h2",{"id":523},"declare-the-producer","Declare the producer",[499,526,527,528,531],{},"A typed integration event is a plain class that extends ",[516,529,530],{},"IntegrationEvent\u003C\"name\", Payload>",". The string-literal\nfirst type argument is both the event name and the dispatch key; the second argument is the payload the producer\nand consumer share.",[533,534,540],"pre",{"className":535,"code":536,"filename":537,"language":538,"meta":539,"style":539},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { IntegrationEvent } from \"@heximon\u002Fintegration\";\n\nexport interface UserSignedUpPayload {\n  readonly userId: string;\n  readonly name: string;\n  readonly email: string;\n}\n\nexport class UserSignedUp extends IntegrationEvent\u003C\"user.signed-up\", UserSignedUpPayload> {}\n","users\u002Fevents.ts","ts","",[516,541,542,578,585,602,620,634,648,654,659],{"__ignoreMap":539},[543,544,547,551,555,559,562,565,568,572,575],"span",{"class":545,"line":546},"line",1,[543,548,550],{"class":549},"s7zQu","import",[543,552,554],{"class":553},"sMK4o"," {",[543,556,558],{"class":557},"sTEyZ"," IntegrationEvent",[543,560,561],{"class":553}," }",[543,563,564],{"class":549}," from",[543,566,567],{"class":553}," \"",[543,569,571],{"class":570},"sfazB","@heximon\u002Fintegration",[543,573,574],{"class":553},"\"",[543,576,577],{"class":553},";\n",[543,579,581],{"class":545,"line":580},2,[543,582,584],{"emptyLinePlaceholder":583},true,"\n",[543,586,588,591,595,599],{"class":545,"line":587},3,[543,589,590],{"class":549},"export",[543,592,594],{"class":593},"spNyl"," interface",[543,596,598],{"class":597},"sBMFI"," UserSignedUpPayload",[543,600,601],{"class":553}," {\n",[543,603,605,608,612,615,618],{"class":545,"line":604},4,[543,606,607],{"class":593},"  readonly",[543,609,611],{"class":610},"swJcz"," userId",[543,613,614],{"class":553},":",[543,616,617],{"class":597}," string",[543,619,577],{"class":553},[543,621,623,625,628,630,632],{"class":545,"line":622},5,[543,624,607],{"class":593},[543,626,627],{"class":610}," name",[543,629,614],{"class":553},[543,631,617],{"class":597},[543,633,577],{"class":553},[543,635,637,639,642,644,646],{"class":545,"line":636},6,[543,638,607],{"class":593},[543,640,641],{"class":610}," email",[543,643,614],{"class":553},[543,645,617],{"class":597},[543,647,577],{"class":553},[543,649,651],{"class":545,"line":650},7,[543,652,653],{"class":553},"}\n",[543,655,657],{"class":545,"line":656},8,[543,658,584],{"emptyLinePlaceholder":583},[543,660,662,664,667,670,673,675,678,680,683,685,688,690,693],{"class":545,"line":661},9,[543,663,590],{"class":549},[543,665,666],{"class":593}," class",[543,668,669],{"class":597}," UserSignedUp",[543,671,672],{"class":593}," extends",[543,674,558],{"class":597},[543,676,677],{"class":553},"\u003C",[543,679,574],{"class":553},[543,681,682],{"class":570},"user.signed-up",[543,684,574],{"class":553},[543,686,687],{"class":553},",",[543,689,598],{"class":597},[543,691,692],{"class":553},">",[543,694,695],{"class":553}," {}\n",[521,697,699],{"id":698},"publish-the-event","Publish the event",[499,701,702,703,706,707,710,711,714],{},"The controller injects the typed event class by class identity — no facade, no string token, no boot seam. The\ncompiler reads the class from the constructor signature and wires its publisher over the bound\n",[516,704,705],{},"IntegrationEventTransport"," (the in-process ",[516,708,709],{},"MemoryIntegrationEventTransport"," by default, assembled at boot with\nno app boilerplate). ",[516,712,713],{},"await publish(data)"," hands the payload off; the request returns right away.",[533,716,719],{"className":535,"code":717,"filename":718,"language":538,"meta":539,"style":539},"import { uuid } from \"@heximon\u002Fruntime\";\nimport type { Controller, Post } from \"@heximon\u002Fhttp\";\nimport { UserSignedUp } from \".\u002Fevents\";\n\nexport class SignupController implements Controller\u003C\"\u002Fusers\"> {\n  private readonly userSignedUp: UserSignedUp;\n\n  public constructor(userSignedUp: UserSignedUp) {\n    this.userSignedUp = userSignedUp;\n  }\n\n  public async signUp(action: Post\u003C\"\u002F\">): Promise\u003C{ id: string; email: string }> {\n    const body = (await action.request.json()) as { name: string; email: string };\n    const userId = uuid.v7();\n\n    \u002F\u002F Publish the integration event; the welcome email is sent when the transport delivers it.\n    await this.userSignedUp.publish({ userId, name: body.name, email: body.email });\n\n    action.response.status = 201;\n    return { id: userId, email: body.email };\n  }\n}\n","users\u002Fsignup.controller.ts",[516,720,721,743,773,794,798,825,842,846,870,884,890,895,954,1011,1032,1037,1044,1099,1104,1128,1156,1161],{"__ignoreMap":539},[543,722,723,725,727,730,732,734,736,739,741],{"class":545,"line":546},[543,724,550],{"class":549},[543,726,554],{"class":553},[543,728,729],{"class":557}," uuid",[543,731,561],{"class":553},[543,733,564],{"class":549},[543,735,567],{"class":553},[543,737,738],{"class":570},"@heximon\u002Fruntime",[543,740,574],{"class":553},[543,742,577],{"class":553},[543,744,745,747,750,752,755,757,760,762,764,766,769,771],{"class":545,"line":580},[543,746,550],{"class":549},[543,748,749],{"class":549}," type",[543,751,554],{"class":553},[543,753,754],{"class":557}," Controller",[543,756,687],{"class":553},[543,758,759],{"class":557}," Post",[543,761,561],{"class":553},[543,763,564],{"class":549},[543,765,567],{"class":553},[543,767,768],{"class":570},"@heximon\u002Fhttp",[543,770,574],{"class":553},[543,772,577],{"class":553},[543,774,775,777,779,781,783,785,787,790,792],{"class":545,"line":587},[543,776,550],{"class":549},[543,778,554],{"class":553},[543,780,669],{"class":557},[543,782,561],{"class":553},[543,784,564],{"class":549},[543,786,567],{"class":553},[543,788,789],{"class":570},".\u002Fevents",[543,791,574],{"class":553},[543,793,577],{"class":553},[543,795,796],{"class":545,"line":604},[543,797,584],{"emptyLinePlaceholder":583},[543,799,800,802,804,807,810,812,814,816,819,821,823],{"class":545,"line":622},[543,801,590],{"class":549},[543,803,666],{"class":593},[543,805,806],{"class":597}," SignupController",[543,808,809],{"class":593}," implements",[543,811,754],{"class":597},[543,813,677],{"class":553},[543,815,574],{"class":553},[543,817,818],{"class":570},"\u002Fusers",[543,820,574],{"class":553},[543,822,692],{"class":553},[543,824,601],{"class":553},[543,826,827,830,833,836,838,840],{"class":545,"line":636},[543,828,829],{"class":593},"  private",[543,831,832],{"class":593}," readonly",[543,834,835],{"class":610}," userSignedUp",[543,837,614],{"class":553},[543,839,669],{"class":597},[543,841,577],{"class":553},[543,843,844],{"class":545,"line":650},[543,845,584],{"emptyLinePlaceholder":583},[543,847,848,851,854,857,861,863,865,868],{"class":545,"line":656},[543,849,850],{"class":593},"  public",[543,852,853],{"class":593}," constructor",[543,855,856],{"class":553},"(",[543,858,860],{"class":859},"sHdIc","userSignedUp",[543,862,614],{"class":553},[543,864,669],{"class":597},[543,866,867],{"class":553},")",[543,869,601],{"class":553},[543,871,872,875,877,880,882],{"class":545,"line":661},[543,873,874],{"class":553},"    this.",[543,876,860],{"class":557},[543,878,879],{"class":553}," =",[543,881,835],{"class":557},[543,883,577],{"class":553},[543,885,887],{"class":545,"line":886},10,[543,888,889],{"class":553},"  }\n",[543,891,893],{"class":545,"line":892},11,[543,894,584],{"emptyLinePlaceholder":583},[543,896,898,900,903,906,908,911,913,915,917,919,922,924,927,930,933,936,938,940,943,945,947,949,952],{"class":545,"line":897},12,[543,899,850],{"class":593},[543,901,902],{"class":593}," async",[543,904,905],{"class":610}," signUp",[543,907,856],{"class":553},[543,909,910],{"class":859},"action",[543,912,614],{"class":553},[543,914,759],{"class":597},[543,916,677],{"class":553},[543,918,574],{"class":553},[543,920,921],{"class":570},"\u002F",[543,923,574],{"class":553},[543,925,926],{"class":553},">):",[543,928,929],{"class":597}," Promise",[543,931,932],{"class":553},"\u003C{",[543,934,935],{"class":610}," id",[543,937,614],{"class":553},[543,939,617],{"class":597},[543,941,942],{"class":553},";",[543,944,641],{"class":610},[543,946,614],{"class":553},[543,948,617],{"class":597},[543,950,951],{"class":553}," }>",[543,953,601],{"class":553},[543,955,957,960,963,965,968,971,974,977,980,982,986,989,992,994,996,998,1000,1002,1004,1006,1008],{"class":545,"line":956},13,[543,958,959],{"class":593},"    const",[543,961,962],{"class":557}," body",[543,964,879],{"class":553},[543,966,967],{"class":610}," (",[543,969,970],{"class":549},"await",[543,972,973],{"class":557}," action",[543,975,976],{"class":553},".",[543,978,979],{"class":557},"request",[543,981,976],{"class":553},[543,983,985],{"class":984},"s2Zo4","json",[543,987,988],{"class":610},"()) ",[543,990,991],{"class":549},"as",[543,993,554],{"class":553},[543,995,627],{"class":610},[543,997,614],{"class":553},[543,999,617],{"class":597},[543,1001,942],{"class":553},[543,1003,641],{"class":610},[543,1005,614],{"class":553},[543,1007,617],{"class":597},[543,1009,1010],{"class":553}," };\n",[543,1012,1014,1016,1018,1020,1022,1024,1027,1030],{"class":545,"line":1013},14,[543,1015,959],{"class":593},[543,1017,611],{"class":557},[543,1019,879],{"class":553},[543,1021,729],{"class":557},[543,1023,976],{"class":553},[543,1025,1026],{"class":984},"v7",[543,1028,1029],{"class":610},"()",[543,1031,577],{"class":553},[543,1033,1035],{"class":545,"line":1034},15,[543,1036,584],{"emptyLinePlaceholder":583},[543,1038,1040],{"class":545,"line":1039},16,[543,1041,1043],{"class":1042},"sHwdD","    \u002F\u002F Publish the integration event; the welcome email is sent when the transport delivers it.\n",[543,1045,1047,1050,1053,1055,1057,1060,1062,1065,1067,1069,1071,1073,1075,1077,1080,1082,1084,1086,1088,1090,1093,1095,1097],{"class":545,"line":1046},17,[543,1048,1049],{"class":549},"    await",[543,1051,1052],{"class":553}," this.",[543,1054,860],{"class":557},[543,1056,976],{"class":553},[543,1058,1059],{"class":984},"publish",[543,1061,856],{"class":610},[543,1063,1064],{"class":553},"{",[543,1066,611],{"class":557},[543,1068,687],{"class":553},[543,1070,627],{"class":610},[543,1072,614],{"class":553},[543,1074,962],{"class":557},[543,1076,976],{"class":553},[543,1078,1079],{"class":557},"name",[543,1081,687],{"class":553},[543,1083,641],{"class":610},[543,1085,614],{"class":553},[543,1087,962],{"class":557},[543,1089,976],{"class":553},[543,1091,1092],{"class":557},"email",[543,1094,561],{"class":553},[543,1096,867],{"class":610},[543,1098,577],{"class":553},[543,1100,1102],{"class":545,"line":1101},18,[543,1103,584],{"emptyLinePlaceholder":583},[543,1105,1107,1110,1112,1115,1117,1120,1122,1126],{"class":545,"line":1106},19,[543,1108,1109],{"class":557},"    action",[543,1111,976],{"class":553},[543,1113,1114],{"class":557},"response",[543,1116,976],{"class":553},[543,1118,1119],{"class":557},"status",[543,1121,879],{"class":553},[543,1123,1125],{"class":1124},"sbssI"," 201",[543,1127,577],{"class":553},[543,1129,1131,1134,1136,1138,1140,1142,1144,1146,1148,1150,1152,1154],{"class":545,"line":1130},20,[543,1132,1133],{"class":549},"    return",[543,1135,554],{"class":553},[543,1137,935],{"class":610},[543,1139,614],{"class":553},[543,1141,611],{"class":557},[543,1143,687],{"class":553},[543,1145,641],{"class":610},[543,1147,614],{"class":553},[543,1149,962],{"class":557},[543,1151,976],{"class":553},[543,1153,1092],{"class":557},[543,1155,1010],{"class":553},[543,1157,1159],{"class":545,"line":1158},21,[543,1160,889],{"class":553},[543,1162,1164],{"class":545,"line":1163},22,[543,1165,653],{"class":553},[499,1167,1168,1169,1172,1173,1176],{},"List the typed event class under the module's ",[516,1170,1171],{},"integration"," namespace, in the ",[516,1174,1175],{},"events"," sub-key:",[533,1178,1181],{"className":535,"code":1179,"filename":1180,"language":538,"meta":539,"style":539},"import { Module } from \"@heximon\u002Fruntime\";\nimport { UserSignedUp } from \".\u002Fevents\";\nimport { SignupController } from \".\u002Fsignup.controller\";\n\nexport class UsersModule extends Module({\n  http: { controllers: [SignupController] },\n  integration: { events: [UserSignedUp] },\n}) {}\n","users\u002Fusers.module.ts",[516,1182,1183,1204,1224,1245,1249,1267,1287,1306],{"__ignoreMap":539},[543,1184,1185,1187,1189,1192,1194,1196,1198,1200,1202],{"class":545,"line":546},[543,1186,550],{"class":549},[543,1188,554],{"class":553},[543,1190,1191],{"class":557}," Module",[543,1193,561],{"class":553},[543,1195,564],{"class":549},[543,1197,567],{"class":553},[543,1199,738],{"class":570},[543,1201,574],{"class":553},[543,1203,577],{"class":553},[543,1205,1206,1208,1210,1212,1214,1216,1218,1220,1222],{"class":545,"line":580},[543,1207,550],{"class":549},[543,1209,554],{"class":553},[543,1211,669],{"class":557},[543,1213,561],{"class":553},[543,1215,564],{"class":549},[543,1217,567],{"class":553},[543,1219,789],{"class":570},[543,1221,574],{"class":553},[543,1223,577],{"class":553},[543,1225,1226,1228,1230,1232,1234,1236,1238,1241,1243],{"class":545,"line":587},[543,1227,550],{"class":549},[543,1229,554],{"class":553},[543,1231,806],{"class":557},[543,1233,561],{"class":553},[543,1235,564],{"class":549},[543,1237,567],{"class":553},[543,1239,1240],{"class":570},".\u002Fsignup.controller",[543,1242,574],{"class":553},[543,1244,577],{"class":553},[543,1246,1247],{"class":545,"line":604},[543,1248,584],{"emptyLinePlaceholder":583},[543,1250,1251,1253,1255,1258,1260,1262,1264],{"class":545,"line":622},[543,1252,590],{"class":549},[543,1254,666],{"class":593},[543,1256,1257],{"class":597}," UsersModule",[543,1259,672],{"class":593},[543,1261,1191],{"class":984},[543,1263,856],{"class":557},[543,1265,1266],{"class":553},"{\n",[543,1268,1269,1272,1274,1276,1279,1281,1284],{"class":545,"line":636},[543,1270,1271],{"class":610},"  http",[543,1273,614],{"class":553},[543,1275,554],{"class":553},[543,1277,1278],{"class":610}," controllers",[543,1280,614],{"class":553},[543,1282,1283],{"class":557}," [SignupController] ",[543,1285,1286],{"class":553},"},\n",[543,1288,1289,1292,1294,1296,1299,1301,1304],{"class":545,"line":650},[543,1290,1291],{"class":610},"  integration",[543,1293,614],{"class":553},[543,1295,554],{"class":553},[543,1297,1298],{"class":610}," events",[543,1300,614],{"class":553},[543,1302,1303],{"class":557}," [UserSignedUp] ",[543,1305,1286],{"class":553},[543,1307,1308,1311,1314],{"class":545,"line":656},[543,1309,1310],{"class":553},"}",[543,1312,1313],{"class":557},") ",[543,1315,1316],{"class":553},"{}\n",[521,1318,1320],{"id":1319},"consume-an-integration-event","Consume an integration event",[499,1322,1323,1324,1327,1328,1331,1332,1335,1336,1339,1340,1343],{},"A consumer is ",[516,1325,1326],{},"class X implements IntegrationEventHandler\u003C\"type\", Payload>"," — its ",[503,1329,1330],{},"own"," discovery concept,\nnot ",[516,1333,1334],{},"EventHandler",", because it rides the queue rather than the in-process bus. The string-literal name matches\nthe producer's first type argument; that shared name is how they meet on the channel. When the transport\ndelivers, ",[516,1337,1338],{},"handle"," runs. (",[516,1341,1342],{},"extends IntegrationEventHandler\u003C...>"," binds identically — use it when you want\nyour own base-class hierarchy on top of a handler.)",[533,1345,1348],{"className":535,"code":1346,"filename":1347,"language":538,"meta":539,"style":539},"import type { IntegrationEventHandler } from \"@heximon\u002Fintegration\";\nimport type { UserSignedUpPayload } from \"..\u002Fusers\u002Fevents\";\nimport { CaptureEmailTransport } from \".\u002Fcapture-email-transport\";\n\nexport class WelcomeEmailHandler implements IntegrationEventHandler\u003C\"user.signed-up\", UserSignedUpPayload> {\n  private readonly transport: CaptureEmailTransport;\n\n  public constructor(transport: CaptureEmailTransport) {\n    this.transport = transport;\n  }\n\n  public async handle(payload: UserSignedUpPayload): Promise\u003Cvoid> {\n    \u002F\u002F compose + send the welcome email through the injected transport\n  }\n}\n","mail\u002Fwelcome-email.handler.ts",[516,1349,1350,1373,1396,1418,1422,1451,1466,1470,1489,1501,1505,1509,1541,1546,1550],{"__ignoreMap":539},[543,1351,1352,1354,1356,1358,1361,1363,1365,1367,1369,1371],{"class":545,"line":546},[543,1353,550],{"class":549},[543,1355,749],{"class":549},[543,1357,554],{"class":553},[543,1359,1360],{"class":557}," IntegrationEventHandler",[543,1362,561],{"class":553},[543,1364,564],{"class":549},[543,1366,567],{"class":553},[543,1368,571],{"class":570},[543,1370,574],{"class":553},[543,1372,577],{"class":553},[543,1374,1375,1377,1379,1381,1383,1385,1387,1389,1392,1394],{"class":545,"line":580},[543,1376,550],{"class":549},[543,1378,749],{"class":549},[543,1380,554],{"class":553},[543,1382,598],{"class":557},[543,1384,561],{"class":553},[543,1386,564],{"class":549},[543,1388,567],{"class":553},[543,1390,1391],{"class":570},"..\u002Fusers\u002Fevents",[543,1393,574],{"class":553},[543,1395,577],{"class":553},[543,1397,1398,1400,1402,1405,1407,1409,1411,1414,1416],{"class":545,"line":587},[543,1399,550],{"class":549},[543,1401,554],{"class":553},[543,1403,1404],{"class":557}," CaptureEmailTransport",[543,1406,561],{"class":553},[543,1408,564],{"class":549},[543,1410,567],{"class":553},[543,1412,1413],{"class":570},".\u002Fcapture-email-transport",[543,1415,574],{"class":553},[543,1417,577],{"class":553},[543,1419,1420],{"class":545,"line":604},[543,1421,584],{"emptyLinePlaceholder":583},[543,1423,1424,1426,1428,1431,1433,1435,1437,1439,1441,1443,1445,1447,1449],{"class":545,"line":622},[543,1425,590],{"class":549},[543,1427,666],{"class":593},[543,1429,1430],{"class":597}," WelcomeEmailHandler",[543,1432,809],{"class":593},[543,1434,1360],{"class":597},[543,1436,677],{"class":553},[543,1438,574],{"class":553},[543,1440,682],{"class":570},[543,1442,574],{"class":553},[543,1444,687],{"class":553},[543,1446,598],{"class":597},[543,1448,692],{"class":553},[543,1450,601],{"class":553},[543,1452,1453,1455,1457,1460,1462,1464],{"class":545,"line":636},[543,1454,829],{"class":593},[543,1456,832],{"class":593},[543,1458,1459],{"class":610}," transport",[543,1461,614],{"class":553},[543,1463,1404],{"class":597},[543,1465,577],{"class":553},[543,1467,1468],{"class":545,"line":650},[543,1469,584],{"emptyLinePlaceholder":583},[543,1471,1472,1474,1476,1478,1481,1483,1485,1487],{"class":545,"line":656},[543,1473,850],{"class":593},[543,1475,853],{"class":593},[543,1477,856],{"class":553},[543,1479,1480],{"class":859},"transport",[543,1482,614],{"class":553},[543,1484,1404],{"class":597},[543,1486,867],{"class":553},[543,1488,601],{"class":553},[543,1490,1491,1493,1495,1497,1499],{"class":545,"line":661},[543,1492,874],{"class":553},[543,1494,1480],{"class":557},[543,1496,879],{"class":553},[543,1498,1459],{"class":557},[543,1500,577],{"class":553},[543,1502,1503],{"class":545,"line":886},[543,1504,889],{"class":553},[543,1506,1507],{"class":545,"line":892},[543,1508,584],{"emptyLinePlaceholder":583},[543,1510,1511,1513,1515,1518,1520,1523,1525,1527,1530,1532,1534,1537,1539],{"class":545,"line":897},[543,1512,850],{"class":593},[543,1514,902],{"class":593},[543,1516,1517],{"class":610}," handle",[543,1519,856],{"class":553},[543,1521,1522],{"class":859},"payload",[543,1524,614],{"class":553},[543,1526,598],{"class":597},[543,1528,1529],{"class":553},"):",[543,1531,929],{"class":597},[543,1533,677],{"class":553},[543,1535,1536],{"class":597},"void",[543,1538,692],{"class":553},[543,1540,601],{"class":553},[543,1542,1543],{"class":545,"line":956},[543,1544,1545],{"class":1042},"    \u002F\u002F compose + send the welcome email through the injected transport\n",[543,1547,1548],{"class":545,"line":1013},[543,1549,889],{"class":553},[543,1551,1552],{"class":545,"line":1034},[543,1553,653],{"class":553},[499,1555,1556,1557,1172,1559,1176],{},"Declare it under the module's ",[516,1558,1171],{},[516,1560,1561],{},"eventHandlers",[533,1563,1566],{"className":535,"code":1564,"filename":1565,"language":538,"meta":539,"style":539},"import { Module } from \"@heximon\u002Fruntime\";\nimport { CaptureEmailTransport } from \".\u002Fcapture-email-transport\";\nimport { WelcomeEmailHandler } from \".\u002Fwelcome-email.handler\";\n\nexport class MailModule extends Module({\n  providers: [CaptureEmailTransport],\n  integration: { eventHandlers: [WelcomeEmailHandler] },\n  exports: [CaptureEmailTransport],\n}) {}\n","mail\u002Fmail.module.ts",[516,1567,1568,1588,1608,1629,1633,1650,1663,1681,1692],{"__ignoreMap":539},[543,1569,1570,1572,1574,1576,1578,1580,1582,1584,1586],{"class":545,"line":546},[543,1571,550],{"class":549},[543,1573,554],{"class":553},[543,1575,1191],{"class":557},[543,1577,561],{"class":553},[543,1579,564],{"class":549},[543,1581,567],{"class":553},[543,1583,738],{"class":570},[543,1585,574],{"class":553},[543,1587,577],{"class":553},[543,1589,1590,1592,1594,1596,1598,1600,1602,1604,1606],{"class":545,"line":580},[543,1591,550],{"class":549},[543,1593,554],{"class":553},[543,1595,1404],{"class":557},[543,1597,561],{"class":553},[543,1599,564],{"class":549},[543,1601,567],{"class":553},[543,1603,1413],{"class":570},[543,1605,574],{"class":553},[543,1607,577],{"class":553},[543,1609,1610,1612,1614,1616,1618,1620,1622,1625,1627],{"class":545,"line":587},[543,1611,550],{"class":549},[543,1613,554],{"class":553},[543,1615,1430],{"class":557},[543,1617,561],{"class":553},[543,1619,564],{"class":549},[543,1621,567],{"class":553},[543,1623,1624],{"class":570},".\u002Fwelcome-email.handler",[543,1626,574],{"class":553},[543,1628,577],{"class":553},[543,1630,1631],{"class":545,"line":604},[543,1632,584],{"emptyLinePlaceholder":583},[543,1634,1635,1637,1639,1642,1644,1646,1648],{"class":545,"line":622},[543,1636,590],{"class":549},[543,1638,666],{"class":593},[543,1640,1641],{"class":597}," MailModule",[543,1643,672],{"class":593},[543,1645,1191],{"class":984},[543,1647,856],{"class":557},[543,1649,1266],{"class":553},[543,1651,1652,1655,1657,1660],{"class":545,"line":636},[543,1653,1654],{"class":610},"  providers",[543,1656,614],{"class":553},[543,1658,1659],{"class":557}," [CaptureEmailTransport]",[543,1661,1662],{"class":553},",\n",[543,1664,1665,1667,1669,1671,1674,1676,1679],{"class":545,"line":650},[543,1666,1291],{"class":610},[543,1668,614],{"class":553},[543,1670,554],{"class":553},[543,1672,1673],{"class":610}," eventHandlers",[543,1675,614],{"class":553},[543,1677,1678],{"class":557}," [WelcomeEmailHandler] ",[543,1680,1286],{"class":553},[543,1682,1683,1686,1688,1690],{"class":545,"line":656},[543,1684,1685],{"class":610},"  exports",[543,1687,614],{"class":553},[543,1689,1659],{"class":557},[543,1691,1662],{"class":553},[543,1693,1694,1696,1698],{"class":545,"line":661},[543,1695,1310],{"class":553},[543,1697,1313],{"class":557},[543,1699,1316],{"class":553},[1701,1702,1704,1707,1708,1710,1711,1714,1715,1718,1719,1722,1723,1707,1726,1729,1730,1732],"callout",{"type":1703},"info",[503,1705,1706],{},"No transport boilerplate."," ",[516,1709,709],{}," is the default: it fans out to\n",[516,1712,1713],{},"IntegrationEventHandler","s over the shared queue channel table and is bound automatically at boot — the app\ndeclares no producer seam, no boot wiring. ",[516,1716,1717],{},"IntegrationEventsPlugin"," (from ",[516,1720,1721],{},"@heximon\u002Fintegration\u002Fcompiler",")\n",[516,1724,1725],{},"requires",[516,1727,1728],{},"QueuePlugin",", so listing the integration plugin auto-pulls the queue plugin — the reverse\ndoesn't hold: a bare ",[516,1731,1728],{}," never activates the integration tier.",[521,1734,1736],{"id":1735},"wire-the-plugin","Wire the plugin",[533,1738,1741],{"className":535,"code":1739,"filename":1740,"language":538,"meta":539,"style":539},"import { defineHeximonConfig } from \"@heximon\u002Fbuild\";\nimport { IntegrationEventsPlugin } from \"@heximon\u002Fintegration\u002Fcompiler\";\nimport { HttpPlugin } from \"@heximon\u002Fhttp\u002Fcompiler\";\n\nexport default defineHeximonConfig({\n  plugins: [new HttpPlugin(), new IntegrationEventsPlugin()],\n});\n","heximon.config.ts",[516,1742,1743,1765,1786,1808,1812,1825,1854],{"__ignoreMap":539},[543,1744,1745,1747,1749,1752,1754,1756,1758,1761,1763],{"class":545,"line":546},[543,1746,550],{"class":549},[543,1748,554],{"class":553},[543,1750,1751],{"class":557}," defineHeximonConfig",[543,1753,561],{"class":553},[543,1755,564],{"class":549},[543,1757,567],{"class":553},[543,1759,1760],{"class":570},"@heximon\u002Fbuild",[543,1762,574],{"class":553},[543,1764,577],{"class":553},[543,1766,1767,1769,1771,1774,1776,1778,1780,1782,1784],{"class":545,"line":580},[543,1768,550],{"class":549},[543,1770,554],{"class":553},[543,1772,1773],{"class":557}," IntegrationEventsPlugin",[543,1775,561],{"class":553},[543,1777,564],{"class":549},[543,1779,567],{"class":553},[543,1781,1721],{"class":570},[543,1783,574],{"class":553},[543,1785,577],{"class":553},[543,1787,1788,1790,1792,1795,1797,1799,1801,1804,1806],{"class":545,"line":587},[543,1789,550],{"class":549},[543,1791,554],{"class":553},[543,1793,1794],{"class":557}," HttpPlugin",[543,1796,561],{"class":553},[543,1798,564],{"class":549},[543,1800,567],{"class":553},[543,1802,1803],{"class":570},"@heximon\u002Fhttp\u002Fcompiler",[543,1805,574],{"class":553},[543,1807,577],{"class":553},[543,1809,1810],{"class":545,"line":604},[543,1811,584],{"emptyLinePlaceholder":583},[543,1813,1814,1816,1819,1821,1823],{"class":545,"line":622},[543,1815,590],{"class":549},[543,1817,1818],{"class":549}," default",[543,1820,1751],{"class":984},[543,1822,856],{"class":557},[543,1824,1266],{"class":553},[543,1826,1827,1830,1832,1835,1838,1840,1842,1844,1847,1849,1852],{"class":545,"line":636},[543,1828,1829],{"class":610},"  plugins",[543,1831,614],{"class":553},[543,1833,1834],{"class":557}," [",[543,1836,1837],{"class":553},"new",[543,1839,1794],{"class":984},[543,1841,1029],{"class":557},[543,1843,687],{"class":553},[543,1845,1846],{"class":553}," new",[543,1848,1773],{"class":984},[543,1850,1851],{"class":557},"()]",[543,1853,1662],{"class":553},[543,1855,1856,1858,1860],{"class":545,"line":650},[543,1857,1310],{"class":553},[543,1859,867],{"class":557},[543,1861,577],{"class":553},[521,1863,1865],{"id":1864},"transactional-outbox","Transactional outbox",[499,1867,1868,1869,1872,1873,1876],{},"The default transport is fire-and-forget: a process crash between the aggregate write and the dispatch loses the\nevent. The ",[503,1870,1871],{},"transactional outbox"," closes that gap by persisting each event to a durable outbox table ",[503,1874,1875],{},"in the\nsame transaction"," as the aggregate write, delivering after the commit, and replaying pending rows on boot — so\ndelivery survives a crash and a rollback discards the buffered event instead of leaking it.",[499,1878,1879,1880,1882,1883,1886,1887,1890,1891,1894,1895,1897,1898,1901,1902,1905,1906,1908,1909,1911,1912,1915,1916,1918,1919,1922,1923,1925,1926,1929],{},"The tier ships as three classes from ",[516,1881,571],{}," — ",[516,1884,1885],{},"OutboxStore",", ",[516,1888,1889],{},"OutboxRelay",", and\n",[516,1892,1893],{},"OutboxIntegrationEventTransport"," (an ",[516,1896,705],{}," satisfier) — plus the Drizzle-backed\n",[516,1899,1900],{},"DrizzleOutboxStore"," from ",[516,1903,1904],{},"@heximon\u002Fdrizzle\u002Fcore",". ",[516,1907,1885],{}," and ",[516,1910,1893],{}," bind as a\nbare provider or a ",[516,1913,1914],{},"useFactory"," on their own token (a ",[516,1917,1914],{}," only where construction needs a non-DI\nargument, like the app's ",[516,1920,1921],{},"outbox"," table). ",[516,1924,1889],{}," is the one piece that needs a thin ",[503,1927,1928],{},"exported local\nsubclass"," instead — and the reason is a disambiguation, not a formality.",[499,1931,1932,1934,1935,1707,1939,1941,1942,1945,1946,1949,1950,1952,1953,1955,1956,1959,1960,976],{},[516,1933,1889],{},"'s own constructor types its delivery target as the ",[1936,1937,1938],"em",{},"abstract",[516,1940,705],{}," — the\nsame port a typed event's ",[516,1943,1944],{},"publish()"," resolves through. Your module also binds\n",[516,1947,1948],{},"{ provide: IntegrationEventTransport, useClass: OutboxIntegrationEventTransport }"," for the producer side, and\nexact-token resolution wins before the compiler's satisfier scan. Bind ",[516,1951,1889],{}," bare (or via ",[516,1954,1914],{},")\nagainst that same abstract type, and its delivery target silently resolves to the very producer transport that\nwrites into the outbox — not an error, a ",[503,1957,1958],{},"loop",": every drained row gets re-buffered into the outbox instead of\nreaching an ",[516,1961,1713],{},[499,1963,1964,1965,1707,1968,1971],{},"The fix types ",[516,1966,1967],{},"target",[503,1969,1970],{},"concretely",", at the actual delivery terminal, in a thin subclass:",[533,1973,1976],{"className":535,"code":1974,"filename":1975,"language":538,"meta":539,"style":539},"import type { Context } from \"@heximon\u002Fruntime\";\nimport { OutboxRelay, type OutboxStore } from \"@heximon\u002Fintegration\";\nimport { MemoryIntegrationEventTransport } from \"@heximon\u002Fqueue\u002Fmemory\";\n\n\u002F**\n * A thin `OutboxRelay` subclass so the compiler reads its constructor directly. Types `target` concretely as\n * `MemoryIntegrationEventTransport`: a bare abstract `IntegrationEventTransport` param would instead exact-match\n * the producer transport bound below.\n *\u002F\nexport class AppOutboxRelay extends OutboxRelay {\n  public constructor(store: OutboxStore, target: MemoryIntegrationEventTransport, context: Context) {\n    super(store, target, context);\n  }\n}\n","orders\u002Foutbox-relay.ts",[516,1977,1978,2001,2029,2051,2055,2060,2065,2070,2075,2080,2095,2132,2153,2157],{"__ignoreMap":539},[543,1979,1980,1982,1984,1986,1989,1991,1993,1995,1997,1999],{"class":545,"line":546},[543,1981,550],{"class":549},[543,1983,749],{"class":549},[543,1985,554],{"class":553},[543,1987,1988],{"class":557}," Context",[543,1990,561],{"class":553},[543,1992,564],{"class":549},[543,1994,567],{"class":553},[543,1996,738],{"class":570},[543,1998,574],{"class":553},[543,2000,577],{"class":553},[543,2002,2003,2005,2007,2010,2012,2014,2017,2019,2021,2023,2025,2027],{"class":545,"line":580},[543,2004,550],{"class":549},[543,2006,554],{"class":553},[543,2008,2009],{"class":557}," OutboxRelay",[543,2011,687],{"class":553},[543,2013,749],{"class":549},[543,2015,2016],{"class":557}," OutboxStore",[543,2018,561],{"class":553},[543,2020,564],{"class":549},[543,2022,567],{"class":553},[543,2024,571],{"class":570},[543,2026,574],{"class":553},[543,2028,577],{"class":553},[543,2030,2031,2033,2035,2038,2040,2042,2044,2047,2049],{"class":545,"line":587},[543,2032,550],{"class":549},[543,2034,554],{"class":553},[543,2036,2037],{"class":557}," MemoryIntegrationEventTransport",[543,2039,561],{"class":553},[543,2041,564],{"class":549},[543,2043,567],{"class":553},[543,2045,2046],{"class":570},"@heximon\u002Fqueue\u002Fmemory",[543,2048,574],{"class":553},[543,2050,577],{"class":553},[543,2052,2053],{"class":545,"line":604},[543,2054,584],{"emptyLinePlaceholder":583},[543,2056,2057],{"class":545,"line":622},[543,2058,2059],{"class":1042},"\u002F**\n",[543,2061,2062],{"class":545,"line":636},[543,2063,2064],{"class":1042}," * A thin `OutboxRelay` subclass so the compiler reads its constructor directly. Types `target` concretely as\n",[543,2066,2067],{"class":545,"line":650},[543,2068,2069],{"class":1042}," * `MemoryIntegrationEventTransport`: a bare abstract `IntegrationEventTransport` param would instead exact-match\n",[543,2071,2072],{"class":545,"line":656},[543,2073,2074],{"class":1042}," * the producer transport bound below.\n",[543,2076,2077],{"class":545,"line":661},[543,2078,2079],{"class":1042}," *\u002F\n",[543,2081,2082,2084,2086,2089,2091,2093],{"class":545,"line":886},[543,2083,590],{"class":549},[543,2085,666],{"class":593},[543,2087,2088],{"class":597}," AppOutboxRelay",[543,2090,672],{"class":593},[543,2092,2009],{"class":597},[543,2094,601],{"class":553},[543,2096,2097,2099,2101,2103,2106,2108,2110,2112,2115,2117,2119,2121,2124,2126,2128,2130],{"class":545,"line":892},[543,2098,850],{"class":593},[543,2100,853],{"class":593},[543,2102,856],{"class":553},[543,2104,2105],{"class":859},"store",[543,2107,614],{"class":553},[543,2109,2016],{"class":597},[543,2111,687],{"class":553},[543,2113,2114],{"class":859}," target",[543,2116,614],{"class":553},[543,2118,2037],{"class":597},[543,2120,687],{"class":553},[543,2122,2123],{"class":859}," context",[543,2125,614],{"class":553},[543,2127,1988],{"class":597},[543,2129,867],{"class":553},[543,2131,601],{"class":553},[543,2133,2134,2137,2139,2141,2143,2145,2147,2149,2151],{"class":545,"line":897},[543,2135,2136],{"class":557},"    super",[543,2138,856],{"class":610},[543,2140,2105],{"class":557},[543,2142,687],{"class":553},[543,2144,2114],{"class":557},[543,2146,687],{"class":553},[543,2148,2123],{"class":557},[543,2150,867],{"class":610},[543,2152,577],{"class":553},[543,2154,2155],{"class":545,"line":956},[543,2156,889],{"class":553},[543,2158,2159],{"class":545,"line":1013},[543,2160,653],{"class":553},[499,2162,2163,2164,1707,2167,2170,2171,2173,2174,2177,2178,2181,2182,2184,2185,2188],{},"Because the constructor is authored in your own source, list ",[516,2165,2166],{},"AppOutboxRelay",[503,2168,2169],{},"bare"," — no ",[516,2172,1914],{},", no\n",[516,2175,2176],{},"eager"," flag. ",[516,2179,2180],{},"OutboxRelay implements OnBootstrap"," for its crash-recovery replay, and unlike an opaque\n",[516,2183,1914],{}," value, a subclass's inherited lifecycle hooks are auto-recovered. (Any local bare provider must be\nan ",[503,2186,2187],{},"exported"," class — the compiler imports it by name.)",[533,2190,2193],{"className":535,"code":2191,"filename":2192,"language":538,"meta":539,"style":539},"import { Module, TransactionContext } from \"@heximon\u002Fruntime\";\nimport { OutboxIntegrationEventTransport, OutboxStore } from \"@heximon\u002Fintegration\";\nimport { DrizzleOutboxStore } from \"@heximon\u002Fdrizzle\u002Fcore\";\nimport { IntegrationEventTransport } from \"@heximon\u002Fqueue\";\nimport { MemoryIntegrationEventTransport } from \"@heximon\u002Fqueue\u002Fmemory\";\nimport { AppOutboxRelay } from \".\u002Foutbox-relay\";\nimport { OrderPlaced } from \".\u002Forder.events\";\nimport { OrdersController } from \".\u002Forders.controller\";\nimport { Database } from \".\u002Fshared-database\";\nimport { outbox } from \".\u002Foutbox-table\";\n\nexport class AppModule extends Module({\n  providers: [\n    Database,\n    {\n      provide: OutboxStore,\n      useFactory: (database: Database) => new DrizzleOutboxStore(database, outbox),\n    },\n    \u002F\u002F The relay's terminal — a distinct concrete token from the producer transport, so the relay delivers to\n    \u002F\u002F local handlers with no self-delivery loop on `IntegrationEventTransport`.\n    MemoryIntegrationEventTransport,\n    AppOutboxRelay,\n    {\n      provide: IntegrationEventTransport,\n      useClass: OutboxIntegrationEventTransport,\n    },\n    TransactionContext,\n  ],\n  integration: { events: [OrderPlaced] },\n  http: { controllers: [OrdersController] },\n}) {}\n","orders\u002Fapp.module.ts",[516,2194,2195,2220,2245,2266,2288,2308,2329,2351,2373,2395,2417,2421,2438,2447,2454,2459,2470,2505,2510,2515,2520,2527,2534,2539,2550,2562,2567,2575,2583,2601,2619],{"__ignoreMap":539},[543,2196,2197,2199,2201,2203,2205,2208,2210,2212,2214,2216,2218],{"class":545,"line":546},[543,2198,550],{"class":549},[543,2200,554],{"class":553},[543,2202,1191],{"class":557},[543,2204,687],{"class":553},[543,2206,2207],{"class":557}," TransactionContext",[543,2209,561],{"class":553},[543,2211,564],{"class":549},[543,2213,567],{"class":553},[543,2215,738],{"class":570},[543,2217,574],{"class":553},[543,2219,577],{"class":553},[543,2221,2222,2224,2226,2229,2231,2233,2235,2237,2239,2241,2243],{"class":545,"line":580},[543,2223,550],{"class":549},[543,2225,554],{"class":553},[543,2227,2228],{"class":557}," OutboxIntegrationEventTransport",[543,2230,687],{"class":553},[543,2232,2016],{"class":557},[543,2234,561],{"class":553},[543,2236,564],{"class":549},[543,2238,567],{"class":553},[543,2240,571],{"class":570},[543,2242,574],{"class":553},[543,2244,577],{"class":553},[543,2246,2247,2249,2251,2254,2256,2258,2260,2262,2264],{"class":545,"line":587},[543,2248,550],{"class":549},[543,2250,554],{"class":553},[543,2252,2253],{"class":557}," DrizzleOutboxStore",[543,2255,561],{"class":553},[543,2257,564],{"class":549},[543,2259,567],{"class":553},[543,2261,1904],{"class":570},[543,2263,574],{"class":553},[543,2265,577],{"class":553},[543,2267,2268,2270,2272,2275,2277,2279,2281,2284,2286],{"class":545,"line":604},[543,2269,550],{"class":549},[543,2271,554],{"class":553},[543,2273,2274],{"class":557}," IntegrationEventTransport",[543,2276,561],{"class":553},[543,2278,564],{"class":549},[543,2280,567],{"class":553},[543,2282,2283],{"class":570},"@heximon\u002Fqueue",[543,2285,574],{"class":553},[543,2287,577],{"class":553},[543,2289,2290,2292,2294,2296,2298,2300,2302,2304,2306],{"class":545,"line":622},[543,2291,550],{"class":549},[543,2293,554],{"class":553},[543,2295,2037],{"class":557},[543,2297,561],{"class":553},[543,2299,564],{"class":549},[543,2301,567],{"class":553},[543,2303,2046],{"class":570},[543,2305,574],{"class":553},[543,2307,577],{"class":553},[543,2309,2310,2312,2314,2316,2318,2320,2322,2325,2327],{"class":545,"line":636},[543,2311,550],{"class":549},[543,2313,554],{"class":553},[543,2315,2088],{"class":557},[543,2317,561],{"class":553},[543,2319,564],{"class":549},[543,2321,567],{"class":553},[543,2323,2324],{"class":570},".\u002Foutbox-relay",[543,2326,574],{"class":553},[543,2328,577],{"class":553},[543,2330,2331,2333,2335,2338,2340,2342,2344,2347,2349],{"class":545,"line":650},[543,2332,550],{"class":549},[543,2334,554],{"class":553},[543,2336,2337],{"class":557}," OrderPlaced",[543,2339,561],{"class":553},[543,2341,564],{"class":549},[543,2343,567],{"class":553},[543,2345,2346],{"class":570},".\u002Forder.events",[543,2348,574],{"class":553},[543,2350,577],{"class":553},[543,2352,2353,2355,2357,2360,2362,2364,2366,2369,2371],{"class":545,"line":656},[543,2354,550],{"class":549},[543,2356,554],{"class":553},[543,2358,2359],{"class":557}," OrdersController",[543,2361,561],{"class":553},[543,2363,564],{"class":549},[543,2365,567],{"class":553},[543,2367,2368],{"class":570},".\u002Forders.controller",[543,2370,574],{"class":553},[543,2372,577],{"class":553},[543,2374,2375,2377,2379,2382,2384,2386,2388,2391,2393],{"class":545,"line":661},[543,2376,550],{"class":549},[543,2378,554],{"class":553},[543,2380,2381],{"class":557}," Database",[543,2383,561],{"class":553},[543,2385,564],{"class":549},[543,2387,567],{"class":553},[543,2389,2390],{"class":570},".\u002Fshared-database",[543,2392,574],{"class":553},[543,2394,577],{"class":553},[543,2396,2397,2399,2401,2404,2406,2408,2410,2413,2415],{"class":545,"line":886},[543,2398,550],{"class":549},[543,2400,554],{"class":553},[543,2402,2403],{"class":557}," outbox",[543,2405,561],{"class":553},[543,2407,564],{"class":549},[543,2409,567],{"class":553},[543,2411,2412],{"class":570},".\u002Foutbox-table",[543,2414,574],{"class":553},[543,2416,577],{"class":553},[543,2418,2419],{"class":545,"line":892},[543,2420,584],{"emptyLinePlaceholder":583},[543,2422,2423,2425,2427,2430,2432,2434,2436],{"class":545,"line":897},[543,2424,590],{"class":549},[543,2426,666],{"class":593},[543,2428,2429],{"class":597}," AppModule",[543,2431,672],{"class":593},[543,2433,1191],{"class":984},[543,2435,856],{"class":557},[543,2437,1266],{"class":553},[543,2439,2440,2442,2444],{"class":545,"line":956},[543,2441,1654],{"class":610},[543,2443,614],{"class":553},[543,2445,2446],{"class":557}," [\n",[543,2448,2449,2452],{"class":545,"line":1013},[543,2450,2451],{"class":557},"    Database",[543,2453,1662],{"class":553},[543,2455,2456],{"class":545,"line":1034},[543,2457,2458],{"class":553},"    {\n",[543,2460,2461,2464,2466,2468],{"class":545,"line":1039},[543,2462,2463],{"class":610},"      provide",[543,2465,614],{"class":553},[543,2467,2016],{"class":557},[543,2469,1662],{"class":553},[543,2471,2472,2475,2477,2479,2482,2484,2486,2488,2491,2493,2495,2498,2500,2503],{"class":545,"line":1046},[543,2473,2474],{"class":984},"      useFactory",[543,2476,614],{"class":553},[543,2478,967],{"class":553},[543,2480,2481],{"class":859},"database",[543,2483,614],{"class":553},[543,2485,2381],{"class":597},[543,2487,867],{"class":553},[543,2489,2490],{"class":593}," =>",[543,2492,1846],{"class":553},[543,2494,2253],{"class":984},[543,2496,2497],{"class":557},"(database",[543,2499,687],{"class":553},[543,2501,2502],{"class":557}," outbox)",[543,2504,1662],{"class":553},[543,2506,2507],{"class":545,"line":1101},[543,2508,2509],{"class":553},"    },\n",[543,2511,2512],{"class":545,"line":1106},[543,2513,2514],{"class":1042},"    \u002F\u002F The relay's terminal — a distinct concrete token from the producer transport, so the relay delivers to\n",[543,2516,2517],{"class":545,"line":1130},[543,2518,2519],{"class":1042},"    \u002F\u002F local handlers with no self-delivery loop on `IntegrationEventTransport`.\n",[543,2521,2522,2525],{"class":545,"line":1158},[543,2523,2524],{"class":557},"    MemoryIntegrationEventTransport",[543,2526,1662],{"class":553},[543,2528,2529,2532],{"class":545,"line":1163},[543,2530,2531],{"class":557},"    AppOutboxRelay",[543,2533,1662],{"class":553},[543,2535,2537],{"class":545,"line":2536},23,[543,2538,2458],{"class":553},[543,2540,2542,2544,2546,2548],{"class":545,"line":2541},24,[543,2543,2463],{"class":610},[543,2545,614],{"class":553},[543,2547,2274],{"class":557},[543,2549,1662],{"class":553},[543,2551,2553,2556,2558,2560],{"class":545,"line":2552},25,[543,2554,2555],{"class":610},"      useClass",[543,2557,614],{"class":553},[543,2559,2228],{"class":557},[543,2561,1662],{"class":553},[543,2563,2565],{"class":545,"line":2564},26,[543,2566,2509],{"class":553},[543,2568,2570,2573],{"class":545,"line":2569},27,[543,2571,2572],{"class":557},"    TransactionContext",[543,2574,1662],{"class":553},[543,2576,2578,2581],{"class":545,"line":2577},28,[543,2579,2580],{"class":557},"  ]",[543,2582,1662],{"class":553},[543,2584,2586,2588,2590,2592,2594,2596,2599],{"class":545,"line":2585},29,[543,2587,1291],{"class":610},[543,2589,614],{"class":553},[543,2591,554],{"class":553},[543,2593,1298],{"class":610},[543,2595,614],{"class":553},[543,2597,2598],{"class":557}," [OrderPlaced] ",[543,2600,1286],{"class":553},[543,2602,2604,2606,2608,2610,2612,2614,2617],{"class":545,"line":2603},30,[543,2605,1271],{"class":610},[543,2607,614],{"class":553},[543,2609,554],{"class":553},[543,2611,1278],{"class":610},[543,2613,614],{"class":553},[543,2615,2616],{"class":557}," [OrdersController] ",[543,2618,1286],{"class":553},[543,2620,2622,2624,2626],{"class":545,"line":2621},31,[543,2623,1310],{"class":553},[543,2625,1313],{"class":557},[543,2627,1316],{"class":553},[499,2629,2630,2631,2633,2634,2636,2637,2640],{},"Inside a command handler or controller, wrap the aggregate write and the ",[516,2632,1059],{}," call in one transaction. The\n",[516,2635,1059],{}," buffers the record; the outbox row appends on the transaction's ",[516,2638,2639],{},"onBeforeCommit"," hook — atomic with the\naggregate write. A rollback discards the buffer, so no order means no event:",[533,2642,2645],{"className":535,"code":2643,"filename":2644,"language":538,"meta":539,"style":539},"await this.database.runInTransaction(async () => {\n  await this.orderPlaced.publish({ orderId });\n});\n","orders\u002Forders.controller.ts (excerpt)",[516,2646,2647,2672,2699],{"__ignoreMap":539},[543,2648,2649,2651,2653,2655,2657,2660,2662,2665,2668,2670],{"class":545,"line":546},[543,2650,970],{"class":549},[543,2652,1052],{"class":553},[543,2654,2481],{"class":557},[543,2656,976],{"class":553},[543,2658,2659],{"class":984},"runInTransaction",[543,2661,856],{"class":557},[543,2663,2664],{"class":593},"async",[543,2666,2667],{"class":553}," ()",[543,2669,2490],{"class":593},[543,2671,601],{"class":553},[543,2673,2674,2677,2679,2682,2684,2686,2688,2690,2693,2695,2697],{"class":545,"line":580},[543,2675,2676],{"class":549},"  await",[543,2678,1052],{"class":553},[543,2680,2681],{"class":557},"orderPlaced",[543,2683,976],{"class":553},[543,2685,1059],{"class":984},[543,2687,856],{"class":610},[543,2689,1064],{"class":553},[543,2691,2692],{"class":557}," orderId",[543,2694,561],{"class":553},[543,2696,867],{"class":610},[543,2698,577],{"class":553},[543,2700,2701,2703,2705],{"class":545,"line":587},[543,2702,1310],{"class":553},[543,2704,867],{"class":557},[543,2706,577],{"class":553},[499,2708,2709,2710,2713,2714,2716,2717,1718,2720,2723,2724,2727,2728,2734],{},"Delivery is ",[503,2711,2712],{},"at-least-once",": the relay re-dispatches a row on a later drain if ",[516,2715,1338],{}," threw. Pair with a\n",[516,2718,2719],{},"QueueIdempotencyInterceptor",[516,2721,2722],{},"@heximon\u002Fqueue\u002Fidempotency",") if your handlers must deduplicate. The relay\nalso replays pending rows on boot — the ",[516,2725,2726],{},"OnBootstrap"," hook fires whether or not a request arrives — so rows left\nby a crashed process are delivered after restart. ",[508,2729,2733],{"href":2730,"rel":2731},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fgap\u002Fcross-service-transports\u002Freliable",[2732],"nofollow","The gap's reliable cross-service example","\nhas this exact wiring plus the rollback proof (place an order that fails, and no event is ever delivered).",[2736,2737,2739],"h3",{"id":2738},"swap-the-relays-terminal-per-platform","Swap the relay's terminal per platform",[499,2741,2742,2743,2745,2746,2748,2749,2751,2752,967,2755,2758,2759,2762,2763,2766],{},"The relay's ",[516,2744,1967],{}," is the delivery surface each drained row is handed to — swapping platforms means retyping\n",[516,2747,2166],{},"'s ",[516,2750,1967],{}," parameter to the platform's own transport (the same disambiguation as above, now\naimed at a durable queue instead of the in-process default) and binding that transport in its place. On\nCloudflare Workers, bind ",[516,2753,2754],{},"CloudflareQueueIntegrationEventTransport",[516,2756,2757],{},"@heximon\u002Fqueue\u002Fcloudflare",") — it ",[516,2760,2761],{},"send","s\neach drained row onto the app's own Cloudflare Queue, and that same worker's ",[516,2764,2765],{},"queue(batch, env, ctx)"," export\ndrains it later in a separate invocation with the platform's own retry\u002Fbackoff\u002FDLQ:",[533,2768,2771],{"className":535,"code":2769,"filename":2770,"language":538,"meta":539,"style":539},"import type { Context } from \"@heximon\u002Fruntime\";\nimport { Platform } from \"@heximon\u002Fruntime\";\nimport { OutboxRelay, type OutboxStore } from \"@heximon\u002Fintegration\";\nimport { CloudflareQueueIntegrationEventTransport } from \"@heximon\u002Fqueue\u002Fcloudflare\";\n\n\u002F**\n * A thin `OutboxRelay` subclass so the compiler reads its constructor directly. Types `target` concretely as\n * {@link CloudflareQueueIntegrationEventTransport} — a bare abstract `IntegrationEventTransport` param would\n * instead exact-match the producer transport bound below.\n *\u002F\nexport class AppOutboxRelay extends OutboxRelay {\n  public constructor(\n    store: OutboxStore,\n    target: CloudflareQueueIntegrationEventTransport,\n    context: Context,\n  ) {\n    super(store, target, context);\n  }\n}\n\n\u002F\u002F two entries in the module's `providers` array:\n{\n  provide: CloudflareQueueIntegrationEventTransport,\n  useFactory: (): CloudflareQueueIntegrationEventTransport =>\n    new CloudflareQueueIntegrationEventTransport(Platform.binding(\"OUTBOX_QUEUE\")),\n},\nAppOutboxRelay,\n","database.module.ts",[516,2772,2773,2795,2816,2842,2863,2867,2871,2875,2894,2899,2903,2917,2926,2937,2948,2959,2966,2986,2990,2994,2998,3003,3007,3018,3033,3064,3068],{"__ignoreMap":539},[543,2774,2775,2777,2779,2781,2783,2785,2787,2789,2791,2793],{"class":545,"line":546},[543,2776,550],{"class":549},[543,2778,749],{"class":549},[543,2780,554],{"class":553},[543,2782,1988],{"class":557},[543,2784,561],{"class":553},[543,2786,564],{"class":549},[543,2788,567],{"class":553},[543,2790,738],{"class":570},[543,2792,574],{"class":553},[543,2794,577],{"class":553},[543,2796,2797,2799,2801,2804,2806,2808,2810,2812,2814],{"class":545,"line":580},[543,2798,550],{"class":549},[543,2800,554],{"class":553},[543,2802,2803],{"class":557}," Platform",[543,2805,561],{"class":553},[543,2807,564],{"class":549},[543,2809,567],{"class":553},[543,2811,738],{"class":570},[543,2813,574],{"class":553},[543,2815,577],{"class":553},[543,2817,2818,2820,2822,2824,2826,2828,2830,2832,2834,2836,2838,2840],{"class":545,"line":587},[543,2819,550],{"class":549},[543,2821,554],{"class":553},[543,2823,2009],{"class":557},[543,2825,687],{"class":553},[543,2827,749],{"class":549},[543,2829,2016],{"class":557},[543,2831,561],{"class":553},[543,2833,564],{"class":549},[543,2835,567],{"class":553},[543,2837,571],{"class":570},[543,2839,574],{"class":553},[543,2841,577],{"class":553},[543,2843,2844,2846,2848,2851,2853,2855,2857,2859,2861],{"class":545,"line":604},[543,2845,550],{"class":549},[543,2847,554],{"class":553},[543,2849,2850],{"class":557}," CloudflareQueueIntegrationEventTransport",[543,2852,561],{"class":553},[543,2854,564],{"class":549},[543,2856,567],{"class":553},[543,2858,2757],{"class":570},[543,2860,574],{"class":553},[543,2862,577],{"class":553},[543,2864,2865],{"class":545,"line":622},[543,2866,584],{"emptyLinePlaceholder":583},[543,2868,2869],{"class":545,"line":636},[543,2870,2059],{"class":1042},[543,2872,2873],{"class":545,"line":650},[543,2874,2064],{"class":1042},[543,2876,2877,2880,2883,2887,2889,2891],{"class":545,"line":656},[543,2878,2879],{"class":1042}," * ",[543,2881,2882],{"class":549},"{@",[543,2884,2886],{"class":2885},"s6hCs","link",[543,2888,2850],{"class":859},[543,2890,1310],{"class":549},[543,2892,2893],{"class":1042}," — a bare abstract `IntegrationEventTransport` param would\n",[543,2895,2896],{"class":545,"line":661},[543,2897,2898],{"class":1042}," * instead exact-match the producer transport bound below.\n",[543,2900,2901],{"class":545,"line":886},[543,2902,2079],{"class":1042},[543,2904,2905,2907,2909,2911,2913,2915],{"class":545,"line":892},[543,2906,590],{"class":549},[543,2908,666],{"class":593},[543,2910,2088],{"class":597},[543,2912,672],{"class":593},[543,2914,2009],{"class":597},[543,2916,601],{"class":553},[543,2918,2919,2921,2923],{"class":545,"line":897},[543,2920,850],{"class":593},[543,2922,853],{"class":593},[543,2924,2925],{"class":553},"(\n",[543,2927,2928,2931,2933,2935],{"class":545,"line":956},[543,2929,2930],{"class":859},"    store",[543,2932,614],{"class":553},[543,2934,2016],{"class":597},[543,2936,1662],{"class":553},[543,2938,2939,2942,2944,2946],{"class":545,"line":1013},[543,2940,2941],{"class":859},"    target",[543,2943,614],{"class":553},[543,2945,2850],{"class":597},[543,2947,1662],{"class":553},[543,2949,2950,2953,2955,2957],{"class":545,"line":1034},[543,2951,2952],{"class":859},"    context",[543,2954,614],{"class":553},[543,2956,1988],{"class":597},[543,2958,1662],{"class":553},[543,2960,2961,2964],{"class":545,"line":1039},[543,2962,2963],{"class":553},"  )",[543,2965,601],{"class":553},[543,2967,2968,2970,2972,2974,2976,2978,2980,2982,2984],{"class":545,"line":1046},[543,2969,2136],{"class":557},[543,2971,856],{"class":610},[543,2973,2105],{"class":557},[543,2975,687],{"class":553},[543,2977,2114],{"class":557},[543,2979,687],{"class":553},[543,2981,2123],{"class":557},[543,2983,867],{"class":610},[543,2985,577],{"class":553},[543,2987,2988],{"class":545,"line":1101},[543,2989,889],{"class":553},[543,2991,2992],{"class":545,"line":1106},[543,2993,653],{"class":553},[543,2995,2996],{"class":545,"line":1130},[543,2997,584],{"emptyLinePlaceholder":583},[543,2999,3000],{"class":545,"line":1158},[543,3001,3002],{"class":1042},"\u002F\u002F two entries in the module's `providers` array:\n",[543,3004,3005],{"class":545,"line":1163},[543,3006,1266],{"class":553},[543,3008,3009,3012,3014,3016],{"class":545,"line":2536},[543,3010,3011],{"class":597},"  provide",[543,3013,614],{"class":553},[543,3015,2850],{"class":557},[543,3017,1662],{"class":553},[543,3019,3020,3023,3025,3028,3030],{"class":545,"line":2541},[543,3021,3022],{"class":597},"  useFactory",[543,3024,614],{"class":553},[543,3026,3027],{"class":553}," ():",[543,3029,2850],{"class":597},[543,3031,3032],{"class":593}," =>\n",[543,3034,3035,3038,3040,3042,3045,3047,3050,3052,3054,3057,3059,3062],{"class":545,"line":2552},[543,3036,3037],{"class":553},"    new",[543,3039,2850],{"class":984},[543,3041,856],{"class":610},[543,3043,3044],{"class":557},"Platform",[543,3046,976],{"class":553},[543,3048,3049],{"class":984},"binding",[543,3051,856],{"class":610},[543,3053,574],{"class":553},[543,3055,3056],{"class":570},"OUTBOX_QUEUE",[543,3058,574],{"class":553},[543,3060,3061],{"class":610},"))",[543,3063,1662],{"class":553},[543,3065,3066],{"class":545,"line":2564},[543,3067,1286],{"class":553},[543,3069,3070,3072],{"class":545,"line":2569},[543,3071,2166],{"class":557},[543,3073,1662],{"class":553},[499,3075,3076,3077,967,3080,3083,3084,3087,3088,3091],{},"On Vercel Functions, bind ",[516,3078,3079],{},"VercelQueueIntegrationEventTransport",[516,3081,3082],{},"@heximon\u002Fqueue\u002Fvercel",") — the same durable\npattern for a freezing platform, delivering onto the app's own Vercel Queue and drained by a separately generated\n",[516,3085,3086],{},"functions\u002Fqueues\u002Fconsumer.func",". See ",[508,3089,151],{"href":3090},"\u002Fdocs\u002Fcapabilities\u002Fbackground-jobs#production-transports","\nfor the full table of durable transports, including the Cloudflare Queues binding this relay uses.",[521,3093,3095],{"id":3094},"fan-out-across-services","Fan out across services",[499,3097,3098,3099,3102,3103,3106,3107,3110,3111,3114,3115,3118,3119,1707,3121,3124,3125,3128,3129,3131,3132,3134,3135,3137],{},"Everything above lives in ",[503,3100,3101],{},"one"," deploy. When the producer and the subscribers are ",[503,3104,3105],{},"separate deploys"," —\n",[516,3108,3109],{},"orders"," publishes ",[516,3112,3113],{},"order.placed",", a separately deployed ",[516,3116,3117],{},"billing"," service reacts — the promise stays the same\nshape: the producer calls ",[516,3120,518],{},[503,3122,3123],{},"once",", and every interested service gets its own delivery, however\nmany subscribers exist or whichever broker sits between them. Which transport carries that delivery (a\nper-service queue split, a native broadcast over Redis\u002FSNS, a Cloudflare Durable Object router, or a push broker\nfor a freezing function) is a ",[516,3126,3127],{},"crossService.transport"," choice in ",[516,3130,1740],{}," — the producer's ",[516,3133,1944],{},"\ncall and the consumer's ",[516,3136,1713],{}," never change.",[1701,3139,3140,3141,3144,3145,3147],{"type":1703},"Picking and wiring a fan-out leg is a deploy-topology concern — see\n",[508,3142,3143],{"href":352},"Cross-Service Events"," for the full comparison and the config for each\ntransport, and ",[508,3146,480],{"href":481}," for composing the outbox\nwith cross-service delivery in one relay pass.",[521,3149,3151],{"id":3150},"see-also","See also",[3153,3154,3155,3161,3166,3174,3179,3184,3195],"ul",{},[3156,3157,3158,3160],"li",{},[508,3159,228],{"href":229}," — the aggregates whose domain events are the usual source of an\nintegration event, and the bounded contexts that talk to each other only through this tier.",[3156,3162,3163,3165],{},[508,3164,146],{"href":147}," — the in-process and domain tiers below this one; start there for a side\neffect that stays inside one deploy.",[3156,3167,3168,3170,3171,3173],{},[508,3169,151],{"href":152}," — the transport integration events ride: ",[516,3172,705],{},",\nthe consumer stack, and the durable Drizzle\u002FSQS\u002FUpstash transports the outbox and cross-service legs build on.",[3156,3175,3176,3178],{},[508,3177,3143],{"href":352}," — the fan-out legs for reaching a separately deployed\nsubscriber: per-service-queue split, native broadcast, and push delivery for freezing platforms.",[3156,3180,3181,3183],{},[508,3182,480],{"href":481}," — the transactional-outbox recipe end to\nend, with the rollback proof.",[3156,3185,3186,3191,3192,3194],{},[508,3187,3190],{"href":3188,"rel":3189},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fladder\u002FL08-queue",[2732],"Example L08 — queue"," — a sign-up\ncontroller that publishes ",[516,3193,682],{}," and a welcome-email handler that consumes it off the in-memory\ntransport.",[3156,3196,3197,3200],{},[508,3198,2733],{"href":2730,"rel":3199},[2732],"\n— the transactional outbox composed with cross-service fan-out in one relay pass, and the crash-rollback proof.",[3202,3203,3204],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}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 .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .s6hCs, html code.shiki .s6hCs{--shiki-light:#9C3EDA;--shiki-light-font-style:italic;--shiki-default:#C792EA;--shiki-default-font-style:italic;--shiki-dark:#C792EA;--shiki-dark-font-style:italic}",{"title":539,"searchDepth":580,"depth":580,"links":3206},[3207,3208,3209,3210,3211,3214,3215],{"id":523,"depth":580,"text":524},{"id":698,"depth":580,"text":699},{"id":1319,"depth":580,"text":1320},{"id":1735,"depth":580,"text":1736},{"id":1864,"depth":580,"text":1865,"children":3212},[3213],{"id":2738,"depth":587,"text":2739},{"id":3094,"depth":580,"text":3095},{"id":3150,"depth":580,"text":3151},"Cross-context and cross-service events with IntegrationEvent producers, IntegrationEventHandler consumers, and the transactional outbox (OutboxStore, OutboxRelay, OutboxIntegrationEventTransport).","md",null,{},{"icon":246},{"title":243,"description":3216},"YqJqyeHgyLmnsLTR7kLXaG3uhO_qLC1tdeFdPoZmD08",[3224,3226],{"title":238,"path":239,"stem":240,"description":3225,"icon":241,"children":-1},"A collection-like persistence boundary with save, getById, getAll, and a zero-codegen EntityQuery, swappable behind an abstract Repository token, with optimistic-concurrency ConcurrencyError.",{"title":248,"path":249,"stem":250,"description":3227,"icon":251,"children":-1},"SagaTimer, TimeoutHandler, DurableTimer, DurableTimerStore, NodeDurableTimer, DrizzleDurableTimerStore, durableTimerColumns, SagaPlugin — durable one-shot deadlines that commit atomically with saga state.",1783300761903]