[{"data":1,"prerenderedAt":3372},["ShallowReactive",2],{"navigation":3,"-docs-cache":445,"-docs-cache-surround":3367},[4,123,260,266,430,442],{"title":5,"path":6,"stem":7,"children":8,"icon":122},"","\u002Fdocs","1.docs\u002F1.index",[9,12,17,22,27,32,37,42,47,52,57,62,67,72,77,82,87,92,97,102,107,112,117],{"title":10,"path":6,"stem":7,"icon":11},"Introduction","i-lucide-compass",{"title":13,"path":14,"stem":15,"icon":16},"Quick Start","\u002Fdocs\u002Fquick-start","1.docs\u002F2.quick-start","i-lucide-zap",{"title":18,"path":19,"stem":20,"icon":21},"Renderer","\u002Fdocs\u002Frenderer","1.docs\u002F4.renderer","ri:layout-masonry-line",{"title":23,"path":24,"stem":25,"icon":26},"Routing","\u002Fdocs\u002Frouting","1.docs\u002F5.routing","ri:direction-line",{"title":28,"path":29,"stem":30,"icon":31},"Assets","\u002Fdocs\u002Fassets","1.docs\u002F50.assets","ri:image-2-line",{"title":33,"path":34,"stem":35,"icon":36},"Configuration","\u002Fdocs\u002Fconfiguration","1.docs\u002F50.configuration","ri:settings-3-line",{"title":38,"path":39,"stem":40,"icon":41},"Database","\u002Fdocs\u002Fdatabase","1.docs\u002F50.database","ri:database-2-line",{"title":43,"path":44,"stem":45,"icon":46},"Lifecycle","\u002Fdocs\u002Flifecycle","1.docs\u002F50.lifecycle","i-lucide-layers",{"title":48,"path":49,"stem":50,"icon":51},"OpenAPI","\u002Fdocs\u002Fopenapi","1.docs\u002F50.openapi","ri:contract-line",{"title":53,"path":54,"stem":55,"icon":56},"Plugins","\u002Fdocs\u002Fplugins","1.docs\u002F50.plugins","ri:plug-line",{"title":58,"path":59,"stem":60,"icon":61},"Prerendering","\u002Fdocs\u002Fprerendering","1.docs\u002F50.prerendering","ri:file-copy-2-line",{"title":63,"path":64,"stem":65,"icon":66},"Tasks","\u002Fdocs\u002Ftasks","1.docs\u002F50.tasks","codicon:run-all",{"title":68,"path":69,"stem":70,"icon":71},"WebSocket","\u002Fdocs\u002Fwebsocket","1.docs\u002F50.websocket","ri:broadcast-fill",{"title":73,"path":74,"stem":75,"icon":76},"Modules","\u002Fdocs\u002Fmodules","1.docs\u002F55.modules","i-lucide-puzzle",{"title":78,"path":79,"stem":80,"icon":81},"Server Entry","\u002Fdocs\u002Fserver-entry","1.docs\u002F6.server-entry","ri:server-line",{"title":83,"path":84,"stem":85,"icon":86},"CLI","\u002Fdocs\u002Fcli","1.docs\u002F60.cli","i-lucide-terminal",{"title":88,"path":89,"stem":90,"icon":91},"Vite","\u002Fdocs\u002Fvite","1.docs\u002F61.vite","i-logos-vitejs",{"title":93,"path":94,"stem":95,"icon":96},"Utils","\u002Fdocs\u002Futils","1.docs\u002F62.utils","i-lucide-braces",{"title":98,"path":99,"stem":100,"icon":101},"TypeScript","\u002Fdocs\u002Ftypescript","1.docs\u002F63.typescript","i-logos-typescript-icon",{"title":103,"path":104,"stem":105,"icon":106},"Cache","\u002Fdocs\u002Fcache","1.docs\u002F7.cache","ri:speed-line",{"title":108,"path":109,"stem":110,"icon":111},"KV Storage","\u002Fdocs\u002Fstorage","1.docs\u002F8.storage","carbon:datastore",{"title":113,"path":114,"stem":115,"icon":116},"Migration Guide","\u002Fdocs\u002Fmigration","1.docs\u002F99.migration","ri:arrow-right-up-line",{"title":118,"path":119,"stem":120,"icon":121},"Nightly Channel","\u002Fdocs\u002Fnightly","1.docs\u002F99.nightly","ri:moon-fill","i-lucide-book-open",{"title":124,"path":125,"stem":126,"children":127,"icon":129},"Deploy","\u002Fdeploy","2.deploy\u002F0.index",[128,130,155],{"title":124,"path":125,"stem":126,"icon":129},"ri:upload-cloud-2-line",{"title":131,"path":132,"stem":133,"children":134,"page":154},"Runtimes","\u002Fdeploy\u002Fruntimes","2.deploy\u002F10.runtimes",[135,140,145,150],{"title":136,"path":137,"stem":138,"icon":139},"Node.js","\u002Fdeploy\u002Fruntimes\u002Fnode","2.deploy\u002F10.runtimes\u002F1.node","akar-icons:node-fill",{"title":141,"path":142,"stem":143,"icon":144},"Bun","\u002Fdeploy\u002Fruntimes\u002Fbun","2.deploy\u002F10.runtimes\u002Fbun","simple-icons:bun",{"title":146,"path":147,"stem":148,"icon":149},"Deno","\u002Fdeploy\u002Fruntimes\u002Fdeno","2.deploy\u002F10.runtimes\u002Fdeno","simple-icons:deno",{"title":151,"path":152,"stem":153},"Standard","\u002Fdeploy\u002Fruntimes\u002Fstandard","2.deploy\u002F10.runtimes\u002Fstandard",false,{"title":156,"path":157,"stem":158,"children":159,"page":154},"Providers","\u002Fdeploy\u002Fproviders","2.deploy\u002F20.providers",[160,164,168,172,176,180,184,188,192,196,200,204,208,212,216,220,224,228,232,236,240,244,248,252,256],{"title":161,"path":162,"stem":163},"Alwaysdata","\u002Fdeploy\u002Fproviders\u002Falwaysdata","2.deploy\u002F20.providers\u002Falwaysdata",{"title":165,"path":166,"stem":167},"AWS Lambda","\u002Fdeploy\u002Fproviders\u002Faws","2.deploy\u002F20.providers\u002Faws",{"title":169,"path":170,"stem":171},"AWS Amplify","\u002Fdeploy\u002Fproviders\u002Faws-amplify","2.deploy\u002F20.providers\u002Faws-amplify",{"title":173,"path":174,"stem":175},"Azure","\u002Fdeploy\u002Fproviders\u002Fazure","2.deploy\u002F20.providers\u002Fazure",{"title":177,"path":178,"stem":179},"Cleavr","\u002Fdeploy\u002Fproviders\u002Fcleavr","2.deploy\u002F20.providers\u002Fcleavr",{"title":181,"path":182,"stem":183},"Cloudflare","\u002Fdeploy\u002Fproviders\u002Fcloudflare","2.deploy\u002F20.providers\u002Fcloudflare",{"title":185,"path":186,"stem":187},"Deno Deploy","\u002Fdeploy\u002Fproviders\u002Fdeno-deploy","2.deploy\u002F20.providers\u002Fdeno-deploy",{"title":189,"path":190,"stem":191},"DigitalOcean","\u002Fdeploy\u002Fproviders\u002Fdigitalocean","2.deploy\u002F20.providers\u002Fdigitalocean",{"title":193,"path":194,"stem":195},"EdgeOne Pages","\u002Fdeploy\u002Fproviders\u002Fedgeone","2.deploy\u002F20.providers\u002Fedgeone",{"title":197,"path":198,"stem":199},"Firebase","\u002Fdeploy\u002Fproviders\u002Ffirebase","2.deploy\u002F20.providers\u002Ffirebase",{"title":201,"path":202,"stem":203},"Flightcontrol","\u002Fdeploy\u002Fproviders\u002Fflightcontrol","2.deploy\u002F20.providers\u002Fflightcontrol",{"title":205,"path":206,"stem":207},"Genezio","\u002Fdeploy\u002Fproviders\u002Fgenezio","2.deploy\u002F20.providers\u002Fgenezio",{"title":209,"path":210,"stem":211},"GitHub Pages","\u002Fdeploy\u002Fproviders\u002Fgithub-pages","2.deploy\u002F20.providers\u002Fgithub-pages",{"title":213,"path":214,"stem":215},"GitLab Pages","\u002Fdeploy\u002Fproviders\u002Fgitlab-pages","2.deploy\u002F20.providers\u002Fgitlab-pages",{"title":217,"path":218,"stem":219},"Heroku","\u002Fdeploy\u002Fproviders\u002Fheroku","2.deploy\u002F20.providers\u002Fheroku",{"title":221,"path":222,"stem":223},"IIS","\u002Fdeploy\u002Fproviders\u002Fiis","2.deploy\u002F20.providers\u002Fiis",{"title":225,"path":226,"stem":227},"Koyeb","\u002Fdeploy\u002Fproviders\u002Fkoyeb","2.deploy\u002F20.providers\u002Fkoyeb",{"title":229,"path":230,"stem":231},"Netlify","\u002Fdeploy\u002Fproviders\u002Fnetlify","2.deploy\u002F20.providers\u002Fnetlify",{"title":233,"path":234,"stem":235},"Platform.sh","\u002Fdeploy\u002Fproviders\u002Fplatform-sh","2.deploy\u002F20.providers\u002Fplatform-sh",{"title":237,"path":238,"stem":239},"Render.com","\u002Fdeploy\u002Fproviders\u002Frender","2.deploy\u002F20.providers\u002Frender",{"title":241,"path":242,"stem":243},"Stormkit","\u002Fdeploy\u002Fproviders\u002Fstormkit","2.deploy\u002F20.providers\u002Fstormkit",{"title":245,"path":246,"stem":247},"Vercel","\u002Fdeploy\u002Fproviders\u002Fvercel","2.deploy\u002F20.providers\u002Fvercel",{"title":249,"path":250,"stem":251},"Zeabur","\u002Fdeploy\u002Fproviders\u002Fzeabur","2.deploy\u002F20.providers\u002Fzeabur",{"title":253,"path":254,"stem":255},"Zephyr Cloud","\u002Fdeploy\u002Fproviders\u002Fzephyr","2.deploy\u002F20.providers\u002Fzephyr",{"title":257,"path":258,"stem":259},"Zerops","\u002Fdeploy\u002Fproviders\u002Fzerops","2.deploy\u002F20.providers\u002Fzerops",{"title":261,"path":262,"stem":263,"children":264,"icon":36},"Config","\u002Fconfig","3.config\u002F0.index",[265],{"title":261,"path":262,"stem":263,"icon":36},{"title":267,"path":268,"stem":269,"children":270,"icon":272},"Examples","\u002Fexamples","4.examples\u002F0.index",[271,273,278,283,288,293,297,302,307,312,317,322,327,331,336,340,344,349,354,359,364,369,374,379,383,388,393,398,402,407,412,416,421,426],{"title":267,"path":268,"stem":269,"icon":272},"i-lucide-folder-code",{"title":274,"path":275,"stem":276,"icon":277},"API Routes","\u002Fexamples\u002Fapi-routes","4.examples\u002Fapi-routes","i-lucide-route",{"title":279,"path":280,"stem":281,"icon":282},"Auto Imports","\u002Fexamples\u002Fauto-imports","4.examples\u002Fauto-imports","i-lucide-import",{"title":284,"path":285,"stem":286,"icon":287},"Cached Handler","\u002Fexamples\u002Fcached-handler","4.examples\u002Fcached-handler","i-lucide-clock",{"title":289,"path":290,"stem":291,"icon":292},"Custom Error Handler","\u002Fexamples\u002Fcustom-error-handler","4.examples\u002Fcustom-error-handler","i-lucide-alert-circle",{"title":38,"path":294,"stem":295,"icon":296},"\u002Fexamples\u002Fdatabase","4.examples\u002Fdatabase","i-lucide-database",{"title":298,"path":299,"stem":300,"icon":301},"Elysia","\u002Fexamples\u002Felysia","4.examples\u002Felysia","i-skill-icons-elysia-dark",{"title":303,"path":304,"stem":305,"icon":306},"Express","\u002Fexamples\u002Fexpress","4.examples\u002Fexpress","i-simple-icons-express",{"title":308,"path":309,"stem":310,"icon":311},"Fastify","\u002Fexamples\u002Ffastify","4.examples\u002Ffastify","i-simple-icons-fastify",{"title":313,"path":314,"stem":315,"icon":316},"Hello World","\u002Fexamples\u002Fhello-world","4.examples\u002Fhello-world","i-lucide-sparkles",{"title":318,"path":319,"stem":320,"icon":321},"Hono","\u002Fexamples\u002Fhono","4.examples\u002Fhono","i-logos-hono",{"title":323,"path":324,"stem":325,"icon":326},"Import Alias","\u002Fexamples\u002Fimport-alias","4.examples\u002Fimport-alias","i-lucide-at-sign",{"title":328,"path":329,"stem":330,"icon":46},"Middleware","\u002Fexamples\u002Fmiddleware","4.examples\u002Fmiddleware",{"title":332,"path":333,"stem":334,"icon":335},"Mono JSX","\u002Fexamples\u002Fmono-jsx","4.examples\u002Fmono-jsx","i-lucide-brackets",{"title":337,"path":338,"stem":339,"icon":335},"Nano JSX","\u002Fexamples\u002Fnano-jsx","4.examples\u002Fnano-jsx",{"title":53,"path":341,"stem":342,"icon":343},"\u002Fexamples\u002Fplugins","4.examples\u002Fplugins","i-lucide-plug",{"title":345,"path":346,"stem":347,"icon":348},"Custom Renderer","\u002Fexamples\u002Frenderer","4.examples\u002Frenderer","i-lucide-code",{"title":350,"path":351,"stem":352,"icon":353},"Runtime Config","\u002Fexamples\u002Fruntime-config","4.examples\u002Fruntime-config","i-lucide-settings",{"title":355,"path":356,"stem":357,"icon":358},"Server Fetch","\u002Fexamples\u002Fserver-fetch","4.examples\u002Fserver-fetch","i-lucide-arrow-right-left",{"title":360,"path":361,"stem":362,"icon":363},"Shiki","\u002Fexamples\u002Fshiki","4.examples\u002Fshiki","i-lucide-highlighter",{"title":365,"path":366,"stem":367,"icon":368},"Takumi","\u002Fexamples\u002Ftakumi","4.examples\u002Ftakumi","i-lucide-image",{"title":370,"path":371,"stem":372,"icon":373},"Tracing","\u002Fexamples\u002Ftracing","4.examples\u002Ftracing","i-lucide-activity",{"title":375,"path":376,"stem":377,"icon":378},"Virtual Routes","\u002Fexamples\u002Fvirtual-routes","4.examples\u002Fvirtual-routes","i-lucide-box",{"title":380,"path":381,"stem":382,"icon":91},"Vite Nitro Plugin","\u002Fexamples\u002Fvite-nitro-plugin","4.examples\u002Fvite-nitro-plugin",{"title":384,"path":385,"stem":386,"icon":387},"Vite RSC","\u002Fexamples\u002Fvite-rsc","4.examples\u002Fvite-rsc","i-logos-react",{"title":389,"path":390,"stem":391,"icon":392},"Vite SSR HTML","\u002Fexamples\u002Fvite-ssr-html","4.examples\u002Fvite-ssr-html","i-logos-html-5",{"title":394,"path":395,"stem":396,"icon":397},"SSR with Preact","\u002Fexamples\u002Fvite-ssr-preact","4.examples\u002Fvite-ssr-preact","i-logos-preact",{"title":399,"path":400,"stem":401,"icon":387},"SSR with React","\u002Fexamples\u002Fvite-ssr-react","4.examples\u002Fvite-ssr-react",{"title":403,"path":404,"stem":405,"icon":406},"SSR with SolidJS","\u002Fexamples\u002Fvite-ssr-solid","4.examples\u002Fvite-ssr-solid","i-logos-solidjs-icon",{"title":408,"path":409,"stem":410,"icon":411},"SSR with TanStack Router","\u002Fexamples\u002Fvite-ssr-tsr-react","4.examples\u002Fvite-ssr-tsr-react","i-simple-icons-tanstack",{"title":413,"path":414,"stem":415,"icon":411},"SSR with TanStack Start","\u002Fexamples\u002Fvite-ssr-tss-react","4.examples\u002Fvite-ssr-tss-react",{"title":417,"path":418,"stem":419,"icon":420},"SSR with Vue Router","\u002Fexamples\u002Fvite-ssr-vue-router","4.examples\u002Fvite-ssr-vue-router","i-logos-vue",{"title":422,"path":423,"stem":424,"icon":425},"Vite + tRPC","\u002Fexamples\u002Fvite-trpc","4.examples\u002Fvite-trpc","i-simple-icons-trpc",{"title":68,"path":427,"stem":428,"icon":429},"\u002Fexamples\u002Fwebsocket","4.examples\u002Fwebsocket","i-lucide-radio",{"title":431,"path":432,"stem":433,"children":434},"Blog","\u002Fblog","9.blog",[435,438],{"title":431,"path":432,"stem":436,"icon":437},"9.blog\u002Findex","i-lucide-file-text",{"title":439,"path":440,"stem":441,"icon":437},"Nitro v3 Beta is here!","\u002Fblog\u002Fv3-beta","9.blog\u002F1.v3-beta",{"title":5,"path":443,"stem":444},"\u002F","index",{"id":446,"title":103,"body":447,"description":3361,"extension":3362,"meta":3363,"navigation":3364,"path":104,"seo":3365,"stem":105,"__hash__":3366},"content\u002F1.docs\u002F7.cache.md",{"type":448,"value":449,"toc":3336,"icon":106},"minimark",[450,454,480,484,492,504,602,614,621,639,644,650,748,759,763,777,781,802,806,809,812,819,822,1121,1137,1190,1195,1484,1487,1495,1499,1506,1692,1696,1701,1842,1846,1850,1913,1916,1928,2017,2022,2039,2044,2052,2060,2064,2072,2126,2129,2221,2224,2250,2262,2273,2303,2307,2313,2323,2332,2364,2376,2589,2597,2601,2613,2628,2723,2731,2756,2789,2793,2807,2814,2824,2898,2904,2983,2989,2993,2996,2999,3060,3069,3167,3171,3189,3255,3261,3316,3326,3332],[451,452,453],"p",{},"Caching lets you store the result of expensive operations — rendered responses, upstream API calls, heavy computations — and serve it again without redoing the work. Nitro offers three ways in:",[455,456,457,466,473],"ul",{},[458,459,460,465],"li",{},[461,462,464],"a",{"href":463},"#cached-handlers","Cached handlers"," — cache the full response of an event handler.",[458,467,468,472],{},[461,469,471],{"href":470},"#cached-functions","Cached functions"," — cache the result of any function and reuse it across handlers.",[458,474,475,479],{},[461,476,478],{"href":477},"#using-route-rules","Route rules"," — enable caching for route patterns from your config, without touching handler code.",[481,482,464],"h2",{"id":483},"cached-handlers",[451,485,486,487,491],{},"To cache an event handler, use the ",[488,489,490],"code",{},"defineCachedHandler"," method.",[451,493,494,495,498,499,503],{},"It works like ",[488,496,497],{},"defineHandler"," but with a second parameter for the ",[461,500,502],{"href":501},"#options","cache options",".",[505,506,511],"pre",{"className":507,"code":508,"filename":509,"language":510,"meta":5,"style":5},"language-ts shiki shiki-themes github-light github-dark github-dark","import { defineCachedHandler } from \"nitro\u002Fcache\";\n\nexport default defineCachedHandler((event) => {\n  return \"I am cached for an hour\";\n}, { maxAge: 60 * 60 });\n","routes\u002Fcached.ts","ts",[488,512,513,536,543,572,583],{"__ignoreMap":5},[514,515,518,522,526,529,533],"span",{"class":516,"line":517},"line",1,[514,519,521],{"class":520},"so5gQ","import",[514,523,525],{"class":524},"slsVL"," { defineCachedHandler } ",[514,527,528],{"class":520},"from",[514,530,532],{"class":531},"sfrk1"," \"nitro\u002Fcache\"",[514,534,535],{"class":524},";\n",[514,537,539],{"class":516,"line":538},2,[514,540,542],{"emptyLinePlaceholder":541},true,"\n",[514,544,546,549,552,556,559,563,566,569],{"class":516,"line":545},3,[514,547,548],{"class":520},"export",[514,550,551],{"class":520}," default",[514,553,555],{"class":554},"shcOC"," defineCachedHandler",[514,557,558],{"class":524},"((",[514,560,562],{"class":561},"sQHwn","event",[514,564,565],{"class":524},") ",[514,567,568],{"class":520},"=>",[514,570,571],{"class":524}," {\n",[514,573,575,578,581],{"class":516,"line":574},4,[514,576,577],{"class":520},"  return",[514,579,580],{"class":531}," \"I am cached for an hour\"",[514,582,535],{"class":524},[514,584,586,589,593,596,599],{"class":516,"line":585},5,[514,587,588],{"class":524},"}, { maxAge: ",[514,590,592],{"class":591},"suiK_","60",[514,594,595],{"class":520}," *",[514,597,598],{"class":591}," 60",[514,600,601],{"class":524}," });\n",[451,603,604,605,608,609,613],{},"With this example, the response will be cached for 1 hour. Once the cache expires, the next request waits for the handler to resolve a fresh value before responding. If you prefer to immediately serve the stale response while it is revalidated in the background, set ",[488,606,607],{},"swr: true"," (see ",[461,610,612],{"href":611},"#swr-behavior","SWR behavior",").",[451,615,616,617,620],{},"See the ",[461,618,619],{"href":501},"options"," section for more details about the available options.",[622,623,624],"important",{},[451,625,626,630,631,638],{},[627,628,629],"strong",{},"Request headers are dropped"," when handling cached responses. Use the ",[461,632,634,637],{"href":633},"#handler-only-options",[488,635,636],{},"varies"," option"," to consider specific headers when caching and serving the responses.",[640,641,643],"h3",{"id":642},"automatic-http-headers","Automatic HTTP headers",[451,645,646,647,649],{},"When using ",[488,648,490],{},", Nitro automatically manages HTTP cache headers on cached responses:",[455,651,652,664,672,720],{},[458,653,654,659,660,663],{},[627,655,656],{},[488,657,658],{},"etag"," -- A weak ETag (",[488,661,662],{},"W\u002F\"...\"",") is generated from the response body hash if not already set by the handler.",[458,665,666,671],{},[627,667,668],{},[488,669,670],{},"last-modified"," -- Set to the current time when the response is first cached, if not already set.",[458,673,674,679,680,683,684,687,688,691,692],{},[627,675,676],{},[488,677,678],{},"cache-control"," -- Automatically set based on the ",[488,681,682],{},"swr",", ",[488,685,686],{},"maxAge",", and ",[488,689,690],{},"staleMaxAge"," options, unless the handler already set one:\n",[455,693,694,704],{},[458,695,696,697,700,701],{},"With ",[488,698,699],{},"swr: false"," (default): ",[488,702,703],{},"max-age=\u003CmaxAge>",[458,705,696,706,708,709,712,713,716,717,719],{},[488,707,607],{},": ",[488,710,711],{},"s-maxage=\u003CmaxAge>, stale-while-revalidate=\u003CstaleMaxAge>"," (a bare ",[488,714,715],{},"stale-while-revalidate"," when ",[488,718,690],{}," is unset)",[458,721,722,727,728,683,731,683,734,737,738,741,742,747],{},[627,723,724],{},[488,725,726],{},"x-cache"," -- A CDN-style cache status header (",[488,729,730],{},"HIT",[488,732,733],{},"STALE",[488,735,736],{},"REVALIDATED"," or ",[488,739,740],{},"MISS","). Customizable with the ",[461,743,744],{"href":633},[488,745,746],{},"cacheStatusHeader"," option.",[451,749,750,751,753,754,503],{},"To keep caching server-side only without advertising ",[488,752,678],{}," to clients and CDNs, set ",[461,755,756],{"href":633},[488,757,758],{},"sendCacheControl: false",[640,760,762],{"id":761},"conditional-requests-304-not-modified","Conditional requests (304 Not Modified)",[451,764,765,766,737,769,772,773,776],{},"Cached handlers automatically support conditional requests. When a client sends ",[488,767,768],{},"if-none-match",[488,770,771],{},"if-modified-since"," headers matching the cached response, Nitro returns a ",[488,774,775],{},"304 Not Modified"," response without a body.",[640,778,780],{"id":779},"request-method-filtering","Request method filtering",[451,782,783,784,787,788,791,792,683,795,683,798,801],{},"Only ",[488,785,786],{},"GET"," and ",[488,789,790],{},"HEAD"," requests are cached. All other HTTP methods (",[488,793,794],{},"POST",[488,796,797],{},"PUT",[488,799,800],{},"DELETE",", etc.) automatically bypass the cache and call the handler directly.",[640,803,805],{"id":804},"request-deduplication","Request deduplication",[451,807,808],{},"When multiple concurrent requests hit the same cache key while the cache is being resolved, only one invocation of the handler runs. All concurrent requests wait for and share the same result.",[481,810,471],{"id":811},"cached-functions",[451,813,814,815,818],{},"You can also cache a function using ",[488,816,817],{},"defineCachedFunction",". This is useful for caching the result of a function that is not an event handler, but is part of one, and reusing it in multiple handlers.",[451,820,821],{},"For example, you might want to cache the result of an API call for one hour:",[505,823,826],{"className":507,"code":824,"filename":825,"language":510,"meta":5,"style":5},"import { defineCachedFunction } from \"nitro\u002Fcache\";\nimport { defineHandler, type H3Event } from \"nitro\";\n\nexport default defineHandler(async (event) => {\n  const { repo } = event.context.params;\n  const stars = await cachedGHStars(repo).catch(() => 0)\n\n  return { repo, stars }\n});\n\nconst cachedGHStars = defineCachedFunction(async (repo: string) => {\n  const data = await fetch(`https:\u002F\u002Fapi.github.com\u002Frepos\u002F${repo}`).then(res => res.json());\n\n  return data.stargazers_count;\n}, {\n  maxAge: 60 * 60,\n  name: \"ghStars\",\n  getKey: (repo: string) => repo\n});\n","routes\u002Fapi\u002Fstars\u002F[...repo].ts",[488,827,828,841,861,865,891,911,945,950,958,964,969,1002,1049,1054,1062,1068,1083,1094,1116],{"__ignoreMap":5},[514,829,830,832,835,837,839],{"class":516,"line":517},[514,831,521],{"class":520},[514,833,834],{"class":524}," { defineCachedFunction } ",[514,836,528],{"class":520},[514,838,532],{"class":531},[514,840,535],{"class":524},[514,842,843,845,848,851,854,856,859],{"class":516,"line":538},[514,844,521],{"class":520},[514,846,847],{"class":524}," { defineHandler, ",[514,849,850],{"class":520},"type",[514,852,853],{"class":524}," H3Event } ",[514,855,528],{"class":520},[514,857,858],{"class":531}," \"nitro\"",[514,860,535],{"class":524},[514,862,863],{"class":516,"line":545},[514,864,542],{"emptyLinePlaceholder":541},[514,866,867,869,871,874,877,880,883,885,887,889],{"class":516,"line":574},[514,868,548],{"class":520},[514,870,551],{"class":520},[514,872,873],{"class":554}," defineHandler",[514,875,876],{"class":524},"(",[514,878,879],{"class":520},"async",[514,881,882],{"class":524}," (",[514,884,562],{"class":561},[514,886,565],{"class":524},[514,888,568],{"class":520},[514,890,571],{"class":524},[514,892,893,896,899,902,905,908],{"class":516,"line":585},[514,894,895],{"class":520},"  const",[514,897,898],{"class":524}," { ",[514,900,901],{"class":591},"repo",[514,903,904],{"class":524}," } ",[514,906,907],{"class":520},"=",[514,909,910],{"class":524}," event.context.params;\n",[514,912,914,916,919,922,925,928,931,934,937,939,942],{"class":516,"line":913},6,[514,915,895],{"class":520},[514,917,918],{"class":591}," stars",[514,920,921],{"class":520}," =",[514,923,924],{"class":520}," await",[514,926,927],{"class":554}," cachedGHStars",[514,929,930],{"class":524},"(repo).",[514,932,933],{"class":554},"catch",[514,935,936],{"class":524},"(() ",[514,938,568],{"class":520},[514,940,941],{"class":591}," 0",[514,943,944],{"class":524},")\n",[514,946,948],{"class":516,"line":947},7,[514,949,542],{"emptyLinePlaceholder":541},[514,951,953,955],{"class":516,"line":952},8,[514,954,577],{"class":520},[514,956,957],{"class":524}," { repo, stars }\n",[514,959,961],{"class":516,"line":960},9,[514,962,963],{"class":524},"});\n",[514,965,967],{"class":516,"line":966},10,[514,968,542],{"emptyLinePlaceholder":541},[514,970,972,975,977,979,982,984,986,988,990,993,996,998,1000],{"class":516,"line":971},11,[514,973,974],{"class":520},"const",[514,976,927],{"class":591},[514,978,921],{"class":520},[514,980,981],{"class":554}," defineCachedFunction",[514,983,876],{"class":524},[514,985,879],{"class":520},[514,987,882],{"class":524},[514,989,901],{"class":561},[514,991,992],{"class":520},":",[514,994,995],{"class":591}," string",[514,997,565],{"class":524},[514,999,568],{"class":520},[514,1001,571],{"class":524},[514,1003,1005,1007,1010,1012,1014,1017,1019,1022,1024,1027,1029,1032,1034,1037,1040,1043,1046],{"class":516,"line":1004},12,[514,1006,895],{"class":520},[514,1008,1009],{"class":591}," data",[514,1011,921],{"class":520},[514,1013,924],{"class":520},[514,1015,1016],{"class":554}," fetch",[514,1018,876],{"class":524},[514,1020,1021],{"class":531},"`https:\u002F\u002Fapi.github.com\u002Frepos\u002F${",[514,1023,901],{"class":524},[514,1025,1026],{"class":531},"}`",[514,1028,613],{"class":524},[514,1030,1031],{"class":554},"then",[514,1033,876],{"class":524},[514,1035,1036],{"class":561},"res",[514,1038,1039],{"class":520}," =>",[514,1041,1042],{"class":524}," res.",[514,1044,1045],{"class":554},"json",[514,1047,1048],{"class":524},"());\n",[514,1050,1052],{"class":516,"line":1051},13,[514,1053,542],{"emptyLinePlaceholder":541},[514,1055,1057,1059],{"class":516,"line":1056},14,[514,1058,577],{"class":520},[514,1060,1061],{"class":524}," data.stargazers_count;\n",[514,1063,1065],{"class":516,"line":1064},15,[514,1066,1067],{"class":524},"}, {\n",[514,1069,1071,1074,1076,1078,1080],{"class":516,"line":1070},16,[514,1072,1073],{"class":524},"  maxAge: ",[514,1075,592],{"class":591},[514,1077,595],{"class":520},[514,1079,598],{"class":591},[514,1081,1082],{"class":524},",\n",[514,1084,1086,1089,1092],{"class":516,"line":1085},17,[514,1087,1088],{"class":524},"  name: ",[514,1090,1091],{"class":531},"\"ghStars\"",[514,1093,1082],{"class":524},[514,1095,1097,1100,1103,1105,1107,1109,1111,1113],{"class":516,"line":1096},18,[514,1098,1099],{"class":554},"  getKey",[514,1101,1102],{"class":524},": (",[514,1104,901],{"class":561},[514,1106,992],{"class":520},[514,1108,995],{"class":591},[514,1110,565],{"class":524},[514,1112,568],{"class":520},[514,1114,1115],{"class":524}," repo\n",[514,1117,1119],{"class":516,"line":1118},19,[514,1120,963],{"class":524},[451,1122,1123,1124,1128,1129,1132,1133,1136],{},"The stars will be cached using the ",[461,1125,1127],{"href":1126},"#cache-storage","cache storage"," (in-memory by default) under a key like ",[488,1130,1131],{},"cache:nitro\u002Ffunctions:ghStars:\u003Cowner>\u002F\u003Crepo>.json",", with ",[488,1134,1135],{},"value"," being the number of stars.",[505,1138,1141],{"className":1139,"code":1140,"language":1045,"meta":5,"style":5},"language-json shiki shiki-themes github-light github-dark github-dark","{\"expires\":1677851092249,\"value\":43991,\"mtime\":1677847492540,\"integrity\":\"ZUHcsxCWEH\"}\n",[488,1142,1143],{"__ignoreMap":5},[514,1144,1145,1148,1151,1153,1156,1159,1162,1164,1167,1169,1172,1174,1177,1179,1182,1184,1187],{"class":516,"line":517},[514,1146,1147],{"class":524},"{",[514,1149,1150],{"class":591},"\"expires\"",[514,1152,992],{"class":524},[514,1154,1155],{"class":591},"1677851092249",[514,1157,1158],{"class":524},",",[514,1160,1161],{"class":591},"\"value\"",[514,1163,992],{"class":524},[514,1165,1166],{"class":591},"43991",[514,1168,1158],{"class":524},[514,1170,1171],{"class":591},"\"mtime\"",[514,1173,992],{"class":524},[514,1175,1176],{"class":591},"1677847492540",[514,1178,1158],{"class":524},[514,1180,1181],{"class":591},"\"integrity\"",[514,1183,992],{"class":524},[514,1185,1186],{"class":531},"\"ZUHcsxCWEH\"",[514,1188,1189],{"class":524},"}\n",[622,1191,1192],{},[451,1193,1194],{},"Because the cached data is serialized to JSON, it is important that the cached function does not return anything that cannot be serialized, such as Symbols, Maps, Sets...",[1196,1197,1198,1201],"callout",{},[451,1199,1200],{},"If you are using edge workers to host your application, you should follow the instructions below.",[1202,1203,1205,1212,1223,1481],"collapsible",{"name":1204},"Edge workers instructions",[451,1206,1207,1208,1211],{},"In edge workers, the instance is destroyed after each request. Nitro automatically uses ",[488,1209,1210],{},"event.waitUntil"," to keep the instance alive while the cache is being updated while the response is sent to the client.",[451,1213,1214,1215],{},"To ensure that your cached functions work as expected in edge workers, ",[627,1216,1217,1218,1220,1221,503],{},"you should always pass the ",[488,1219,562],{}," as the first argument to the function using ",[488,1222,817],{},[505,1224,1227],{"className":507,"code":1225,"filename":825,"highlights":1226,"language":510,"meta":5,"style":5},"import { defineCachedFunction } from \"nitro\u002Fcache\";\nimport { defineHandler, type H3Event } from \"nitro\";\n\nexport default defineHandler(async (event) => {\n  const { repo } = event.context.params;\n  const stars = await cachedGHStars(event, repo).catch(() => 0)\n\n  return { repo, stars }\n});\n\nconst cachedGHStars = defineCachedFunction(async (event: H3Event, repo: string) => {\n  const data = await fetch(`https:\u002F\u002Fapi.github.com\u002Frepos\u002F${repo}`).then(res => res.json());\n\n  return data.stargazers_count;\n}, {\n  maxAge: 60 * 60,\n  name: \"ghStars\",\n  getKey: (event: H3Event, repo: string) => repo\n});\n",[585,966,1085],[488,1228,1229,1241,1257,1261,1283,1299,1324,1328,1334,1338,1343,1380,1416,1420,1426,1430,1442,1451,1477],{"__ignoreMap":5},[514,1230,1231,1233,1235,1237,1239],{"class":516,"line":517},[514,1232,521],{"class":520},[514,1234,834],{"class":524},[514,1236,528],{"class":520},[514,1238,532],{"class":531},[514,1240,535],{"class":524},[514,1242,1243,1245,1247,1249,1251,1253,1255],{"class":516,"line":538},[514,1244,521],{"class":520},[514,1246,847],{"class":524},[514,1248,850],{"class":520},[514,1250,853],{"class":524},[514,1252,528],{"class":520},[514,1254,858],{"class":531},[514,1256,535],{"class":524},[514,1258,1259],{"class":516,"line":545},[514,1260,542],{"emptyLinePlaceholder":541},[514,1262,1263,1265,1267,1269,1271,1273,1275,1277,1279,1281],{"class":516,"line":574},[514,1264,548],{"class":520},[514,1266,551],{"class":520},[514,1268,873],{"class":554},[514,1270,876],{"class":524},[514,1272,879],{"class":520},[514,1274,882],{"class":524},[514,1276,562],{"class":561},[514,1278,565],{"class":524},[514,1280,568],{"class":520},[514,1282,571],{"class":524},[514,1284,1287,1289,1291,1293,1295,1297],{"class":1285,"line":585},[516,1286],"highlight",[514,1288,895],{"class":520},[514,1290,898],{"class":524},[514,1292,901],{"class":591},[514,1294,904],{"class":524},[514,1296,907],{"class":520},[514,1298,910],{"class":524},[514,1300,1301,1303,1305,1307,1309,1311,1314,1316,1318,1320,1322],{"class":516,"line":913},[514,1302,895],{"class":520},[514,1304,918],{"class":591},[514,1306,921],{"class":520},[514,1308,924],{"class":520},[514,1310,927],{"class":554},[514,1312,1313],{"class":524},"(event, repo).",[514,1315,933],{"class":554},[514,1317,936],{"class":524},[514,1319,568],{"class":520},[514,1321,941],{"class":591},[514,1323,944],{"class":524},[514,1325,1326],{"class":516,"line":947},[514,1327,542],{"emptyLinePlaceholder":541},[514,1329,1330,1332],{"class":516,"line":952},[514,1331,577],{"class":520},[514,1333,957],{"class":524},[514,1335,1336],{"class":516,"line":960},[514,1337,963],{"class":524},[514,1339,1341],{"class":1340,"line":966},[516,1286],[514,1342,542],{"emptyLinePlaceholder":541},[514,1344,1345,1347,1349,1351,1353,1355,1357,1359,1361,1363,1366,1368,1370,1372,1374,1376,1378],{"class":516,"line":971},[514,1346,974],{"class":520},[514,1348,927],{"class":591},[514,1350,921],{"class":520},[514,1352,981],{"class":554},[514,1354,876],{"class":524},[514,1356,879],{"class":520},[514,1358,882],{"class":524},[514,1360,562],{"class":561},[514,1362,992],{"class":520},[514,1364,1365],{"class":554}," H3Event",[514,1367,683],{"class":524},[514,1369,901],{"class":561},[514,1371,992],{"class":520},[514,1373,995],{"class":591},[514,1375,565],{"class":524},[514,1377,568],{"class":520},[514,1379,571],{"class":524},[514,1381,1382,1384,1386,1388,1390,1392,1394,1396,1398,1400,1402,1404,1406,1408,1410,1412,1414],{"class":516,"line":1004},[514,1383,895],{"class":520},[514,1385,1009],{"class":591},[514,1387,921],{"class":520},[514,1389,924],{"class":520},[514,1391,1016],{"class":554},[514,1393,876],{"class":524},[514,1395,1021],{"class":531},[514,1397,901],{"class":524},[514,1399,1026],{"class":531},[514,1401,613],{"class":524},[514,1403,1031],{"class":554},[514,1405,876],{"class":524},[514,1407,1036],{"class":561},[514,1409,1039],{"class":520},[514,1411,1042],{"class":524},[514,1413,1045],{"class":554},[514,1415,1048],{"class":524},[514,1417,1418],{"class":516,"line":1051},[514,1419,542],{"emptyLinePlaceholder":541},[514,1421,1422,1424],{"class":516,"line":1056},[514,1423,577],{"class":520},[514,1425,1061],{"class":524},[514,1427,1428],{"class":516,"line":1064},[514,1429,1067],{"class":524},[514,1431,1432,1434,1436,1438,1440],{"class":516,"line":1070},[514,1433,1073],{"class":524},[514,1435,592],{"class":591},[514,1437,595],{"class":520},[514,1439,598],{"class":591},[514,1441,1082],{"class":524},[514,1443,1445,1447,1449],{"class":1444,"line":1085},[516,1286],[514,1446,1088],{"class":524},[514,1448,1091],{"class":531},[514,1450,1082],{"class":524},[514,1452,1453,1455,1457,1459,1461,1463,1465,1467,1469,1471,1473,1475],{"class":516,"line":1096},[514,1454,1099],{"class":554},[514,1456,1102],{"class":524},[514,1458,562],{"class":561},[514,1460,992],{"class":520},[514,1462,1365],{"class":554},[514,1464,683],{"class":524},[514,1466,901],{"class":561},[514,1468,992],{"class":520},[514,1470,995],{"class":591},[514,1472,565],{"class":524},[514,1474,568],{"class":520},[514,1476,1115],{"class":524},[514,1478,1479],{"class":516,"line":1118},[514,1480,963],{"class":524},[451,1482,1483],{},"This way, the function will be able to keep the instance alive while the cache is being updated without slowing down the response to the client.",[481,1485,1486],{"id":619},"Options",[451,1488,1489,1490,787,1492,1494],{},"The ",[488,1491,490],{},[488,1493,817],{}," functions accept the following options:",[640,1496,1498],{"id":1497},"shared-options","Shared options",[451,1500,1501,1502,787,1504,992],{},"These options are available for both ",[488,1503,490],{},[488,1505,817],{},[1507,1508,1509,1529,1540,1554,1568,1581,1593,1614,1634,1664,1674,1682],"field-group",{},[1510,1511,1514],"field",{"name":1512,"type":1513},"base","string | string[]",[451,1515,1516,1517,1520,1521,1524,1525,1528],{},"Storage base (prefix) used for cache keys, usually matching a storage mount point. ",[1518,1519],"br",{},"\nDefaults to ",[488,1522,1523],{},"\u002Fcache"," (stored under the ",[488,1526,1527],{},"cache:"," prefix). When an array is provided, reads try each base in order and writes go to all of them (multi-tier caching).",[1510,1530,1533],{"name":1531,"type":1532},"name","string",[451,1534,1535,1536,1539],{},"Guessed from the function name if not provided, and falls back to ",[488,1537,1538],{},"anon_\u003Chash>"," (computed from the function code) otherwise.",[1510,1541,1543],{"name":1542,"type":1532},"group",[451,1544,1545,1546,1549,1550,1553],{},"Defaults to ",[488,1547,1548],{},"'nitro\u002Fhandlers'"," for handlers and ",[488,1551,1552],{},"'nitro\u002Ffunctions'"," for functions.",[1510,1555,1558],{"name":1556,"type":1557},"getKey()","(...args) => string",[451,1559,1560,1561,1564,1565,1567],{},"A function that accepts the same arguments as the original function and returns a cache key (",[488,1562,1563],{},"String","). ",[1518,1566],{},"\nIf not provided, a built-in hash function will be used to generate a key based on the function arguments. For cached handlers, the key is derived from the request URL path and search params.",[1510,1569,1571],{"name":1570,"type":1532},"integrity",[451,1572,1573,1574,1576,1577,1580],{},"A value that invalidates the cache when changed. ",[1518,1575],{},"\nBy default, it is computed from ",[627,1578,1579],{},"function code",", used in development to invalidate the cache when the function code changes.",[1510,1582,1584],{"name":686,"type":1583},"number",[451,1585,1586,1587,1520,1589,1592],{},"Maximum age that cache is valid, in seconds. ",[1518,1588],{},[488,1590,1591],{},"1"," (second).",[1510,1594,1595],{"name":690,"type":1583},[451,1596,1597,1598,1600,1601,1603,1604,1606,1607,1610,1611,1613],{},"Maximum number of seconds a stale value can still be served after ",[488,1599,686],{}," expires, while revalidation happens in the background. Only applies when ",[488,1602,682],{}," is enabled. ",[1518,1605],{},"\nWhen set to ",[488,1608,1609],{},"0",", stale values are never served (equivalent to disabling ",[488,1612,682],{},"). When unset, stale values can be served without a time limit.",[1510,1615,1617],{"name":682,"type":1616},"boolean",[451,1618,1619,1620,1622,1623,1625,1626,1520,1628,1631,1632,503],{},"Enable ",[488,1621,715],{}," behavior to serve a stale cached value while asynchronously revalidating it. ",[1518,1624],{},"\nWhen enabled, expired cached values are returned immediately while revalidation happens in the background. When disabled, the caller waits for the fresh value once the cache has expired (the stale entry is cleared). ",[1518,1627],{},[488,1629,1630],{},"false",". See ",[461,1633,612],{"href":611},[1510,1635,1638],{"name":1636,"type":1637},"getMaxAge()","(entry: CacheEntry) => number | { maxAge?, staleMaxAge? }",[451,1639,1640,1641,1643,1644,1646,1647,1649,1650,1652,1653,1655,1656,1659,1660,1663],{},"Derive the cache lifetime per entry from the resolved value, overriding the static ",[488,1642,686],{}," \u002F ",[488,1645,690],{}," options for that entry. Return a number of seconds (shorthand for ",[488,1648,686],{},") or an object to also override ",[488,1651,690],{},". ",[1518,1654],{},"\nUseful for values that carry their own expiry, such as access tokens: ",[488,1657,1658],{},"getMaxAge: (entry) => entry.value.expires_in",". A resolved value ",[488,1661,1662],{},"\u003C= 0"," disables caching for that entry.",[1510,1665,1668],{"name":1666,"type":1667},"shouldInvalidateCache()","(...args) => boolean | Promise\u003Cboolean>",[451,1669,1670,1671,1673],{},"A function that returns a ",[488,1672,1616],{}," to invalidate the current cache and create a new one.",[1510,1675,1677],{"name":1676,"type":1667},"shouldBypassCache()",[451,1678,1670,1679,1681],{},[488,1680,1616],{}," to bypass the current cache without invalidating the existing entry.",[1510,1683,1686],{"name":1684,"type":1685},"onError()","(error: unknown) => void",[451,1687,1688,1689,1691],{},"A custom error handler called when the cached function throws. ",[1518,1690],{},"\nBy default, errors are logged to the console and captured by the Nitro error handler.",[640,1693,1695],{"id":1694},"handler-only-options","Handler-only options",[451,1697,1698,1699,992],{},"These options are only available for ",[488,1700,490],{},[1507,1702,1703,1721,1753,1759,1791,1811,1827],{},[1510,1704,1706],{"name":1705,"type":1616},"headersOnly",[451,1707,1708,1709,1712,1713,683,1715,1717,1718,1720],{},"When ",[488,1710,1711],{},"true",", skip full response caching and only handle conditional request headers (",[488,1714,768],{},[488,1716,771],{},") for ",[488,1719,775],{}," responses. The handler is called on every request but benefits from conditional caching.",[1510,1722,1724],{"name":636,"type":1723},"string[]",[451,1725,1726,1727,1730,1731,1733,1734,1736,1737,1740,1741,1743,1744,1733,1746,1748,1749,1752],{},"An array of request header names to vary the cache key on. Headers listed here are preserved on the request during cache resolution and included in the cache key, making the cache unique per combination of header values. They are also merged into the response's ",[488,1728,1729],{},"Vary"," header. ",[1518,1732],{}," ",[1518,1735],{},"\nHeaders ",[627,1738,1739],{},"not"," listed in ",[488,1742,636],{}," are stripped from the request before calling the handler to ensure consistent cache hits. ",[1518,1745],{},[1518,1747],{},"\nFor multi-tenant environments, you may want to pass ",[488,1750,1751],{},"['host', 'x-forwarded-host']"," to ensure these headers are not discarded and that the cache is unique per tenant.",[1510,1754,1756],{"name":1755,"type":1723},"allowQuery",[451,1757,1758],{},"Allowlist of query parameter names that vary the cache key. When set, only the listed params affect the generated key, and all other params are stripped from the URL the handler sees. When unset, the full query string varies the key.",[1510,1760,1762],{"name":1761,"type":1723},"allowCookies",[451,1763,1764,1765,1768,1769,1733,1771,1773,1776,1777,1779,1780,1783,1784,737,1787,1790],{},"Allowlist of cookie names that participate in caching. Listed cookies vary the cache key and are kept in the ",[488,1766,1767],{},"cookie"," header the handler sees. ",[1518,1770],{},[1518,1772],{},[627,1774,1775],{},"By default, no cookies are allowed",": the ",[488,1778,1767],{}," request header is stripped before the handler runs, and any ",[488,1781,1782],{},"set-cookie"," header is dropped from the response before it is cached or returned, so a per-user cookie (such as a session id) can never leak to another user through the cache. Only allowlist cookies whose values are safe to share across every user hitting the same cache key (e.g. a ",[488,1785,1786],{},"theme",[488,1788,1789],{},"locale"," preference) — never per-user secrets.",[1510,1792,1794],{"name":1793,"type":1616},"sendCacheControl",[451,1795,1796,1797,1799,1800,1652,1802,1804,1805,1807,1808,1810],{},"Whether to automatically set a ",[488,1798,678],{}," response header. Defaults to ",[488,1801,1711],{},[1518,1803],{},"\nSet to ",[488,1806,1630],{}," for server-only caching: responses are still stored and served from cache, but no ",[488,1809,678],{}," header is advertised to clients and CDNs.",[1510,1812,1814],{"name":746,"type":1813},"boolean | string",[451,1815,1816,1817,1820,1821,1823,1824,1826],{},"Add a cache status response header (",[488,1818,1819],{},"X-Cache: HIT | STALE | REVALIDATED | MISS","). Defaults to ",[488,1822,1711],{},". Pass a string to use a custom header name, or ",[488,1825,1630],{}," to disable.",[1510,1828,1831],{"name":1829,"type":1830},"shouldCache()","(entry: ResponseCacheEntry) => boolean | Promise\u003Cboolean>",[451,1832,1833,1834,1838,1839,1841],{},"Additional predicate deciding whether a response is cacheable, running on top of the ",[461,1835,1837],{"href":1836},"#cache-keys","built-in checks"," (which always apply and can only be narrowed). Return ",[488,1840,1630],{}," to skip caching a response — it is still returned to the caller, just not stored.",[640,1843,1845],{"id":1844},"function-only-options","Function-only options",[451,1847,1698,1848,992],{},[488,1849,817],{},[1507,1851,1852,1878,1896],{},[1510,1853,1856],{"name":1854,"type":1855},"transform()","(entry: CacheEntry, ...args) => any",[451,1857,1858,1859,1861,1862,882,1865,683,1868,683,1871,737,1874,1877],{},"Transform the cache entry before returning. The return value replaces the cached value. ",[1518,1860],{},"\nThe entry also carries a per-call ",[488,1863,1864],{},"entry.status",[488,1866,1867],{},"\"hit\"",[488,1869,1870],{},"\"stale\"",[488,1872,1873],{},"\"revalidated\"",[488,1875,1876],{},"\"miss\"",") describing how the value was served — useful for metrics or conditional logic.",[1510,1879,1882],{"name":1880,"type":1881},"serialize()","(entry: CacheEntry, ctx: { args }) => any",[451,1883,1884,1885,1888,1889,1892,1893,1895],{},"Prepare the resolved value for storage, right before the entry is persisted (the write-side counterpart of ",[488,1886,1887],{},"transform","). Useful when the function returns something that cannot be stored as-is (e.g. a stream or a class instance): ",[488,1890,1891],{},"serialize"," converts it on write and ",[488,1894,1887],{}," restores it on read.",[1510,1897,1900],{"name":1898,"type":1899},"validate()","(entry: CacheEntry, ctx: { args }) => boolean | Promise\u003Cboolean>",[451,1901,1902,1903,1905,1906,1908,1909,1912],{},"Validate a cache entry. Return ",[488,1904,1630],{}," (or a Promise resolving to ",[488,1907,1630],{},") to treat the entry as invalid and trigger re-resolution. The second argument carries the ",[488,1910,1911],{},"args"," of the current call, so the entry can be validated against it.",[481,1914,612],{"id":1915},"swr-behavior",[451,1917,1489,1918,1920,1921,1924,1925,1927],{},[488,1919,715],{}," (SWR) pattern is ",[627,1922,1923],{},"opt-in"," via the ",[488,1926,682],{}," option (disabled by default). Understanding how it interacts with other options:",[1929,1930,1931,1949],"table",{},[1932,1933,1934],"thead",{},[1935,1936,1937,1942,1946],"tr",{},[1938,1939,1940],"th",{},[488,1941,682],{},[1938,1943,1944],{},[488,1945,686],{},[1938,1947,1948],{},"Behavior",[1950,1951,1952,1968,1981,1998],"tbody",{},[1935,1953,1954,1960,1965],{},[1955,1956,1957,1959],"td",{},[488,1958,1630],{}," (default)",[1955,1961,1962],{},[488,1963,1964],{},"3600",[1955,1966,1967],{},"Cache for 1 hour, wait for the fresh value when expired",[1935,1969,1970,1974,1978],{},[1955,1971,1972],{},[488,1973,1711],{},[1955,1975,1976],{},[488,1977,1964],{},[1955,1979,1980],{},"Cache for 1 hour, serve stale while revalidating",[1935,1982,1983,1987,1995],{},[1955,1984,1985],{},[488,1986,1711],{},[1955,1988,1989,1991,1992],{},[488,1990,1964],{}," with ",[488,1993,1994],{},"staleMaxAge: 600",[1955,1996,1997],{},"Cache for 1 hour, serve stale for up to 10 more minutes while revalidating",[1935,1999,2000,2004,2011],{},[1955,2001,2002],{},[488,2003,1711],{},[1955,2005,2006,1991,2008],{},[488,2007,1964],{},[488,2009,2010],{},"staleMaxAge: 0",[1955,2012,2013,2014,2016],{},"Cache for 1 hour, never serve stale (same as ",[488,2015,699],{},")",[451,2018,1708,2019,2021],{},[488,2020,682],{}," is enabled and a cached value exists but has expired:",[2023,2024,2026,2030,2033],"steps",{"level":2025},"4",[2027,2028,2029],"h4",{},"The stale cached value is returned immediately to the client.",[2027,2031,2032],{},"The function\u002Fhandler is called in the background to refresh the cache.",[2027,2034,2035,2036,2038],{},"On edge workers, ",[488,2037,1210],{}," is used to keep the background refresh alive.",[451,2040,1708,2041,2043],{},[488,2042,682],{}," is disabled (default) and a cached value has expired:",[2023,2045,2046,2049],{"level":2025},[2027,2047,2048],{},"The stale entry is cleared.",[2027,2050,2051],{},"The client waits for the function\u002Fhandler to resolve with a fresh value.",[2053,2054,2055],"tip",{},[451,2056,1619,2057,2059],{},[488,2058,682],{}," when slightly outdated data is acceptable — content pages, listings, mirrored third-party APIs — so response times stay flat even when the cache expires. Keep it disabled when callers must never receive stale data, such as access tokens or per-request authorization checks.",[481,2061,2063],{"id":2062},"cache-keys","Cache keys",[451,2065,2066,2067,737,2069,2071],{},"When using the ",[488,2068,817],{},[488,2070,490],{}," functions, the cache key is generated using the following pattern:",[505,2073,2075],{"className":507,"code":2074,"language":510,"meta":5,"style":5},"`${options.base}:${options.group}:${options.name}:${options.getKey(...args)}.json`\n",[488,2076,2077],{"__ignoreMap":5},[514,2078,2079,2082,2084,2086,2088,2091,2093,2095,2097,2099,2101,2103,2105,2107,2109,2111,2114,2116,2119,2121,2123],{"class":516,"line":517},[514,2080,2081],{"class":531},"`${",[514,2083,619],{"class":524},[514,2085,503],{"class":531},[514,2087,1512],{"class":524},[514,2089,2090],{"class":531},"}:${",[514,2092,619],{"class":524},[514,2094,503],{"class":531},[514,2096,1542],{"class":524},[514,2098,2090],{"class":531},[514,2100,619],{"class":524},[514,2102,503],{"class":531},[514,2104,1531],{"class":524},[514,2106,2090],{"class":531},[514,2108,619],{"class":524},[514,2110,503],{"class":531},[514,2112,2113],{"class":554},"getKey",[514,2115,876],{"class":531},[514,2117,2118],{"class":520},"...",[514,2120,1911],{"class":524},[514,2122,2016],{"class":531},[514,2124,2125],{"class":531},"}.json`\n",[451,2127,2128],{},"For example, the following function:",[505,2130,2132],{"className":507,"code":2131,"language":510,"meta":5,"style":5},"import { defineCachedFunction } from \"nitro\u002Fcache\";\n\nconst getAccessToken = defineCachedFunction(() => {\n  return String(Date.now())\n}, {\n  maxAge: 10,\n  name: \"getAccessToken\",\n  getKey: () => \"default\"\n});\n",[488,2133,2134,2146,2150,2167,2183,2187,2196,2205,2217],{"__ignoreMap":5},[514,2135,2136,2138,2140,2142,2144],{"class":516,"line":517},[514,2137,521],{"class":520},[514,2139,834],{"class":524},[514,2141,528],{"class":520},[514,2143,532],{"class":531},[514,2145,535],{"class":524},[514,2147,2148],{"class":516,"line":538},[514,2149,542],{"emptyLinePlaceholder":541},[514,2151,2152,2154,2157,2159,2161,2163,2165],{"class":516,"line":545},[514,2153,974],{"class":520},[514,2155,2156],{"class":591}," getAccessToken",[514,2158,921],{"class":520},[514,2160,981],{"class":554},[514,2162,936],{"class":524},[514,2164,568],{"class":520},[514,2166,571],{"class":524},[514,2168,2169,2171,2174,2177,2180],{"class":516,"line":574},[514,2170,577],{"class":520},[514,2172,2173],{"class":554}," String",[514,2175,2176],{"class":524},"(Date.",[514,2178,2179],{"class":554},"now",[514,2181,2182],{"class":524},"())\n",[514,2184,2185],{"class":516,"line":585},[514,2186,1067],{"class":524},[514,2188,2189,2191,2194],{"class":516,"line":913},[514,2190,1073],{"class":524},[514,2192,2193],{"class":591},"10",[514,2195,1082],{"class":524},[514,2197,2198,2200,2203],{"class":516,"line":947},[514,2199,1088],{"class":524},[514,2201,2202],{"class":531},"\"getAccessToken\"",[514,2204,1082],{"class":524},[514,2206,2207,2209,2212,2214],{"class":516,"line":952},[514,2208,1099],{"class":554},[514,2210,2211],{"class":524},": () ",[514,2213,568],{"class":520},[514,2215,2216],{"class":531}," \"default\"\n",[514,2218,2219],{"class":516,"line":960},[514,2220,963],{"class":524},[451,2222,2223],{},"Will generate the following cache key:",[505,2225,2227],{"className":507,"code":2226,"language":510,"meta":5,"style":5},"cache:nitro\u002Ffunctions:getAccessToken:default.json\n",[488,2228,2229],{"__ignoreMap":5},[514,2230,2231,2234,2237,2239,2242,2244,2247],{"class":516,"line":517},[514,2232,2233],{"class":554},"cache",[514,2235,2236],{"class":524},":nitro",[514,2238,443],{"class":520},[514,2240,2241],{"class":554},"functions",[514,2243,992],{"class":524},[514,2245,2246],{"class":554},"getAccessToken",[514,2248,2249],{"class":524},":default.json\n",[451,2251,2252,2253,2255,2256,2258,2259,2261],{},"The default ",[488,2254,1512],{}," is ",[488,2257,1523],{},", which the storage layer normalizes to the ",[488,2260,1527],{}," prefix.",[2263,2264,2265],"note",{},[451,2266,2267,2268,2272],{},"For cached handlers, the cache key includes a hash of the URL path and, when using the ",[461,2269,2270],{"href":633},[488,2271,636],{}," option, hashes of the specified header values appended to the key.",[2263,2274,2275],{},[451,2276,2277,2278,2281,2282,2284,2285,737,2288,2291,2292,1643,2294,2296,2297,2302],{},"Responses are not cached when they have an HTTP status code ",[488,2279,2280],{},">= 400",", an undefined body, a ",[488,2283,678],{}," header containing ",[488,2286,2287],{},"no-store",[488,2289,2290],{},"private",", or missing ",[488,2293,658],{},[488,2295,670],{}," headers. This prevents caching error responses and responses explicitly marked as non-cacheable. Use the ",[461,2298,2299],{"href":633},[488,2300,2301],{},"shouldCache"," option to further narrow what gets cached.",[481,2304,2306],{"id":2305},"cache-invalidation","Cache invalidation",[451,2308,2309,2310,2312],{},"Cached entries can be invalidated programmatically at runtime (for example from a webhook when the underlying data changes) without waiting for ",[488,2311,686],{}," to expire.",[640,2314,2316,787,2319,2322],{"id":2315},"invalidate-and-expire-methods",[488,2317,2318],{},".invalidate()",[488,2320,2321],{},".expire()"," methods",[451,2324,2325,2326,2328,2329,2331],{},"Every function created with ",[488,2327,817],{}," (and every handler created with ",[488,2330,490],{},") exposes on-demand revalidation methods:",[455,2333,2334,2342,2353],{},[458,2335,2336,2341],{},[627,2337,2338],{},[488,2339,2340],{},".invalidate(...args)"," — removes the cached entry entirely. The next call re-invokes the function and waits for the fresh value.",[458,2343,2344,2349,2350,2352],{},[627,2345,2346],{},[488,2347,2348],{},".expire(...args)"," — marks the cached entry as stale without removing it. With ",[488,2351,682],{}," enabled, the stale value is still served while the next call triggers a background refresh; without SWR, the next call re-resolves before returning.",[458,2354,2355,2360,2361,2363],{},[627,2356,2357],{},[488,2358,2359],{},".resolveKeys(...args)"," — resolves the storage key(s) the entry is cached under (one per ",[488,2362,1512],{}," prefix).",[451,2365,2366,2367,2369,2370,2372,2373,613],{},"Arguments are passed through ",[488,2368,2113],{}," to generate the cache key. For cached handlers, pass the ",[488,2371,562],{}," (e.g. ",[488,2374,2375],{},".invalidate(event)",[505,2377,2379],{"className":507,"code":2378,"language":510,"meta":5,"style":5},"import { defineCachedFunction } from \"nitro\u002Fcache\";\n\nconst cachedGHStars = defineCachedFunction(async (repo: string) => {\n  const data = await fetch(`https:\u002F\u002Fapi.github.com\u002Frepos\u002F${repo}`).then(res => res.json());\n  return data.stargazers_count;\n}, {\n  maxAge: 60 * 60,\n  name: \"ghStars\",\n  getKey: (repo: string) => repo,\n});\n\nawait cachedGHStars(\"unjs\u002Fnitro\"); \u002F\u002F populates the cache\nawait cachedGHStars.expire(\"unjs\u002Fnitro\"); \u002F\u002F marks the entry as stale\nawait cachedGHStars.invalidate(\"unjs\u002Fnitro\"); \u002F\u002F removes the entry\nawait cachedGHStars(\"unjs\u002Fnitro\"); \u002F\u002F re-invokes the function\n",[488,2380,2381,2393,2397,2425,2461,2467,2471,2483,2491,2510,2514,2518,2537,2556,2574],{"__ignoreMap":5},[514,2382,2383,2385,2387,2389,2391],{"class":516,"line":517},[514,2384,521],{"class":520},[514,2386,834],{"class":524},[514,2388,528],{"class":520},[514,2390,532],{"class":531},[514,2392,535],{"class":524},[514,2394,2395],{"class":516,"line":538},[514,2396,542],{"emptyLinePlaceholder":541},[514,2398,2399,2401,2403,2405,2407,2409,2411,2413,2415,2417,2419,2421,2423],{"class":516,"line":545},[514,2400,974],{"class":520},[514,2402,927],{"class":591},[514,2404,921],{"class":520},[514,2406,981],{"class":554},[514,2408,876],{"class":524},[514,2410,879],{"class":520},[514,2412,882],{"class":524},[514,2414,901],{"class":561},[514,2416,992],{"class":520},[514,2418,995],{"class":591},[514,2420,565],{"class":524},[514,2422,568],{"class":520},[514,2424,571],{"class":524},[514,2426,2427,2429,2431,2433,2435,2437,2439,2441,2443,2445,2447,2449,2451,2453,2455,2457,2459],{"class":516,"line":574},[514,2428,895],{"class":520},[514,2430,1009],{"class":591},[514,2432,921],{"class":520},[514,2434,924],{"class":520},[514,2436,1016],{"class":554},[514,2438,876],{"class":524},[514,2440,1021],{"class":531},[514,2442,901],{"class":524},[514,2444,1026],{"class":531},[514,2446,613],{"class":524},[514,2448,1031],{"class":554},[514,2450,876],{"class":524},[514,2452,1036],{"class":561},[514,2454,1039],{"class":520},[514,2456,1042],{"class":524},[514,2458,1045],{"class":554},[514,2460,1048],{"class":524},[514,2462,2463,2465],{"class":516,"line":585},[514,2464,577],{"class":520},[514,2466,1061],{"class":524},[514,2468,2469],{"class":516,"line":913},[514,2470,1067],{"class":524},[514,2472,2473,2475,2477,2479,2481],{"class":516,"line":947},[514,2474,1073],{"class":524},[514,2476,592],{"class":591},[514,2478,595],{"class":520},[514,2480,598],{"class":591},[514,2482,1082],{"class":524},[514,2484,2485,2487,2489],{"class":516,"line":952},[514,2486,1088],{"class":524},[514,2488,1091],{"class":531},[514,2490,1082],{"class":524},[514,2492,2493,2495,2497,2499,2501,2503,2505,2507],{"class":516,"line":960},[514,2494,1099],{"class":554},[514,2496,1102],{"class":524},[514,2498,901],{"class":561},[514,2500,992],{"class":520},[514,2502,995],{"class":591},[514,2504,565],{"class":524},[514,2506,568],{"class":520},[514,2508,2509],{"class":524}," repo,\n",[514,2511,2512],{"class":516,"line":966},[514,2513,963],{"class":524},[514,2515,2516],{"class":516,"line":971},[514,2517,542],{"emptyLinePlaceholder":541},[514,2519,2520,2523,2525,2527,2530,2533],{"class":516,"line":1004},[514,2521,2522],{"class":520},"await",[514,2524,927],{"class":554},[514,2526,876],{"class":524},[514,2528,2529],{"class":531},"\"unjs\u002Fnitro\"",[514,2531,2532],{"class":524},"); ",[514,2534,2536],{"class":2535},"sCsY4","\u002F\u002F populates the cache\n",[514,2538,2539,2541,2544,2547,2549,2551,2553],{"class":516,"line":1051},[514,2540,2522],{"class":520},[514,2542,2543],{"class":524}," cachedGHStars.",[514,2545,2546],{"class":554},"expire",[514,2548,876],{"class":524},[514,2550,2529],{"class":531},[514,2552,2532],{"class":524},[514,2554,2555],{"class":2535},"\u002F\u002F marks the entry as stale\n",[514,2557,2558,2560,2562,2565,2567,2569,2571],{"class":516,"line":1056},[514,2559,2522],{"class":520},[514,2561,2543],{"class":524},[514,2563,2564],{"class":554},"invalidate",[514,2566,876],{"class":524},[514,2568,2529],{"class":531},[514,2570,2532],{"class":524},[514,2572,2573],{"class":2535},"\u002F\u002F removes the entry\n",[514,2575,2576,2578,2580,2582,2584,2586],{"class":516,"line":1064},[514,2577,2522],{"class":520},[514,2579,927],{"class":554},[514,2581,876],{"class":524},[514,2583,2529],{"class":531},[514,2585,2532],{"class":524},[514,2587,2588],{"class":2535},"\u002F\u002F re-invokes the function\n",[451,2590,2591,2592,787,2594,2596],{},"If no cached entry matches the given arguments, ",[488,2593,2318],{},[488,2595,2321],{}," resolve without error and leave storage unchanged.",[640,2598,2600],{"id":2599},"standalone-helpers","Standalone helpers",[451,2602,1489,2603,683,2606,687,2609,2612],{},[488,2604,2605],{},"invalidateCache()",[488,2607,2608],{},"expireCache()",[488,2610,2611],{},"resolveCacheKeys()"," helpers work from the cache options used to define a cached function, so invalidation can live anywhere in your app, independent of where the cached function is defined.",[451,2614,2615,2616,683,2618,683,2620,687,2622,2624,2625,2627],{},"Pass the same ",[488,2617,1531],{},[488,2619,1542],{},[488,2621,1512],{},[488,2623,2113],{}," used when defining the function, along with the ",[488,2626,1911],{}," identifying the entry:",[505,2629,2631],{"className":507,"code":2630,"language":510,"meta":5,"style":5},"import { invalidateCache } from \"ocache\";\n\nawait invalidateCache({\n  options: {\n    name: \"ghStars\",\n    group: \"nitro\u002Ffunctions\",\n    getKey: (repo: string) => repo,\n  },\n  args: [\"unjs\u002Fnitro\"],\n});\n",[488,2632,2633,2647,2651,2661,2666,2675,2685,2704,2709,2719],{"__ignoreMap":5},[514,2634,2635,2637,2640,2642,2645],{"class":516,"line":517},[514,2636,521],{"class":520},[514,2638,2639],{"class":524}," { invalidateCache } ",[514,2641,528],{"class":520},[514,2643,2644],{"class":531}," \"ocache\"",[514,2646,535],{"class":524},[514,2648,2649],{"class":516,"line":538},[514,2650,542],{"emptyLinePlaceholder":541},[514,2652,2653,2655,2658],{"class":516,"line":545},[514,2654,2522],{"class":520},[514,2656,2657],{"class":554}," invalidateCache",[514,2659,2660],{"class":524},"({\n",[514,2662,2663],{"class":516,"line":574},[514,2664,2665],{"class":524},"  options: {\n",[514,2667,2668,2671,2673],{"class":516,"line":585},[514,2669,2670],{"class":524},"    name: ",[514,2672,1091],{"class":531},[514,2674,1082],{"class":524},[514,2676,2677,2680,2683],{"class":516,"line":913},[514,2678,2679],{"class":524},"    group: ",[514,2681,2682],{"class":531},"\"nitro\u002Ffunctions\"",[514,2684,1082],{"class":524},[514,2686,2687,2690,2692,2694,2696,2698,2700,2702],{"class":516,"line":947},[514,2688,2689],{"class":554},"    getKey",[514,2691,1102],{"class":524},[514,2693,901],{"class":561},[514,2695,992],{"class":520},[514,2697,995],{"class":591},[514,2699,565],{"class":524},[514,2701,568],{"class":520},[514,2703,2509],{"class":524},[514,2705,2706],{"class":516,"line":952},[514,2707,2708],{"class":524},"  },\n",[514,2710,2711,2714,2716],{"class":516,"line":960},[514,2712,2713],{"class":524},"  args: [",[514,2715,2529],{"class":531},[514,2717,2718],{"class":524},"],\n",[514,2720,2721],{"class":516,"line":966},[514,2722,963],{"class":524},[451,2724,2725,2727,2728,2730],{},[488,2726,2608],{}," accepts the same input and marks the entry as stale instead of removing it, while ",[488,2729,2611],{}," returns the storage keys so you can operate on them directly.",[2263,2732,2733],{},[451,2734,2735,2736,2739,2740,2748,2749,2751,2752,2755],{},"These helpers are not re-exported by ",[488,2737,2738],{},"nitro\u002Fcache"," — import them from ",[461,2741,2745],{"href":2742,"rel":2743},"https:\u002F\u002Fgithub.com\u002Funjs\u002Focache",[2744],"nofollow",[488,2746,2747],{},"ocache"," directly. Since ",[488,2750,2747],{}," is a transitive dependency of Nitro, add it to your own ",[488,2753,2754],{},"package.json"," dependencies to depend on it explicitly.",[622,2757,2758],{},[451,2759,1489,2760,683,2762,683,2764,687,2766,2768,2769,1733,2771,2773,2774,2777,2778,2781,2782,2785,2786,613],{},[488,2761,1531],{},[488,2763,1542],{},[488,2765,1512],{},[488,2767,2113],{}," passed to these helpers must match the ones used when the cached function was defined. Mismatched options resolve to a different storage key and will not affect the intended entry. ",[1518,2770],{},[1518,2772],{},"\nNitro defaults to ",[488,2775,2776],{},"group: 'nitro\u002Ffunctions'"," for cached functions and ",[488,2779,2780],{},"group: 'nitro\u002Fhandlers'"," for cached handlers (or ",[488,2783,2784],{},"'nitro\u002Froute-rules'"," when using ",[461,2787,2788],{"href":477},"route rules",[481,2790,2792],{"id":2791},"cache-storage","Cache storage",[451,2794,2795,2796,2799,2800,2802,2803,2806],{},"Cache entries are stored using the ",[461,2797,2798],{"href":109},"storage layer"," under the ",[488,2801,1527],{}," prefix (derived from the default ",[488,2804,2805],{},"base: \"\u002Fcache\""," option).",[451,2808,2809,2810,2813],{},"By default, no dedicated mount point is configured for it: entries live in the root storage, which uses an in-memory driver and is ",[627,2811,2812],{},"not persisted across restarts"," — in both development and production.",[451,2815,2816,2817,2819,2820,2823],{},"To use a persistent backend, set the ",[488,2818,2233],{}," mount point using the ",[488,2821,2822],{},"storage"," option:",[505,2825,2828],{"className":507,"code":2826,"filename":2827,"language":510,"meta":5,"style":5},"import { defineConfig } from \"nitro\";\n\nexport default defineConfig({\n  storage: {\n    cache: {\n      driver: 'redis',\n      \u002F* redis connector options *\u002F\n    }\n  }\n})\n","nitro.config.ts",[488,2829,2830,2843,2847,2858,2863,2868,2878,2883,2888,2893],{"__ignoreMap":5},[514,2831,2832,2834,2837,2839,2841],{"class":516,"line":517},[514,2833,521],{"class":520},[514,2835,2836],{"class":524}," { defineConfig } ",[514,2838,528],{"class":520},[514,2840,858],{"class":531},[514,2842,535],{"class":524},[514,2844,2845],{"class":516,"line":538},[514,2846,542],{"emptyLinePlaceholder":541},[514,2848,2849,2851,2853,2856],{"class":516,"line":545},[514,2850,548],{"class":520},[514,2852,551],{"class":520},[514,2854,2855],{"class":554}," defineConfig",[514,2857,2660],{"class":524},[514,2859,2860],{"class":516,"line":574},[514,2861,2862],{"class":524},"  storage: {\n",[514,2864,2865],{"class":516,"line":585},[514,2866,2867],{"class":524},"    cache: {\n",[514,2869,2870,2873,2876],{"class":516,"line":913},[514,2871,2872],{"class":524},"      driver: ",[514,2874,2875],{"class":531},"'redis'",[514,2877,1082],{"class":524},[514,2879,2880],{"class":516,"line":947},[514,2881,2882],{"class":2535},"      \u002F* redis connector options *\u002F\n",[514,2884,2885],{"class":516,"line":952},[514,2886,2887],{"class":524},"    }\n",[514,2889,2890],{"class":516,"line":960},[514,2891,2892],{"class":524},"  }\n",[514,2894,2895],{"class":516,"line":966},[514,2896,2897],{"class":524},"})\n",[451,2899,2900,2901,2823],{},"In development, you can also overwrite the cache mount point using the ",[488,2902,2903],{},"devStorage",[505,2905,2907],{"className":507,"code":2906,"filename":2827,"language":510,"meta":5,"style":5},"import { defineConfig } from \"nitro\";\n\nexport default defineConfig({\n  storage: {\n    cache: {\n      \u002F\u002F production cache storage\n    },\n  },\n  devStorage: {\n    cache: {\n      \u002F\u002F development cache storage\n    }\n  }\n})\n",[488,2908,2909,2921,2925,2935,2939,2943,2948,2953,2957,2962,2966,2971,2975,2979],{"__ignoreMap":5},[514,2910,2911,2913,2915,2917,2919],{"class":516,"line":517},[514,2912,521],{"class":520},[514,2914,2836],{"class":524},[514,2916,528],{"class":520},[514,2918,858],{"class":531},[514,2920,535],{"class":524},[514,2922,2923],{"class":516,"line":538},[514,2924,542],{"emptyLinePlaceholder":541},[514,2926,2927,2929,2931,2933],{"class":516,"line":545},[514,2928,548],{"class":520},[514,2930,551],{"class":520},[514,2932,2855],{"class":554},[514,2934,2660],{"class":524},[514,2936,2937],{"class":516,"line":574},[514,2938,2862],{"class":524},[514,2940,2941],{"class":516,"line":585},[514,2942,2867],{"class":524},[514,2944,2945],{"class":516,"line":913},[514,2946,2947],{"class":2535},"      \u002F\u002F production cache storage\n",[514,2949,2950],{"class":516,"line":947},[514,2951,2952],{"class":524},"    },\n",[514,2954,2955],{"class":516,"line":952},[514,2956,2708],{"class":524},[514,2958,2959],{"class":516,"line":960},[514,2960,2961],{"class":524},"  devStorage: {\n",[514,2963,2964],{"class":516,"line":966},[514,2965,2867],{"class":524},[514,2967,2968],{"class":516,"line":971},[514,2969,2970],{"class":2535},"      \u002F\u002F development cache storage\n",[514,2972,2973],{"class":516,"line":1004},[514,2974,2887],{"class":524},[514,2976,2977],{"class":516,"line":1051},[514,2978,2892],{"class":524},[514,2980,2981],{"class":516,"line":1056},[514,2982,2897],{"class":524},[2984,2985,2986],"read-more",{"to":109},[451,2987,2988],{},"Read more about the Nitro storage layer and available drivers.",[481,2990,2992],{"id":2991},"using-route-rules","Using route rules",[451,2994,2995],{},"Route rules let you enable caching for all routes matching a glob pattern, directly from your configuration. This is especially useful for a global cache strategy across a part of your application, without touching handler code.",[451,2997,2998],{},"Cache all the blog routes for 1 hour:",[505,3000,3002],{"className":507,"code":3001,"filename":2827,"language":510,"meta":5,"style":5},"import { defineConfig } from \"nitro\";\n\nexport default defineConfig({\n  routeRules: {\n    \"\u002Fblog\u002F**\": { cache: { maxAge: 60 * 60 } },\n  },\n});\n",[488,3003,3004,3016,3020,3030,3035,3052,3056],{"__ignoreMap":5},[514,3005,3006,3008,3010,3012,3014],{"class":516,"line":517},[514,3007,521],{"class":520},[514,3009,2836],{"class":524},[514,3011,528],{"class":520},[514,3013,858],{"class":531},[514,3015,535],{"class":524},[514,3017,3018],{"class":516,"line":538},[514,3019,542],{"emptyLinePlaceholder":541},[514,3021,3022,3024,3026,3028],{"class":516,"line":545},[514,3023,548],{"class":520},[514,3025,551],{"class":520},[514,3027,2855],{"class":554},[514,3029,2660],{"class":524},[514,3031,3032],{"class":516,"line":574},[514,3033,3034],{"class":524},"  routeRules: {\n",[514,3036,3037,3040,3043,3045,3047,3049],{"class":516,"line":585},[514,3038,3039],{"class":531},"    \"\u002Fblog\u002F**\"",[514,3041,3042],{"class":524},": { cache: { maxAge: ",[514,3044,592],{"class":591},[514,3046,595],{"class":520},[514,3048,598],{"class":591},[514,3050,3051],{"class":524}," } },\n",[514,3053,3054],{"class":516,"line":913},[514,3055,2708],{"class":524},[514,3057,3058],{"class":516,"line":947},[514,3059,963],{"class":524},[451,3061,3062,3063,3066,3067,747],{},"If we want to use a ",[461,3064,3065],{"href":1126},"custom cache storage"," mount point, we can use the ",[488,3068,1512],{},[505,3070,3072],{"className":507,"code":3071,"filename":2827,"language":510,"meta":5,"style":5},"import { defineConfig } from \"nitro\";\n\nexport default defineConfig({\n  storage: {\n    redis: {\n      driver: \"redis\",\n      url: \"redis:\u002F\u002Flocalhost:6379\",\n    },\n  },\n  routeRules: {\n    \"\u002Fblog\u002F**\": { cache: { maxAge: 60 * 60, base: \"redis\" } },\n  },\n});\n",[488,3073,3074,3086,3090,3100,3104,3109,3118,3128,3132,3136,3140,3159,3163],{"__ignoreMap":5},[514,3075,3076,3078,3080,3082,3084],{"class":516,"line":517},[514,3077,521],{"class":520},[514,3079,2836],{"class":524},[514,3081,528],{"class":520},[514,3083,858],{"class":531},[514,3085,535],{"class":524},[514,3087,3088],{"class":516,"line":538},[514,3089,542],{"emptyLinePlaceholder":541},[514,3091,3092,3094,3096,3098],{"class":516,"line":545},[514,3093,548],{"class":520},[514,3095,551],{"class":520},[514,3097,2855],{"class":554},[514,3099,2660],{"class":524},[514,3101,3102],{"class":516,"line":574},[514,3103,2862],{"class":524},[514,3105,3106],{"class":516,"line":585},[514,3107,3108],{"class":524},"    redis: {\n",[514,3110,3111,3113,3116],{"class":516,"line":913},[514,3112,2872],{"class":524},[514,3114,3115],{"class":531},"\"redis\"",[514,3117,1082],{"class":524},[514,3119,3120,3123,3126],{"class":516,"line":947},[514,3121,3122],{"class":524},"      url: ",[514,3124,3125],{"class":531},"\"redis:\u002F\u002Flocalhost:6379\"",[514,3127,1082],{"class":524},[514,3129,3130],{"class":516,"line":952},[514,3131,2952],{"class":524},[514,3133,3134],{"class":516,"line":960},[514,3135,2708],{"class":524},[514,3137,3138],{"class":516,"line":966},[514,3139,3034],{"class":524},[514,3141,3142,3144,3146,3148,3150,3152,3155,3157],{"class":516,"line":971},[514,3143,3039],{"class":531},[514,3145,3042],{"class":524},[514,3147,592],{"class":591},[514,3149,595],{"class":520},[514,3151,598],{"class":591},[514,3153,3154],{"class":524},", base: ",[514,3156,3115],{"class":531},[514,3158,3051],{"class":524},[514,3160,3161],{"class":516,"line":1004},[514,3162,2708],{"class":524},[514,3164,3165],{"class":516,"line":1051},[514,3166,963],{"class":524},[640,3168,3170],{"id":3169},"route-rules-shortcuts","Route rules shortcuts",[451,3172,3173,3174,3176,3177,3179,3180,3182,3183,3185,3186,3188],{},"You can use the ",[488,3175,682],{}," shortcut for enabling ",[488,3178,715],{}," caching on route rules. When set to ",[488,3181,1711],{},", SWR is enabled with the default ",[488,3184,686],{},". When set to a number, it is used as the ",[488,3187,686],{}," value in seconds.",[505,3190,3192],{"className":507,"code":3191,"filename":2827,"language":510,"meta":5,"style":5},"import { defineConfig } from \"nitro\";\n\nexport default defineConfig({\n  routeRules: {\n    \"\u002Fblog\u002F**\": { swr: true },\n    \"\u002Fapi\u002F**\": { swr: 3600 },\n  },\n});\n",[488,3193,3194,3206,3210,3220,3224,3236,3247,3251],{"__ignoreMap":5},[514,3195,3196,3198,3200,3202,3204],{"class":516,"line":517},[514,3197,521],{"class":520},[514,3199,2836],{"class":524},[514,3201,528],{"class":520},[514,3203,858],{"class":531},[514,3205,535],{"class":524},[514,3207,3208],{"class":516,"line":538},[514,3209,542],{"emptyLinePlaceholder":541},[514,3211,3212,3214,3216,3218],{"class":516,"line":545},[514,3213,548],{"class":520},[514,3215,551],{"class":520},[514,3217,2855],{"class":554},[514,3219,2660],{"class":524},[514,3221,3222],{"class":516,"line":574},[514,3223,3034],{"class":524},[514,3225,3226,3228,3231,3233],{"class":516,"line":585},[514,3227,3039],{"class":531},[514,3229,3230],{"class":524},": { swr: ",[514,3232,1711],{"class":591},[514,3234,3235],{"class":524}," },\n",[514,3237,3238,3241,3243,3245],{"class":516,"line":913},[514,3239,3240],{"class":531},"    \"\u002Fapi\u002F**\"",[514,3242,3230],{"class":524},[514,3244,1964],{"class":591},[514,3246,3235],{"class":524},[514,3248,3249],{"class":516,"line":947},[514,3250,2708],{"class":524},[514,3252,3253],{"class":516,"line":952},[514,3254,963],{"class":524},[451,3256,3257,3258,992],{},"To explicitly disable caching on a route, set ",[488,3259,3260],{},"cache: false",[505,3262,3264],{"className":507,"code":3263,"filename":2827,"language":510,"meta":5,"style":5},"import { defineConfig } from \"nitro\";\n\nexport default defineConfig({\n  routeRules: {\n    \"\u002Fapi\u002Frealtime\u002F**\": { cache: false },\n  },\n});\n",[488,3265,3266,3278,3282,3292,3296,3308,3312],{"__ignoreMap":5},[514,3267,3268,3270,3272,3274,3276],{"class":516,"line":517},[514,3269,521],{"class":520},[514,3271,2836],{"class":524},[514,3273,528],{"class":520},[514,3275,858],{"class":531},[514,3277,535],{"class":524},[514,3279,3280],{"class":516,"line":538},[514,3281,542],{"emptyLinePlaceholder":541},[514,3283,3284,3286,3288,3290],{"class":516,"line":545},[514,3285,548],{"class":520},[514,3287,551],{"class":520},[514,3289,2855],{"class":554},[514,3291,2660],{"class":524},[514,3293,3294],{"class":516,"line":574},[514,3295,3034],{"class":524},[514,3297,3298,3301,3304,3306],{"class":516,"line":585},[514,3299,3300],{"class":531},"    \"\u002Fapi\u002Frealtime\u002F**\"",[514,3302,3303],{"class":524},": { cache: ",[514,3305,1630],{"class":591},[514,3307,3235],{"class":524},[514,3309,3310],{"class":516,"line":913},[514,3311,2708],{"class":524},[514,3313,3314],{"class":516,"line":947},[514,3315,963],{"class":524},[2263,3317,3318],{},[451,3319,3320,3321,3323,3324,503],{},"When using route rules, cached handlers use the group ",[488,3322,2784],{}," instead of the default ",[488,3325,1548],{},[2984,3327,3329],{"to":3328},"\u002Fdocs\u002Frouting#route-rules",[451,3330,3331],{},"Route rules can do much more than caching — headers, redirects, proxying, and more.",[3333,3334,3335],"style",{},"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 .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}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 .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}",{"title":5,"searchDepth":538,"depth":538,"links":3337},[3338,3344,3345,3350,3351,3352,3357,3358],{"id":483,"depth":538,"text":464,"children":3339},[3340,3341,3342,3343],{"id":642,"depth":545,"text":643},{"id":761,"depth":545,"text":762},{"id":779,"depth":545,"text":780},{"id":804,"depth":545,"text":805},{"id":811,"depth":538,"text":471},{"id":619,"depth":538,"text":1486,"children":3346},[3347,3348,3349],{"id":1497,"depth":545,"text":1498},{"id":1694,"depth":545,"text":1695},{"id":1844,"depth":545,"text":1845},{"id":1915,"depth":538,"text":612},{"id":2062,"depth":538,"text":2063},{"id":2305,"depth":538,"text":2306,"children":3353},[3354,3356],{"id":2315,"depth":545,"text":3355},".invalidate() and .expire() methods",{"id":2599,"depth":545,"text":2600},{"id":2791,"depth":538,"text":2792},{"id":2991,"depth":538,"text":2992,"children":3359},[3360],{"id":3169,"depth":545,"text":3170},"Nitro provides a caching system built on top of the storage layer, powered by ocache.","md",{"icon":106},{"icon":106},{"title":103,"description":3361},"a1XUsdGEJjWdca9Z2VfgqwTjzapVL8GT3lq3cibzci4",[3368,3370],{"title":98,"path":99,"stem":100,"description":3369,"icon":101,"children":-1},"Nitro is TypeScript-first: write your config, handlers, and server code in TypeScript with zero setup.",{"title":108,"path":109,"stem":110,"description":3371,"icon":111,"children":-1},"Nitro provides a built-in storage layer that can abstract the filesystem, a database, or any other data source.",1784019064242]