[{"data":1,"prerenderedAt":1828},["ShallowReactive",2],{"navigation_docs":3,"-docs-recipes-health-probes-and-a-nightly-job":493,"-docs-recipes-health-probes-and-a-nightly-job-surround":1823},[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":449,"body":495,"description":1816,"extension":1817,"links":1818,"meta":1819,"navigation":1820,"path":450,"seo":1821,"stem":451,"__hash__":1822},"docs\u002Fdocs\u002F09.recipes\u002F06.health-probes-and-a-nightly-job.md",{"type":496,"value":497,"toc":1808},"minimark",[498,519,524,537,933,942,957,961,972,1203,1210,1235,1273,1277,1285,1479,1487,1505,1509,1519,1699,1705,1724,1728,1743,1755,1759,1804],[499,500,501,502,506,507,510,511,514,515,518],"p",{},"Two small operational pieces most services need on day one: a ",[503,504,505],"code",{},"\u002Fhealth"," + ",[503,508,509],{},"\u002Fready"," pair an orchestrator can\npoll, and a job that runs on a wall-clock schedule instead of waiting for a request. Neither needs a compiler\nplugin beyond the ones you already register for HTTP — ",[503,512,513],{},"@heximon\u002Fhealth"," never mounts routes itself, and\n",[503,516,517],{},"@heximon\u002Fschedule"," validates your cron expression at build time so a typo fails the compile, not a 3am page.",[520,521,523],"h2",{"id":522},"_1-expose-the-probes-over-your-own-controller","1. Expose the probes over your own controller",[499,525,526,528,529,532,533,536],{},[503,527,513],{}," discovers your ",[503,530,531],{},"HealthIndicator"," classes and aggregates them into an injectable\n",[503,534,535],{},"HealthRegistry"," — nothing more. You own the HTTP surface: paths, status codes, response shape.",[538,539,545],"pre",{"className":540,"code":541,"filename":542,"language":543,"meta":544,"style":544},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { type AggregatedHealthResult, HealthRegistry } from \"@heximon\u002Fhealth\";\nimport type { Controller, Get } from \"@heximon\u002Fhttp\";\n\nexport class HealthController implements Controller {\n  public constructor(private readonly health: HealthRegistry) {}\n\n  public live(_action: Get\u003C\"\u002Fhealth\">): { status: string } {\n    return { status: \"up\" };\n  }\n\n  public async ready(action: Get\u003C\"\u002Fready\">): Promise\u003CAggregatedHealthResult> {\n    const result = await this.health.checkAll();\n\n    if (result.status === \"down\") {\n      action.response.status = 503;\n    }\n\n    return result;\n  }\n}\n","src\u002Fhealth\u002Fhealth.controller.ts","ts","",[503,546,547,591,621,628,650,683,688,732,754,760,765,808,841,846,879,902,908,913,922,927],{"__ignoreMap":544},[548,549,552,556,560,563,567,570,573,576,579,582,585,588],"span",{"class":550,"line":551},"line",1,[548,553,555],{"class":554},"s7zQu","import",[548,557,559],{"class":558},"sMK4o"," {",[548,561,562],{"class":554}," type",[548,564,566],{"class":565},"sTEyZ"," AggregatedHealthResult",[548,568,569],{"class":558},",",[548,571,572],{"class":565}," HealthRegistry",[548,574,575],{"class":558}," }",[548,577,578],{"class":554}," from",[548,580,581],{"class":558}," \"",[548,583,513],{"class":584},"sfazB",[548,586,587],{"class":558},"\"",[548,589,590],{"class":558},";\n",[548,592,594,596,598,600,603,605,608,610,612,614,617,619],{"class":550,"line":593},2,[548,595,555],{"class":554},[548,597,562],{"class":554},[548,599,559],{"class":558},[548,601,602],{"class":565}," Controller",[548,604,569],{"class":558},[548,606,607],{"class":565}," Get",[548,609,575],{"class":558},[548,611,578],{"class":554},[548,613,581],{"class":558},[548,615,616],{"class":584},"@heximon\u002Fhttp",[548,618,587],{"class":558},[548,620,590],{"class":558},[548,622,624],{"class":550,"line":623},3,[548,625,627],{"emptyLinePlaceholder":626},true,"\n",[548,629,631,634,638,642,645,647],{"class":550,"line":630},4,[548,632,633],{"class":554},"export",[548,635,637],{"class":636},"spNyl"," class",[548,639,641],{"class":640},"sBMFI"," HealthController",[548,643,644],{"class":636}," implements",[548,646,602],{"class":640},[548,648,649],{"class":558}," {\n",[548,651,653,656,659,662,665,668,672,675,677,680],{"class":550,"line":652},5,[548,654,655],{"class":636},"  public",[548,657,658],{"class":636}," constructor",[548,660,661],{"class":558},"(",[548,663,664],{"class":636},"private",[548,666,667],{"class":636}," readonly",[548,669,671],{"class":670},"sHdIc"," health",[548,673,674],{"class":558},":",[548,676,572],{"class":640},[548,678,679],{"class":558},")",[548,681,682],{"class":558}," {}\n",[548,684,686],{"class":550,"line":685},6,[548,687,627],{"emptyLinePlaceholder":626},[548,689,691,693,697,699,702,704,706,709,711,713,715,718,720,723,725,728,730],{"class":550,"line":690},7,[548,692,655],{"class":636},[548,694,696],{"class":695},"swJcz"," live",[548,698,661],{"class":558},[548,700,701],{"class":670},"_action",[548,703,674],{"class":558},[548,705,607],{"class":640},[548,707,708],{"class":558},"\u003C",[548,710,587],{"class":558},[548,712,505],{"class":584},[548,714,587],{"class":558},[548,716,717],{"class":558},">):",[548,719,559],{"class":558},[548,721,722],{"class":695}," status",[548,724,674],{"class":558},[548,726,727],{"class":640}," string",[548,729,575],{"class":558},[548,731,649],{"class":558},[548,733,735,738,740,742,744,746,749,751],{"class":550,"line":734},8,[548,736,737],{"class":554},"    return",[548,739,559],{"class":558},[548,741,722],{"class":695},[548,743,674],{"class":558},[548,745,581],{"class":558},[548,747,748],{"class":584},"up",[548,750,587],{"class":558},[548,752,753],{"class":558}," };\n",[548,755,757],{"class":550,"line":756},9,[548,758,759],{"class":558},"  }\n",[548,761,763],{"class":550,"line":762},10,[548,764,627],{"emptyLinePlaceholder":626},[548,766,768,770,773,776,778,781,783,785,787,789,791,793,795,798,800,803,806],{"class":550,"line":767},11,[548,769,655],{"class":636},[548,771,772],{"class":636}," async",[548,774,775],{"class":695}," ready",[548,777,661],{"class":558},[548,779,780],{"class":670},"action",[548,782,674],{"class":558},[548,784,607],{"class":640},[548,786,708],{"class":558},[548,788,587],{"class":558},[548,790,509],{"class":584},[548,792,587],{"class":558},[548,794,717],{"class":558},[548,796,797],{"class":640}," Promise",[548,799,708],{"class":558},[548,801,802],{"class":640},"AggregatedHealthResult",[548,804,805],{"class":558},">",[548,807,649],{"class":558},[548,809,811,814,817,820,823,826,829,832,836,839],{"class":550,"line":810},12,[548,812,813],{"class":636},"    const",[548,815,816],{"class":565}," result",[548,818,819],{"class":558}," =",[548,821,822],{"class":554}," await",[548,824,825],{"class":558}," this.",[548,827,828],{"class":565},"health",[548,830,831],{"class":558},".",[548,833,835],{"class":834},"s2Zo4","checkAll",[548,837,838],{"class":695},"()",[548,840,590],{"class":558},[548,842,844],{"class":550,"line":843},13,[548,845,627],{"emptyLinePlaceholder":626},[548,847,849,852,855,858,860,863,866,868,871,873,876],{"class":550,"line":848},14,[548,850,851],{"class":554},"    if",[548,853,854],{"class":695}," (",[548,856,857],{"class":565},"result",[548,859,831],{"class":558},[548,861,862],{"class":565},"status",[548,864,865],{"class":558}," ===",[548,867,581],{"class":558},[548,869,870],{"class":584},"down",[548,872,587],{"class":558},[548,874,875],{"class":695},") ",[548,877,878],{"class":558},"{\n",[548,880,882,885,887,890,892,894,896,900],{"class":550,"line":881},15,[548,883,884],{"class":565},"      action",[548,886,831],{"class":558},[548,888,889],{"class":565},"response",[548,891,831],{"class":558},[548,893,862],{"class":565},[548,895,819],{"class":558},[548,897,899],{"class":898},"sbssI"," 503",[548,901,590],{"class":558},[548,903,905],{"class":550,"line":904},16,[548,906,907],{"class":558},"    }\n",[548,909,911],{"class":550,"line":910},17,[548,912,627],{"emptyLinePlaceholder":626},[548,914,916,918,920],{"class":550,"line":915},18,[548,917,737],{"class":554},[548,919,816],{"class":565},[548,921,590],{"class":558},[548,923,925],{"class":550,"line":924},19,[548,926,759],{"class":558},[548,928,930],{"class":550,"line":929},20,[548,931,932],{"class":558},"}\n",[499,934,935],{},[936,937,938,939,679],"em",{},"(Source: ",[503,940,941],{},"examples\u002Fflagship\u002Fpackages\u002Fapp\u002Fsrc\u002Fhealth\u002Fhealth.controller.ts",[499,943,944,946,947,949,950,952,953,956],{},[503,945,505],{}," returns immediately with no indicator run and no boot promise awaited — safe for a liveness probe\nthat fires while the app is still starting. ",[503,948,509],{}," runs every registered indicator and maps ",[503,951,870],{}," to ",[503,954,955],{},"503","\nso an orchestrator stops routing traffic there.",[520,958,960],{"id":959},"_2-register-the-shipped-indicators","2. Register the shipped indicators",[499,962,963,964,967,968,971],{},"List indicator classes under ",[503,965,966],{},"health: { indicators }"," — never in ",[503,969,970],{},"providers",", or the compiler treats them as\nplain injectables instead of routing them into the registry. The two shipped indicators are bare providers:\ntheir constructors are plain DI tokens, so the compiler recovers them straight from the package types.",[538,973,976],{"className":540,"code":974,"filename":975,"language":543,"meta":544,"style":544},"import { Module } from \"@heximon\u002Fruntime\";\nimport { DatabaseHealthIndicator } from \"@heximon\u002Fhealth\u002Fdatabase\";\nimport { StorageHealthIndicator } from \"@heximon\u002Fhealth\u002Fstorage\";\nimport { Storage } from \"@heximon\u002Fkv\";\nimport { Database } from \"@heximon\u002Fpersistence\";\nimport { HealthController } from \".\u002Fhealth.controller\";\n\nexport class HealthModule extends Module({\n  requires: [Database, Storage],\n  http: { controllers: [HealthController] },\n  health: { indicators: [DatabaseHealthIndicator, StorageHealthIndicator] },\n}) {}\n","src\u002Fhealth\u002Fhealth.module.ts",[503,977,978,1000,1022,1044,1066,1088,1109,1113,1131,1149,1169,1193],{"__ignoreMap":544},[548,979,980,982,984,987,989,991,993,996,998],{"class":550,"line":551},[548,981,555],{"class":554},[548,983,559],{"class":558},[548,985,986],{"class":565}," Module",[548,988,575],{"class":558},[548,990,578],{"class":554},[548,992,581],{"class":558},[548,994,995],{"class":584},"@heximon\u002Fruntime",[548,997,587],{"class":558},[548,999,590],{"class":558},[548,1001,1002,1004,1006,1009,1011,1013,1015,1018,1020],{"class":550,"line":593},[548,1003,555],{"class":554},[548,1005,559],{"class":558},[548,1007,1008],{"class":565}," DatabaseHealthIndicator",[548,1010,575],{"class":558},[548,1012,578],{"class":554},[548,1014,581],{"class":558},[548,1016,1017],{"class":584},"@heximon\u002Fhealth\u002Fdatabase",[548,1019,587],{"class":558},[548,1021,590],{"class":558},[548,1023,1024,1026,1028,1031,1033,1035,1037,1040,1042],{"class":550,"line":623},[548,1025,555],{"class":554},[548,1027,559],{"class":558},[548,1029,1030],{"class":565}," StorageHealthIndicator",[548,1032,575],{"class":558},[548,1034,578],{"class":554},[548,1036,581],{"class":558},[548,1038,1039],{"class":584},"@heximon\u002Fhealth\u002Fstorage",[548,1041,587],{"class":558},[548,1043,590],{"class":558},[548,1045,1046,1048,1050,1053,1055,1057,1059,1062,1064],{"class":550,"line":630},[548,1047,555],{"class":554},[548,1049,559],{"class":558},[548,1051,1052],{"class":565}," Storage",[548,1054,575],{"class":558},[548,1056,578],{"class":554},[548,1058,581],{"class":558},[548,1060,1061],{"class":584},"@heximon\u002Fkv",[548,1063,587],{"class":558},[548,1065,590],{"class":558},[548,1067,1068,1070,1072,1075,1077,1079,1081,1084,1086],{"class":550,"line":652},[548,1069,555],{"class":554},[548,1071,559],{"class":558},[548,1073,1074],{"class":565}," Database",[548,1076,575],{"class":558},[548,1078,578],{"class":554},[548,1080,581],{"class":558},[548,1082,1083],{"class":584},"@heximon\u002Fpersistence",[548,1085,587],{"class":558},[548,1087,590],{"class":558},[548,1089,1090,1092,1094,1096,1098,1100,1102,1105,1107],{"class":550,"line":685},[548,1091,555],{"class":554},[548,1093,559],{"class":558},[548,1095,641],{"class":565},[548,1097,575],{"class":558},[548,1099,578],{"class":554},[548,1101,581],{"class":558},[548,1103,1104],{"class":584},".\u002Fhealth.controller",[548,1106,587],{"class":558},[548,1108,590],{"class":558},[548,1110,1111],{"class":550,"line":690},[548,1112,627],{"emptyLinePlaceholder":626},[548,1114,1115,1117,1119,1122,1125,1127,1129],{"class":550,"line":734},[548,1116,633],{"class":554},[548,1118,637],{"class":636},[548,1120,1121],{"class":640}," HealthModule",[548,1123,1124],{"class":636}," extends",[548,1126,986],{"class":834},[548,1128,661],{"class":565},[548,1130,878],{"class":558},[548,1132,1133,1136,1138,1141,1143,1146],{"class":550,"line":756},[548,1134,1135],{"class":695},"  requires",[548,1137,674],{"class":558},[548,1139,1140],{"class":565}," [Database",[548,1142,569],{"class":558},[548,1144,1145],{"class":565}," Storage]",[548,1147,1148],{"class":558},",\n",[548,1150,1151,1154,1156,1158,1161,1163,1166],{"class":550,"line":762},[548,1152,1153],{"class":695},"  http",[548,1155,674],{"class":558},[548,1157,559],{"class":558},[548,1159,1160],{"class":695}," controllers",[548,1162,674],{"class":558},[548,1164,1165],{"class":565}," [HealthController] ",[548,1167,1168],{"class":558},"},\n",[548,1170,1171,1174,1176,1178,1181,1183,1186,1188,1191],{"class":550,"line":767},[548,1172,1173],{"class":695},"  health",[548,1175,674],{"class":558},[548,1177,559],{"class":558},[548,1179,1180],{"class":695}," indicators",[548,1182,674],{"class":558},[548,1184,1185],{"class":565}," [DatabaseHealthIndicator",[548,1187,569],{"class":558},[548,1189,1190],{"class":565}," StorageHealthIndicator] ",[548,1192,1168],{"class":558},[548,1194,1195,1198,1200],{"class":550,"line":810},[548,1196,1197],{"class":558},"}",[548,1199,875],{"class":565},[548,1201,1202],{"class":558},"{}\n",[499,1204,1205],{},[936,1206,938,1207,679],{},[503,1208,1209],{},"examples\u002Fflagship\u002Fpackages\u002Fapp\u002Fsrc\u002Fhealth\u002Fhealth.module.ts",[499,1211,1212,1215,1216,1219,1220,1222,1223,1226,1227,1230,1231,1234],{},[503,1213,1214],{},"DatabaseHealthIndicator"," pings the pool via an empty transaction; ",[503,1217,1218],{},"StorageHealthIndicator"," round-trips a\nsentinel key. Both inject an abstract port (",[503,1221,77],{},", ",[503,1224,1225],{},"Storage",") rather than a concrete class, which is why\nthis module lists them under ",[503,1228,1229],{},"requires"," — the app composing ",[503,1232,1233],{},"HealthModule"," must supply a satisfier for each.",[538,1236,1241],{"className":1237,"code":1238,"filename":1239,"language":1240,"meta":544,"style":544},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","curl http:\u002F\u002Flocalhost:3000\u002Fhealth\n# { \"status\": \"up\" }\n\ncurl http:\u002F\u002Flocalhost:3000\u002Fready\n# { \"status\": \"up\", \"checks\": { \"database\": { \"status\": \"up\" }, \"storage\": { \"status\": \"up\" } } }\n","terminal","bash",[503,1242,1243,1251,1257,1261,1268],{"__ignoreMap":544},[548,1244,1245,1248],{"class":550,"line":551},[548,1246,1247],{"class":640},"curl",[548,1249,1250],{"class":584}," http:\u002F\u002Flocalhost:3000\u002Fhealth\n",[548,1252,1253],{"class":550,"line":593},[548,1254,1256],{"class":1255},"sHwdD","# { \"status\": \"up\" }\n",[548,1258,1259],{"class":550,"line":623},[548,1260,627],{"emptyLinePlaceholder":626},[548,1262,1263,1265],{"class":550,"line":630},[548,1264,1247],{"class":640},[548,1266,1267],{"class":584}," http:\u002F\u002Flocalhost:3000\u002Fready\n",[548,1269,1270],{"class":550,"line":652},[548,1271,1272],{"class":1255},"# { \"status\": \"up\", \"checks\": { \"database\": { \"status\": \"up\" }, \"storage\": { \"status\": \"up\" } } }\n",[520,1274,1276],{"id":1275},"_3-declare-the-nightly-job","3. Declare the nightly job",[499,1278,1279,1280,1284],{},"A scheduled job is a class whose cron expression is a ",[1281,1282,1283],"strong",{},"string-literal type argument"," — the compiler reads it\nas the dispatch key at build time, so a malformed cron is a build error, not a job that silently never fires.",[538,1286,1289],{"className":540,"code":1287,"filename":1288,"language":543,"meta":544,"style":544},"import type { ScheduledHandler } from \"@heximon\u002Fschedule\";\nimport { ReportsRepository } from \".\u002Freports.repository\";\n\nexport class NightlyReport implements ScheduledHandler\u003C\"0 3 * * *\", { timezone: \"UTC\"; name: \"nightly-report\" }> {\n  public constructor(private readonly reports: ReportsRepository) {}\n\n  public handle(scheduledAt: Date): void {\n    this.reports.record(scheduledAt);\n  }\n}\n","nightly-report.ts",[503,1290,1291,1314,1336,1340,1398,1421,1425,1450,1471,1475],{"__ignoreMap":544},[548,1292,1293,1295,1297,1299,1302,1304,1306,1308,1310,1312],{"class":550,"line":551},[548,1294,555],{"class":554},[548,1296,562],{"class":554},[548,1298,559],{"class":558},[548,1300,1301],{"class":565}," ScheduledHandler",[548,1303,575],{"class":558},[548,1305,578],{"class":554},[548,1307,581],{"class":558},[548,1309,517],{"class":584},[548,1311,587],{"class":558},[548,1313,590],{"class":558},[548,1315,1316,1318,1320,1323,1325,1327,1329,1332,1334],{"class":550,"line":593},[548,1317,555],{"class":554},[548,1319,559],{"class":558},[548,1321,1322],{"class":565}," ReportsRepository",[548,1324,575],{"class":558},[548,1326,578],{"class":554},[548,1328,581],{"class":558},[548,1330,1331],{"class":584},".\u002Freports.repository",[548,1333,587],{"class":558},[548,1335,590],{"class":558},[548,1337,1338],{"class":550,"line":623},[548,1339,627],{"emptyLinePlaceholder":626},[548,1341,1342,1344,1346,1349,1351,1353,1355,1357,1360,1362,1364,1366,1369,1371,1373,1376,1378,1381,1384,1386,1388,1391,1393,1396],{"class":550,"line":630},[548,1343,633],{"class":554},[548,1345,637],{"class":636},[548,1347,1348],{"class":640}," NightlyReport",[548,1350,644],{"class":636},[548,1352,1301],{"class":640},[548,1354,708],{"class":558},[548,1356,587],{"class":558},[548,1358,1359],{"class":584},"0 3 * * *",[548,1361,587],{"class":558},[548,1363,569],{"class":558},[548,1365,559],{"class":558},[548,1367,1368],{"class":695}," timezone",[548,1370,674],{"class":558},[548,1372,581],{"class":558},[548,1374,1375],{"class":584},"UTC",[548,1377,587],{"class":558},[548,1379,1380],{"class":558},";",[548,1382,1383],{"class":695}," name",[548,1385,674],{"class":558},[548,1387,581],{"class":558},[548,1389,1390],{"class":584},"nightly-report",[548,1392,587],{"class":558},[548,1394,1395],{"class":558}," }>",[548,1397,649],{"class":558},[548,1399,1400,1402,1404,1406,1408,1410,1413,1415,1417,1419],{"class":550,"line":652},[548,1401,655],{"class":636},[548,1403,658],{"class":636},[548,1405,661],{"class":558},[548,1407,664],{"class":636},[548,1409,667],{"class":636},[548,1411,1412],{"class":670}," reports",[548,1414,674],{"class":558},[548,1416,1322],{"class":640},[548,1418,679],{"class":558},[548,1420,682],{"class":558},[548,1422,1423],{"class":550,"line":685},[548,1424,627],{"emptyLinePlaceholder":626},[548,1426,1427,1429,1432,1434,1437,1439,1442,1445,1448],{"class":550,"line":690},[548,1428,655],{"class":636},[548,1430,1431],{"class":695}," handle",[548,1433,661],{"class":558},[548,1435,1436],{"class":670},"scheduledAt",[548,1438,674],{"class":558},[548,1440,1441],{"class":640}," Date",[548,1443,1444],{"class":558},"):",[548,1446,1447],{"class":640}," void",[548,1449,649],{"class":558},[548,1451,1452,1455,1458,1460,1463,1465,1467,1469],{"class":550,"line":734},[548,1453,1454],{"class":558},"    this.",[548,1456,1457],{"class":565},"reports",[548,1459,831],{"class":558},[548,1461,1462],{"class":834},"record",[548,1464,661],{"class":695},[548,1466,1436],{"class":565},[548,1468,679],{"class":695},[548,1470,590],{"class":558},[548,1472,1473],{"class":550,"line":756},[548,1474,759],{"class":558},[548,1476,1477],{"class":550,"line":762},[548,1478,932],{"class":558},[499,1480,1481],{},[936,1482,938,1483,1486],{},[503,1484,1485],{},"docs\u002Fcontent\u002Fdocs\u002F03.capabilities\u002F04.scheduled-jobs.md",", already-verified fence)",[499,1488,1489,1492,1493,1496,1497,1500,1501,1504],{},[503,1490,1491],{},"handle"," always receives the platform's scheduled time, never ",[503,1494,1495],{},"Date.now()"," — a late or replayed fire still\ncomputes against the intended wall-clock instant. ",[503,1498,1499],{},"{ timezone, name }"," ride the second type argument;\n",[503,1502,1503],{},"timezone"," defaults to UTC.",[520,1506,1508],{"id":1507},"_4-list-it-under-the-schedule-namespace","4. List it under the schedule namespace",[499,1510,1511,1512,1515,1516,1518],{},"Same rule as indicators: the handler goes under ",[503,1513,1514],{},"schedule: { handlers }",", never ",[503,1517,970],{}," — that's what\nroutes it to its cron instead of constructing it as a plain injectable.",[538,1520,1523],{"className":540,"code":1521,"filename":1522,"language":543,"meta":544,"style":544},"import { Module } from \"@heximon\u002Fruntime\";\nimport { NightlyReport } from \".\u002Fnightly-report\";\nimport { ReportsController } from \".\u002Freports.controller\";\nimport { ReportsRepository } from \".\u002Freports.repository\";\n\nexport class ReportsModule extends Module({\n  providers: [ReportsRepository],\n  http: {\n    controllers: [ReportsController],\n  },\n  schedule: {\n    handlers: [NightlyReport],\n  },\n}) {}\n","reports.module.ts",[503,1524,1525,1545,1566,1588,1608,1612,1629,1641,1649,1661,1666,1675,1687,1691],{"__ignoreMap":544},[548,1526,1527,1529,1531,1533,1535,1537,1539,1541,1543],{"class":550,"line":551},[548,1528,555],{"class":554},[548,1530,559],{"class":558},[548,1532,986],{"class":565},[548,1534,575],{"class":558},[548,1536,578],{"class":554},[548,1538,581],{"class":558},[548,1540,995],{"class":584},[548,1542,587],{"class":558},[548,1544,590],{"class":558},[548,1546,1547,1549,1551,1553,1555,1557,1559,1562,1564],{"class":550,"line":593},[548,1548,555],{"class":554},[548,1550,559],{"class":558},[548,1552,1348],{"class":565},[548,1554,575],{"class":558},[548,1556,578],{"class":554},[548,1558,581],{"class":558},[548,1560,1561],{"class":584},".\u002Fnightly-report",[548,1563,587],{"class":558},[548,1565,590],{"class":558},[548,1567,1568,1570,1572,1575,1577,1579,1581,1584,1586],{"class":550,"line":623},[548,1569,555],{"class":554},[548,1571,559],{"class":558},[548,1573,1574],{"class":565}," ReportsController",[548,1576,575],{"class":558},[548,1578,578],{"class":554},[548,1580,581],{"class":558},[548,1582,1583],{"class":584},".\u002Freports.controller",[548,1585,587],{"class":558},[548,1587,590],{"class":558},[548,1589,1590,1592,1594,1596,1598,1600,1602,1604,1606],{"class":550,"line":630},[548,1591,555],{"class":554},[548,1593,559],{"class":558},[548,1595,1322],{"class":565},[548,1597,575],{"class":558},[548,1599,578],{"class":554},[548,1601,581],{"class":558},[548,1603,1331],{"class":584},[548,1605,587],{"class":558},[548,1607,590],{"class":558},[548,1609,1610],{"class":550,"line":652},[548,1611,627],{"emptyLinePlaceholder":626},[548,1613,1614,1616,1618,1621,1623,1625,1627],{"class":550,"line":685},[548,1615,633],{"class":554},[548,1617,637],{"class":636},[548,1619,1620],{"class":640}," ReportsModule",[548,1622,1124],{"class":636},[548,1624,986],{"class":834},[548,1626,661],{"class":565},[548,1628,878],{"class":558},[548,1630,1631,1634,1636,1639],{"class":550,"line":690},[548,1632,1633],{"class":695},"  providers",[548,1635,674],{"class":558},[548,1637,1638],{"class":565}," [ReportsRepository]",[548,1640,1148],{"class":558},[548,1642,1643,1645,1647],{"class":550,"line":734},[548,1644,1153],{"class":695},[548,1646,674],{"class":558},[548,1648,649],{"class":558},[548,1650,1651,1654,1656,1659],{"class":550,"line":756},[548,1652,1653],{"class":695},"    controllers",[548,1655,674],{"class":558},[548,1657,1658],{"class":565}," [ReportsController]",[548,1660,1148],{"class":558},[548,1662,1663],{"class":550,"line":762},[548,1664,1665],{"class":558},"  },\n",[548,1667,1668,1671,1673],{"class":550,"line":767},[548,1669,1670],{"class":695},"  schedule",[548,1672,674],{"class":558},[548,1674,649],{"class":558},[548,1676,1677,1680,1682,1685],{"class":550,"line":810},[548,1678,1679],{"class":695},"    handlers",[548,1681,674],{"class":558},[548,1683,1684],{"class":565}," [NightlyReport]",[548,1686,1148],{"class":558},[548,1688,1689],{"class":550,"line":843},[548,1690,1665],{"class":558},[548,1692,1693,1695,1697],{"class":550,"line":848},[548,1694,1197],{"class":558},[548,1696,875],{"class":565},[548,1698,1202],{"class":558},[499,1700,1701],{},[936,1702,938,1703,1486],{},[503,1704,1485],{},[499,1706,1707,1708,1711,1712,1715,1716,1719,1720,1723],{},"On Node, ",[503,1709,1710],{},"NodeScheduleDriver"," self-starts one process-local timer per schedule at boot — no host wiring, and\nit's the tier ",[503,1713,1714],{},"pnpm dev"," runs under. Overlap is skip-if-running, so a slow nightly job never stacks two runs.\nOn a Cloudflare deploy, the same cron list is emitted into ",[503,1717,1718],{},"wrangler.json","'s ",[503,1721,1722],{},"triggers.crons"," instead, and the\nplatform's own clock fires your handler.",[520,1725,1727],{"id":1726},"pitfalls","Pitfalls",[499,1729,1730,1738,1739,1742],{},[1281,1731,1732,1733,1735,1736,831],{},"Registering a handler under ",[503,1734,970],{}," instead of ",[503,1737,1514],{}," It still constructs — DI\ndoesn't complain — but nothing ever calls it. The compiler only routes classes to their cron when they're\nlisted under the ",[503,1740,1741],{},"schedule"," namespace.",[499,1744,1745,1748,1749,1751,1752,1754],{},[1281,1746,1747],{},"Expecting exactly-once delivery."," Scheduled dispatch is at-least-once on Cloudflare and best-effort on Node\n(a process down across the tick misses that run). Key ",[503,1750,1491],{}," off ",[503,1753,1436],{}," — stable across replays of the\nsame tick — if the job needs to be idempotent.",[520,1756,1758],{"id":1757},"see-also","See also",[1760,1761,1762,1783,1788],"ul",{},[1763,1764,1765,1768,1769,1771,1772,1775,1776,1775,1779,1782],"li",{},[1766,1767,175],"a",{"href":176}," — writing your own ",[503,1770,531],{},", the ",[503,1773,1774],{},"Up","\u002F",[503,1777,1778],{},"Degraded",[503,1780,1781],{},"Down","\nstatus table, and customizing a shipped indicator with a delegating wrapper.",[1763,1784,1785,1787],{},[1766,1786,156],{"href":157}," — per-host firing semantics, the Cloudflare cron-trigger\npath, and multi-replica considerations.",[1763,1789,1790,1798,1799,506,1801,1803],{},[1766,1791,1795],{"href":1792,"rel":1793},"https:\u002F\u002Fgithub.com\u002Fheximon\u002Fheximon\u002Ftree\u002Fmain\u002Fexamples\u002Fflagship",[1794],"nofollow",[1281,1796,1797],{},"Flagship Health \u002F Readiness"," — the\nrunnable ",[503,1800,1214],{},[503,1802,1218],{}," behind these two probes.",[1805,1806,1807],"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 .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 .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":544,"searchDepth":593,"depth":593,"links":1809},[1810,1811,1812,1813,1814,1815],{"id":522,"depth":593,"text":523},{"id":959,"depth":593,"text":960},{"id":1275,"depth":593,"text":1276},{"id":1507,"depth":593,"text":1508},{"id":1726,"depth":593,"text":1727},{"id":1757,"depth":593,"text":1758},"Expose liveness and readiness over an app-owned controller with an injected HealthRegistry, and run a nightly report on a build-time-validated cron with ScheduledHandler.","md",null,{},{"icon":178},{"title":449,"description":1816},"9PAwFV_J5sJtCFkuyqvQ3wcFo1igYiaQyABVL7gvaxk",[1824,1826],{"title":445,"path":446,"stem":447,"description":1825,"icon":65,"children":-1},"Gate an admin-only surface with JWTAuthMiddleware for authentication and AuthContext.isAllowed for a scope-guarded 401\u002F403\u002F200 ladder on inline routes.",{"title":453,"path":454,"stem":455,"description":1827,"icon":80,"children":-1},"A typed CRUD feature end-to-end — a zod-validated body, an inline-route Controller, a plain repository over Drizzle, boot-time table creation, and an in-process test.",1783300761903]