[{"data":1,"prerenderedAt":3358},["ShallowReactive",2],{"navigation":3,"/blog":184,"$WW8D6uk0Ck":202},[4,91,133,161,168],{"title":5,"path":6,"stem":7,"children":8,"icon":90},"Guide","/guide","1.guide/0.index",[9,12,53,69],{"title":10,"path":6,"stem":7,"icon":11},"Getting Started","pixel:play",{"title":5,"icon":13,"path":14,"stem":15,"children":16,"page":52},"ph:book-open-duotone","/guide/basics","1.guide/1.basics",[17,22,27,32,37,42,47],{"title":18,"path":19,"stem":20,"icon":21},"Request Lifecycle","/guide/basics/lifecycle","1.guide/1.basics/1.lifecycle","icon-park-outline:handle-round",{"title":23,"path":24,"stem":25,"icon":26},"Routing","/guide/basics/routing","1.guide/1.basics/2.routing","solar:routing-bold",{"title":28,"path":29,"stem":30,"icon":31},"Middleware","/guide/basics/middleware","1.guide/1.basics/3.middleware","mdi:middleware-outline",{"title":33,"path":34,"stem":35,"icon":36},"Event Handlers","/guide/basics/handler","1.guide/1.basics/4.handler","mdi:function",{"title":38,"path":39,"stem":40,"icon":41},"Sending Response","/guide/basics/response","1.guide/1.basics/5.response","tabler:json",{"title":43,"path":44,"stem":45,"icon":46},"Error Handling","/guide/basics/error","1.guide/1.basics/6.error","tabler:error-404",{"title":48,"path":49,"stem":50,"icon":51},"Nested Apps","/guide/basics/nested-apps","1.guide/1.basics/7.nested-apps","material-symbols-light:layers-outline",false,{"title":54,"icon":55,"path":56,"stem":57,"children":58,"page":52},"API","material-symbols-light:api-rounded","/guide/api","1.guide/900.api",[59,64],{"title":60,"path":61,"stem":62,"icon":63},"H3","/guide/api/h3","1.guide/900.api/1.h3","material-symbols:bolt-rounded",{"title":65,"path":66,"stem":67,"icon":68},"H3Event","/guide/api/h3event","1.guide/900.api/2.h3event","material-symbols:data-object-rounded",{"title":70,"icon":71,"path":72,"stem":73,"children":74,"page":52},"Advanced","hugeicons:more-01","/guide/advanced","1.guide/901.advanced",[75,80,85],{"title":76,"path":77,"stem":78,"icon":79},"Plugins","/guide/advanced/plugins","1.guide/901.advanced/1.plugins","clarity:plugin-line",{"title":81,"path":82,"stem":83,"icon":84},"WebSockets","/guide/advanced/websocket","1.guide/901.advanced/2.websocket","hugeicons:live-streaming-02",{"title":86,"path":87,"stem":88,"icon":89},"Nightly Builds","/guide/advanced/nightly","1.guide/901.advanced/9.nightly","game-icons:barn-owl","i-ph:book-open-duotone",{"title":92,"path":93,"stem":94,"children":95,"icon":97},"Utils","/utils","2.utils/0.index",[96,98,103,108,113,118,123,128],{"title":92,"path":93,"stem":94,"icon":97},"ph:function-bold",{"title":99,"path":100,"stem":101,"icon":102},"Request","/utils/request","2.utils/1.request","material-symbols-light:input",{"title":104,"path":105,"stem":106,"icon":107},"Response","/utils/response","2.utils/2.response","material-symbols-light:output",{"title":109,"path":110,"stem":111,"icon":112},"Cookie","/utils/cookie","2.utils/3.cookie","material-symbols:cookie-outline",{"title":114,"path":115,"stem":116,"icon":117},"Security","/utils/security","2.utils/4.security","wpf:key-security",{"title":119,"path":120,"stem":121,"icon":122},"Proxy","/utils/proxy","2.utils/5.proxy","arcticons:super-proxy",{"title":124,"path":125,"stem":126,"icon":127},"More utils","/utils/more","2.utils/9.more","mingcute:plus-line",{"title":129,"path":130,"stem":131,"icon":132},"Community","/utils/community","2.utils/99.community","lets-icons:external",{"title":134,"path":135,"stem":136,"children":137,"icon":139},"Examples","/examples","4.examples/0.index",[138,140,145,149,153,157],{"title":134,"path":135,"stem":136,"icon":139},"ph:code",{"title":141,"path":142,"stem":143,"icon":144},"Cookies","/examples/handle-cookie","4.examples/handle-cookie","ph:arrow-right",{"title":146,"path":147,"stem":148,"icon":144},"Sessions","/examples/handle-session","4.examples/handle-session",{"title":150,"path":151,"stem":152,"icon":144},"Static Assets","/examples/serve-static-assets","4.examples/serve-static-assets",{"title":154,"path":155,"stem":156,"icon":144},"Stream Response","/examples/stream-response","4.examples/stream-response",{"title":158,"path":159,"stem":160,"icon":144},"Validate Data","/examples/validate-data","4.examples/validate-data",{"title":162,"path":163,"stem":164,"children":165,"icon":167},"Migration","/migration","5.migration/0.index",[166],{"title":162,"path":163,"stem":164,"icon":167},"icons8:up-round",{"title":169,"path":170,"stem":171,"children":172},"Blog","/blog","99.blog",[173,176,180],{"title":169,"path":170,"stem":174,"icon":175},"99.blog/index","i-lucide-file-text",{"title":177,"path":178,"stem":179,"icon":175},"H3 1.8 - Towards the Edge of the Web","/blog/v1.8","99.blog/1.v1.8",{"title":181,"path":182,"stem":183,"icon":175},"H3 v2 beta","/blog/v2-beta","99.blog/2.v2-beta",{"id":185,"title":169,"body":186,"description":194,"extension":197,"meta":198,"navigation":199,"path":170,"seo":200,"stem":174,"__hash__":201},"content/99.blog/index.md",{"type":187,"value":188,"toc":193,"icon":175},"minimark",[189],[190,191,192],"p",{},"H3 release highlights.",{"title":194,"searchDepth":195,"depth":195,"links":196},"",2,[],"md",{"icon":175},{"icon":175},{"title":169,"description":194},"ga-AtZUFbPhtioBjNlhQVtNLoDrumIIwUDlQiWDglPc",[203,2144],{"id":204,"title":181,"body":205,"description":2133,"extension":197,"meta":2134,"navigation":2141,"path":182,"seo":2142,"stem":183,"__hash__":2143},"content/99.blog/2.v2-beta.md",{"type":187,"value":206,"toc":2122,"icon":175},[207,221,241,244,271,290,295,336,346,355,489,499,503,506,559,636,640,643,755,768,785,789,812,821,1110,1119,1173,1178,1182,1195,1200,1949,1957,1961,1964,1972,1976,2001,2004,2011,2043,2047,2075,2079,2084,2099,2110,2118],[208,209,210],"read-more",{"to":6},[190,211,212,213,220],{},"Visit the new ",[214,215,216],"a",{"href":6},[217,218,219],"strong",{},"H3 Guide"," to get started quickly.",[190,222,223,224,230,231,236,237,240],{},"H3 started in late 2020, during the rise of edge workers. With H3 + ",[214,225,229],{"href":226,"rel":227},"https://github.com/unjs/unenv",[228],"nofollow","unjs/unenv",", we could run ",[214,232,235],{"href":233,"rel":234},"https://nitro.build",[228],"Nitro"," deployments in worker environments with Node.js compatibility, best of both worlds! Since ",[214,238,239],{"href":178},"v1.8",", H3 has improved its support for web standards.",[190,242,243],{},"But still, H3 was primarily based on Node.js APIs with a compatibility layer for web standards. Logical choice at the time, given Node.js's popularity amongst JavaScript server runtimes.",[190,245,246,247,252,253,258,259,264,265,270],{},"Thanks to evolving web standards by initiatives like ",[214,248,251],{"href":249,"rel":250},"https://wintertc.org/",[228],"WinterTC"," and runtime support in ",[214,254,257],{"href":255,"rel":256},"https://deno.com/",[228],"Deno",", ",[214,260,263],{"href":261,"rel":262},"https://bun.sh/",[228],"Bun",", and the latest ",[214,266,269],{"href":267,"rel":268},"https://nodejs.org/en",[228],"Node.js",", ecosystem is ready to embrace web standards first class for server development. Benefits include:",[272,273,274,278,281,284,287],"ul",{},[275,276,277],"li",{},"Cross-runtime interoperability (Node.js, Deno, Bun, Workers, etc.)",[275,279,280],{},"Cross-framework compatibility (H3, Hono, Elysia, etc.)",[275,282,283],{},"Cross-environment compatibility (shared and familiar code between frontend and backend)",[275,285,286],{},"Leverage more of runtime native primitives like (Request, URL, Headers, etc.)",[275,288,289],{},"Easier API testing",[291,292,294],"h2",{"id":293},"srvx-universal-web-server-api","💥 srvx: Universal Web Server API",[190,296,297,298,302,303,306,307,309,310,312,313,316,317,322,323,329,330,335],{},"A major challenge was that Node.js lacks built-in support for web-standard HTTP servers. For ",[299,300,301],"code",{},"node:http"," compatibility, an adapter is needed to bridge Node.js ",[299,304,305],{},"IncomingMessage"," to web ",[299,308,99],{},", and to handle web ",[299,311,104],{}," via Node.js ",[299,314,315],{},"ServerResponse",". We have implemented a ",[214,318,321],{"href":319,"rel":320},"https://srvx.h3.dev/guide/node",[228],"compatibility layer"," that bridges interfaces and achieves ",[217,324,325,326,328],{},"up to 96.98% of native ",[299,327,301],{}," performance"," (see ",[214,331,334],{"href":332,"rel":333},"https://github.com/h3js/srvx/tree/main/test/bench-node",[228],"benchmarks",").",[190,337,338,339,258,342,345],{},"Runtimes such as ",[214,340,257],{"href":255,"rel":341},[228],[214,343,263],{"href":261,"rel":344},[228],", and Edge Workers pioneered the adoption of web standards for servers, but they did not agree on the same interface due to lack of enough specs. So how do you access the client IP address and additional context? How do you set the server port and TLS options? How do you handle WebSocket upgrades? Each runtime created its own API.",[190,347,348,349,354],{},"We have created ",[214,350,353],{"href":351,"rel":352},"https://srvx.h3.dev",[228],"💥 srvx",": A unified layer that works everywhere exactly the same. Compatible with Deno, Bun, Node.js, Service Workers, Edge Workers.",[356,357,358,362],"details",{},[359,360,361],"summary",{},"Example",[363,364,368],"pre",{"className":365,"code":366,"language":367,"meta":194,"style":194},"language-js shiki shiki-themes github-light github-dark github-dark","// Dynamic adapter will be used based export conditions of each runtime\nimport { serve } from \"srvx\";\n\nserve({\n  port: 3000,\n  // tls: { cert: \"server.crt\", key: \"server.key\" }\n  fetch(req) {\n    // Server Extensions: req.ip, req.waitUntil(), req.runtime?.{bun,deno,node,cloudflare,...}\n    return new Response(\"👋 Hello there!\");\n  },\n});\n","js",[299,369,370,379,399,406,416,429,435,451,457,477,483],{"__ignoreMap":194},[371,372,375],"span",{"class":373,"line":374},"line",1,[371,376,378],{"class":377},"sCsY4","// Dynamic adapter will be used based export conditions of each runtime\n",[371,380,381,385,389,392,396],{"class":373,"line":195},[371,382,384],{"class":383},"so5gQ","import",[371,386,388],{"class":387},"slsVL"," { serve } ",[371,390,391],{"class":383},"from",[371,393,395],{"class":394},"sfrk1"," \"srvx\"",[371,397,398],{"class":387},";\n",[371,400,402],{"class":373,"line":401},3,[371,403,405],{"emptyLinePlaceholder":404},true,"\n",[371,407,409,413],{"class":373,"line":408},4,[371,410,412],{"class":411},"shcOC","serve",[371,414,415],{"class":387},"({\n",[371,417,419,422,426],{"class":373,"line":418},5,[371,420,421],{"class":387},"  port: ",[371,423,425],{"class":424},"suiK_","3000",[371,427,428],{"class":387},",\n",[371,430,432],{"class":373,"line":431},6,[371,433,434],{"class":377},"  // tls: { cert: \"server.crt\", key: \"server.key\" }\n",[371,436,438,441,444,448],{"class":373,"line":437},7,[371,439,440],{"class":411},"  fetch",[371,442,443],{"class":387},"(",[371,445,447],{"class":446},"sQHwn","req",[371,449,450],{"class":387},") {\n",[371,452,454],{"class":373,"line":453},8,[371,455,456],{"class":377},"    // Server Extensions: req.ip, req.waitUntil(), req.runtime?.{bun,deno,node,cloudflare,...}\n",[371,458,460,463,466,469,471,474],{"class":373,"line":459},9,[371,461,462],{"class":383},"    return",[371,464,465],{"class":383}," new",[371,467,468],{"class":411}," Response",[371,470,443],{"class":387},[371,472,473],{"class":394},"\"👋 Hello there!\"",[371,475,476],{"class":387},");\n",[371,478,480],{"class":373,"line":479},10,[371,481,482],{"class":387},"  },\n",[371,484,486],{"class":373,"line":485},11,[371,487,488],{"class":387},"});\n",[490,491,492],"tip",{},[190,493,494,495,498],{},"\nWith ",[214,496,353],{"href":351,"rel":497},[228]," unifying runtime differences, H3 can remain simpler, focusing exclusively on web standard APIs.",[291,500,502],{"id":501},"h3-tiny-server-composer","⚡ H3: Tiny Server Composer 🎶",[190,504,505],{},"We worked hard to minimize and simplify H3’s scope.",[272,507,508,516,530,539,545,551],{},[275,509,510,511,515],{},"🪶 Optimized for performances, ",[214,512,514],{"href":513},"#lighter-than-a-feather","lighter"," than a feather.",[275,517,518,519,258,522,525,526,529],{},"👌 Intuitive ",[214,520,521],{"href":34},"typed handlers",[214,523,524],{"href":39},"responses"," and ",[214,527,528],{"href":44},"errors",".",[275,531,532,533,525,536,529],{},"🧩 Reusable ",[214,534,535],{"href":29},"middleware",[214,537,538],{"href":77},"plugins",[275,540,541,542,529],{},"🌳 Fast ",[214,543,544],{"href":24},"routing",[275,546,547,548,529],{},"➕ Built-in ",[214,549,550],{"href":93},"utilities",[275,552,553,554,558],{},"❤️ Maximum ",[214,555,557],{"href":556},"/guide/api/h3#h3mount","compatibility"," based on web standards.",[363,560,562],{"className":365,"code":561,"language":367,"meta":194,"style":194},"import { H3, serve } from \"h3\";\n\nconst app = new H3().get(\"/\", () => \"⚡️ Tadaa!\");\n\nserve(app, { port: 3000 });\n",[299,563,564,578,582,620,624],{"__ignoreMap":194},[371,565,566,568,571,573,576],{"class":373,"line":374},[371,567,384],{"class":383},[371,569,570],{"class":387}," { H3, serve } ",[371,572,391],{"class":383},[371,574,575],{"class":394}," \"h3\"",[371,577,398],{"class":387},[371,579,580],{"class":373,"line":195},[371,581,405],{"emptyLinePlaceholder":404},[371,583,584,587,590,593,595,598,601,604,606,609,612,615,618],{"class":373,"line":401},[371,585,586],{"class":383},"const",[371,588,589],{"class":424}," app",[371,591,592],{"class":383}," =",[371,594,465],{"class":383},[371,596,597],{"class":411}," H3",[371,599,600],{"class":387},"().",[371,602,603],{"class":411},"get",[371,605,443],{"class":387},[371,607,608],{"class":394},"\"/\"",[371,610,611],{"class":387},", () ",[371,613,614],{"class":383},"=>",[371,616,617],{"class":394}," \"⚡️ Tadaa!\"",[371,619,476],{"class":387},[371,621,622],{"class":373,"line":408},[371,623,405],{"emptyLinePlaceholder":404},[371,625,626,628,631,633],{"class":373,"line":418},[371,627,412],{"class":411},[371,629,630],{"class":387},"(app, { port: ",[371,632,425],{"class":424},[371,634,635],{"class":387}," });\n",[291,637,639],{"id":638},"lighter-than-a-feather","🪶 Lighter Than a Feather",[190,641,642],{},"We approached benchmarking with a new method that focuses on measuring the overhead introduced by the framework itself, rather than the network layer. Our goal is to optimize all relevant measurements together, making the numbers as close as possible to a baseline where no framework is added or used. This method allowed H3 to achieve optimized latency improvements per request and a dramatically smaller core bundle size.",[644,645,646,662],"table",{},[647,648,649],"thead",{},[650,651,652,656,659],"tr",{},[653,654,655],"th",{},"Measurement",[653,657,658],{},"H3 v1",[653,660,661],{},"🚀 H3 v2",[663,664,665,711],"tbody",{},[650,666,667,671,681],{},[668,669,670],"td",{},"Request Handling",[668,672,673,674,677,678,680],{},"Node: 36 µs ",[675,676],"br",{}," Bun: 27 µs ",[675,679],{}," Deno: 7 ms",[668,682,683,684,687,688,691,692,694,695,687,698,691,701,703,704,687,707,710],{},"Node: ",[217,685,686],{},"7 µs"," (",[217,689,690],{},"5x faster",") ",[675,693],{}," Bun: ",[217,696,697],{},"3 µs",[217,699,700],{},"9x faster",[675,702],{}," Deno: ",[217,705,706],{},"1.2 µs",[217,708,709],{},"156x faster",")",[650,712,713,716,722],{},[668,714,715],{},"Bundle Size",[668,717,718,719,721],{},"min: 101 kB ",[675,720],{}," min+gzip: 39.6 kB",[668,723,724,725,687,728,691,731,733,734,687,737,691,740,742,743,746,747,687,750,754],{},"min: ",[217,726,727],{},"9,1 kB",[217,729,730],{},"91% smaller",[675,732],{}," min+gzip: ",[217,735,736],{},"3.6 kB",[217,738,739],{},"90% smaller",[675,741],{}," min: ",[217,744,745],{},"5.2 kB"," / min+gzip: ",[217,748,749],{},"2.1 kB",[214,751,753],{"href":752},"/guide/basics/handler#handler-fetch","fetchable"," handlers)",[490,756,757],{},[190,758,759,760,763,764,767],{},"\nH3 v2 performance is nearly identical to plain ",[299,761,762],{},"fetch"," handler with ",[299,765,766],{},"new URL(req.url).pathname"," for routing. In other words, you get the benefits of H3 with nearly zero performance cost!",[769,770,771],"note",{},[190,772,773,774,779,780,784],{},"\nBenchmarks apply to the H3 core using the Web Standard target and do not include adapters. They are primarily intended for internal optimization purposes. See the ",[214,775,778],{"href":776,"rel":777},"https://github.com/h3js/h3/tree/main/test/bench",[228],"benchmark"," for details and ",[214,781,783],{"href":332,"rel":782},[228],"srvx benchmarks"," for Node.js adapter performances.",[291,786,788],{"id":787},"typed-web-standards","✅ Typed Web Standards",[190,790,791,792,258,796,258,800,805,806,811],{},"H3 adopts web standard APIs such as ",[214,793,99],{"href":794,"rel":795},"https://developer.mozilla.org/en-US/docs/Web/API/Request",[228],[214,797,104],{"href":798,"rel":799},"https://developer.mozilla.org/en-US/docs/Web/API/Response",[228],[214,801,804],{"href":802,"rel":803},"https://developer.mozilla.org/en-US/docs/Web/API/URL",[228],"URL",", and ",[214,807,810],{"href":808,"rel":809},"https://developer.mozilla.org/en-US/docs/Web/API/Headers",[228],"Headers",", without introducing new conventions on top of the standards.",[190,813,814,815,820],{},"We have launched a new initiative to strongly type Web APIs: ",[214,816,819],{"href":817,"rel":818},"https://github.com/unjs/fetchdts",[228],"✅ fetchdts",". Integrated into the H3, now we combine the best of both worlds—standards and the convenience of types.",[363,822,824],{"className":365,"code":823,"language":367,"meta":194,"style":194},"import { defineHandler } from \"h3\";\n\nconst handler = defineHandler(async (event) => {\n  // URL Parsing\n  const { pathname, searchParams } = event.url;\n\n  // Access to request headers (try auto-completion in editor!)\n  const accept = event.req.headers.get(\"Accept\");\n\n  // Read body\n  const bodyStream = await event.req.body;\n  const bodyText = await event.req.text();\n  const bodyJSON = await event.req.json();\n  const bodyFormData = await event.req.formData();\n\n  // Access to runtime specific context\n  const { deno, bun, node } = event.req.runtime;\n\n  // Prepare response (h3 does this smartly)\n  event.res.headers.set(\"Content-Type\", \"application/json\");\n\n  return { hello: \"web\" };\n});\n",[299,825,826,839,843,872,877,902,906,911,932,936,941,956,977,996,1015,1020,1026,1053,1058,1064,1085,1090,1105],{"__ignoreMap":194},[371,827,828,830,833,835,837],{"class":373,"line":374},[371,829,384],{"class":383},[371,831,832],{"class":387}," { defineHandler } ",[371,834,391],{"class":383},[371,836,575],{"class":394},[371,838,398],{"class":387},[371,840,841],{"class":373,"line":195},[371,842,405],{"emptyLinePlaceholder":404},[371,844,845,847,850,852,855,857,860,862,865,867,869],{"class":373,"line":401},[371,846,586],{"class":383},[371,848,849],{"class":424}," handler",[371,851,592],{"class":383},[371,853,854],{"class":411}," defineHandler",[371,856,443],{"class":387},[371,858,859],{"class":383},"async",[371,861,687],{"class":387},[371,863,864],{"class":446},"event",[371,866,691],{"class":387},[371,868,614],{"class":383},[371,870,871],{"class":387}," {\n",[371,873,874],{"class":373,"line":408},[371,875,876],{"class":377},"  // URL Parsing\n",[371,878,879,882,885,888,890,893,896,899],{"class":373,"line":418},[371,880,881],{"class":383},"  const",[371,883,884],{"class":387}," { ",[371,886,887],{"class":424},"pathname",[371,889,258],{"class":387},[371,891,892],{"class":424},"searchParams",[371,894,895],{"class":387}," } ",[371,897,898],{"class":383},"=",[371,900,901],{"class":387}," event.url;\n",[371,903,904],{"class":373,"line":431},[371,905,405],{"emptyLinePlaceholder":404},[371,907,908],{"class":373,"line":437},[371,909,910],{"class":377},"  // Access to request headers (try auto-completion in editor!)\n",[371,912,913,915,918,920,923,925,927,930],{"class":373,"line":453},[371,914,881],{"class":383},[371,916,917],{"class":424}," accept",[371,919,592],{"class":383},[371,921,922],{"class":387}," event.req.headers.",[371,924,603],{"class":411},[371,926,443],{"class":387},[371,928,929],{"class":394},"\"Accept\"",[371,931,476],{"class":387},[371,933,934],{"class":373,"line":459},[371,935,405],{"emptyLinePlaceholder":404},[371,937,938],{"class":373,"line":479},[371,939,940],{"class":377},"  // Read body\n",[371,942,943,945,948,950,953],{"class":373,"line":485},[371,944,881],{"class":383},[371,946,947],{"class":424}," bodyStream",[371,949,592],{"class":383},[371,951,952],{"class":383}," await",[371,954,955],{"class":387}," event.req.body;\n",[371,957,959,961,964,966,968,971,974],{"class":373,"line":958},12,[371,960,881],{"class":383},[371,962,963],{"class":424}," bodyText",[371,965,592],{"class":383},[371,967,952],{"class":383},[371,969,970],{"class":387}," event.req.",[371,972,973],{"class":411},"text",[371,975,976],{"class":387},"();\n",[371,978,980,982,985,987,989,991,994],{"class":373,"line":979},13,[371,981,881],{"class":383},[371,983,984],{"class":424}," bodyJSON",[371,986,592],{"class":383},[371,988,952],{"class":383},[371,990,970],{"class":387},[371,992,993],{"class":411},"json",[371,995,976],{"class":387},[371,997,999,1001,1004,1006,1008,1010,1013],{"class":373,"line":998},14,[371,1000,881],{"class":383},[371,1002,1003],{"class":424}," bodyFormData",[371,1005,592],{"class":383},[371,1007,952],{"class":383},[371,1009,970],{"class":387},[371,1011,1012],{"class":411},"formData",[371,1014,976],{"class":387},[371,1016,1018],{"class":373,"line":1017},15,[371,1019,405],{"emptyLinePlaceholder":404},[371,1021,1023],{"class":373,"line":1022},16,[371,1024,1025],{"class":377},"  // Access to runtime specific context\n",[371,1027,1029,1031,1033,1036,1038,1041,1043,1046,1048,1050],{"class":373,"line":1028},17,[371,1030,881],{"class":383},[371,1032,884],{"class":387},[371,1034,1035],{"class":424},"deno",[371,1037,258],{"class":387},[371,1039,1040],{"class":424},"bun",[371,1042,258],{"class":387},[371,1044,1045],{"class":424},"node",[371,1047,895],{"class":387},[371,1049,898],{"class":383},[371,1051,1052],{"class":387}," event.req.runtime;\n",[371,1054,1056],{"class":373,"line":1055},18,[371,1057,405],{"emptyLinePlaceholder":404},[371,1059,1061],{"class":373,"line":1060},19,[371,1062,1063],{"class":377},"  // Prepare response (h3 does this smartly)\n",[371,1065,1067,1070,1073,1075,1078,1080,1083],{"class":373,"line":1066},20,[371,1068,1069],{"class":387},"  event.res.headers.",[371,1071,1072],{"class":411},"set",[371,1074,443],{"class":387},[371,1076,1077],{"class":394},"\"Content-Type\"",[371,1079,258],{"class":387},[371,1081,1082],{"class":394},"\"application/json\"",[371,1084,476],{"class":387},[371,1086,1088],{"class":373,"line":1087},21,[371,1089,405],{"emptyLinePlaceholder":404},[371,1091,1093,1096,1099,1102],{"class":373,"line":1092},22,[371,1094,1095],{"class":383},"  return",[371,1097,1098],{"class":387}," { hello: ",[371,1100,1101],{"class":394},"\"web\"",[371,1103,1104],{"class":387}," };\n",[371,1106,1108],{"class":373,"line":1107},23,[371,1109,488],{"class":387},[190,1111,1112,1113,1118],{},"Now go ahead and call handler ",[214,1114,1115],{"href":752},[299,1116,1117],{},".fetch",":",[363,1120,1122],{"className":365,"code":1121,"language":367,"meta":194,"style":194},"const response = await handler.fetch(\"/\");\n\n// 🧙 Typed response: { hello: string; }\nconst json = await response.json();\n",[299,1123,1124,1146,1150,1155],{"__ignoreMap":194},[371,1125,1126,1128,1131,1133,1135,1138,1140,1142,1144],{"class":373,"line":374},[371,1127,586],{"class":383},[371,1129,1130],{"class":424}," response",[371,1132,592],{"class":383},[371,1134,952],{"class":383},[371,1136,1137],{"class":387}," handler.",[371,1139,762],{"class":411},[371,1141,443],{"class":387},[371,1143,608],{"class":394},[371,1145,476],{"class":387},[371,1147,1148],{"class":373,"line":195},[371,1149,405],{"emptyLinePlaceholder":404},[371,1151,1152],{"class":373,"line":401},[371,1153,1154],{"class":377},"// 🧙 Typed response: { hello: string; }\n",[371,1156,1157,1159,1162,1164,1166,1169,1171],{"class":373,"line":408},[371,1158,586],{"class":383},[371,1160,1161],{"class":424}," json",[371,1163,592],{"class":383},[371,1165,952],{"class":383},[371,1167,1168],{"class":387}," response.",[371,1170,993],{"class":411},[371,1172,976],{"class":387},[490,1174,1175],{},[190,1176,1177],{},"\nYou can directly use event handlers as a standalone, even smaller web handlers without h3 core!",[291,1179,1181],{"id":1180},"middleware-and-plugins","🧩 Middleware and Plugins",[190,1183,1184,1185,1188,1189,1194],{},"H3 now offers an ergonomic, composable way to chain middleware using ",[299,1186,1187],{},"next()"," function (inspired by ",[214,1190,1193],{"href":1191,"rel":1192},"https://hono.dev/docs/guides/middleware",[228],"Hono middleware"," 💛).",[190,1196,1197,1198,529],{},"Additionally, we have introduced a simple yet powerful pattern to extend H3 apps using reusable ",[214,1199,538],{"href":77},[1201,1202,1203,1333,1428,1538,1645,1768],"CodeGroup",{},[363,1204,1206],{"className":365,"code":1205,"filename":535,"language":367,"meta":194,"style":194},"import { H3 } from \"h3\";\n\nconst app = new H3().use(async (event, next) => {\n  // ... before response ...\n  const body = await next();\n  // ... after response ...\n  event.res.headers.append(\"x-middleware\", \"works\");\n  event.waitUntil(sendMetrics(event));\n  return body;\n});\n",[299,1207,1208,1221,1225,1261,1266,1282,1287,1306,1322,1329],{"__ignoreMap":194},[371,1209,1210,1212,1215,1217,1219],{"class":373,"line":374},[371,1211,384],{"class":383},[371,1213,1214],{"class":387}," { H3 } ",[371,1216,391],{"class":383},[371,1218,575],{"class":394},[371,1220,398],{"class":387},[371,1222,1223],{"class":373,"line":195},[371,1224,405],{"emptyLinePlaceholder":404},[371,1226,1227,1229,1231,1233,1235,1237,1239,1242,1244,1246,1248,1250,1252,1255,1257,1259],{"class":373,"line":401},[371,1228,586],{"class":383},[371,1230,589],{"class":424},[371,1232,592],{"class":383},[371,1234,465],{"class":383},[371,1236,597],{"class":411},[371,1238,600],{"class":387},[371,1240,1241],{"class":411},"use",[371,1243,443],{"class":387},[371,1245,859],{"class":383},[371,1247,687],{"class":387},[371,1249,864],{"class":446},[371,1251,258],{"class":387},[371,1253,1254],{"class":446},"next",[371,1256,691],{"class":387},[371,1258,614],{"class":383},[371,1260,871],{"class":387},[371,1262,1263],{"class":373,"line":408},[371,1264,1265],{"class":377},"  // ... before response ...\n",[371,1267,1268,1270,1273,1275,1277,1280],{"class":373,"line":418},[371,1269,881],{"class":383},[371,1271,1272],{"class":424}," body",[371,1274,592],{"class":383},[371,1276,952],{"class":383},[371,1278,1279],{"class":411}," next",[371,1281,976],{"class":387},[371,1283,1284],{"class":373,"line":431},[371,1285,1286],{"class":377},"  // ... after response ...\n",[371,1288,1289,1291,1294,1296,1299,1301,1304],{"class":373,"line":437},[371,1290,1069],{"class":387},[371,1292,1293],{"class":411},"append",[371,1295,443],{"class":387},[371,1297,1298],{"class":394},"\"x-middleware\"",[371,1300,258],{"class":387},[371,1302,1303],{"class":394},"\"works\"",[371,1305,476],{"class":387},[371,1307,1308,1311,1314,1316,1319],{"class":373,"line":453},[371,1309,1310],{"class":387},"  event.",[371,1312,1313],{"class":411},"waitUntil",[371,1315,443],{"class":387},[371,1317,1318],{"class":411},"sendMetrics",[371,1320,1321],{"class":387},"(event));\n",[371,1323,1324,1326],{"class":373,"line":459},[371,1325,1095],{"class":383},[371,1327,1328],{"class":387}," body;\n",[371,1330,1331],{"class":373,"line":479},[371,1332,488],{"class":387},[363,1334,1337],{"className":365,"code":1335,"filename":1336,"language":367,"meta":194,"style":194},"import { defineHandler, basicAuth } from \"h3\";\n\nexport default defineHandler({\n  middleware: [basicAuth({ password: \"test\" })],\n  handler: (event) => `Hello ${event.context.basicAuth?.username}!`,\n});\n","basic auth",[299,1338,1339,1352,1356,1368,1385,1424],{"__ignoreMap":194},[371,1340,1341,1343,1346,1348,1350],{"class":373,"line":374},[371,1342,384],{"class":383},[371,1344,1345],{"class":387}," { defineHandler, basicAuth } ",[371,1347,391],{"class":383},[371,1349,575],{"class":394},[371,1351,398],{"class":387},[371,1353,1354],{"class":373,"line":195},[371,1355,405],{"emptyLinePlaceholder":404},[371,1357,1358,1361,1364,1366],{"class":373,"line":401},[371,1359,1360],{"class":383},"export",[371,1362,1363],{"class":383}," default",[371,1365,854],{"class":411},[371,1367,415],{"class":387},[371,1369,1370,1373,1376,1379,1382],{"class":373,"line":408},[371,1371,1372],{"class":387},"  middleware: [",[371,1374,1375],{"class":411},"basicAuth",[371,1377,1378],{"class":387},"({ password: ",[371,1380,1381],{"class":394},"\"test\"",[371,1383,1384],{"class":387}," })],\n",[371,1386,1387,1390,1393,1395,1397,1399,1402,1404,1406,1409,1411,1413,1416,1419,1422],{"class":373,"line":418},[371,1388,1389],{"class":411},"  handler",[371,1391,1392],{"class":387},": (",[371,1394,864],{"class":446},[371,1396,691],{"class":387},[371,1398,614],{"class":383},[371,1400,1401],{"class":394}," `Hello ${",[371,1403,864],{"class":387},[371,1405,529],{"class":394},[371,1407,1408],{"class":387},"context",[371,1410,529],{"class":394},[371,1412,1375],{"class":387},[371,1414,1415],{"class":394},"?.",[371,1417,1418],{"class":387},"username",[371,1420,1421],{"class":394},"}!`",[371,1423,428],{"class":387},[371,1425,1426],{"class":373,"line":431},[371,1427,488],{"class":387},[363,1429,1432],{"className":365,"code":1430,"filename":1431,"language":367,"meta":194,"style":194},"import { H3, onRequest } from \"h3\";\n\nconst app = new H3().use(\n  onRequest((event) => {\n    console.log(`Request: [${event.req.method}] ${event.url.pathname}`);\n  }),\n);\n","onRequest",[299,1433,1434,1447,1451,1470,1486,1529,1534],{"__ignoreMap":194},[371,1435,1436,1438,1441,1443,1445],{"class":373,"line":374},[371,1437,384],{"class":383},[371,1439,1440],{"class":387}," { H3, onRequest } ",[371,1442,391],{"class":383},[371,1444,575],{"class":394},[371,1446,398],{"class":387},[371,1448,1449],{"class":373,"line":195},[371,1450,405],{"emptyLinePlaceholder":404},[371,1452,1453,1455,1457,1459,1461,1463,1465,1467],{"class":373,"line":401},[371,1454,586],{"class":383},[371,1456,589],{"class":424},[371,1458,592],{"class":383},[371,1460,465],{"class":383},[371,1462,597],{"class":411},[371,1464,600],{"class":387},[371,1466,1241],{"class":411},[371,1468,1469],{"class":387},"(\n",[371,1471,1472,1475,1478,1480,1482,1484],{"class":373,"line":408},[371,1473,1474],{"class":411},"  onRequest",[371,1476,1477],{"class":387},"((",[371,1479,864],{"class":446},[371,1481,691],{"class":387},[371,1483,614],{"class":383},[371,1485,871],{"class":387},[371,1487,1488,1491,1494,1496,1499,1501,1503,1505,1507,1510,1513,1515,1517,1520,1522,1524,1527],{"class":373,"line":418},[371,1489,1490],{"class":387},"    console.",[371,1492,1493],{"class":411},"log",[371,1495,443],{"class":387},[371,1497,1498],{"class":394},"`Request: [${",[371,1500,864],{"class":387},[371,1502,529],{"class":394},[371,1504,447],{"class":387},[371,1506,529],{"class":394},[371,1508,1509],{"class":387},"method",[371,1511,1512],{"class":394},"}] ${",[371,1514,864],{"class":387},[371,1516,529],{"class":394},[371,1518,1519],{"class":387},"url",[371,1521,529],{"class":394},[371,1523,887],{"class":387},[371,1525,1526],{"class":394},"}`",[371,1528,476],{"class":387},[371,1530,1531],{"class":373,"line":431},[371,1532,1533],{"class":387},"  }),\n",[371,1535,1536],{"class":373,"line":437},[371,1537,476],{"class":387},[363,1539,1542],{"className":365,"code":1540,"filename":1541,"language":367,"meta":194,"style":194},"import { H3, onResponse } from \"h3\";\n\nconst app = new H3().use(\n  onResponse((response, event) => {\n    console.log(`Response: [${event.req.method}] ${event.url.pathname}`, body);\n  }),\n);\n","onResponse",[299,1543,1544,1557,1561,1579,1599,1637,1641],{"__ignoreMap":194},[371,1545,1546,1548,1551,1553,1555],{"class":373,"line":374},[371,1547,384],{"class":383},[371,1549,1550],{"class":387}," { H3, onResponse } ",[371,1552,391],{"class":383},[371,1554,575],{"class":394},[371,1556,398],{"class":387},[371,1558,1559],{"class":373,"line":195},[371,1560,405],{"emptyLinePlaceholder":404},[371,1562,1563,1565,1567,1569,1571,1573,1575,1577],{"class":373,"line":401},[371,1564,586],{"class":383},[371,1566,589],{"class":424},[371,1568,592],{"class":383},[371,1570,465],{"class":383},[371,1572,597],{"class":411},[371,1574,600],{"class":387},[371,1576,1241],{"class":411},[371,1578,1469],{"class":387},[371,1580,1581,1584,1586,1589,1591,1593,1595,1597],{"class":373,"line":408},[371,1582,1583],{"class":411},"  onResponse",[371,1585,1477],{"class":387},[371,1587,1588],{"class":446},"response",[371,1590,258],{"class":387},[371,1592,864],{"class":446},[371,1594,691],{"class":387},[371,1596,614],{"class":383},[371,1598,871],{"class":387},[371,1600,1601,1603,1605,1607,1610,1612,1614,1616,1618,1620,1622,1624,1626,1628,1630,1632,1634],{"class":373,"line":418},[371,1602,1490],{"class":387},[371,1604,1493],{"class":411},[371,1606,443],{"class":387},[371,1608,1609],{"class":394},"`Response: [${",[371,1611,864],{"class":387},[371,1613,529],{"class":394},[371,1615,447],{"class":387},[371,1617,529],{"class":394},[371,1619,1509],{"class":387},[371,1621,1512],{"class":394},[371,1623,864],{"class":387},[371,1625,529],{"class":394},[371,1627,1519],{"class":387},[371,1629,529],{"class":394},[371,1631,887],{"class":387},[371,1633,1526],{"class":394},[371,1635,1636],{"class":387},", body);\n",[371,1638,1639],{"class":373,"line":431},[371,1640,1533],{"class":387},[371,1642,1643],{"class":373,"line":437},[371,1644,476],{"class":387},[363,1646,1649],{"className":365,"code":1647,"filename":1648,"language":367,"meta":194,"style":194},"import { H3, onError } from \"h3\";\n\nconst app = new H3().use(\n  onError((error, event) => {\n    console.error(\n      `[${event.req.method}] ${event.url.pathname} !! ${error.message}`,\n    );\n  }),\n);\n","onError",[299,1650,1651,1664,1668,1686,1706,1714,1755,1760,1764],{"__ignoreMap":194},[371,1652,1653,1655,1658,1660,1662],{"class":373,"line":374},[371,1654,384],{"class":383},[371,1656,1657],{"class":387}," { H3, onError } ",[371,1659,391],{"class":383},[371,1661,575],{"class":394},[371,1663,398],{"class":387},[371,1665,1666],{"class":373,"line":195},[371,1667,405],{"emptyLinePlaceholder":404},[371,1669,1670,1672,1674,1676,1678,1680,1682,1684],{"class":373,"line":401},[371,1671,586],{"class":383},[371,1673,589],{"class":424},[371,1675,592],{"class":383},[371,1677,465],{"class":383},[371,1679,597],{"class":411},[371,1681,600],{"class":387},[371,1683,1241],{"class":411},[371,1685,1469],{"class":387},[371,1687,1688,1691,1693,1696,1698,1700,1702,1704],{"class":373,"line":408},[371,1689,1690],{"class":411},"  onError",[371,1692,1477],{"class":387},[371,1694,1695],{"class":446},"error",[371,1697,258],{"class":387},[371,1699,864],{"class":446},[371,1701,691],{"class":387},[371,1703,614],{"class":383},[371,1705,871],{"class":387},[371,1707,1708,1710,1712],{"class":373,"line":418},[371,1709,1490],{"class":387},[371,1711,1695],{"class":411},[371,1713,1469],{"class":387},[371,1715,1716,1719,1721,1723,1725,1727,1729,1731,1733,1735,1737,1739,1741,1744,1746,1748,1751,1753],{"class":373,"line":431},[371,1717,1718],{"class":394},"      `[${",[371,1720,864],{"class":387},[371,1722,529],{"class":394},[371,1724,447],{"class":387},[371,1726,529],{"class":394},[371,1728,1509],{"class":387},[371,1730,1512],{"class":394},[371,1732,864],{"class":387},[371,1734,529],{"class":394},[371,1736,1519],{"class":387},[371,1738,529],{"class":394},[371,1740,887],{"class":387},[371,1742,1743],{"class":394},"} !! ${",[371,1745,1695],{"class":387},[371,1747,529],{"class":394},[371,1749,1750],{"class":387},"message",[371,1752,1526],{"class":394},[371,1754,428],{"class":387},[371,1756,1757],{"class":373,"line":437},[371,1758,1759],{"class":387},"    );\n",[371,1761,1762],{"class":373,"line":453},[371,1763,1533],{"class":387},[371,1765,1766],{"class":373,"line":459},[371,1767,476],{"class":387},[363,1769,1771],{"className":365,"code":1770,"filename":538,"language":367,"meta":194,"style":194},"import { H3, serve, definePlugin } from \"h3\";\n\nconst logger = definePlugin((h3, _options) => {\n  if (h3.config.debug) {\n    h3.use((req) => {\n      console.log(`[${req.method}] ${req.url}`);\n    });\n  }\n});\n\nconst app = new H3({ debug: true })\n  .register(logger())\n  .all(\"/**\", () => \"Hello!\");\n",[299,1772,1773,1786,1790,1818,1826,1843,1873,1878,1883,1887,1891,1912,1928],{"__ignoreMap":194},[371,1774,1775,1777,1780,1782,1784],{"class":373,"line":374},[371,1776,384],{"class":383},[371,1778,1779],{"class":387}," { H3, serve, definePlugin } ",[371,1781,391],{"class":383},[371,1783,575],{"class":394},[371,1785,398],{"class":387},[371,1787,1788],{"class":373,"line":195},[371,1789,405],{"emptyLinePlaceholder":404},[371,1791,1792,1794,1797,1799,1802,1804,1807,1809,1812,1814,1816],{"class":373,"line":401},[371,1793,586],{"class":383},[371,1795,1796],{"class":424}," logger",[371,1798,592],{"class":383},[371,1800,1801],{"class":411}," definePlugin",[371,1803,1477],{"class":387},[371,1805,1806],{"class":446},"h3",[371,1808,258],{"class":387},[371,1810,1811],{"class":446},"_options",[371,1813,691],{"class":387},[371,1815,614],{"class":383},[371,1817,871],{"class":387},[371,1819,1820,1823],{"class":373,"line":408},[371,1821,1822],{"class":383},"  if",[371,1824,1825],{"class":387}," (h3.config.debug) {\n",[371,1827,1828,1831,1833,1835,1837,1839,1841],{"class":373,"line":418},[371,1829,1830],{"class":387},"    h3.",[371,1832,1241],{"class":411},[371,1834,1477],{"class":387},[371,1836,447],{"class":446},[371,1838,691],{"class":387},[371,1840,614],{"class":383},[371,1842,871],{"class":387},[371,1844,1845,1848,1850,1852,1855,1857,1859,1861,1863,1865,1867,1869,1871],{"class":373,"line":431},[371,1846,1847],{"class":387},"      console.",[371,1849,1493],{"class":411},[371,1851,443],{"class":387},[371,1853,1854],{"class":394},"`[${",[371,1856,447],{"class":387},[371,1858,529],{"class":394},[371,1860,1509],{"class":387},[371,1862,1512],{"class":394},[371,1864,447],{"class":387},[371,1866,529],{"class":394},[371,1868,1519],{"class":387},[371,1870,1526],{"class":394},[371,1872,476],{"class":387},[371,1874,1875],{"class":373,"line":437},[371,1876,1877],{"class":387},"    });\n",[371,1879,1880],{"class":373,"line":453},[371,1881,1882],{"class":387},"  }\n",[371,1884,1885],{"class":373,"line":459},[371,1886,488],{"class":387},[371,1888,1889],{"class":373,"line":479},[371,1890,405],{"emptyLinePlaceholder":404},[371,1892,1893,1895,1897,1899,1901,1903,1906,1909],{"class":373,"line":485},[371,1894,586],{"class":383},[371,1896,589],{"class":424},[371,1898,592],{"class":383},[371,1900,465],{"class":383},[371,1902,597],{"class":411},[371,1904,1905],{"class":387},"({ debug: ",[371,1907,1908],{"class":424},"true",[371,1910,1911],{"class":387}," })\n",[371,1913,1914,1917,1920,1922,1925],{"class":373,"line":958},[371,1915,1916],{"class":387},"  .",[371,1918,1919],{"class":411},"register",[371,1921,443],{"class":387},[371,1923,1924],{"class":411},"logger",[371,1926,1927],{"class":387},"())\n",[371,1929,1930,1932,1935,1937,1940,1942,1944,1947],{"class":373,"line":979},[371,1931,1916],{"class":387},[371,1933,1934],{"class":411},"all",[371,1936,443],{"class":387},[371,1938,1939],{"class":394},"\"/**\"",[371,1941,611],{"class":387},[371,1943,614],{"class":383},[371,1945,1946],{"class":394}," \"Hello!\"",[371,1948,476],{"class":387},[769,1950,1951],{},[190,1952,1953,1954,1956],{},"\nAccepting ",[299,1955,1254],{}," callback is optional. Middleware can be written like v1 without returning a response.",[291,1958,1960],{"id":1959},"️-migration-from-version-1","⬆️ Migration from Version 1",[190,1962,1963],{},"We've tried to minimize breaking changes. Most of utilities preserved backward compatibility.",[208,1965,1966],{"to":163},[190,1967,1968,1969,529],{},"Check out ",[214,1970,1971],{"href":163},"Migration Guide",[291,1973,1975],{"id":1974},"unified-http-server-tools-for-everyone","🙌 Unified H(TTP) Server Tools for Everyone",[190,1977,1978,1979,1984,1985,1990,1991,1996,1997,1194],{},"H3 and related projects moved to a dedicated ",[214,1980,1983],{"href":1981,"rel":1982},"https://github.com/h3js",[228],"github org"," and new ",[214,1986,1989],{"href":1987,"rel":1988},"https://h3.dev",[228],"h3.dev"," domain (thanks to the donation from ",[214,1992,1995],{"href":1993,"rel":1994},"https://syntax.fm/",[228],"syntax.fm"," and other ",[214,1998,2000],{"href":1999},"/#sponsors","sponsors",[190,2002,2003],{},"Under the H3 umbrella, we maintain several key components for universal JavaScript servers.",[190,2005,2006,2007,2010],{},"All fully open and usable with ",[217,2008,2009],{},"or without"," H3, and with any JavaScript runtime.",[272,2012,2013,2021,2029,2035],{},[275,2014,2015,2020],{},[214,2016,2019],{"href":2017,"rel":2018},"https://github.com/h3js/h3",[228],"⚡️ h3",": Minimal HTTP Framework.",[275,2022,2023,2028],{},[214,2024,2027],{"href":2025,"rel":2026},"https://github.com/h3js/rou3",[228],"🌳 rou3",": Lightweight JavaScript Router.",[275,2030,2031,2034],{},[214,2032,353],{"href":351,"rel":2033},[228],": Universal Web-based Server API.",[275,2036,2037,2042],{},[214,2038,2041],{"href":2039,"rel":2040},"https://crossws.h3.dev",[228],"🔌 crossws",": Cross-platform WebSocket support.",[291,2044,2046],{"id":2045},"️-special-thanks","❤️ Special Thanks",[190,2048,2049,2050,2055,2056,2061,2062,525,2067,805,2072,2074],{},"This release would not have been possible without wonderful ",[214,2051,2054],{"href":2052,"rel":2053},"https://github.com/h3js/h3/graphs/contributors",[228],"contributors",", feedback from the ",[214,2057,2060],{"href":2058,"rel":2059},"https://discord.h3.dev",[228],"community",", inspirations from web-standard frameworks including ",[214,2063,2066],{"href":2064,"rel":2065},"https://hono.dev/",[228],"Hono",[214,2068,2071],{"href":2069,"rel":2070},"https://elysiajs.com/",[228],"Elysia",[214,2073,2000],{"href":1999}," who made it possible to work on open source.",[291,2076,2078],{"id":2077},"️-roadmap-to-v2-stable","🗺️ Roadmap to v2 (stable)",[190,2080,2081],{},[217,2082,2083],{},"Next steps:",[272,2085,2086,2089,2092],{},[275,2087,2088],{},"Gather feedback from community.",[275,2090,2091],{},"Finalize API updates based on feedbacks.",[275,2093,2094,2095,2098],{},"Ensure ecosystem compatibility and upgrade for ",[214,2096,235],{"href":233,"rel":2097},[228]," v3.",[2100,2101,2102],"callout",{"to":2058},[190,2103,2104,2105,2109],{},"Join our ",[214,2106,2108],{"href":2058,"rel":2107},[228],"Discord"," to share your experience and feedback!",[208,2111,2112],{"to":6},[190,2113,212,2114,220],{},[214,2115,2116],{"href":6},[217,2117,219],{},[2119,2120,2121],"style",{},"html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}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);}",{"title":194,"searchDepth":195,"depth":195,"links":2123},[2124,2125,2126,2127,2128,2129,2130,2131,2132],{"id":293,"depth":195,"text":294},{"id":501,"depth":195,"text":502},{"id":638,"depth":195,"text":639},{"id":787,"depth":195,"text":788},{"id":1180,"depth":195,"text":1181},{"id":1959,"depth":195,"text":1960},{"id":1974,"depth":195,"text":1975},{"id":2045,"depth":195,"text":2046},{"id":2077,"depth":195,"text":2078},"⚡ H3 v2 beta is here — fully rewritten on web standards, backward-compatible, and faster than ever!",{"date":2135,"category":2136,"authors":2137,"icon":175},"2025-06-10","release",[2138],{"name":2139,"github":2140},"Pooya Parsa","pi0",{"icon":175},{"title":181,"description":2133},"_Gc1GFOhnKksZAwOYig0rmBniGFvwtrf58WA-j5AdSQ",{"id":2145,"title":177,"body":2146,"description":3350,"extension":197,"meta":3351,"navigation":3355,"path":178,"seo":3356,"stem":179,"__hash__":3357},"content/99.blog/1.v1.8.md",{"type":187,"value":2147,"toc":3340,"icon":175},[2148,2164,2181,2194,2197,2216,2220,2236,2257,2266,2374,2381,2394,2397,2426,2430,2450,2461,2661,2671,2675,2678,2835,2839,2842,2855,2964,2968,2984,3174,3178,3181,3224,3228,3237,3244,3304,3311,3318,3325,3329,3337],[2149,2150,2151],"blockquote",{},[190,2152,2153,2154,525,2158,2163],{},"H3 is a versatile H(TTP) framework written in TypeScript that powers both ",[214,2155,235],{"href":2156,"rel":2157},"https://nitro.unjs.io/",[228],[214,2159,2162],{"href":2160,"rel":2161},"https://nuxt.com/",[228],"Nuxt"," today.",[190,2165,2166,2171,2172,2176,2177,2180],{},[214,2167,2170],{"href":2168,"rel":2169},"https://github.com/unjs/h3/tree/cbc8909b2003d6d5df694ab7a36aa067cc990c74",[228],"Almost two years ago",", we made H3 with the ambition to become the smallest HTTP framework for ",[214,2173,2175],{"href":2160,"rel":2174},[228],"Nuxt 3",", ensuring compatibility with ",[214,2178,269],{"href":267,"rel":2179},[228]," and providing an elegant developer experience. It also aimed to have a futuristic design, being adaptable to Edge and Web Worker runtimes, a concept that was relatively new at the time.",[190,2182,2183,2184,2188,2189,2193],{},"During the same period, we also developed ",[214,2185,229],{"href":2186,"rel":2187},"https://github.com/unjs/unenv/tree/main",[228],", a thin layer that enabled the utilization of Node.js libraries and HTTP middleware for Edge-compatible runtimes without the need for Node.js. This innovation played a pivotal role in enabling us to harness the power of the NPM and Node.js ecosystem without starting everything from scratch for web compatibility. The synergistic combination of H3 and unenv culminated in making ",[214,2190,235],{"href":2191,"rel":2192},"https://nitro.unjs.io",[228]," one of the pioneering web frameworks fully compatible with Edge runtimes.",[190,2195,2196],{},"This latest release takes H3 even closer to offering native Web API compatibility right out of the box.",[2149,2198,2199],{},[190,2200,2201,2202,525,2205,2208,2209,525,2212,2215],{},"🚀 This release is immediately available for all ecosystem packages including ",[214,2203,235],{"href":2156,"rel":2204},[228],[214,2206,2175],{"href":2160,"rel":2207},[228],". Please remember to refresh your ",[299,2210,2211],{},"lockfile",[299,2213,2214],{},"node_modules"," to receive the updates.",[291,2217,2219],{"id":2218},"web-and-plain-adapters","Web and Plain Adapters",[190,2221,2222,2223,2227,2228,2231,2232,2235],{},"We have introduced a new built-in adapter with a ",[214,2224,762],{"href":2225,"rel":2226},"https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API",[228],"-compatible signature, with ",[214,2229,99],{"href":794,"rel":2230},[228]," as input and ",[214,2233,104],{"href":798,"rel":2234},[228]," as the return value.",[190,2237,2238,2239,258,2244,258,2249,805,2252,529],{},"What this signifies is that you can now seamlessly deploy your H3 applications on runtimes such as ",[214,2240,2243],{"href":2241,"rel":2242},"https://workers.cloudflare.com/",[228],"Cloudflare Workers",[214,2245,2248],{"href":2246,"rel":2247},"https://deno.com/deploy",[228],"Deno Deploy",[214,2250,263],{"href":261,"rel":2251},[228],[214,2253,2256],{"href":2254,"rel":2255},"https://lagon.app/",[228],"Lagon",[190,2258,2259,2260,2265],{},"For practical examples and a demo, check out the ",[214,2261,2264],{"href":2262,"rel":2263},"https://github.com/pi0/h3-on-edge",[228],"h3-on-edge"," repository.",[363,2267,2271],{"className":2268,"code":2269,"language":2270,"meta":194,"style":194},"language-ts shiki shiki-themes github-light github-dark github-dark","// import { createApp, eventHandler, toWebHandler } from 'h3'\nimport { createApp, eventHandler, toWebHandler } from \"https://esm.sh/h3@1.8.0\";\n\nconst app = createApp();\n\napp.use(\n  \"/\",\n  eventHandler((event) => \"H3 works on edge!\"),\n);\n\nconst webHandler = toWebHandler(app); // (Request) => Promise\u003CResponse>\n","ts",[299,2272,2273,2278,2292,2296,2309,2313,2322,2329,2348,2352,2356],{"__ignoreMap":194},[371,2274,2275],{"class":373,"line":374},[371,2276,2277],{"class":377},"// import { createApp, eventHandler, toWebHandler } from 'h3'\n",[371,2279,2280,2282,2285,2287,2290],{"class":373,"line":195},[371,2281,384],{"class":383},[371,2283,2284],{"class":387}," { createApp, eventHandler, toWebHandler } ",[371,2286,391],{"class":383},[371,2288,2289],{"class":394}," \"https://esm.sh/h3@1.8.0\"",[371,2291,398],{"class":387},[371,2293,2294],{"class":373,"line":401},[371,2295,405],{"emptyLinePlaceholder":404},[371,2297,2298,2300,2302,2304,2307],{"class":373,"line":408},[371,2299,586],{"class":383},[371,2301,589],{"class":424},[371,2303,592],{"class":383},[371,2305,2306],{"class":411}," createApp",[371,2308,976],{"class":387},[371,2310,2311],{"class":373,"line":418},[371,2312,405],{"emptyLinePlaceholder":404},[371,2314,2315,2318,2320],{"class":373,"line":431},[371,2316,2317],{"class":387},"app.",[371,2319,1241],{"class":411},[371,2321,1469],{"class":387},[371,2323,2324,2327],{"class":373,"line":437},[371,2325,2326],{"class":394},"  \"/\"",[371,2328,428],{"class":387},[371,2330,2331,2334,2336,2338,2340,2342,2345],{"class":373,"line":453},[371,2332,2333],{"class":411},"  eventHandler",[371,2335,1477],{"class":387},[371,2337,864],{"class":446},[371,2339,691],{"class":387},[371,2341,614],{"class":383},[371,2343,2344],{"class":394}," \"H3 works on edge!\"",[371,2346,2347],{"class":387},"),\n",[371,2349,2350],{"class":373,"line":459},[371,2351,476],{"class":387},[371,2353,2354],{"class":373,"line":479},[371,2355,405],{"emptyLinePlaceholder":404},[371,2357,2358,2360,2363,2365,2368,2371],{"class":373,"line":485},[371,2359,586],{"class":383},[371,2361,2362],{"class":424}," webHandler",[371,2364,592],{"class":383},[371,2366,2367],{"class":411}," toWebHandler",[371,2369,2370],{"class":387},"(app); ",[371,2372,2373],{"class":377},"// (Request) => Promise\u003CResponse>\n",[190,2375,2376,2377,2380],{},"In addition to web handlers, we've also introduced a new plain adapter format using the ",[299,2378,2379],{},"toPlainHandler(app)"," syntax. This facilitates the seamless integration of H3 with any serverless platform using plain input and response objects.",[190,2382,2383,2384,2388,2389,529],{},"All of these became possible due to the implementation of new streaming capabilities and ",[214,2385,229],{"href":2386,"rel":2387},"https://unenv.unjs.io",[228],", which provides a lightweight Node.js compatibility layer. Previously, this level of integration was only possible through ",[214,2390,2393],{"href":2391,"rel":2392},"https://nitro.unjs.io/deploy",[228],"Nitro presets",[190,2395,2396],{},"Furthermore, we've introduced a set of new web helpers:",[272,2398,2399,2408,2414,2420],{},[275,2400,2401,2404,2405,529],{},[299,2402,2403],{},"toWebRequest(event)",": Convert a H3 event object into a web ",[214,2406,99],{"href":794,"rel":2407},[228],[275,2409,2410,2413],{},[299,2411,2412],{},"getRequestWebStream(event)",": Retrieve a readable stream from the current H3 event request.",[275,2415,2416,2419],{},[299,2417,2418],{},"fromPlainHandler(plainHandler)",": Convert a plain object handler into an H3-compatible event handler.",[275,2421,2422,2425],{},[299,2423,2424],{},"fromWebHandler(webHandler)",": Convert a Web Request/Response handler into an H3-compatible event handler.",[291,2427,2429],{"id":2428},"web-streams-support","Web Streams Support",[190,2431,2432,2433,2438,2439,2444,2445,335],{},"H3 now supports native ",[214,2434,2437],{"href":2435,"rel":2436},"https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream",[228],"Readable Stream"," response support. This inherently brings compatibility with libraries like ",[214,2440,2443],{"href":2441,"rel":2442},"https://github.com/vercel/ai",[228],"Vercel/AI",", which rely on streaming responses (",[214,2446,2449],{"href":2447,"rel":2448},"https://github.com/Hebilicious/nuxt-openai-vercel-edge-demo",[228],"demo",[190,2451,2452,2453,2456,2457,2460],{},"Leveraging this functionality is straightforward—simply return a ",[214,2454,2437],{"href":2435,"rel":2455},[228]," or ",[214,2458,104],{"href":798,"rel":2459},[228]," object from your event handlers.",[363,2462,2464],{"className":2268,"code":2463,"language":2270,"meta":194,"style":194},"export default defineHandler((event) => {\n  setResponseHeader(event, \"Content-Type\", \"text/html\");\n  const encoder = new TextEncoder();\n  const stream = new ReadableStream({\n    async start(controller) {\n      for (const token of \"Streaming is so cool with H3!\".split(\" \")) {\n        controller.enqueue(encoder.encode(token));\n        await new Promise((resolve) => {\n          setTimeout(resolve, 300);\n        });\n      }\n    },\n  });\n  return stream;\n});\n",[299,2465,2466,2484,2501,2517,2533,2548,2579,2596,2617,2630,2635,2640,2645,2650,2657],{"__ignoreMap":194},[371,2467,2468,2470,2472,2474,2476,2478,2480,2482],{"class":373,"line":374},[371,2469,1360],{"class":383},[371,2471,1363],{"class":383},[371,2473,854],{"class":411},[371,2475,1477],{"class":387},[371,2477,864],{"class":446},[371,2479,691],{"class":387},[371,2481,614],{"class":383},[371,2483,871],{"class":387},[371,2485,2486,2489,2492,2494,2496,2499],{"class":373,"line":195},[371,2487,2488],{"class":411},"  setResponseHeader",[371,2490,2491],{"class":387},"(event, ",[371,2493,1077],{"class":394},[371,2495,258],{"class":387},[371,2497,2498],{"class":394},"\"text/html\"",[371,2500,476],{"class":387},[371,2502,2503,2505,2508,2510,2512,2515],{"class":373,"line":401},[371,2504,881],{"class":383},[371,2506,2507],{"class":424}," encoder",[371,2509,592],{"class":383},[371,2511,465],{"class":383},[371,2513,2514],{"class":411}," TextEncoder",[371,2516,976],{"class":387},[371,2518,2519,2521,2524,2526,2528,2531],{"class":373,"line":408},[371,2520,881],{"class":383},[371,2522,2523],{"class":424}," stream",[371,2525,592],{"class":383},[371,2527,465],{"class":383},[371,2529,2530],{"class":411}," ReadableStream",[371,2532,415],{"class":387},[371,2534,2535,2538,2541,2543,2546],{"class":373,"line":418},[371,2536,2537],{"class":383},"    async",[371,2539,2540],{"class":411}," start",[371,2542,443],{"class":387},[371,2544,2545],{"class":446},"controller",[371,2547,450],{"class":387},[371,2549,2550,2553,2555,2557,2560,2563,2566,2568,2571,2573,2576],{"class":373,"line":431},[371,2551,2552],{"class":383},"      for",[371,2554,687],{"class":387},[371,2556,586],{"class":383},[371,2558,2559],{"class":424}," token",[371,2561,2562],{"class":383}," of",[371,2564,2565],{"class":394}," \"Streaming is so cool with H3!\"",[371,2567,529],{"class":387},[371,2569,2570],{"class":411},"split",[371,2572,443],{"class":387},[371,2574,2575],{"class":394},"\" \"",[371,2577,2578],{"class":387},")) {\n",[371,2580,2581,2584,2587,2590,2593],{"class":373,"line":437},[371,2582,2583],{"class":387},"        controller.",[371,2585,2586],{"class":411},"enqueue",[371,2588,2589],{"class":387},"(encoder.",[371,2591,2592],{"class":411},"encode",[371,2594,2595],{"class":387},"(token));\n",[371,2597,2598,2601,2603,2606,2608,2611,2613,2615],{"class":373,"line":453},[371,2599,2600],{"class":383},"        await",[371,2602,465],{"class":383},[371,2604,2605],{"class":424}," Promise",[371,2607,1477],{"class":387},[371,2609,2610],{"class":446},"resolve",[371,2612,691],{"class":387},[371,2614,614],{"class":383},[371,2616,871],{"class":387},[371,2618,2619,2622,2625,2628],{"class":373,"line":459},[371,2620,2621],{"class":411},"          setTimeout",[371,2623,2624],{"class":387},"(resolve, ",[371,2626,2627],{"class":424},"300",[371,2629,476],{"class":387},[371,2631,2632],{"class":373,"line":479},[371,2633,2634],{"class":387},"        });\n",[371,2636,2637],{"class":373,"line":485},[371,2638,2639],{"class":387},"      }\n",[371,2641,2642],{"class":373,"line":958},[371,2643,2644],{"class":387},"    },\n",[371,2646,2647],{"class":373,"line":979},[371,2648,2649],{"class":387},"  });\n",[371,2651,2652,2654],{"class":373,"line":998},[371,2653,1095],{"class":383},[371,2655,2656],{"class":387}," stream;\n",[371,2658,2659],{"class":373,"line":1017},[371,2660,488],{"class":387},[190,2662,2663,2664,525,2667,2670],{},"For more advanced scenarios, you might choose to utilize the ",[299,2665,2666],{},"sendStream(event, stream)",[299,2668,2669],{},"sendWebResponse(event, stream)"," utilities instead of directly returning the stream.",[291,2672,2674],{"id":2673},"object-syntax-event-handlers","Object Syntax Event Handlers",[190,2676,2677],{},"H3 introduces support for defining event handlers using an Object syntax. With this approach, you can define hooks that run before or after each handler, such as authentication or compression middleware.",[363,2679,2681],{"className":2268,"code":2680,"language":2270,"meta":194,"style":194},"const auth = defineRequestMiddleware((event) => {\n  event.context.auth = { name: \"admin\" };\n});\n\nconst compression = defineResponseMiddleware((event) => {\n  // Example: https://stackblitz.com/edit/github-mb6bz3\n});\n\nexport default eventHandler({\n  onRequest: [auth],\n  onResponse: [compression],\n  async handler(event) {\n    return `Hello ${event.context.auth?.name || \"Guest\"}`;\n  },\n});\n",[299,2682,2683,2705,2720,2724,2728,2750,2755,2759,2763,2774,2779,2784,2797,2827,2831],{"__ignoreMap":194},[371,2684,2685,2687,2690,2692,2695,2697,2699,2701,2703],{"class":373,"line":374},[371,2686,586],{"class":383},[371,2688,2689],{"class":424}," auth",[371,2691,592],{"class":383},[371,2693,2694],{"class":411}," defineRequestMiddleware",[371,2696,1477],{"class":387},[371,2698,864],{"class":446},[371,2700,691],{"class":387},[371,2702,614],{"class":383},[371,2704,871],{"class":387},[371,2706,2707,2710,2712,2715,2718],{"class":373,"line":195},[371,2708,2709],{"class":387},"  event.context.auth ",[371,2711,898],{"class":383},[371,2713,2714],{"class":387}," { name: ",[371,2716,2717],{"class":394},"\"admin\"",[371,2719,1104],{"class":387},[371,2721,2722],{"class":373,"line":401},[371,2723,488],{"class":387},[371,2725,2726],{"class":373,"line":408},[371,2727,405],{"emptyLinePlaceholder":404},[371,2729,2730,2732,2735,2737,2740,2742,2744,2746,2748],{"class":373,"line":418},[371,2731,586],{"class":383},[371,2733,2734],{"class":424}," compression",[371,2736,592],{"class":383},[371,2738,2739],{"class":411}," defineResponseMiddleware",[371,2741,1477],{"class":387},[371,2743,864],{"class":446},[371,2745,691],{"class":387},[371,2747,614],{"class":383},[371,2749,871],{"class":387},[371,2751,2752],{"class":373,"line":431},[371,2753,2754],{"class":377},"  // Example: https://stackblitz.com/edit/github-mb6bz3\n",[371,2756,2757],{"class":373,"line":437},[371,2758,488],{"class":387},[371,2760,2761],{"class":373,"line":453},[371,2762,405],{"emptyLinePlaceholder":404},[371,2764,2765,2767,2769,2772],{"class":373,"line":459},[371,2766,1360],{"class":383},[371,2768,1363],{"class":383},[371,2770,2771],{"class":411}," eventHandler",[371,2773,415],{"class":387},[371,2775,2776],{"class":373,"line":479},[371,2777,2778],{"class":387},"  onRequest: [auth],\n",[371,2780,2781],{"class":373,"line":485},[371,2782,2783],{"class":387},"  onResponse: [compression],\n",[371,2785,2786,2789,2791,2793,2795],{"class":373,"line":958},[371,2787,2788],{"class":383},"  async",[371,2790,849],{"class":411},[371,2792,443],{"class":387},[371,2794,864],{"class":446},[371,2796,450],{"class":387},[371,2798,2799,2801,2803,2805,2807,2809,2811,2814,2816,2819,2822,2825],{"class":373,"line":979},[371,2800,462],{"class":383},[371,2802,1401],{"class":394},[371,2804,864],{"class":387},[371,2806,529],{"class":394},[371,2808,1408],{"class":387},[371,2810,529],{"class":394},[371,2812,2813],{"class":387},"auth",[371,2815,1415],{"class":394},[371,2817,2818],{"class":387},"name",[371,2820,2821],{"class":383}," ||",[371,2823,2824],{"class":394}," \"Guest\"}`",[371,2826,398],{"class":387},[371,2828,2829],{"class":373,"line":998},[371,2830,482],{"class":387},[371,2832,2833],{"class":373,"line":1017},[371,2834,488],{"class":387},[291,2836,2838],{"id":2837},"typed-event-handler-requests","Typed Event Handler Requests",[190,2840,2841],{},"H3 now supports defining event types using new generic type support.",[190,2843,2844,2845,2848,2849,525,2852,529],{},"When you define types, request utilities will be aware of the event input types. This enhancenment also allows us to enhance type safety for ",[299,2846,2847],{},"$fetch"," handlers in upstream frameworks like ",[214,2850,235],{"href":2156,"rel":2851},[228],[214,2853,2162],{"href":2160,"rel":2854},[228],[363,2856,2858],{"className":2268,"code":2857,"language":2270,"meta":194,"style":194},"export default eventHandler\u003C{ body: { name: string }; query: { id: string } }>(\n  async (event) => {\n    const query = getQuery(event); // Query is typed as { id: string }\n    const body = await readBody(event); // Body is typed as { name: string }\n  },\n);\n",[299,2859,2860,2905,2919,2938,2956,2960],{"__ignoreMap":194},[371,2861,2862,2864,2866,2868,2871,2874,2876,2878,2880,2882,2885,2888,2891,2893,2895,2898,2900,2902],{"class":373,"line":374},[371,2863,1360],{"class":383},[371,2865,1363],{"class":383},[371,2867,2771],{"class":411},[371,2869,2870],{"class":387},"\u003C{ ",[371,2872,2873],{"class":446},"body",[371,2875,1118],{"class":383},[371,2877,884],{"class":387},[371,2879,2818],{"class":446},[371,2881,1118],{"class":383},[371,2883,2884],{"class":424}," string",[371,2886,2887],{"class":387}," }; ",[371,2889,2890],{"class":446},"query",[371,2892,1118],{"class":383},[371,2894,884],{"class":387},[371,2896,2897],{"class":446},"id",[371,2899,1118],{"class":383},[371,2901,2884],{"class":424},[371,2903,2904],{"class":387}," } }>(\n",[371,2906,2907,2909,2911,2913,2915,2917],{"class":373,"line":195},[371,2908,2788],{"class":383},[371,2910,687],{"class":387},[371,2912,864],{"class":446},[371,2914,691],{"class":387},[371,2916,614],{"class":383},[371,2918,871],{"class":387},[371,2920,2921,2924,2927,2929,2932,2935],{"class":373,"line":401},[371,2922,2923],{"class":383},"    const",[371,2925,2926],{"class":424}," query",[371,2928,592],{"class":383},[371,2930,2931],{"class":411}," getQuery",[371,2933,2934],{"class":387},"(event); ",[371,2936,2937],{"class":377},"// Query is typed as { id: string }\n",[371,2939,2940,2942,2944,2946,2948,2951,2953],{"class":373,"line":408},[371,2941,2923],{"class":383},[371,2943,1272],{"class":424},[371,2945,592],{"class":383},[371,2947,952],{"class":383},[371,2949,2950],{"class":411}," readBody",[371,2952,2934],{"class":387},[371,2954,2955],{"class":377},"// Body is typed as { name: string }\n",[371,2957,2958],{"class":373,"line":418},[371,2959,482],{"class":387},[371,2961,2962],{"class":373,"line":431},[371,2963,476],{"class":387},[291,2965,2967],{"id":2966},"runtime-type-safe-request-utils","Runtime + Type-Safe Request Utils",[190,2969,2970,2971,525,2974,2977,2978,2983],{},"Two new utility functions, ",[299,2972,2973],{},"getValidatedQuery(event, validator)",[299,2975,2976],{},"readValidatedBody(event, validator)",", facilitate integration with schema validators such as ",[214,2979,2982],{"href":2980,"rel":2981},"https://zod.dev/",[228],"zod"," for both runtime and type safety.",[363,2985,2987],{"className":2268,"code":2986,"language":2270,"meta":194,"style":194},"import { z } from \"zod\";\n\nconst userSchema = z.object({\n  name: z.string().default(\"Guest\"),\n  email: z.string().email(),\n});\n\nexport default defineHandler(async (event) => {\n  const result = await readValidatedBody(event, (body) =>\n    userSchema.safeParse(body),\n  ); // or `.parse` to directly throw an error\n\n  if (!result.success) throw result.error.issues;\n\n  // User object is validated and typed!\n  return result.data;\n});\n",[299,2988,2989,3003,3007,3024,3044,3059,3063,3067,3089,3113,3124,3132,3136,3154,3158,3163,3170],{"__ignoreMap":194},[371,2990,2991,2993,2996,2998,3001],{"class":373,"line":374},[371,2992,384],{"class":383},[371,2994,2995],{"class":387}," { z } ",[371,2997,391],{"class":383},[371,2999,3000],{"class":394}," \"zod\"",[371,3002,398],{"class":387},[371,3004,3005],{"class":373,"line":195},[371,3006,405],{"emptyLinePlaceholder":404},[371,3008,3009,3011,3014,3016,3019,3022],{"class":373,"line":401},[371,3010,586],{"class":383},[371,3012,3013],{"class":424}," userSchema",[371,3015,592],{"class":383},[371,3017,3018],{"class":387}," z.",[371,3020,3021],{"class":411},"object",[371,3023,415],{"class":387},[371,3025,3026,3029,3032,3034,3037,3039,3042],{"class":373,"line":408},[371,3027,3028],{"class":387},"  name: z.",[371,3030,3031],{"class":411},"string",[371,3033,600],{"class":387},[371,3035,3036],{"class":411},"default",[371,3038,443],{"class":387},[371,3040,3041],{"class":394},"\"Guest\"",[371,3043,2347],{"class":387},[371,3045,3046,3049,3051,3053,3056],{"class":373,"line":418},[371,3047,3048],{"class":387},"  email: z.",[371,3050,3031],{"class":411},[371,3052,600],{"class":387},[371,3054,3055],{"class":411},"email",[371,3057,3058],{"class":387},"(),\n",[371,3060,3061],{"class":373,"line":431},[371,3062,488],{"class":387},[371,3064,3065],{"class":373,"line":437},[371,3066,405],{"emptyLinePlaceholder":404},[371,3068,3069,3071,3073,3075,3077,3079,3081,3083,3085,3087],{"class":373,"line":453},[371,3070,1360],{"class":383},[371,3072,1363],{"class":383},[371,3074,854],{"class":411},[371,3076,443],{"class":387},[371,3078,859],{"class":383},[371,3080,687],{"class":387},[371,3082,864],{"class":446},[371,3084,691],{"class":387},[371,3086,614],{"class":383},[371,3088,871],{"class":387},[371,3090,3091,3093,3096,3098,3100,3103,3106,3108,3110],{"class":373,"line":459},[371,3092,881],{"class":383},[371,3094,3095],{"class":424}," result",[371,3097,592],{"class":383},[371,3099,952],{"class":383},[371,3101,3102],{"class":411}," readValidatedBody",[371,3104,3105],{"class":387},"(event, (",[371,3107,2873],{"class":446},[371,3109,691],{"class":387},[371,3111,3112],{"class":383},"=>\n",[371,3114,3115,3118,3121],{"class":373,"line":479},[371,3116,3117],{"class":387},"    userSchema.",[371,3119,3120],{"class":411},"safeParse",[371,3122,3123],{"class":387},"(body),\n",[371,3125,3126,3129],{"class":373,"line":485},[371,3127,3128],{"class":387},"  ); ",[371,3130,3131],{"class":377},"// or `.parse` to directly throw an error\n",[371,3133,3134],{"class":373,"line":958},[371,3135,405],{"emptyLinePlaceholder":404},[371,3137,3138,3140,3142,3145,3148,3151],{"class":373,"line":979},[371,3139,1822],{"class":383},[371,3141,687],{"class":387},[371,3143,3144],{"class":383},"!",[371,3146,3147],{"class":387},"result.success) ",[371,3149,3150],{"class":383},"throw",[371,3152,3153],{"class":387}," result.error.issues;\n",[371,3155,3156],{"class":373,"line":998},[371,3157,405],{"emptyLinePlaceholder":404},[371,3159,3160],{"class":373,"line":1017},[371,3161,3162],{"class":377},"  // User object is validated and typed!\n",[371,3164,3165,3167],{"class":373,"line":1022},[371,3166,1095],{"class":383},[371,3168,3169],{"class":387}," result.data;\n",[371,3171,3172],{"class":373,"line":1028},[371,3173,488],{"class":387},[291,3175,3177],{"id":3176},"additional-utilities","Additional Utilities",[190,3179,3180],{},"We've introduced several other utilities to further enhance the web app development experience:",[272,3182,3183,3189,3200,3206,3212],{},[275,3184,3185,3188],{},[299,3186,3187],{},"getRequestIP(event, { xForwardedFor? })",": Retrieve the incoming request IP.",[275,3190,3191,3194,3195,529],{},[299,3192,3193],{},"readFormData(event)",": Read the request body into ",[214,3196,3199],{"href":3197,"rel":3198},"https://developer.mozilla.org/en-US/docs/Web/API/FormData",[228],"FormData",[275,3201,3202,3205],{},[299,3203,3204],{},"clearResponseHeaders(event)",": Clear all response headers.",[275,3207,3208,3211],{},[299,3209,3210],{},"removeResponseHeader(event, name)",": Remove a specific response header.",[275,3213,3214,3217,3218,3223],{},[299,3215,3216],{},"serveStatic(event, options)",": Platform-agnostic static asset server. Check out the ",[214,3219,3222],{"href":3220,"rel":3221},"https://github.com/unjs/listhen/blob/af6ea3af3fec4289c00b0ba589ca6f63c6a5dbbd/src/server/dev.ts#L66",[228],"listhen source"," for an example of usage with Node.js.",[291,3225,3227],{"id":3226},"effortless-typescript-development-with-hmr","Effortless TypeScript Development with HMR",[190,3229,3230,3231,3236],{},"We've also released an updated version of ",[214,3232,3235],{"href":3233,"rel":3234},"https://listhen.unjs.io",[228],"unjs/listhen"," that seamlessly integrates with H3 apps.",[190,3238,3239,3240,3243],{},"All you need to do is create an ",[299,3241,3242],{},"index.ts"," file:",[363,3245,3247],{"className":2268,"code":3246,"language":2270,"meta":194,"style":194},"import { createApp, eventHandler } from \"h3\";\n\nexport const app = createApp();\n\napp.use(\"/\", () => \"Hello world!\");\n",[299,3248,3249,3262,3266,3281,3285],{"__ignoreMap":194},[371,3250,3251,3253,3256,3258,3260],{"class":373,"line":374},[371,3252,384],{"class":383},[371,3254,3255],{"class":387}," { createApp, eventHandler } ",[371,3257,391],{"class":383},[371,3259,575],{"class":394},[371,3261,398],{"class":387},[371,3263,3264],{"class":373,"line":195},[371,3265,405],{"emptyLinePlaceholder":404},[371,3267,3268,3270,3273,3275,3277,3279],{"class":373,"line":401},[371,3269,1360],{"class":383},[371,3271,3272],{"class":383}," const",[371,3274,589],{"class":424},[371,3276,592],{"class":383},[371,3278,2306],{"class":411},[371,3280,976],{"class":387},[371,3282,3283],{"class":373,"line":408},[371,3284,405],{"emptyLinePlaceholder":404},[371,3286,3287,3289,3291,3293,3295,3297,3299,3302],{"class":373,"line":418},[371,3288,2317],{"class":387},[371,3290,1241],{"class":411},[371,3292,443],{"class":387},[371,3294,608],{"class":394},[371,3296,611],{"class":387},[371,3298,614],{"class":383},[371,3300,3301],{"class":394}," \"Hello world!\"",[371,3303,476],{"class":387},[190,3305,3306,3307,3310],{},"Run ",[299,3308,3309],{},"npx listhen@latest -w ./index.ts"," to initiate a development server with TypeScript support, Hot Module Replacement (HMR), and static asset server.",[190,3312,3313],{},[214,3314,3317],{"href":3315,"rel":3316},"https://stackblitz.com/github/unjs/h3/tree/main/playground?startScript=dev",[228],"Online Playground",[190,3319,3320],{},[3321,3322],"img",{"alt":3323,"src":3324,"without-border":194},"Screenshot of listhen","https://raw.githubusercontent.com/unjs/listhen/main/.assets/screenshot.png",[291,3326,3328],{"id":3327},"full-changelog","Full Changelog",[190,3330,3331,3332,529],{},"For a comprehensive list of changes, refer to the ",[214,3333,3336],{"href":3334,"rel":3335},"https://github.com/unjs/h3/releases/tag/v1.8.0",[228],"release notes",[2119,3338,3339],{},"html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}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);}",{"title":194,"searchDepth":195,"depth":195,"links":3341},[3342,3343,3344,3345,3346,3347,3348,3349],{"id":2218,"depth":195,"text":2219},{"id":2428,"depth":195,"text":2429},{"id":2673,"depth":195,"text":2674},{"id":2837,"depth":195,"text":2838},{"id":2966,"depth":195,"text":2967},{"id":3176,"depth":195,"text":3177},{"id":3226,"depth":195,"text":3227},{"id":3327,"depth":195,"text":3328},"New H3 release with web and plain adapters, web streams support, object syntax event handlers, typed event handler requests and more!",{"date":3352,"category":2136,"authors":3353,"icon":175},"2023-08-15",[3354],{"name":2139,"github":2140},{"icon":175},{"title":177,"description":3350},"Sr2oMJWVyYVPJnXelzQbTT6r2asavesHYmZCyh_taLE",1768646385964]