[{"data":1,"prerenderedAt":1065},["ShallowReactive",2],{"navigation":3,"\u002Fdocs\u002Froadmap\u002Fshort-term":176,"\u002Fdocs\u002Froadmap\u002Fshort-term-surround":1060},[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":165,"body":178,"description":1054,"extension":1055,"meta":1056,"navigation":1057,"path":166,"seo":1058,"status":11,"stem":167,"__hash__":1059},"docs\u002F1.docs\u002F4.roadmap\u002F2.short-term.md",{"type":179,"value":180,"toc":1040},"minimark",[181,197,205,211,282,297,301,310,352,360,364,378,381,422,437,446,460,462,473,519,672,689,702,720,725,729,731,754,763,767,769,791,925,930,934,937,957,960,963,1015,1019,1030,1036],[182,183,184,185,189,190,193,194,196],"p",{},"The short-term horizon is mostly ",[186,187,188],"strong",{},"debt and gaps in existing packages"," rather than new things. The goal is to take everything currently labelled ",[191,192,96],"code",{}," to ",[191,195,103],{}," and unblock common app shapes that today require user-supplied glue.",[198,199,201,202,204],"h2",{"id":200},"validating-the-experimental-packages","Validating the ",[191,203,96],{}," packages",[182,206,207,208,210],{},"Two packages currently sit at ",[191,209,96],{}," because they have not been validated by real adoption, not because their internal coverage is poor.",[212,213,214,233],"table",{},[215,216,217],"thead",{},[218,219,220,224,227,230],"tr",{},[221,222,223],"th",{},"Package",[221,225,226],{},"Status",[221,228,229],{},"Why experimental",[221,231,232],{},"What promotes it",[234,235,236,259],"tbody",{},[218,237,238,244,246,253],{},[239,240,241],"td",{},[191,242,243],{},"@miiajs\u002Fcli",[239,245,96],{},[239,247,248,249,252],{},"49 tests, but the 11 scaffold features have not been exercised by real ",[191,250,251],{},"miia new"," runs in production projects.",[239,254,255,256,258],{},"Run ",[191,257,251],{}," to bootstrap a real app, fix anything that breaks, write end-to-end scaffold tests.",[218,260,261,266,268,279],{},[239,262,263],{},[191,264,265],{},"@miiajs\u002Fmessaging-redis",[239,267,96],{},[239,269,270,271,274,275,278],{},"14 tests; 1 still TODO (",[191,272,273],{},"survives consumer crash via XAUTOCLAIM",", marked ",[191,276,277],{},"it.todo","). No production deployment.",[239,280,281],{},"Build a small worker app on top of it, exercise crash recovery, write the XAUTOCLAIM test.",[182,283,284,287,288,290,291,296],{},[191,285,286],{},"@miiajs\u002Fauth\u002Foauth2"," recipe page is also marked ",[191,289,96],{}," until the GitHub OAuth flow is validated end-to-end on a real app. The plan is to keep OAuth2 as a recipe rather than a separate package - see ",[292,293,295],"a",{"href":294},"#examples-and-docs-gaps","Examples and docs gaps",".",[198,298,300],{"id":299},"test-depth-on-small-surface-packages","Test depth on small-surface packages",[182,302,303,304,306,307,309],{},"These are ",[191,305,103],{}," (small but well-targeted test coverage) but would benefit from a few more edge-case tests as we hit them in real apps. None block their ",[191,308,103],{}," status today.",[212,311,312,324],{},[215,313,314],{},[218,315,316,318,321],{},[221,317,223],{},[221,319,320],{},"Tests today",[221,322,323],{},"Edges worth adding when we touch them",[234,325,326,339],{},[218,327,328,333,336],{},[239,329,330],{},[191,331,332],{},"@miiajs\u002Fjwt",[239,334,335],{},"6",[239,337,338],{},"Algorithm allowlist enforcement, expired tokens, key rotation, missing config.",[218,340,341,346,349],{},[239,342,343],{},[191,344,345],{},"@miiajs\u002Fauth",[239,347,348],{},"12",[239,350,351],{},"Multi-strategy resolution, token extractor edge cases, AuthGuard composition.",[198,353,355,356,359],{"id":354},"multipart-file-upload-miiajsmultipart","Multipart \u002F file upload (",[191,357,358],{},"@miiajs\u002Fmultipart",")",[361,362],"badge",{"label":363},"planned",[182,365,366,369,370,373,374,377],{},[191,367,368],{},"await ctx.req.formData()"," already works today via Web Standards - good enough for small uploads where loading the whole body into memory is fine. The gap is ",[186,371,372],{},"streaming"," large files and a uniform ",[191,375,376],{},"UploadedFile"," shape across runtimes.",[182,379,380],{},"The package will be a thin per-runtime layer behind a single decorator. Each runtime gets the fastest streaming path it natively supports:",[382,383,384,399],"ul",{},[385,386,387,390,391,394,395,398],"li",{},[186,388,389],{},"Bun \u002F Deno"," - native streaming ",[191,392,393],{},"formData()",". Bun 1.1+ and Deno 1.40+ both expose multipart parts as ",[191,396,397],{},"ReadableStream",", so the parser is the runtime's job.",[385,400,401,404,405,413,414,417,418,421],{},[186,402,403],{},"Node.js \u002F uWebSockets"," - ",[292,406,410],{"href":407,"rel":408},"https:\u002F\u002Fgithub.com\u002Fmscdex\u002Fbusboy",[409],"nofollow",[191,411,412],{},"busboy"," (the battle-tested stream parser that powers ",[191,415,416],{},"multer"," and ",[191,419,420],{},"@fastify\u002Fmultipart"," under the hood).",[182,423,424,425,428,429,432,433,436],{},"Method-level decorator (similar to ",[191,426,427],{},"@ValidateBody",") wraps a Koa-style middleware - no new framework concept, just a more ergonomic surface than raw ",[191,430,431],{},"@Use",". Built-in: file size limits, MIME filters, abort handling, direct pipe to your storage of choice (S3 SDK, GCS client, local filesystem). We ",[186,434,435],{},"do not"," reimplement the multipart protocol on Node.js; busboy does the parsing. Bun\u002FDeno parsing stays delegated to the runtime. The exact API surface gets locked in once we exercise it on a real upload-heavy app.",[182,438,439,442,443,445],{},[186,440,441],{},"Why now:"," every real app eventually needs file upload, and \"use ",[191,444,393],{}," for small files, write your own busboy plumbing for large ones\" is not a great pitch for a \"decorators + Web Standards\" framework.",[198,447,449,450,453,454,453,457,359],{"id":448},"rate-limiting-miiajsrate-limit-miiajsrate-limit-redis-miiajsrate-limit-upstash","Rate limiting (",[191,451,452],{},"@miiajs\u002Frate-limit"," + ",[191,455,456],{},"@miiajs\u002Frate-limit-redis",[191,458,459],{},"@miiajs\u002Frate-limit-upstash",[361,461],{"label":363},[182,463,464,465,468,469,472],{},"Own implementation, not a wrapper. Token bucket and sliding window built against a small ",[191,466,467],{},"RateLimitStore"," interface with atomic ",[191,470,471],{},"consume(key, points, window)"," semantics. Three packages ship together:",[382,474,475,493,504],{},[385,476,477,481,482,484,485,488,489,492],{},[186,478,479],{},[191,480,452],{}," - core: ",[191,483,467],{}," interface, ",[191,486,487],{},"@RateLimit({ window, max, key? })"," decorator, middleware form, standard ",[191,490,491],{},"RateLimit-*"," response headers, in-memory store (default for dev).",[385,494,495,499,500,503],{},[186,496,497],{},[191,498,456],{}," - ioredis-backed store using a Lua script for atomic ",[191,501,502],{},"INCR"," + window expiry. Covers typical Node\u002FBun\u002FDeno deployments.",[385,505,506,510,511,518],{},[186,507,508],{},[191,509,459],{}," - thin adapter over ",[292,512,515],{"href":513,"rel":514},"https:\u002F\u002Fgithub.com\u002Fupstash\u002Fredis-js",[409],[191,516,517],{},"@upstash\u002Fredis"," (HTTP REST API). This is the edge story: works on Vercel Edge, Netlify, Cloudflare Workers, and any other runtime where TCP-based clients like ioredis don't start.",[520,521,526],"pre",{"className":522,"code":523,"language":524,"meta":525,"style":525},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","@Get('\u002Flogin')\n@RateLimit({ window: '1m', max: 5, key: (ctx) => ctx.req.headers.get('x-forwarded-for') })\nasync login(ctx) { ... }\n","ts","",[191,527,528,557,652],{"__ignoreMap":525},[529,530,533,537,541,545,548,552,554],"span",{"class":531,"line":532},"line",1,[529,534,536],{"class":535},"sMK4o","@",[529,538,540],{"class":539},"s2Zo4","Get",[529,542,544],{"class":543},"sTEyZ","(",[529,546,547],{"class":535},"'",[529,549,551],{"class":550},"sfazB","\u002Flogin",[529,553,547],{"class":535},[529,555,556],{"class":543},")\n",[529,558,560,562,565,567,570,574,577,580,583,585,588,591,593,597,599,602,604,607,611,613,617,620,622,625,627,630,632,635,637,639,642,644,647,650],{"class":531,"line":559},2,[529,561,536],{"class":535},[529,563,564],{"class":539},"RateLimit",[529,566,544],{"class":543},[529,568,569],{"class":535},"{",[529,571,573],{"class":572},"swJcz"," window",[529,575,576],{"class":535},":",[529,578,579],{"class":535}," '",[529,581,582],{"class":550},"1m",[529,584,547],{"class":535},[529,586,587],{"class":535},",",[529,589,590],{"class":572}," max",[529,592,576],{"class":535},[529,594,596],{"class":595},"sbssI"," 5",[529,598,587],{"class":535},[529,600,601],{"class":539}," key",[529,603,576],{"class":535},[529,605,606],{"class":535}," (",[529,608,610],{"class":609},"sHdIc","ctx",[529,612,359],{"class":535},[529,614,616],{"class":615},"spNyl"," =>",[529,618,619],{"class":543}," ctx",[529,621,296],{"class":535},[529,623,624],{"class":543},"req",[529,626,296],{"class":535},[529,628,629],{"class":543},"headers",[529,631,296],{"class":535},[529,633,634],{"class":539},"get",[529,636,544],{"class":543},[529,638,547],{"class":535},[529,640,641],{"class":550},"x-forwarded-for",[529,643,547],{"class":535},[529,645,646],{"class":543},") ",[529,648,649],{"class":535},"}",[529,651,556],{"class":543},[529,653,655,658,661,664,666,669],{"class":531,"line":654},3,[529,656,657],{"class":543},"async ",[529,659,660],{"class":539},"login",[529,662,663],{"class":543},"(ctx) ",[529,665,569],{"class":535},[529,667,668],{"class":535}," ...",[529,670,671],{"class":535}," }\n",[182,673,674,677,678,681,682,684,685,688],{},[186,675,676],{},"Why our own."," Wrappers over ",[191,679,680],{},"rate-limiter-flexible"," looked appealing but bring two problems: official Bun support is unverified, and the library's store list is Node-shaped (no native edge story). A token bucket is ~150 lines, the ",[191,683,467],{}," interface is ~20, and we control runtime compatibility by construction. Same pattern as ",[191,686,687],{},"IdempotencyStore"," in messaging - users learn one shape across the framework.",[182,690,691,694,695,698,699,701],{},[186,692,693],{},"Serverless story."," Unlike cache, rate limiting needs atomic counter increments with TTL. Unstorage's ",[191,696,697],{},"getItem\u002FsetItem"," is not atomic - we cannot reuse that bridge here without race conditions under load. Instead, the dedicated ",[191,700,459],{}," package gives Vercel\u002FNetlify\u002FCF Workers users a working store from day one.",[182,703,704,705,707,708,711,712,715,716,719],{},"Because ",[191,706,467],{}," is our interface, native first-party drivers (",[191,709,710],{},"@miiajs\u002Frate-limit-cloudflare-do"," for Durable Objects, ",[191,713,714],{},"@miiajs\u002Frate-limit-dynamodb"," for AWS Lambda) can land later without breaking users. They swap the ",[191,717,718],{},"store"," instance, nothing else changes.",[182,721,722,724],{},[186,723,441],{}," rate limiting is table-stakes for any public API. Owning the implementation lets us ship a clean serverless story without depending on a third-party library's stance on edge runtimes.",[198,726,728],{"id":727},"request-body-size-limits","Request body size limits",[361,730],{"label":363},[182,732,733,734,737,738,741,742,745,746,749,750,753],{},"Per-app and per-route ceiling on incoming body size. Configured via middleware factory (",[191,735,736],{},"bodyLimit('1mb')",") and a decorator (",[191,739,740],{},"@BodyLimit('500kb')"," for overrides). Adapters that buffer (",[191,743,744],{},"node-server"," \u002F ",[191,747,748],{},"uws-server"," optimized mode) enforce the cap before allocating; streaming paths abort the stream when the cap is reached. Returns ",[191,751,752],{},"413 Payload Too Large"," with a structured exception.",[182,755,756,758,759,762],{},[186,757,441],{}," missing body limits is a common DoS surface. Adapters today have an internal ",[191,760,761],{},"bufferThreshold"," for the buffered fast path, but no enforced ceiling for streaming - the user has to write it, and most don't.",[198,764,766],{"id":765},"server-sent-events-helper","Server-Sent Events helper",[361,768],{"label":363},[182,770,771,774,775,778,779,782,783,786,787,790],{},[191,772,773],{},"ctx.res.sse(stream | iterable)"," helper plus a small ",[191,776,777],{},"SseStream"," builder that handles event framing, keep-alive comments, and back-pressure. ",[186,780,781],{},"No decorator, no new package"," - this lives in ",[191,784,785],{},"@miiajs\u002Fcore"," and composes with existing guards\u002Fmiddleware\u002FDI. There will not be a ",[191,788,789],{},"@miiajs\u002Fsse"," package.",[520,792,794],{"className":522,"code":793,"language":524,"meta":525,"style":525},"@Get('\u002Fevents')\nasync stream(ctx: RequestContext) {\n  return ctx.res.sse(async function* () {\n    yield { event: 'tick', data: { now: Date.now() } }\n  })\n}\n",[191,795,796,813,826,861,911,919],{"__ignoreMap":525},[529,797,798,800,802,804,806,809,811],{"class":531,"line":532},[529,799,536],{"class":535},[529,801,540],{"class":539},[529,803,544],{"class":543},[529,805,547],{"class":535},[529,807,808],{"class":550},"\u002Fevents",[529,810,547],{"class":535},[529,812,556],{"class":543},[529,814,815,817,820,823],{"class":531,"line":559},[529,816,657],{"class":543},[529,818,819],{"class":539},"stream",[529,821,822],{"class":543},"(ctx: RequestContext) ",[529,824,825],{"class":535},"{\n",[529,827,828,832,834,836,839,841,844,846,849,852,855,858],{"class":531,"line":654},[529,829,831],{"class":830},"s7zQu","  return",[529,833,619],{"class":543},[529,835,296],{"class":535},[529,837,838],{"class":543},"res",[529,840,296],{"class":535},[529,842,843],{"class":539},"sse",[529,845,544],{"class":572},[529,847,848],{"class":615},"async",[529,850,851],{"class":615}," function",[529,853,854],{"class":535},"*",[529,856,857],{"class":535}," ()",[529,859,860],{"class":535}," {\n",[529,862,864,867,870,873,875,877,880,882,884,887,889,891,894,896,899,901,904,907,909],{"class":531,"line":863},4,[529,865,866],{"class":830},"    yield",[529,868,869],{"class":535}," {",[529,871,872],{"class":572}," event",[529,874,576],{"class":535},[529,876,579],{"class":535},[529,878,879],{"class":550},"tick",[529,881,547],{"class":535},[529,883,587],{"class":535},[529,885,886],{"class":572}," data",[529,888,576],{"class":535},[529,890,869],{"class":535},[529,892,893],{"class":572}," now",[529,895,576],{"class":535},[529,897,898],{"class":543}," Date",[529,900,296],{"class":535},[529,902,903],{"class":539},"now",[529,905,906],{"class":572},"() ",[529,908,649],{"class":535},[529,910,671],{"class":535},[529,912,914,917],{"class":531,"line":913},5,[529,915,916],{"class":535},"  }",[529,918,556],{"class":572},[529,920,922],{"class":531,"line":921},6,[529,923,924],{"class":535},"}\n",[182,926,927,929],{},[186,928,441],{}," SSE solves 70% of \"I need server-push\" use cases (notifications, progress updates, log tails) without WebSocket-level complexity. WebSocket lands mid-term; SSE is ~50 lines of code today and unblocks real apps now.",[198,931,933],{"id":932},"request-validation-pipe-sugar","Request validation pipe sugar",[361,935],{"label":936},"idea",[182,938,939,941,942,941,945,948,949,952,953,956],{},[191,940,427],{},"\u002F",[191,943,944],{},"@ValidateQuery",[191,946,947],{},"@ValidateParams"," exist but are Zod-flavoured. Add a thin pipe layer so consumers can plug arbitrary schema libraries (Valibot, ArkType, Yup) by passing a ",[191,950,951],{},"safeParse","-shaped function. Mostly already there via ",[191,954,955],{},"ZodLike"," interface; needs docs and one or two non-Zod tests to demonstrate.",[198,958,295],{"id":959},"examples-and-docs-gaps",[182,961,962],{},"Add small, focused example apps and recipes so contributors and users can copy-paste:",[382,964,965,971,977,987,997],{},[385,966,967,970],{},[191,968,969],{},"examples\u002Fmultipart-upload"," - file upload with progress, alongside the new package.",[385,972,973,976],{},[186,974,975],{},"Auth recipes",": validate the existing OAuth2 recipe end-to-end with GitHub\u002FGoogle, add API-key recipe, add session-based recipe. Recipes only - no separate auth packages (per design choice).",[385,978,979,982,983,986],{},[186,980,981],{},"Production logger recipes",": how to plug winston \u002F pino into the existing ",[191,984,985],{},"LoggerService"," interface for structured JSON logs. The interface is already there; the docs aren't.",[385,988,989,992,993,996],{},[186,990,991],{},"Health check recipe",": small core helper plus a controller pattern. We deliberately do not ship a ",[191,994,995],{},"@miiajs\u002Fhealth"," package - 50 lines of glue do not earn one.",[385,998,999,1002,1003,1006,1007,1010,1011,1014],{},[186,1000,1001],{},"Transactions recipes",": explicit ",[191,1004,1005],{},"db.transaction()"," patterns for Drizzle, Mongoose, Papr. No ",[191,1008,1009],{},"@Transactional"," decorator, no ",[191,1012,1013],{},"AsyncLocalStorage"," indirection.",[198,1016,1018],{"id":1017},"out-of-scope-deferred-to-mid-term","Out of scope (deferred to mid-term)",[382,1020,1021,1024,1027],{},[385,1022,1023],{},"WebSocket support",[385,1025,1026],{},"OpenTelemetry integration",[385,1028,1029],{},"Cache abstraction",[182,1031,1032,1033,1035],{},"These are valuable but bigger commitments than 0-3 months. Items removed from short-term entirely after re-scoping: dedicated health-checks package (now a recipe), separate auth-strategy packages (recipes only, never packages), Request-Reply for messaging (long-term), scheduler (long-term ",[191,1034,936],{},").",[1037,1038,1039],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}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 .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html 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 .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}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 .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}",{"title":525,"searchDepth":559,"depth":559,"links":1041},[1042,1044,1045,1047,1049,1050,1051,1052,1053],{"id":200,"depth":559,"text":1043},"Validating the experimental packages",{"id":299,"depth":559,"text":300},{"id":354,"depth":559,"text":1046},"Multipart \u002F file upload (@miiajs\u002Fmultipart)",{"id":448,"depth":559,"text":1048},"Rate limiting (@miiajs\u002Frate-limit + @miiajs\u002Frate-limit-redis + @miiajs\u002Frate-limit-upstash)",{"id":727,"depth":559,"text":728},{"id":765,"depth":559,"text":766},{"id":932,"depth":559,"text":933},{"id":959,"depth":559,"text":295},{"id":1017,"depth":559,"text":1018},"Hardening and gap-fills - what gets attention next.","md",{},true,{"title":165,"description":1054},"YM9XvcBfZL_UOK85d_bs7xlmlkHNQqpvztC9ULdOrgc",[1061,1063],{"title":27,"path":160,"stem":161,"description":1062,"children":-1},"Public roadmap for MiiaJS - what is shipped, what is coming, and how items are prioritized.",{"title":169,"path":170,"stem":171,"description":1064,"children":-1},"Production essentials - features that unblock real-world deployments at scale.",1778575274713]