[{"data":1,"prerenderedAt":2408},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Fcore-concepts\u002Fdiscovery":176,"\u002Fdocs\u002Fcore-concepts\u002Fdiscovery-surround":2403},[4,21,86,158],{"title":5,"path":6,"stem":7,"children":8,"status":11,"icon":20},"Getting Started","\u002Fdocs\u002Fgetting-started","1.docs\u002F1.getting-started\u002F1.index",[9,12,16],{"title":10,"path":6,"stem":7,"status":11},"Introduction",null,{"title":13,"path":14,"stem":15,"status":11},"Installation","\u002Fdocs\u002Fgetting-started\u002Finstallation","1.docs\u002F1.getting-started\u002F2.installation",{"title":17,"path":18,"stem":19,"status":11},"Quick Start","\u002Fdocs\u002Fgetting-started\u002Fquick-start","1.docs\u002F1.getting-started\u002F3.quick-start",false,{"title":22,"path":23,"stem":24,"children":25,"status":11,"icon":20},"Core Concepts","\u002Fdocs\u002Fcore-concepts","1.docs\u002F2.core-concepts\u002F1.index",[26,28,32,36,46,50,54,58,62,66,70,74,78,82],{"title":27,"path":23,"stem":24,"status":11},"Overview",{"title":29,"path":30,"stem":31,"status":11},"Response","\u002Fdocs\u002Fcore-concepts\u002Fresponse","1.docs\u002F2.core-concepts\u002F10.response",{"title":33,"path":34,"stem":35,"status":11},"Testing","\u002Fdocs\u002Fcore-concepts\u002Ftesting","1.docs\u002F2.core-concepts\u002F12.testing",{"title":37,"path":38,"stem":39,"children":40,"status":11,"icon":20,"defaultOpen":20},"Decorators","\u002Fdocs\u002Fcore-concepts\u002Fdecorators","1.docs\u002F2.core-concepts\u002F13.decorators\u002F1.index",[41,42],{"title":27,"path":38,"stem":39,"status":11},{"title":43,"path":44,"stem":45,"status":11},"Custom","\u002Fdocs\u002Fcore-concepts\u002Fdecorators\u002Fcustom","1.docs\u002F2.core-concepts\u002F13.decorators\u002F2.custom",{"title":47,"path":48,"stem":49,"status":11},"Discovery Service","\u002Fdocs\u002Fcore-concepts\u002Fdiscovery","1.docs\u002F2.core-concepts\u002F14.discovery",{"title":51,"path":52,"stem":53,"status":11},"Application Lifecycle","\u002Fdocs\u002Fcore-concepts\u002Fapp-lifecycle","1.docs\u002F2.core-concepts\u002F15.app-lifecycle",{"title":55,"path":56,"stem":57,"status":11},"Controllers","\u002Fdocs\u002Fcore-concepts\u002Fcontrollers","1.docs\u002F2.core-concepts\u002F2.controllers",{"title":59,"path":60,"stem":61,"status":11},"Routing","\u002Fdocs\u002Fcore-concepts\u002Frouting","1.docs\u002F2.core-concepts\u002F3.routing",{"title":63,"path":64,"stem":65,"status":11},"Providers","\u002Fdocs\u002Fcore-concepts\u002Fproviders","1.docs\u002F2.core-concepts\u002F4.providers",{"title":67,"path":68,"stem":69,"status":11},"Modules","\u002Fdocs\u002Fcore-concepts\u002Fmodules","1.docs\u002F2.core-concepts\u002F5.modules",{"title":71,"path":72,"stem":73,"status":11},"Configuration","\u002Fdocs\u002Fcore-concepts\u002Fconfiguration","1.docs\u002F2.core-concepts\u002F6.configuration",{"title":75,"path":76,"stem":77,"status":11},"Middleware","\u002Fdocs\u002Fcore-concepts\u002Fmiddleware","1.docs\u002F2.core-concepts\u002F7.middleware",{"title":79,"path":80,"stem":81,"status":11},"Guards","\u002Fdocs\u002Fcore-concepts\u002Fguards","1.docs\u002F2.core-concepts\u002F8.guards",{"title":83,"path":84,"stem":85,"status":11},"Exceptions","\u002Fdocs\u002Fcore-concepts\u002Fexceptions","1.docs\u002F2.core-concepts\u002F9.exceptions",{"title":87,"path":88,"stem":89,"children":90,"status":11,"icon":20},"Packages","\u002Fdocs\u002Fpackages","1.docs\u002F3.packages\u002F1.index",[91,92,97,108,112,130,134,138,142,146,150,154],{"title":27,"path":88,"stem":89,"status":11},{"title":93,"path":94,"stem":95,"status":96},"CLI","\u002Fdocs\u002Fpackages\u002Fcli","1.docs\u002F3.packages\u002F10.cli","experimental",{"title":98,"path":99,"stem":100,"children":101,"status":11,"icon":20,"defaultOpen":20},"Events","\u002Fdocs\u002Fpackages\u002Fmessaging","1.docs\u002F3.packages\u002F11.messaging\u002F1.index",[102,104],{"title":27,"path":99,"stem":100,"status":103},"beta",{"title":105,"path":106,"stem":107,"status":96},"Redis","\u002Fdocs\u002Fpackages\u002Fmessaging\u002Fredis","1.docs\u002F3.packages\u002F11.messaging\u002F2.redis",{"title":109,"path":110,"stem":111,"status":103},"Serve Static","\u002Fdocs\u002Fpackages\u002Fserve-static","1.docs\u002F3.packages\u002F12.serve-static",{"title":113,"path":114,"stem":115,"children":116,"status":11,"icon":20,"defaultOpen":20},"Auth","\u002Fdocs\u002Fpackages\u002Fauth","1.docs\u002F3.packages\u002F2.auth\u002F1.index",[117,118,122,126],{"title":27,"path":114,"stem":115,"status":103},{"title":119,"path":120,"stem":121,"status":103},"JWT Provider","\u002Fdocs\u002Fpackages\u002Fauth\u002Fjwt","1.docs\u002F3.packages\u002F2.auth\u002F2.jwt",{"title":123,"path":124,"stem":125,"status":103},"Local Provider","\u002Fdocs\u002Fpackages\u002Fauth\u002Flocal","1.docs\u002F3.packages\u002F2.auth\u002F3.local",{"title":127,"path":128,"stem":129,"status":96},"OAuth2 Provider","\u002Fdocs\u002Fpackages\u002Fauth\u002Foauth2","1.docs\u002F3.packages\u002F2.auth\u002F4.oauth2",{"title":131,"path":132,"stem":133,"status":103},"JWT","\u002Fdocs\u002Fpackages\u002Fjwt","1.docs\u002F3.packages\u002F3.jwt",{"title":135,"path":136,"stem":137,"status":103},"Drizzle","\u002Fdocs\u002Fpackages\u002Fdrizzle","1.docs\u002F3.packages\u002F4.drizzle",{"title":139,"path":140,"stem":141,"status":103},"Papr","\u002Fdocs\u002Fpackages\u002Fpapr","1.docs\u002F3.packages\u002F5.papr",{"title":143,"path":144,"stem":145,"status":103},"Mongoose","\u002Fdocs\u002Fpackages\u002Fmongoose","1.docs\u002F3.packages\u002F6.mongoose",{"title":147,"path":148,"stem":149,"status":103},"Swagger","\u002Fdocs\u002Fpackages\u002Fswagger","1.docs\u002F3.packages\u002F7.swagger",{"title":151,"path":152,"stem":153,"status":103},"Node Server","\u002Fdocs\u002Fpackages\u002Fnode-server","1.docs\u002F3.packages\u002F8.node-server",{"title":155,"path":156,"stem":157,"status":103},"uWS Server","\u002Fdocs\u002Fpackages\u002Fuws-server","1.docs\u002F3.packages\u002F9.uws-server",{"title":159,"path":160,"stem":161,"children":162,"status":11,"icon":20},"Roadmap","\u002Fdocs\u002Froadmap","1.docs\u002F4.roadmap\u002F1.index",[163,164,168,172],{"title":27,"path":160,"stem":161,"status":11},{"title":165,"path":166,"stem":167,"status":11},"Short term (0-3 months)","\u002Fdocs\u002Froadmap\u002Fshort-term","1.docs\u002F4.roadmap\u002F2.short-term",{"title":169,"path":170,"stem":171,"status":11},"Mid term (3-9 months)","\u002Fdocs\u002Froadmap\u002Fmid-term","1.docs\u002F4.roadmap\u002F3.mid-term",{"title":173,"path":174,"stem":175,"status":11},"Long term (9-12+ months)","\u002Fdocs\u002Froadmap\u002Flong-term","1.docs\u002F4.roadmap\u002F4.long-term",{"id":177,"title":47,"body":178,"description":2398,"extension":2399,"meta":2400,"navigation":369,"path":48,"seo":2401,"status":11,"stem":49,"__hash__":2402},"docs\u002F1.docs\u002F2.core-concepts\u002F14.discovery.md",{"type":179,"value":180,"toc":2388},"minimark",[181,205,219,224,227,284,298,302,311,479,532,535,542,616,626,630,655,681,684,926,937,941,960,963,1038,1042,1056,1881,1911,1915,1927,2197,2206,2210,2219,2244,2263,2273,2330,2335,2339,2384],[182,183,184,188,189,192,193,196,197,200,201,204],"p",{},[185,186,187],"code",{},"DiscoveryService"," lets a provider walk the DI container at startup and find every method decorated with a given symbol - across every other provider, controller, and guard in the app. You write ",[185,190,191],{},"@Cron('* * * * *')",", ",[185,194,195],{},"@QueueHandler('emails')",", or ",[185,198,199],{},"@On('user.created')"," on a method, and a discovery-aware service finds it automatically. No manual ",[185,202,203],{},"register([...])"," list, no central registry to keep in sync.",[182,206,207,208,211,212,215,216,218],{},"This is the same mechanism the framework uses internally for ",[185,209,210],{},"@Get","\u002F",[185,213,214],{},"@Post"," route discovery on controllers - ",[185,217,187],{}," exposes it as a public API so userland packages and your own code can build the same pattern.",[220,221,223],"h2",{"id":222},"mental-model","Mental model",[182,225,226],{},"The whole story is three steps:",[228,229,230,242,264],"ol",{},[231,232,233,237,238,241],"li",{},[234,235,236],"strong",{},"A custom method decorator writes metadata"," to ",[185,239,240],{},"Symbol.metadata[KEY]"," on the class at definition time. Each method that carries the decorator pushes one entry into an array under the same symbol key.",[231,243,244,251,252,192,255,259,260,263],{},[234,245,246,247,250],{},"The framework calls ",[185,248,249],{},"onReady()"," on every singleton"," during ",[185,253,254],{},"app.init()",[256,257,258],"em",{},"after"," every ",[185,261,262],{},"onInit()"," has completed. By this point every provider in the container has a fully-initialized instance, regardless of registration order.",[231,265,266,276,277,279,280,283],{},[234,267,268,269,272,273],{},"A singleton holding ",[185,270,271],{},"inject(DiscoveryService)"," calls ",[185,274,275],{},"getMethodsWithMeta(KEY)"," in its ",[185,278,249],{},". It receives a flat list of ",[185,281,282],{},"{ instance, methodName, metadata }"," tuples - one per decorated method across the whole container - ready to bind handlers, register subscriptions, or whatever the discovery-aware service needs to do.",[182,285,286,287,293,294,297],{},"This is exactly how ",[288,289,290],"a",{"href":99},[185,291,292],{},"@miiajs\u002Fmessaging"," wires up ",[185,295,296],{},"@On"," handlers under the hood, and it's how any future scheduler, queue worker, or metrics package will work too.",[220,299,301],{"id":300},"discoveryservice-api","DiscoveryService API",[182,303,304,305,307,308,310],{},"Inject ",[185,306,187],{}," like any other provider, then call one of its two methods inside an ",[185,309,249],{}," hook.",[312,313,318],"pre",{"className":314,"code":315,"language":316,"meta":317,"style":317},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { DiscoveryService, Injectable, inject } from '@miiajs\u002Fcore'\n\n@Injectable()\nclass MyDiscoveryService {\n  private discovery = inject(DiscoveryService)\n\n  async onReady() {\n    const singletons = this.discovery.getSingletons()\n    \u002F\u002F ... or scan for a specific decorator key\n  }\n}\n","typescript","",[185,319,320,364,371,384,398,416,421,435,460,467,473],{"__ignoreMap":317},[321,322,325,329,333,337,340,343,345,348,351,354,357,361],"span",{"class":323,"line":324},"line",1,[321,326,328],{"class":327},"s7zQu","import",[321,330,332],{"class":331},"sMK4o"," {",[321,334,336],{"class":335},"sTEyZ"," DiscoveryService",[321,338,339],{"class":331},",",[321,341,342],{"class":335}," Injectable",[321,344,339],{"class":331},[321,346,347],{"class":335}," inject",[321,349,350],{"class":331}," }",[321,352,353],{"class":327}," from",[321,355,356],{"class":331}," '",[321,358,360],{"class":359},"sfazB","@miiajs\u002Fcore",[321,362,363],{"class":331},"'\n",[321,365,367],{"class":323,"line":366},2,[321,368,370],{"emptyLinePlaceholder":369},true,"\n",[321,372,374,377,381],{"class":323,"line":373},3,[321,375,376],{"class":331},"@",[321,378,380],{"class":379},"s2Zo4","Injectable",[321,382,383],{"class":335},"()\n",[321,385,387,391,395],{"class":323,"line":386},4,[321,388,390],{"class":389},"spNyl","class",[321,392,394],{"class":393},"sBMFI"," MyDiscoveryService",[321,396,397],{"class":331}," {\n",[321,399,401,404,408,411,413],{"class":323,"line":400},5,[321,402,403],{"class":389},"  private",[321,405,407],{"class":406},"swJcz"," discovery",[321,409,410],{"class":331}," =",[321,412,347],{"class":406},[321,414,415],{"class":335},"(DiscoveryService)\n",[321,417,419],{"class":323,"line":418},6,[321,420,370],{"emptyLinePlaceholder":369},[321,422,424,427,430,433],{"class":323,"line":423},7,[321,425,426],{"class":389},"  async",[321,428,429],{"class":406}," onReady",[321,431,432],{"class":331},"()",[321,434,397],{"class":331},[321,436,438,441,444,446,449,452,455,458],{"class":323,"line":437},8,[321,439,440],{"class":389},"    const",[321,442,443],{"class":335}," singletons",[321,445,410],{"class":331},[321,447,448],{"class":331}," this.",[321,450,451],{"class":335},"discovery",[321,453,454],{"class":331},".",[321,456,457],{"class":379},"getSingletons",[321,459,383],{"class":406},[321,461,463],{"class":323,"line":462},9,[321,464,466],{"class":465},"sHwdD","    \u002F\u002F ... or scan for a specific decorator key\n",[321,468,470],{"class":323,"line":469},10,[321,471,472],{"class":331},"  }\n",[321,474,476],{"class":323,"line":475},11,[321,477,478],{"class":331},"}\n",[480,481,482,498],"table",{},[483,484,485],"thead",{},[486,487,488,492,495],"tr",{},[489,490,491],"th",{},"Method",[489,493,494],{},"Returns",[489,496,497],{},"Description",[499,500,501,517],"tbody",{},[486,502,503,509,514],{},[504,505,506],"td",{},[185,507,508],{},"getSingletons()",[504,510,511],{},[185,512,513],{},"Array\u003C{ ctor, instance }>",[504,515,516],{},"Every singleton currently in the container - providers, controllers, and guards that have been instantiated. Useful for raw inspection.",[486,518,519,524,529],{},[504,520,521],{},[185,522,523],{},"getMethodsWithMeta\u003CT>(key)",[504,525,526],{},[185,527,528],{},"DiscoveredMethod\u003CT>[]",[504,530,531],{},"Scans every singleton for the given metadata key and returns one entry per discovered method. The primary API for ambient discovery.",[182,533,534],{},"Transient and request-scoped providers are deliberately excluded - they have no stable instance to bind a handler to. If you need discovery on those, restructure as a singleton.",[182,536,537,538,541],{},"The shape returned by ",[185,539,540],{},"getMethodsWithMeta()",":",[312,543,545],{"className":314,"code":544,"language":316,"meta":317,"style":317},"interface DiscoveredMethod\u003CT extends DiscoverableMethodMeta> {\n  instance: object\n  ctor: Constructor\n  methodName: string\n  metadata: T\n}\n",[185,546,547,572,582,592,602,612],{"__ignoreMap":317},[321,548,549,552,555,558,561,564,567,570],{"class":323,"line":324},[321,550,551],{"class":389},"interface",[321,553,554],{"class":393}," DiscoveredMethod",[321,556,557],{"class":331},"\u003C",[321,559,560],{"class":393},"T",[321,562,563],{"class":389}," extends",[321,565,566],{"class":393}," DiscoverableMethodMeta",[321,568,569],{"class":331},">",[321,571,397],{"class":331},[321,573,574,577,579],{"class":323,"line":366},[321,575,576],{"class":406},"  instance",[321,578,541],{"class":331},[321,580,581],{"class":393}," object\n",[321,583,584,587,589],{"class":323,"line":373},[321,585,586],{"class":406},"  ctor",[321,588,541],{"class":331},[321,590,591],{"class":393}," Constructor\n",[321,593,594,597,599],{"class":323,"line":386},[321,595,596],{"class":406},"  methodName",[321,598,541],{"class":331},[321,600,601],{"class":393}," string\n",[321,603,604,607,609],{"class":323,"line":400},[321,605,606],{"class":406},"  metadata",[321,608,541],{"class":331},[321,610,611],{"class":393}," T\n",[321,613,614],{"class":323,"line":418},[321,615,478],{"class":331},[182,617,618,619,622,623,454],{},"Bind a handler with ",[185,620,621],{},"(instance as any)[methodName].bind(instance)"," and you have a callable function that preserves ",[185,624,625],{},"this",[220,627,629],{"id":628},"the-discoverablemethodmeta-convention","The DiscoverableMethodMeta convention",[182,631,632,634,635,638,639,650,651,654],{},[185,633,540],{}," doesn't know the shape of ",[256,636,637],{},"your"," metadata - it relies on a single contract: ",[234,640,641,642,645,646,649],{},"the metadata stored under ",[185,643,644],{},"key"," must be an array of objects, and each object must include a ",[185,647,648],{},"handlerName: string"," field",". The framework uses ",[185,652,653],{},"handlerName"," to bind the discovered metadata back to the actual method on the instance.",[312,656,658],{"className":314,"code":657,"language":316,"meta":317,"style":317},"interface DiscoverableMethodMeta {\n  handlerName: string\n}\n",[185,659,660,668,677],{"__ignoreMap":317},[321,661,662,664,666],{"class":323,"line":324},[321,663,551],{"class":389},[321,665,566],{"class":393},[321,667,397],{"class":331},[321,669,670,673,675],{"class":323,"line":366},[321,671,672],{"class":406},"  handlerName",[321,674,541],{"class":331},[321,676,601],{"class":393},[321,678,679],{"class":323,"line":373},[321,680,478],{"class":331},[182,682,683],{},"Everything else in the metadata object is yours to define. A minimal custom decorator looks like this:",[312,685,687],{"className":314,"code":686,"language":316,"meta":317,"style":317},"import { createMethodDecorator, pushMeta } from '@miiajs\u002Fcore'\n\nconst METRIC = Symbol('metric')\n\ninterface MetricMeta {\n  handlerName: string\n  name: string\n}\n\nexport const Metric = createMethodDecorator\u003C[name: string]>(\n  (_target, ctx, name) => {\n    pushMeta(ctx.metadata!, METRIC, {\n      handlerName: ctx.name as string,\n      name,\n    } satisfies MetricMeta)\n  },\n)\n",[185,688,689,713,717,745,749,758,766,775,779,783,819,846,872,894,902,915,921],{"__ignoreMap":317},[321,690,691,693,695,698,700,703,705,707,709,711],{"class":323,"line":324},[321,692,328],{"class":327},[321,694,332],{"class":331},[321,696,697],{"class":335}," createMethodDecorator",[321,699,339],{"class":331},[321,701,702],{"class":335}," pushMeta",[321,704,350],{"class":331},[321,706,353],{"class":327},[321,708,356],{"class":331},[321,710,360],{"class":359},[321,712,363],{"class":331},[321,714,715],{"class":323,"line":366},[321,716,370],{"emptyLinePlaceholder":369},[321,718,719,722,725,728,731,734,737,740,742],{"class":323,"line":373},[321,720,721],{"class":389},"const",[321,723,724],{"class":335}," METRIC ",[321,726,727],{"class":331},"=",[321,729,730],{"class":379}," Symbol",[321,732,733],{"class":335},"(",[321,735,736],{"class":331},"'",[321,738,739],{"class":359},"metric",[321,741,736],{"class":331},[321,743,744],{"class":335},")\n",[321,746,747],{"class":323,"line":386},[321,748,370],{"emptyLinePlaceholder":369},[321,750,751,753,756],{"class":323,"line":400},[321,752,551],{"class":389},[321,754,755],{"class":393}," MetricMeta",[321,757,397],{"class":331},[321,759,760,762,764],{"class":323,"line":418},[321,761,672],{"class":406},[321,763,541],{"class":331},[321,765,601],{"class":393},[321,767,768,771,773],{"class":323,"line":423},[321,769,770],{"class":406},"  name",[321,772,541],{"class":331},[321,774,601],{"class":393},[321,776,777],{"class":323,"line":437},[321,778,478],{"class":331},[321,780,781],{"class":323,"line":462},[321,782,370],{"emptyLinePlaceholder":369},[321,784,785,788,791,794,796,798,800,803,806,808,811,814,816],{"class":323,"line":469},[321,786,787],{"class":327},"export",[321,789,790],{"class":389}," const",[321,792,793],{"class":335}," Metric ",[321,795,727],{"class":331},[321,797,697],{"class":379},[321,799,557],{"class":331},[321,801,802],{"class":335},"[",[321,804,805],{"class":393},"name",[321,807,541],{"class":331},[321,809,810],{"class":393}," string",[321,812,813],{"class":335},"]",[321,815,569],{"class":331},[321,817,818],{"class":335},"(\n",[321,820,821,824,828,830,833,835,838,841,844],{"class":323,"line":475},[321,822,823],{"class":331},"  (",[321,825,827],{"class":826},"sHdIc","_target",[321,829,339],{"class":331},[321,831,832],{"class":826}," ctx",[321,834,339],{"class":331},[321,836,837],{"class":826}," name",[321,839,840],{"class":331},")",[321,842,843],{"class":389}," =>",[321,845,397],{"class":331},[321,847,849,852,854,857,859,862,865,868,870],{"class":323,"line":848},12,[321,850,851],{"class":379},"    pushMeta",[321,853,733],{"class":406},[321,855,856],{"class":335},"ctx",[321,858,454],{"class":331},[321,860,861],{"class":335},"metadata",[321,863,864],{"class":331},"!,",[321,866,867],{"class":335}," METRIC",[321,869,339],{"class":331},[321,871,397],{"class":331},[321,873,875,878,880,882,884,886,889,891],{"class":323,"line":874},13,[321,876,877],{"class":406},"      handlerName",[321,879,541],{"class":331},[321,881,832],{"class":335},[321,883,454],{"class":331},[321,885,805],{"class":335},[321,887,888],{"class":327}," as",[321,890,810],{"class":393},[321,892,893],{"class":331},",\n",[321,895,897,900],{"class":323,"line":896},14,[321,898,899],{"class":335},"      name",[321,901,893],{"class":331},[321,903,905,908,911,913],{"class":323,"line":904},15,[321,906,907],{"class":331},"    }",[321,909,910],{"class":327}," satisfies",[321,912,755],{"class":393},[321,914,744],{"class":406},[321,916,918],{"class":323,"line":917},16,[321,919,920],{"class":331},"  },\n",[321,922,924],{"class":323,"line":923},17,[321,925,744],{"class":335},[182,927,928,929,932,933,936],{},"Use ",[185,930,931],{},"ctx.name"," from the TC39 decorator context to capture the method name automatically. The user just writes ",[185,934,935],{},"@Metric('signups') async onSignup() {}"," and the convention is satisfied.",[220,938,940],{"id":939},"the-onready-lifecycle-hook","The onReady lifecycle hook",[182,942,943,945,946,950,951,953,954,956,957,959],{},[185,944,249],{}," is the third ",[288,947,949],{"href":948},"\u002Fdocs\u002Fcore-concepts\u002Fproviders#lifecycle-hooks","provider lifecycle hook",", called after every ",[185,952,262],{}," has completed. It exists specifically to give discovery-aware services a safe scanning point - by the time any ",[185,955,249],{}," runs, every singleton in the container is fully initialized, so a single sweep through ",[185,958,540],{}," will find every decorated method without race conditions.",[182,961,962],{},"Two caveats worth internalising:",[964,965,966,1022],"ul",{},[231,967,968,980,981,984,985,988,989,991,992,995,996,998,999,1002,1003,1006,1007,1009,1010,1013,1014,1017,1018,1021],{},[234,969,970,971,974,975,977,978,454],{},"Don't ",[185,972,973],{},"emit"," or trigger work from inside ",[185,976,262],{}," or ",[185,979,249],{}," The three-phase ordering only guarantees that ",[256,982,983],{},"all"," singletons exist before ",[256,986,987],{},"any"," ",[185,990,249],{}," runs - it does ",[234,993,994],{},"not"," guarantee an order between ",[185,997,249],{}," calls themselves. If your ",[185,1000,1001],{},"MyDiscoveryService.onReady()"," runs before ",[185,1004,1005],{},"OtherService.onReady()"," and ",[185,1008,1005],{}," synchronously fires an event, the subscription ",[185,1011,1012],{},"MyDiscoveryService"," is supposed to wire might not be installed yet. Lifecycle hooks should ",[256,1015,1016],{},"scan and subscribe",", not ",[256,1019,1020],{},"trigger work",". Real work happens later - in request handlers, timers, or external triggers.",[231,1023,1024,1030,1031,1006,1034,1037],{},[234,1025,1026,1029],{},[185,1027,1028],{},"onReady"," is singleton-only",", same as ",[185,1032,1033],{},"onInit",[185,1035,1036],{},"onDestroy",". Transient and request-scoped providers do not run lifecycle hooks at all.",[220,1039,1041],{"id":1040},"complete-example-a-tiny-event-emitter","Complete example: a tiny event emitter",[182,1043,1044,1045,1047,1048,1050,1051,1055],{},"Here's the entire ",[185,1046,187],{}," pattern in one example: a 30-line in-process event emitter built on pure ",[185,1049,360],{},", with no ecosystem dependencies. This is exactly the pattern ",[288,1052,1053],{"href":99},[185,1054,292],{}," implements - with retry, DLQ, and pluggable transports layered on top.",[312,1057,1059],{"className":314,"code":1058,"language":316,"meta":317,"style":317},"import {\n  createMethodDecorator,\n  DiscoveryService,\n  Injectable,\n  inject,\n  Module,\n  pushMeta,\n  type DiscoverableMethodMeta,\n} from '@miiajs\u002Fcore'\n\n\u002F\u002F 1. The decorator\nconst FIRE = Symbol('fire')\n\ninterface FireMeta extends DiscoverableMethodMeta {\n  topic: string\n}\n\nconst Fire = createMethodDecorator\u003C[topic: string]>((_target, ctx, topic) => {\n  pushMeta(ctx.metadata!, FIRE, {\n    handlerName: ctx.name as string,\n    topic,\n  } satisfies FireMeta)\n})\n\n\u002F\u002F 2. The discovery-aware bus\ntype Handler = (payload: unknown) => void | Promise\u003Cvoid>\n\n@Injectable()\nclass MiniEventBus {\n  private discovery = inject(DiscoveryService)\n  private handlers = new Map\u003Cstring, Handler[]>()\n\n  async onReady() {\n    for (const { instance, methodName, metadata } of this.discovery.getMethodsWithMeta\u003CFireMeta>(FIRE)) {\n      const list = this.handlers.get(metadata.topic) ?? []\n      list.push(((instance as any)[methodName] as Handler).bind(instance))\n      this.handlers.set(metadata.topic, list)\n    }\n  }\n\n  async emit(topic: string, payload: unknown) {\n    for (const fn of this.handlers.get(topic) ?? []) await fn(payload)\n  }\n}\n\n\u002F\u002F 3. A provider with a discovered handler\n@Injectable()\nclass NotificationService {\n  @Fire('user.created')\n  async sendWelcome(payload: unknown) {\n    console.log('welcome:', payload)\n  }\n}\n\n\u002F\u002F 4. Wire everything up\n@Module({ providers: [MiniEventBus, NotificationService] })\nclass AppModule {}\n",[185,1060,1061,1067,1074,1081,1088,1095,1102,1109,1118,1131,1135,1140,1162,1166,1179,1188,1192,1196,1244,1266,1286,1294,1306,1313,1318,1324,1367,1372,1381,1391,1404,1436,1441,1452,1509,1547,1597,1624,1630,1635,1640,1669,1713,1718,1723,1728,1734,1743,1753,1773,1793,1819,1824,1829,1834,1840,1870],{"__ignoreMap":317},[321,1062,1063,1065],{"class":323,"line":324},[321,1064,328],{"class":327},[321,1066,397],{"class":331},[321,1068,1069,1072],{"class":323,"line":366},[321,1070,1071],{"class":335},"  createMethodDecorator",[321,1073,893],{"class":331},[321,1075,1076,1079],{"class":323,"line":373},[321,1077,1078],{"class":335},"  DiscoveryService",[321,1080,893],{"class":331},[321,1082,1083,1086],{"class":323,"line":386},[321,1084,1085],{"class":335},"  Injectable",[321,1087,893],{"class":331},[321,1089,1090,1093],{"class":323,"line":400},[321,1091,1092],{"class":335},"  inject",[321,1094,893],{"class":331},[321,1096,1097,1100],{"class":323,"line":418},[321,1098,1099],{"class":335},"  Module",[321,1101,893],{"class":331},[321,1103,1104,1107],{"class":323,"line":423},[321,1105,1106],{"class":335},"  pushMeta",[321,1108,893],{"class":331},[321,1110,1111,1114,1116],{"class":323,"line":437},[321,1112,1113],{"class":327},"  type",[321,1115,566],{"class":335},[321,1117,893],{"class":331},[321,1119,1120,1123,1125,1127,1129],{"class":323,"line":462},[321,1121,1122],{"class":331},"}",[321,1124,353],{"class":327},[321,1126,356],{"class":331},[321,1128,360],{"class":359},[321,1130,363],{"class":331},[321,1132,1133],{"class":323,"line":469},[321,1134,370],{"emptyLinePlaceholder":369},[321,1136,1137],{"class":323,"line":475},[321,1138,1139],{"class":465},"\u002F\u002F 1. The decorator\n",[321,1141,1142,1144,1147,1149,1151,1153,1155,1158,1160],{"class":323,"line":848},[321,1143,721],{"class":389},[321,1145,1146],{"class":335}," FIRE ",[321,1148,727],{"class":331},[321,1150,730],{"class":379},[321,1152,733],{"class":335},[321,1154,736],{"class":331},[321,1156,1157],{"class":359},"fire",[321,1159,736],{"class":331},[321,1161,744],{"class":335},[321,1163,1164],{"class":323,"line":874},[321,1165,370],{"emptyLinePlaceholder":369},[321,1167,1168,1170,1173,1175,1177],{"class":323,"line":896},[321,1169,551],{"class":389},[321,1171,1172],{"class":393}," FireMeta",[321,1174,563],{"class":389},[321,1176,566],{"class":393},[321,1178,397],{"class":331},[321,1180,1181,1184,1186],{"class":323,"line":904},[321,1182,1183],{"class":406},"  topic",[321,1185,541],{"class":331},[321,1187,601],{"class":393},[321,1189,1190],{"class":323,"line":917},[321,1191,478],{"class":331},[321,1193,1194],{"class":323,"line":923},[321,1195,370],{"emptyLinePlaceholder":369},[321,1197,1199,1201,1204,1206,1208,1210,1212,1215,1217,1219,1221,1223,1225,1227,1229,1231,1233,1235,1238,1240,1242],{"class":323,"line":1198},18,[321,1200,721],{"class":389},[321,1202,1203],{"class":335}," Fire ",[321,1205,727],{"class":331},[321,1207,697],{"class":379},[321,1209,557],{"class":331},[321,1211,802],{"class":335},[321,1213,1214],{"class":393},"topic",[321,1216,541],{"class":331},[321,1218,810],{"class":393},[321,1220,813],{"class":335},[321,1222,569],{"class":331},[321,1224,733],{"class":335},[321,1226,733],{"class":331},[321,1228,827],{"class":826},[321,1230,339],{"class":331},[321,1232,832],{"class":826},[321,1234,339],{"class":331},[321,1236,1237],{"class":826}," topic",[321,1239,840],{"class":331},[321,1241,843],{"class":389},[321,1243,397],{"class":331},[321,1245,1247,1249,1251,1253,1255,1257,1259,1262,1264],{"class":323,"line":1246},19,[321,1248,1106],{"class":379},[321,1250,733],{"class":406},[321,1252,856],{"class":335},[321,1254,454],{"class":331},[321,1256,861],{"class":335},[321,1258,864],{"class":331},[321,1260,1261],{"class":335}," FIRE",[321,1263,339],{"class":331},[321,1265,397],{"class":331},[321,1267,1269,1272,1274,1276,1278,1280,1282,1284],{"class":323,"line":1268},20,[321,1270,1271],{"class":406},"    handlerName",[321,1273,541],{"class":331},[321,1275,832],{"class":335},[321,1277,454],{"class":331},[321,1279,805],{"class":335},[321,1281,888],{"class":327},[321,1283,810],{"class":393},[321,1285,893],{"class":331},[321,1287,1289,1292],{"class":323,"line":1288},21,[321,1290,1291],{"class":335},"    topic",[321,1293,893],{"class":331},[321,1295,1297,1300,1302,1304],{"class":323,"line":1296},22,[321,1298,1299],{"class":331},"  }",[321,1301,910],{"class":327},[321,1303,1172],{"class":393},[321,1305,744],{"class":406},[321,1307,1309,1311],{"class":323,"line":1308},23,[321,1310,1122],{"class":331},[321,1312,744],{"class":335},[321,1314,1316],{"class":323,"line":1315},24,[321,1317,370],{"emptyLinePlaceholder":369},[321,1319,1321],{"class":323,"line":1320},25,[321,1322,1323],{"class":465},"\u002F\u002F 2. The discovery-aware bus\n",[321,1325,1327,1330,1333,1335,1338,1341,1343,1346,1348,1350,1353,1356,1359,1361,1364],{"class":323,"line":1326},26,[321,1328,1329],{"class":389},"type",[321,1331,1332],{"class":393}," Handler",[321,1334,410],{"class":331},[321,1336,1337],{"class":331}," (",[321,1339,1340],{"class":826},"payload",[321,1342,541],{"class":331},[321,1344,1345],{"class":393}," unknown",[321,1347,840],{"class":331},[321,1349,843],{"class":389},[321,1351,1352],{"class":393}," void",[321,1354,1355],{"class":331}," |",[321,1357,1358],{"class":393}," Promise",[321,1360,557],{"class":331},[321,1362,1363],{"class":393},"void",[321,1365,1366],{"class":331},">\n",[321,1368,1370],{"class":323,"line":1369},27,[321,1371,370],{"emptyLinePlaceholder":369},[321,1373,1375,1377,1379],{"class":323,"line":1374},28,[321,1376,376],{"class":335},[321,1378,380],{"class":393},[321,1380,383],{"class":331},[321,1382,1384,1386,1389],{"class":323,"line":1383},29,[321,1385,390],{"class":389},[321,1387,1388],{"class":393}," MiniEventBus",[321,1390,397],{"class":331},[321,1392,1394,1396,1398,1400,1402],{"class":323,"line":1393},30,[321,1395,403],{"class":389},[321,1397,407],{"class":406},[321,1399,410],{"class":331},[321,1401,347],{"class":406},[321,1403,415],{"class":335},[321,1405,1407,1409,1412,1414,1417,1420,1422,1425,1427,1429,1432,1434],{"class":323,"line":1406},31,[321,1408,403],{"class":389},[321,1410,1411],{"class":406}," handlers",[321,1413,410],{"class":331},[321,1415,1416],{"class":331}," new",[321,1418,1419],{"class":406}," Map",[321,1421,557],{"class":331},[321,1423,1424],{"class":393},"string",[321,1426,339],{"class":331},[321,1428,1332],{"class":393},[321,1430,1431],{"class":335},"[]",[321,1433,569],{"class":331},[321,1435,383],{"class":335},[321,1437,1439],{"class":323,"line":1438},32,[321,1440,370],{"emptyLinePlaceholder":369},[321,1442,1444,1446,1448,1450],{"class":323,"line":1443},33,[321,1445,426],{"class":389},[321,1447,429],{"class":406},[321,1449,432],{"class":331},[321,1451,397],{"class":331},[321,1453,1455,1458,1460,1462,1464,1467,1469,1472,1474,1477,1479,1482,1484,1486,1488,1491,1493,1496,1498,1500,1503,1506],{"class":323,"line":1454},34,[321,1456,1457],{"class":327},"    for",[321,1459,1337],{"class":406},[321,1461,721],{"class":389},[321,1463,332],{"class":331},[321,1465,1466],{"class":335}," instance",[321,1468,339],{"class":331},[321,1470,1471],{"class":335}," methodName",[321,1473,339],{"class":331},[321,1475,1476],{"class":335}," metadata",[321,1478,350],{"class":331},[321,1480,1481],{"class":331}," of",[321,1483,448],{"class":331},[321,1485,451],{"class":335},[321,1487,454],{"class":331},[321,1489,1490],{"class":379},"getMethodsWithMeta",[321,1492,557],{"class":331},[321,1494,1495],{"class":393},"FireMeta",[321,1497,569],{"class":331},[321,1499,733],{"class":406},[321,1501,1502],{"class":335},"FIRE",[321,1504,1505],{"class":406},")) ",[321,1507,1508],{"class":331},"{\n",[321,1510,1512,1515,1518,1520,1522,1525,1527,1530,1532,1534,1536,1538,1541,1544],{"class":323,"line":1511},35,[321,1513,1514],{"class":389},"      const",[321,1516,1517],{"class":335}," list",[321,1519,410],{"class":331},[321,1521,448],{"class":331},[321,1523,1524],{"class":335},"handlers",[321,1526,454],{"class":331},[321,1528,1529],{"class":379},"get",[321,1531,733],{"class":406},[321,1533,861],{"class":335},[321,1535,454],{"class":331},[321,1537,1214],{"class":335},[321,1539,1540],{"class":406},") ",[321,1542,1543],{"class":331},"??",[321,1545,1546],{"class":406}," []\n",[321,1548,1550,1553,1555,1558,1561,1564,1566,1569,1572,1575,1578,1581,1583,1585,1587,1590,1592,1594],{"class":323,"line":1549},36,[321,1551,1552],{"class":335},"      list",[321,1554,454],{"class":331},[321,1556,1557],{"class":379},"push",[321,1559,1560],{"class":406},"(((",[321,1562,1563],{"class":335},"instance",[321,1565,888],{"class":327},[321,1567,1568],{"class":393}," any",[321,1570,1571],{"class":406},")[",[321,1573,1574],{"class":335},"methodName",[321,1576,1577],{"class":406},"] ",[321,1579,1580],{"class":327},"as",[321,1582,1332],{"class":393},[321,1584,840],{"class":406},[321,1586,454],{"class":331},[321,1588,1589],{"class":379},"bind",[321,1591,733],{"class":406},[321,1593,1563],{"class":335},[321,1595,1596],{"class":406},"))\n",[321,1598,1600,1603,1605,1607,1610,1612,1614,1616,1618,1620,1622],{"class":323,"line":1599},37,[321,1601,1602],{"class":331},"      this.",[321,1604,1524],{"class":335},[321,1606,454],{"class":331},[321,1608,1609],{"class":379},"set",[321,1611,733],{"class":406},[321,1613,861],{"class":335},[321,1615,454],{"class":331},[321,1617,1214],{"class":335},[321,1619,339],{"class":331},[321,1621,1517],{"class":335},[321,1623,744],{"class":406},[321,1625,1627],{"class":323,"line":1626},38,[321,1628,1629],{"class":331},"    }\n",[321,1631,1633],{"class":323,"line":1632},39,[321,1634,472],{"class":331},[321,1636,1638],{"class":323,"line":1637},40,[321,1639,370],{"emptyLinePlaceholder":369},[321,1641,1643,1645,1648,1650,1652,1654,1656,1658,1661,1663,1665,1667],{"class":323,"line":1642},41,[321,1644,426],{"class":389},[321,1646,1647],{"class":406}," emit",[321,1649,733],{"class":331},[321,1651,1214],{"class":826},[321,1653,541],{"class":331},[321,1655,810],{"class":393},[321,1657,339],{"class":331},[321,1659,1660],{"class":826}," payload",[321,1662,541],{"class":331},[321,1664,1345],{"class":393},[321,1666,840],{"class":331},[321,1668,397],{"class":331},[321,1670,1672,1674,1676,1678,1681,1683,1685,1687,1689,1691,1693,1695,1697,1699,1702,1705,1707,1709,1711],{"class":323,"line":1671},42,[321,1673,1457],{"class":327},[321,1675,1337],{"class":406},[321,1677,721],{"class":389},[321,1679,1680],{"class":335}," fn",[321,1682,1481],{"class":331},[321,1684,448],{"class":331},[321,1686,1524],{"class":335},[321,1688,454],{"class":331},[321,1690,1529],{"class":379},[321,1692,733],{"class":406},[321,1694,1214],{"class":335},[321,1696,1540],{"class":406},[321,1698,1543],{"class":331},[321,1700,1701],{"class":406}," []) ",[321,1703,1704],{"class":327},"await",[321,1706,1680],{"class":379},[321,1708,733],{"class":406},[321,1710,1340],{"class":335},[321,1712,744],{"class":406},[321,1714,1716],{"class":323,"line":1715},43,[321,1717,472],{"class":331},[321,1719,1721],{"class":323,"line":1720},44,[321,1722,478],{"class":331},[321,1724,1726],{"class":323,"line":1725},45,[321,1727,370],{"emptyLinePlaceholder":369},[321,1729,1731],{"class":323,"line":1730},46,[321,1732,1733],{"class":465},"\u002F\u002F 3. A provider with a discovered handler\n",[321,1735,1737,1739,1741],{"class":323,"line":1736},47,[321,1738,376],{"class":331},[321,1740,380],{"class":379},[321,1742,383],{"class":335},[321,1744,1746,1748,1751],{"class":323,"line":1745},48,[321,1747,390],{"class":389},[321,1749,1750],{"class":393}," NotificationService",[321,1752,397],{"class":331},[321,1754,1756,1759,1762,1764,1766,1769,1771],{"class":323,"line":1755},49,[321,1757,1758],{"class":331},"  @",[321,1760,1761],{"class":379},"Fire",[321,1763,733],{"class":335},[321,1765,736],{"class":331},[321,1767,1768],{"class":359},"user.created",[321,1770,736],{"class":331},[321,1772,744],{"class":335},[321,1774,1776,1778,1781,1783,1785,1787,1789,1791],{"class":323,"line":1775},50,[321,1777,426],{"class":389},[321,1779,1780],{"class":406}," sendWelcome",[321,1782,733],{"class":331},[321,1784,1340],{"class":826},[321,1786,541],{"class":331},[321,1788,1345],{"class":393},[321,1790,840],{"class":331},[321,1792,397],{"class":331},[321,1794,1796,1799,1801,1804,1806,1808,1811,1813,1815,1817],{"class":323,"line":1795},51,[321,1797,1798],{"class":335},"    console",[321,1800,454],{"class":331},[321,1802,1803],{"class":379},"log",[321,1805,733],{"class":406},[321,1807,736],{"class":331},[321,1809,1810],{"class":359},"welcome:",[321,1812,736],{"class":331},[321,1814,339],{"class":331},[321,1816,1660],{"class":335},[321,1818,744],{"class":406},[321,1820,1822],{"class":323,"line":1821},52,[321,1823,472],{"class":331},[321,1825,1827],{"class":323,"line":1826},53,[321,1828,478],{"class":331},[321,1830,1832],{"class":323,"line":1831},54,[321,1833,370],{"emptyLinePlaceholder":369},[321,1835,1837],{"class":323,"line":1836},55,[321,1838,1839],{"class":465},"\u002F\u002F 4. Wire everything up\n",[321,1841,1843,1845,1848,1850,1853,1856,1858,1861,1863,1866,1868],{"class":323,"line":1842},56,[321,1844,376],{"class":331},[321,1846,1847],{"class":379},"Module",[321,1849,733],{"class":335},[321,1851,1852],{"class":331},"{",[321,1854,1855],{"class":406}," providers",[321,1857,541],{"class":331},[321,1859,1860],{"class":335}," [MiniEventBus",[321,1862,339],{"class":331},[321,1864,1865],{"class":335}," NotificationService] ",[321,1867,1122],{"class":331},[321,1869,744],{"class":335},[321,1871,1873,1875,1878],{"class":323,"line":1872},57,[321,1874,390],{"class":389},[321,1876,1877],{"class":393}," AppModule",[321,1879,1880],{"class":331}," {}\n",[182,1882,1883,1884,1886,1887,1890,1891,1894,1895,1898,1899,1902,1903,1906,1907,1910],{},"After ",[185,1885,254],{}," returns, ",[185,1888,1889],{},"MiniEventBus.onReady()"," has already scanned every singleton, found ",[185,1892,1893],{},"NotificationService.sendWelcome"," via its ",[185,1896,1897],{},"@Fire('user.created')"," metadata, and subscribed it to the ",[185,1900,1901],{},"'user.created'"," topic. Calling ",[185,1904,1905],{},"bus.emit('user.created', { id: 1 })"," from anywhere in the app fires the handler. No registration list, no manual wiring - every ",[185,1908,1909],{},"@Fire","-decorated method on every singleton just works.",[220,1912,1914],{"id":1913},"discovering-controllers","Discovering controllers",[182,1916,1917,1919,1920,1923,1924,1926],{},[185,1918,187],{}," also powers class-level discovery. Every controller in the app carries a ",[185,1921,1922],{},"RESOLVED_PREFIX"," metadata entry - the fully-joined path under which its routes are served, including the prefix of every module it was imported through. Filter ",[185,1925,508],{}," by presence of that key and you have a live map of controllers to their routing prefixes.",[312,1928,1930],{"className":314,"code":1929,"language":316,"meta":317,"style":317},"import {\n  DiscoveryService,\n  Injectable,\n  RESOLVED_PREFIX,\n  Router,\n  getMeta,\n  inject,\n  type Constructor,\n} from '@miiajs\u002Fcore'\n\n@Injectable()\nexport class RouteInspector {\n  private discovery = inject(DiscoveryService)\n  private router = inject(Router)\n\n  async onReady() {\n    for (const { ctor } of this.discovery.getSingletons()) {\n      const prefix = getMeta\u003Cstring>(ctor, RESOLVED_PREFIX)\n      if (prefix === undefined) continue\n      console.log(`${(ctor as Constructor).name} -> \u002F${prefix}`)\n    }\n  }\n}\n",[185,1931,1932,1938,1944,1950,1957,1964,1971,1977,1986,1998,2002,2010,2022,2034,2048,2052,2062,2092,2122,2143,2185,2189,2193],{"__ignoreMap":317},[321,1933,1934,1936],{"class":323,"line":324},[321,1935,328],{"class":327},[321,1937,397],{"class":331},[321,1939,1940,1942],{"class":323,"line":366},[321,1941,1078],{"class":335},[321,1943,893],{"class":331},[321,1945,1946,1948],{"class":323,"line":373},[321,1947,1085],{"class":335},[321,1949,893],{"class":331},[321,1951,1952,1955],{"class":323,"line":386},[321,1953,1954],{"class":335},"  RESOLVED_PREFIX",[321,1956,893],{"class":331},[321,1958,1959,1962],{"class":323,"line":400},[321,1960,1961],{"class":335},"  Router",[321,1963,893],{"class":331},[321,1965,1966,1969],{"class":323,"line":418},[321,1967,1968],{"class":335},"  getMeta",[321,1970,893],{"class":331},[321,1972,1973,1975],{"class":323,"line":423},[321,1974,1092],{"class":335},[321,1976,893],{"class":331},[321,1978,1979,1981,1984],{"class":323,"line":437},[321,1980,1113],{"class":327},[321,1982,1983],{"class":335}," Constructor",[321,1985,893],{"class":331},[321,1987,1988,1990,1992,1994,1996],{"class":323,"line":462},[321,1989,1122],{"class":331},[321,1991,353],{"class":327},[321,1993,356],{"class":331},[321,1995,360],{"class":359},[321,1997,363],{"class":331},[321,1999,2000],{"class":323,"line":469},[321,2001,370],{"emptyLinePlaceholder":369},[321,2003,2004,2006,2008],{"class":323,"line":475},[321,2005,376],{"class":331},[321,2007,380],{"class":379},[321,2009,383],{"class":335},[321,2011,2012,2014,2017,2020],{"class":323,"line":848},[321,2013,787],{"class":327},[321,2015,2016],{"class":389}," class",[321,2018,2019],{"class":393}," RouteInspector",[321,2021,397],{"class":331},[321,2023,2024,2026,2028,2030,2032],{"class":323,"line":874},[321,2025,403],{"class":389},[321,2027,407],{"class":406},[321,2029,410],{"class":331},[321,2031,347],{"class":406},[321,2033,415],{"class":335},[321,2035,2036,2038,2041,2043,2045],{"class":323,"line":896},[321,2037,403],{"class":389},[321,2039,2040],{"class":406}," router",[321,2042,410],{"class":331},[321,2044,347],{"class":406},[321,2046,2047],{"class":335},"(Router)\n",[321,2049,2050],{"class":323,"line":904},[321,2051,370],{"emptyLinePlaceholder":369},[321,2053,2054,2056,2058,2060],{"class":323,"line":917},[321,2055,426],{"class":389},[321,2057,429],{"class":406},[321,2059,432],{"class":331},[321,2061,397],{"class":331},[321,2063,2064,2066,2068,2070,2072,2075,2077,2079,2081,2083,2085,2087,2090],{"class":323,"line":923},[321,2065,1457],{"class":327},[321,2067,1337],{"class":406},[321,2069,721],{"class":389},[321,2071,332],{"class":331},[321,2073,2074],{"class":335}," ctor",[321,2076,350],{"class":331},[321,2078,1481],{"class":331},[321,2080,448],{"class":331},[321,2082,451],{"class":335},[321,2084,454],{"class":331},[321,2086,457],{"class":379},[321,2088,2089],{"class":406},"()) ",[321,2091,1508],{"class":331},[321,2093,2094,2096,2099,2101,2104,2106,2108,2110,2112,2115,2117,2120],{"class":323,"line":1198},[321,2095,1514],{"class":389},[321,2097,2098],{"class":335}," prefix",[321,2100,410],{"class":331},[321,2102,2103],{"class":379}," getMeta",[321,2105,557],{"class":331},[321,2107,1424],{"class":393},[321,2109,569],{"class":331},[321,2111,733],{"class":406},[321,2113,2114],{"class":335},"ctor",[321,2116,339],{"class":331},[321,2118,2119],{"class":335}," RESOLVED_PREFIX",[321,2121,744],{"class":406},[321,2123,2124,2127,2129,2132,2135,2138,2140],{"class":323,"line":1246},[321,2125,2126],{"class":327},"      if",[321,2128,1337],{"class":406},[321,2130,2131],{"class":335},"prefix",[321,2133,2134],{"class":331}," ===",[321,2136,2137],{"class":331}," undefined",[321,2139,1540],{"class":406},[321,2141,2142],{"class":327},"continue\n",[321,2144,2145,2148,2150,2152,2154,2157,2160,2162,2164,2166,2168,2170,2172,2175,2178,2180,2183],{"class":323,"line":1268},[321,2146,2147],{"class":335},"      console",[321,2149,454],{"class":331},[321,2151,1803],{"class":379},[321,2153,733],{"class":406},[321,2155,2156],{"class":331},"`${",[321,2158,2159],{"class":335},"(ctor ",[321,2161,1580],{"class":327},[321,2163,1983],{"class":393},[321,2165,840],{"class":335},[321,2167,454],{"class":331},[321,2169,805],{"class":335},[321,2171,1122],{"class":331},[321,2173,2174],{"class":359}," -> \u002F",[321,2176,2177],{"class":331},"${",[321,2179,2131],{"class":335},[321,2181,2182],{"class":331},"}`",[321,2184,744],{"class":406},[321,2186,2187],{"class":323,"line":1288},[321,2188,1629],{"class":331},[321,2190,2191],{"class":323,"line":1296},[321,2192,472],{"class":331},[321,2194,2195],{"class":323,"line":1308},[321,2196,478],{"class":331},[182,2198,2199,2200,2205],{},"This is the pattern ",[288,2201,2202],{"href":148},[185,2203,2204],{},"@miiajs\u002Fswagger"," uses internally to walk every controller and emit the OpenAPI spec. Any package that needs to enumerate live routes - metrics exporters, route tables, tracing instrumentation - can use the same two-line filter.",[220,2207,2209],{"id":2208},"registering-routes-in-onready","Registering routes in onReady",[182,2211,2212,2215,2216,2218],{},[185,2213,2214],{},"Router"," is injectable too, so a discovery-aware provider can both scan for metadata and register brand-new routes based on what it finds - all inside ",[185,2217,249],{},", before the HTTP server accepts its first request.",[182,2220,2221,2222,2225,2226,988,2229,2232,2233,2235,2236,2239,2240,2243],{},"::warning Routes added in onReady skip per-route compilation\n",[185,2223,2224],{},"router.compileAll()"," runs in the compile phase, which is ",[234,2227,2228],{},"before",[185,2230,2231],{},"bootstrapAll()",". Routes you register from inside an ",[185,2234,249],{}," hook never see that pass, so they never receive a per-route ",[185,2237,2238],{},"compiledPipeline"," - no controller-level guards or ",[185,2241,2242],{},"@Use()"," middleware is attached.",[182,2245,2246,2247,2250,2251,2254,2255,2258,2259,2262],{},"They ",[234,2248,2249],{},"do"," still run inside the global pipeline (",[185,2252,2253],{},"app.use()"," wraps the entire dispatch), so CORS, request logging, and request-id middleware apply normally. What's missing is per-route middleware and ",[234,2256,2257],{},"global guards"," - which is exactly what you want for a spec endpoint like ",[185,2260,2261],{},"\u002Fdocs\u002Fjson",", but worth knowing about.",[182,2264,2265,2266,2269,2270,541],{},"To opt out explicitly and guarantee that a late-registered route stays guard-free even after a future ",[185,2267,2268],{},"app.addRoute()"," triggers recompilation, pass ",[185,2271,2272],{},"{ skipGlobalGuards: true }",[312,2274,2276],{"className":314,"code":2275,"language":316,"meta":317,"style":317},"this.router.add('GET', '\u002Fdocs\u002Fjson', handler, { skipGlobalGuards: true })\n",[185,2277,2278],{"__ignoreMap":317},[321,2279,2280,2283,2286,2288,2291,2293,2295,2298,2300,2302,2304,2306,2308,2310,2313,2315,2317,2320,2322,2326,2328],{"class":323,"line":324},[321,2281,2282],{"class":331},"this.",[321,2284,2285],{"class":335},"router",[321,2287,454],{"class":331},[321,2289,2290],{"class":379},"add",[321,2292,733],{"class":335},[321,2294,736],{"class":331},[321,2296,2297],{"class":359},"GET",[321,2299,736],{"class":331},[321,2301,339],{"class":331},[321,2303,356],{"class":331},[321,2305,2261],{"class":359},[321,2307,736],{"class":331},[321,2309,339],{"class":331},[321,2311,2312],{"class":335}," handler",[321,2314,339],{"class":331},[321,2316,332],{"class":331},[321,2318,2319],{"class":406}," skipGlobalGuards",[321,2321,541],{"class":331},[321,2323,2325],{"class":2324},"sfNiH"," true",[321,2327,350],{"class":331},[321,2329,744],{"class":335},[182,2331,2199,2332,2334],{},[185,2333,2204],{}," uses internally. Global middleware still applies; only global guards are bypassed.\n::",[220,2336,2338],{"id":2337},"exports","Exports",[312,2340,2342],{"className":314,"code":2341,"language":316,"meta":317,"style":317},"import {\n  DiscoveryService,\n  type DiscoverableMethodMeta,\n  type DiscoveredMethod,\n} from '@miiajs\u002Fcore'\n",[185,2343,2344,2350,2356,2364,2372],{"__ignoreMap":317},[321,2345,2346,2348],{"class":323,"line":324},[321,2347,328],{"class":327},[321,2349,397],{"class":331},[321,2351,2352,2354],{"class":323,"line":366},[321,2353,1078],{"class":335},[321,2355,893],{"class":331},[321,2357,2358,2360,2362],{"class":323,"line":373},[321,2359,1113],{"class":327},[321,2361,566],{"class":335},[321,2363,893],{"class":331},[321,2365,2366,2368,2370],{"class":323,"line":386},[321,2367,1113],{"class":327},[321,2369,554],{"class":335},[321,2371,893],{"class":331},[321,2373,2374,2376,2378,2380,2382],{"class":323,"line":400},[321,2375,1122],{"class":331},[321,2377,353],{"class":327},[321,2379,356],{"class":331},[321,2381,360],{"class":359},[321,2383,363],{"class":331},[2385,2386,2387],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .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 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 .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sfNiH, html code.shiki .sfNiH{--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC}",{"title":317,"searchDepth":366,"depth":366,"links":2389},[2390,2391,2392,2393,2394,2395,2396,2397],{"id":222,"depth":366,"text":223},{"id":300,"depth":366,"text":301},{"id":628,"depth":366,"text":629},{"id":939,"depth":366,"text":940},{"id":1040,"depth":366,"text":1041},{"id":1913,"depth":366,"text":1914},{"id":2208,"depth":366,"text":2209},{"id":2337,"depth":366,"text":2338},"Scan every singleton provider for decorator metadata at startup - the foundation of ambient discovery in MiiaJS.","md",{},{"title":47,"description":2398},"BPely2xe8EZiX2MRhV0YJL23OKA-osOhmuKCAfwOdDw",[2404,2406],{"title":43,"path":44,"stem":45,"description":2405,"children":-1},"Build your own decorators with createClassDecorator, createMethodDecorator, createDecorator, createFieldDecorator, and the metadata helpers.",{"title":51,"path":52,"stem":53,"description":2407,"children":-1},"Init, active, and shutdown phases of a Miia app - graceful destroy on SIGTERM\u002FSIGINT\u002FSIGHUP by default.",1778575270760]