[{"data":1,"prerenderedAt":4031},["ShallowReactive",2],{"navigation":3,"-guide":9,"-guide-surround":4029},[4],{"title":5,"path":6,"stem":7,"icon":8},"ocache","\u002Fguide","1.guide","pixel:play",{"id":10,"title":5,"body":11,"description":39,"extension":4024,"meta":4025,"navigation":4026,"path":6,"seo":4027,"stem":7,"__hash__":4028},"content\u002F1.guide.md",{"type":12,"value":13,"toc":3999,"icon":8},"minimark",[14,19,24,33,239,244,526,530,557,652,656,677,768,772,790,1008,1012,1046,1088,1092,1110,1125,1155,1197,1200,1242,1246,1253,1291,1295,1304,1337,1356,1364,1380,1394,1443,1449,1456,1482,1552,1564,1568,1574,1696,1699,1732,1739,1752,1788,1799,1823,1995,2023,2027,2033,2208,2215,2287,2294,2326,2330,2342,2366,2384,2461,2465,2472,2569,2572,2576,2583,2824,2839,2902,2906,2912,2929,2937,2940,2946,2982,2985,3011,3013,3018,3043,3049,3051,3056,3155,3158,3163,3180,3190,3192,3197,3258,3261,3275,3279,3296,3301,3303,3309,3339,3349,3351,3357,3395,3398,3411,3427,3431,3447,3452,3515,3517,3522,3557,3560,3566,3570,3582,3586,3640,3642,3647,3683,3686,3691,3716,3735,3739,3751,3756,3760,3862,3864,3869,3897,3900,3902,3908,3927,3933,3937,3982,3986,3995],[15,16,18],"h2",{"id":17},"usage","Usage",[20,21,23],"h3",{"id":22},"caching-functions","Caching Functions",[25,26,27,28,32],"p",{},"Wrap any function with ",[29,30,31],"code",{},"defineCachedFunction"," to add caching with TTL, stale-while-revalidate, and request deduplication:",[34,35,40],"pre",{"className":36,"code":37,"language":38,"meta":39,"style":39},"language-ts shiki shiki-themes github-light github-dark github-dark","import { defineCachedFunction } from \"ocache\";\n\nconst cachedFetch = defineCachedFunction(\n  async (url: string) => {\n    const res = await fetch(url);\n    return res.json();\n  },\n  {\n    maxAge: 60, \u002F\u002F Cache for 60 seconds\n    name: \"api-fetch\",\n  },\n);\n\n\u002F\u002F First call hits the function, subsequent calls return cached result\nconst data = await cachedFetch(\"https:\u002F\u002Fapi.example.com\u002Fdata\");\n","ts","",[29,41,42,65,72,92,120,140,155,161,167,183,195,200,206,211,217],{"__ignoreMap":39},[43,44,47,51,55,58,62],"span",{"class":45,"line":46},"line",1,[43,48,50],{"class":49},"so5gQ","import",[43,52,54],{"class":53},"slsVL"," { defineCachedFunction } ",[43,56,57],{"class":49},"from",[43,59,61],{"class":60},"sfrk1"," \"ocache\"",[43,63,64],{"class":53},";\n",[43,66,68],{"class":45,"line":67},2,[43,69,71],{"emptyLinePlaceholder":70},true,"\n",[43,73,75,78,82,85,89],{"class":45,"line":74},3,[43,76,77],{"class":49},"const",[43,79,81],{"class":80},"suiK_"," cachedFetch",[43,83,84],{"class":49}," =",[43,86,88],{"class":87},"shcOC"," defineCachedFunction",[43,90,91],{"class":53},"(\n",[43,93,95,98,101,105,108,111,114,117],{"class":45,"line":94},4,[43,96,97],{"class":49},"  async",[43,99,100],{"class":53}," (",[43,102,104],{"class":103},"sQHwn","url",[43,106,107],{"class":49},":",[43,109,110],{"class":80}," string",[43,112,113],{"class":53},") ",[43,115,116],{"class":49},"=>",[43,118,119],{"class":53}," {\n",[43,121,123,126,129,131,134,137],{"class":45,"line":122},5,[43,124,125],{"class":49},"    const",[43,127,128],{"class":80}," res",[43,130,84],{"class":49},[43,132,133],{"class":49}," await",[43,135,136],{"class":87}," fetch",[43,138,139],{"class":53},"(url);\n",[43,141,143,146,149,152],{"class":45,"line":142},6,[43,144,145],{"class":49},"    return",[43,147,148],{"class":53}," res.",[43,150,151],{"class":87},"json",[43,153,154],{"class":53},"();\n",[43,156,158],{"class":45,"line":157},7,[43,159,160],{"class":53},"  },\n",[43,162,164],{"class":45,"line":163},8,[43,165,166],{"class":53},"  {\n",[43,168,170,173,176,179],{"class":45,"line":169},9,[43,171,172],{"class":53},"    maxAge: ",[43,174,175],{"class":80},"60",[43,177,178],{"class":53},", ",[43,180,182],{"class":181},"sCsY4","\u002F\u002F Cache for 60 seconds\n",[43,184,186,189,192],{"class":45,"line":185},10,[43,187,188],{"class":53},"    name: ",[43,190,191],{"class":60},"\"api-fetch\"",[43,193,194],{"class":53},",\n",[43,196,198],{"class":45,"line":197},11,[43,199,160],{"class":53},[43,201,203],{"class":45,"line":202},12,[43,204,205],{"class":53},");\n",[43,207,209],{"class":45,"line":208},13,[43,210,71],{"emptyLinePlaceholder":70},[43,212,214],{"class":45,"line":213},14,[43,215,216],{"class":181},"\u002F\u002F First call hits the function, subsequent calls return cached result\n",[43,218,220,222,225,227,229,231,234,237],{"class":45,"line":219},15,[43,221,77],{"class":49},[43,223,224],{"class":80}," data",[43,226,84],{"class":49},[43,228,133],{"class":49},[43,230,81],{"class":87},[43,232,233],{"class":53},"(",[43,235,236],{"class":60},"\"https:\u002F\u002Fapi.example.com\u002Fdata\"",[43,238,205],{"class":53},[240,241,243],"h4",{"id":242},"options","Options",[34,245,247],{"className":36,"code":246,"language":38,"meta":39,"style":39},"const cached = defineCachedFunction(fn, {\n  name: \"my-fn\", \u002F\u002F Cache key name (defaults to function name)\n  maxAge: 10, \u002F\u002F TTL in seconds (default: 1)\n  swr: false, \u002F\u002F Stale-while-revalidate (default: false — opt in to serve stale)\n  staleMaxAge: 60, \u002F\u002F Max seconds to serve stale content\n  getMaxAge: (entry) => entry.value?.expires_in, \u002F\u002F Per-entry TTL from the resolved value\n  base: \"\u002Fcache\", \u002F\u002F Base prefix for cache keys (string or string[] for multi-tier)\n  group: \"my-group\", \u002F\u002F Cache key group (default: \"functions\")\n  getKey: (...args) => \"custom-key\", \u002F\u002F Custom cache key generator\n  shouldBypassCache: (...args) => false, \u002F\u002F Skip cache entirely when true\n  shouldInvalidateCache: (...args) => false, \u002F\u002F Force refresh when true\n  validate: (entry) => entry.value !== undefined, \u002F\u002F Custom validation\n  serialize: (entry) => entry.value, \u002F\u002F Prepare value for storage (transform restores it on read)\n  transform: (entry) => entry.value, \u002F\u002F Transform before returning\n  onError: (error) => console.error(error), \u002F\u002F Error handler\n});\n",[29,248,249,263,276,289,302,314,335,348,361,386,409,431,458,477,495,520],{"__ignoreMap":39},[43,250,251,253,256,258,260],{"class":45,"line":46},[43,252,77],{"class":49},[43,254,255],{"class":80}," cached",[43,257,84],{"class":49},[43,259,88],{"class":87},[43,261,262],{"class":53},"(fn, {\n",[43,264,265,268,271,273],{"class":45,"line":67},[43,266,267],{"class":53},"  name: ",[43,269,270],{"class":60},"\"my-fn\"",[43,272,178],{"class":53},[43,274,275],{"class":181},"\u002F\u002F Cache key name (defaults to function name)\n",[43,277,278,281,284,286],{"class":45,"line":74},[43,279,280],{"class":53},"  maxAge: ",[43,282,283],{"class":80},"10",[43,285,178],{"class":53},[43,287,288],{"class":181},"\u002F\u002F TTL in seconds (default: 1)\n",[43,290,291,294,297,299],{"class":45,"line":94},[43,292,293],{"class":53},"  swr: ",[43,295,296],{"class":80},"false",[43,298,178],{"class":53},[43,300,301],{"class":181},"\u002F\u002F Stale-while-revalidate (default: false — opt in to serve stale)\n",[43,303,304,307,309,311],{"class":45,"line":122},[43,305,306],{"class":53},"  staleMaxAge: ",[43,308,175],{"class":80},[43,310,178],{"class":53},[43,312,313],{"class":181},"\u002F\u002F Max seconds to serve stale content\n",[43,315,316,319,322,325,327,329,332],{"class":45,"line":142},[43,317,318],{"class":87},"  getMaxAge",[43,320,321],{"class":53},": (",[43,323,324],{"class":103},"entry",[43,326,113],{"class":53},[43,328,116],{"class":49},[43,330,331],{"class":53}," entry.value?.expires_in, ",[43,333,334],{"class":181},"\u002F\u002F Per-entry TTL from the resolved value\n",[43,336,337,340,343,345],{"class":45,"line":157},[43,338,339],{"class":53},"  base: ",[43,341,342],{"class":60},"\"\u002Fcache\"",[43,344,178],{"class":53},[43,346,347],{"class":181},"\u002F\u002F Base prefix for cache keys (string or string[] for multi-tier)\n",[43,349,350,353,356,358],{"class":45,"line":163},[43,351,352],{"class":53},"  group: ",[43,354,355],{"class":60},"\"my-group\"",[43,357,178],{"class":53},[43,359,360],{"class":181},"\u002F\u002F Cache key group (default: \"functions\")\n",[43,362,363,366,368,371,374,376,378,381,383],{"class":45,"line":169},[43,364,365],{"class":87},"  getKey",[43,367,321],{"class":53},[43,369,370],{"class":49},"...",[43,372,373],{"class":103},"args",[43,375,113],{"class":53},[43,377,116],{"class":49},[43,379,380],{"class":60}," \"custom-key\"",[43,382,178],{"class":53},[43,384,385],{"class":181},"\u002F\u002F Custom cache key generator\n",[43,387,388,391,393,395,397,399,401,404,406],{"class":45,"line":185},[43,389,390],{"class":87},"  shouldBypassCache",[43,392,321],{"class":53},[43,394,370],{"class":49},[43,396,373],{"class":103},[43,398,113],{"class":53},[43,400,116],{"class":49},[43,402,403],{"class":80}," false",[43,405,178],{"class":53},[43,407,408],{"class":181},"\u002F\u002F Skip cache entirely when true\n",[43,410,411,414,416,418,420,422,424,426,428],{"class":45,"line":197},[43,412,413],{"class":87},"  shouldInvalidateCache",[43,415,321],{"class":53},[43,417,370],{"class":49},[43,419,373],{"class":103},[43,421,113],{"class":53},[43,423,116],{"class":49},[43,425,403],{"class":80},[43,427,178],{"class":53},[43,429,430],{"class":181},"\u002F\u002F Force refresh when true\n",[43,432,433,436,438,440,442,444,447,450,453,455],{"class":45,"line":202},[43,434,435],{"class":87},"  validate",[43,437,321],{"class":53},[43,439,324],{"class":103},[43,441,113],{"class":53},[43,443,116],{"class":49},[43,445,446],{"class":53}," entry.value ",[43,448,449],{"class":49},"!==",[43,451,452],{"class":80}," undefined",[43,454,178],{"class":53},[43,456,457],{"class":181},"\u002F\u002F Custom validation\n",[43,459,460,463,465,467,469,471,474],{"class":45,"line":208},[43,461,462],{"class":87},"  serialize",[43,464,321],{"class":53},[43,466,324],{"class":103},[43,468,113],{"class":53},[43,470,116],{"class":49},[43,472,473],{"class":53}," entry.value, ",[43,475,476],{"class":181},"\u002F\u002F Prepare value for storage (transform restores it on read)\n",[43,478,479,482,484,486,488,490,492],{"class":45,"line":213},[43,480,481],{"class":87},"  transform",[43,483,321],{"class":53},[43,485,324],{"class":103},[43,487,113],{"class":53},[43,489,116],{"class":49},[43,491,473],{"class":53},[43,493,494],{"class":181},"\u002F\u002F Transform before returning\n",[43,496,497,500,502,505,507,509,512,514,517],{"class":45,"line":219},[43,498,499],{"class":87},"  onError",[43,501,321],{"class":53},[43,503,504],{"class":103},"error",[43,506,113],{"class":53},[43,508,116],{"class":49},[43,510,511],{"class":53}," console.",[43,513,504],{"class":87},[43,515,516],{"class":53},"(error), ",[43,518,519],{"class":181},"\u002F\u002F Error handler\n",[43,521,523],{"class":45,"line":522},16,[43,524,525],{"class":53},"});\n",[240,527,529],{"id":528},"dynamic-ttl","Dynamic TTL",[25,531,532,533,536,537,540,541,544,545,548,549,552,553,556],{},"Some cached values carry their own expiry — an OAuth token with ",[29,534,535],{},"expires_in",", an upstream response with ",[29,538,539],{},"Cache-Control: max-age",". Use ",[29,542,543],{},"getMaxAge"," to derive the lifetime from the resolved value instead of a fixed constant. It runs after the resolver and returns either a number (seconds, shorthand for ",[29,546,547],{},"maxAge",") or ",[29,550,551],{},"{ maxAge?, staleMaxAge? }"," to also override the stale window. The resolved values override the static options for that entry and are used for both the freshness check and the storage TTL. Return ",[29,554,555],{},"undefined"," (or omit a field) to fall back to the static option.",[34,558,560],{"className":36,"code":559,"language":38,"meta":39,"style":39},"const getToken = defineCachedFunction(\n  () => fetchToken(), \u002F\u002F resolves { access_token, expires_in }\n  {\n    \u002F\u002F Cache each token for exactly its own lifetime (minus a small safety margin)\n    getMaxAge: (entry) => Math.max(1, (entry.value?.expires_in ?? 60) - 5),\n  },\n);\n",[29,561,562,575,591,595,600,644,648],{"__ignoreMap":39},[43,563,564,566,569,571,573],{"class":45,"line":46},[43,565,77],{"class":49},[43,567,568],{"class":80}," getToken",[43,570,84],{"class":49},[43,572,88],{"class":87},[43,574,91],{"class":53},[43,576,577,580,582,585,588],{"class":45,"line":67},[43,578,579],{"class":53},"  () ",[43,581,116],{"class":49},[43,583,584],{"class":87}," fetchToken",[43,586,587],{"class":53},"(), ",[43,589,590],{"class":181},"\u002F\u002F resolves { access_token, expires_in }\n",[43,592,593],{"class":45,"line":74},[43,594,166],{"class":53},[43,596,597],{"class":45,"line":94},[43,598,599],{"class":181},"    \u002F\u002F Cache each token for exactly its own lifetime (minus a small safety margin)\n",[43,601,602,605,607,609,611,613,616,619,621,624,627,630,633,635,638,641],{"class":45,"line":122},[43,603,604],{"class":87},"    getMaxAge",[43,606,321],{"class":53},[43,608,324],{"class":103},[43,610,113],{"class":53},[43,612,116],{"class":49},[43,614,615],{"class":53}," Math.",[43,617,618],{"class":87},"max",[43,620,233],{"class":53},[43,622,623],{"class":80},"1",[43,625,626],{"class":53},", (entry.value?.expires_in ",[43,628,629],{"class":49},"??",[43,631,632],{"class":80}," 60",[43,634,113],{"class":53},[43,636,637],{"class":49},"-",[43,639,640],{"class":80}," 5",[43,642,643],{"class":53},"),\n",[43,645,646],{"class":45,"line":142},[43,647,160],{"class":53},[43,649,650],{"class":45,"line":157},[43,651,205],{"class":53},[240,653,655],{"id":654},"custom-serialization","Custom Serialization",[25,657,658,659,662,663,666,667,670,671,673,674,676],{},"Some resolver outputs can't be persisted as-is — a ",[29,660,661],{},"ReadableStream",", a class instance. Use ",[29,664,665],{},"serialize"," to convert the value to a storable form on write, and ",[29,668,669],{},"transform"," to reconstruct the usable value on read. ",[29,672,665],{}," runs exactly once per resolution, right after the resolver (and after ",[29,675,543],{},", so that hook still sees the raw value) — shared across concurrent deduplicated calls, so consuming a one-shot source like a stream is safe.",[34,678,680],{"className":36,"code":679,"language":38,"meta":39,"style":39},"const getReport = defineCachedFunction(\n  () => generateReportStream(), \u002F\u002F resolves a one-shot ReadableStream\n  {\n    \u002F\u002F Persist the stream as a string...\n    serialize: (entry) => streamToString(entry.value),\n    \u002F\u002F ...and recreate a fresh stream on every read.\n    transform: (entry) => stringToStream(entry.value),\n  },\n);\n",[29,681,682,695,709,713,718,737,742,760,764],{"__ignoreMap":39},[43,683,684,686,689,691,693],{"class":45,"line":46},[43,685,77],{"class":49},[43,687,688],{"class":80}," getReport",[43,690,84],{"class":49},[43,692,88],{"class":87},[43,694,91],{"class":53},[43,696,697,699,701,704,706],{"class":45,"line":67},[43,698,579],{"class":53},[43,700,116],{"class":49},[43,702,703],{"class":87}," generateReportStream",[43,705,587],{"class":53},[43,707,708],{"class":181},"\u002F\u002F resolves a one-shot ReadableStream\n",[43,710,711],{"class":45,"line":74},[43,712,166],{"class":53},[43,714,715],{"class":45,"line":94},[43,716,717],{"class":181},"    \u002F\u002F Persist the stream as a string...\n",[43,719,720,723,725,727,729,731,734],{"class":45,"line":122},[43,721,722],{"class":87},"    serialize",[43,724,321],{"class":53},[43,726,324],{"class":103},[43,728,113],{"class":53},[43,730,116],{"class":49},[43,732,733],{"class":87}," streamToString",[43,735,736],{"class":53},"(entry.value),\n",[43,738,739],{"class":45,"line":142},[43,740,741],{"class":181},"    \u002F\u002F ...and recreate a fresh stream on every read.\n",[43,743,744,747,749,751,753,755,758],{"class":45,"line":157},[43,745,746],{"class":87},"    transform",[43,748,321],{"class":53},[43,750,324],{"class":103},[43,752,113],{"class":53},[43,754,116],{"class":49},[43,756,757],{"class":87}," stringToStream",[43,759,736],{"class":53},[43,761,762],{"class":45,"line":163},[43,763,160],{"class":53},[43,765,766],{"class":45,"line":169},[43,767,205],{"class":53},[20,769,771],{"id":770},"caching-http-handlers","Caching HTTP Handlers",[25,773,774,775,778,779,178,782,785,786,789],{},"Wrap HTTP handlers with ",[29,776,777],{},"defineCachedHandler"," for automatic response caching with ",[29,780,781],{},"etag",[29,783,784],{},"last-modified",", and ",[29,787,788],{},"304 Not Modified"," support:",[34,791,793],{"className":36,"code":792,"language":38,"meta":39,"style":39},"import { defineCachedHandler } from \"ocache\";\n\nconst handler = defineCachedHandler(\n  async (event) => {\n    \u002F\u002F event.req is a standard Request object\n    const url = event.url ?? new URL(event.req.url);\n    const data = await getExpensiveData(url.pathname);\n    return new Response(JSON.stringify(data), {\n      headers: { \"content-type\": \"application\u002Fjson\" },\n    });\n  },\n  {\n    maxAge: 300, \u002F\u002F Cache for 5 minutes\n    swr: true,\n    staleMaxAge: 600,\n    varies: [\"accept-language\"], \u002F\u002F Vary cache key by these headers (also emitted as `Vary`)\n    allowQuery: [\"color\"], \u002F\u002F Vary cache by these query params only\n  },\n);\n",[29,794,795,808,812,826,841,846,869,885,908,925,930,934,938,950,960,970,984,998,1003],{"__ignoreMap":39},[43,796,797,799,802,804,806],{"class":45,"line":46},[43,798,50],{"class":49},[43,800,801],{"class":53}," { defineCachedHandler } ",[43,803,57],{"class":49},[43,805,61],{"class":60},[43,807,64],{"class":53},[43,809,810],{"class":45,"line":67},[43,811,71],{"emptyLinePlaceholder":70},[43,813,814,816,819,821,824],{"class":45,"line":74},[43,815,77],{"class":49},[43,817,818],{"class":80}," handler",[43,820,84],{"class":49},[43,822,823],{"class":87}," defineCachedHandler",[43,825,91],{"class":53},[43,827,828,830,832,835,837,839],{"class":45,"line":94},[43,829,97],{"class":49},[43,831,100],{"class":53},[43,833,834],{"class":103},"event",[43,836,113],{"class":53},[43,838,116],{"class":49},[43,840,119],{"class":53},[43,842,843],{"class":45,"line":122},[43,844,845],{"class":181},"    \u002F\u002F event.req is a standard Request object\n",[43,847,848,850,853,855,858,860,863,866],{"class":45,"line":142},[43,849,125],{"class":49},[43,851,852],{"class":80}," url",[43,854,84],{"class":49},[43,856,857],{"class":53}," event.url ",[43,859,629],{"class":49},[43,861,862],{"class":49}," new",[43,864,865],{"class":87}," URL",[43,867,868],{"class":53},"(event.req.url);\n",[43,870,871,873,875,877,879,882],{"class":45,"line":157},[43,872,125],{"class":49},[43,874,224],{"class":80},[43,876,84],{"class":49},[43,878,133],{"class":49},[43,880,881],{"class":87}," getExpensiveData",[43,883,884],{"class":53},"(url.pathname);\n",[43,886,887,889,891,894,896,899,902,905],{"class":45,"line":163},[43,888,145],{"class":49},[43,890,862],{"class":49},[43,892,893],{"class":87}," Response",[43,895,233],{"class":53},[43,897,898],{"class":80},"JSON",[43,900,901],{"class":53},".",[43,903,904],{"class":87},"stringify",[43,906,907],{"class":53},"(data), {\n",[43,909,910,913,916,919,922],{"class":45,"line":169},[43,911,912],{"class":53},"      headers: { ",[43,914,915],{"class":60},"\"content-type\"",[43,917,918],{"class":53},": ",[43,920,921],{"class":60},"\"application\u002Fjson\"",[43,923,924],{"class":53}," },\n",[43,926,927],{"class":45,"line":185},[43,928,929],{"class":53},"    });\n",[43,931,932],{"class":45,"line":197},[43,933,160],{"class":53},[43,935,936],{"class":45,"line":202},[43,937,166],{"class":53},[43,939,940,942,945,947],{"class":45,"line":208},[43,941,172],{"class":53},[43,943,944],{"class":80},"300",[43,946,178],{"class":53},[43,948,949],{"class":181},"\u002F\u002F Cache for 5 minutes\n",[43,951,952,955,958],{"class":45,"line":213},[43,953,954],{"class":53},"    swr: ",[43,956,957],{"class":80},"true",[43,959,194],{"class":53},[43,961,962,965,968],{"class":45,"line":219},[43,963,964],{"class":53},"    staleMaxAge: ",[43,966,967],{"class":80},"600",[43,969,194],{"class":53},[43,971,972,975,978,981],{"class":45,"line":522},[43,973,974],{"class":53},"    varies: [",[43,976,977],{"class":60},"\"accept-language\"",[43,979,980],{"class":53},"], ",[43,982,983],{"class":181},"\u002F\u002F Vary cache key by these headers (also emitted as `Vary`)\n",[43,985,987,990,993,995],{"class":45,"line":986},17,[43,988,989],{"class":53},"    allowQuery: [",[43,991,992],{"class":60},"\"color\"",[43,994,980],{"class":53},[43,996,997],{"class":181},"\u002F\u002F Vary cache by these query params only\n",[43,999,1001],{"class":45,"line":1000},18,[43,1002,160],{"class":53},[43,1004,1006],{"class":45,"line":1005},19,[43,1007,205],{"class":53},[240,1009,1011],{"id":1010},"query-parameters","Query Parameters",[25,1013,1014,1015,1018,1019,1022,1023,1026,1027,1030,1031,1034,1035,1038,1039,1042,1043,1045],{},"By default the full query string varies the cache key, so ",[29,1016,1017],{},"?color=red"," and ",[29,1020,1021],{},"?color=red&utm=x"," are cached separately and unknown params can bust the cache. Set ",[29,1024,1025],{},"allowQuery"," to an allowlist of param names so only those affect the key — all other params are ignored. Ignored params are also stripped from the URL the handler receives (like non-",[29,1028,1029],{},"varies"," headers), so a handler can never accidentally produce output that depends on a param outside the key. Param order is normalized, and repeated (array) params like ",[29,1032,1033],{},"?color=red&color=blue"," are matched regardless of order. Passing an empty array (",[29,1036,1037],{},"allowQuery: []",") varies by nothing — every query shares one entry. If you set a custom ",[29,1040,1041],{},"getKey",", it controls the key entirely and ",[29,1044,1025],{}," no longer affects it, but non-allowlisted params are still stripped from the URL the handler receives:",[34,1047,1049],{"className":36,"code":1048,"language":38,"meta":39,"style":39},"const handler = defineCachedHandler(myHandler, {\n  maxAge: 300,\n  allowQuery: [\"color\"], \u002F\u002F ?color=red&lang=en and ?color=red&lang=de share one entry\n});\n",[29,1050,1051,1064,1072,1084],{"__ignoreMap":39},[43,1052,1053,1055,1057,1059,1061],{"class":45,"line":46},[43,1054,77],{"class":49},[43,1056,818],{"class":80},[43,1058,84],{"class":49},[43,1060,823],{"class":87},[43,1062,1063],{"class":53},"(myHandler, {\n",[43,1065,1066,1068,1070],{"class":45,"line":67},[43,1067,280],{"class":53},[43,1069,944],{"class":80},[43,1071,194],{"class":53},[43,1073,1074,1077,1079,1081],{"class":45,"line":74},[43,1075,1076],{"class":53},"  allowQuery: [",[43,1078,992],{"class":60},[43,1080,980],{"class":53},[43,1082,1083],{"class":181},"\u002F\u002F ?color=red&lang=en and ?color=red&lang=de share one entry\n",[43,1085,1086],{"class":45,"line":94},[43,1087,525],{"class":53},[240,1089,1091],{"id":1090},"cookies","Cookies",[25,1093,1094,1098,1099,1102,1103,1106,1107,1109],{},[1095,1096,1097],"strong",{},"By default no cookies participate in caching."," This is a secure default: the ",[29,1100,1101],{},"Cookie"," request header is stripped before the handler runs (so it can never produce cookie-dependent output that gets cached and served to other users), cookies never vary the cache key, and any response carrying a ",[29,1104,1105],{},"Set-Cookie"," header is refused storage — it is still returned to the caller that triggered it, but never cached and replayed to other requests (which would leak a per-request cookie such as a session id). Stored entries carrying a disallowed ",[29,1108,1105],{}," (e.g. cached before upgrading to this default) are likewise rejected on read instead of replayed.",[25,1111,1112,1113,1116,1117,1120,1121,1124],{},"This only applies to cacheable requests (",[29,1114,1115],{},"GET","\u002F",[29,1118,1119],{},"HEAD","). Methods that bypass caching entirely (e.g. ",[29,1122,1123],{},"POST",") reach the handler with their request untouched — cookies, headers, query, and body included.",[25,1126,1127,1128,1131,1132,1134,1135,1137,1138,1140,1141,1143,1144,1148,1149,1151,1152,901],{},"Set ",[29,1129,1130],{},"allowCookies"," to an allowlist of cookie names to opt specific cookies back in. Only the listed cookies survive in the ",[29,1133,1101],{}," header the handler sees, and their name\u002Fvalue pairs vary the cache key — sorted and order-independent, like ",[29,1136,1025],{},", so only the relevant cookie subset is hashed rather than the entire raw ",[29,1139,1101],{}," header. A ",[29,1142,1105],{}," response becomes cacheable only when ",[1145,1146,1147],"em",{},"every"," cookie it sets is in the list. Cookie names are case-sensitive. ",[29,1150,1130],{}," supersedes ",[29,1153,1154],{},"varies: [\"cookie\"]",[34,1156,1158],{"className":36,"code":1157,"language":38,"meta":39,"style":39},"const handler = defineCachedHandler(myHandler, {\n  maxAge: 300,\n  allowCookies: [\"theme\"], \u002F\u002F theme=dark and theme=light cache separately; sid is ignored\n});\n",[29,1159,1160,1172,1180,1193],{"__ignoreMap":39},[43,1161,1162,1164,1166,1168,1170],{"class":45,"line":46},[43,1163,77],{"class":49},[43,1165,818],{"class":80},[43,1167,84],{"class":49},[43,1169,823],{"class":87},[43,1171,1063],{"class":53},[43,1173,1174,1176,1178],{"class":45,"line":67},[43,1175,280],{"class":53},[43,1177,944],{"class":80},[43,1179,194],{"class":53},[43,1181,1182,1185,1188,1190],{"class":45,"line":74},[43,1183,1184],{"class":53},"  allowCookies: [",[43,1186,1187],{"class":60},"\"theme\"",[43,1189,980],{"class":53},[43,1191,1192],{"class":181},"\u002F\u002F theme=dark and theme=light cache separately; sid is ignored\n",[43,1194,1195],{"class":45,"line":94},[43,1196,525],{"class":53},[25,1198,1199],{},"Two caveats:",[1201,1202,1203,1224],"ul",{},[1204,1205,1206,1211,1212,1214,1215,1217,1218,1220,1221,1223],"li",{},[1095,1207,1208,1209,901],{},"Custom ",[29,1210,1041],{}," As with ",[29,1213,1025],{},", a custom ",[29,1216,1041],{}," controls the cache key entirely, so allowlisted cookies no longer vary it automatically — if your handler's output depends on a cookie, incorporate it into ",[29,1219,1041],{}," yourself (the handler-visible ",[29,1222,1101],{}," header is still filtered to the allowlist regardless).",[1204,1225,1226,1229,1230,1233,1234,1236,1237,1116,1239,1241],{},[1095,1227,1228],{},"Request coalescing."," Concurrent requests that resolve to the same cache key are de-duplicated into a single handler call and share its response. A handler that ",[1145,1231,1232],{},"mints"," a per-request cookie (e.g. initializing an anonymous session with a fresh ",[29,1235,1105],{},") is not isolated by the storage guard in that in-flight window — the guard prevents the response from being stored and replayed later, but coalesced callers still receive the same minted value. Give such handlers a user-specific ",[29,1238,1041],{},[29,1240,1029],{}," (or don't cache them).",[240,1243,1245],{"id":1244},"headers-only-mode","Headers-only Mode",[25,1247,1248,1249,1252],{},"Use ",[29,1250,1251],{},"headersOnly"," to handle conditional requests without caching the full response:",[34,1254,1256],{"className":36,"code":1255,"language":38,"meta":39,"style":39},"const handler = defineCachedHandler(myHandler, {\n  headersOnly: true,\n  maxAge: 60,\n});\n",[29,1257,1258,1270,1279,1287],{"__ignoreMap":39},[43,1259,1260,1262,1264,1266,1268],{"class":45,"line":46},[43,1261,77],{"class":49},[43,1263,818],{"class":80},[43,1265,84],{"class":49},[43,1267,823],{"class":87},[43,1269,1063],{"class":53},[43,1271,1272,1275,1277],{"class":45,"line":67},[43,1273,1274],{"class":53},"  headersOnly: ",[43,1276,957],{"class":80},[43,1278,194],{"class":53},[43,1280,1281,1283,1285],{"class":45,"line":74},[43,1282,280],{"class":53},[43,1284,175],{"class":80},[43,1286,194],{"class":53},[43,1288,1289],{"class":45,"line":94},[43,1290,525],{"class":53},[240,1292,1294],{"id":1293},"private-non-cacheable-responses","Private \u002F non-cacheable responses",[25,1296,1297,1299,1300,1303],{},[29,1298,777],{}," honors an explicit ",[29,1301,1302],{},"Cache-Control"," on the response:",[1201,1305,1306,1317],{},[1204,1307,1308,1309,1312,1313,1316],{},"If the handler sets ",[29,1310,1311],{},"Cache-Control: no-store"," or ",[29,1314,1315],{},"private",", the response is returned to the caller but never written to the cache — the handler runs on every request.",[1204,1318,1319,1320,1322,1323,1326,1327,1326,1330,1333,1334,1336],{},"If the handler sets any other ",[29,1321,1302],{},", it is preserved verbatim. The synthesized ",[29,1324,1325],{},"s-maxage"," \u002F ",[29,1328,1329],{},"stale-while-revalidate",[29,1331,1332],{},"max-age"," directives are only added when the handler didn't set a ",[29,1335,1302],{}," of its own.",[1338,1339,1340],"note",{},[25,1341,1342,1343,1346,1347,1349,1350,1326,1353,1355],{},"\nThis only governs what is ",[1095,1344,1345],{},"stored",". Concurrent requests are still coalesced by cache key, so per-user responses must be keyed correctly (e.g. via ",[29,1348,1029],{},") — ",[29,1351,1352],{},"no-store",[29,1354,1315],{}," prevents caching, it does not by itself partition the cache key.",[240,1357,1359,1360,1363],{"id":1358},"server-only-caching-sendcachecontrol","Server-only caching (",[29,1361,1362],{},"sendCacheControl",")",[25,1365,1366,1367,1370,1371,1374,1375,1116,1377,1379],{},"Sometimes you want to cache a response ",[1095,1368,1369],{},"in storage"," (to save re-computing it) while telling clients and CDNs ",[1145,1372,1373],{},"not"," to cache it — for example a personalized page that is cheap to serve from your own cache but must always be revalidated by the browser. Reaching for ",[29,1376,1311],{},[29,1378,1315],{}," doesn't work here: those also disqualify the response from storage caching.",[25,1381,1127,1382,1385,1386,785,1388,1390,1391,1393],{},[29,1383,1384],{},"sendCacheControl: false"," to decouple the two. The response is still stored and served from cache (SWR, ",[29,1387,781],{},[29,1389,784],{}," are unaffected), but no ",[29,1392,1302],{}," header is synthesized:",[34,1395,1397],{"className":36,"code":1396,"language":38,"meta":39,"style":39},"const handler = defineCachedHandler(myHandler, {\n  maxAge: 60,\n  swr: true,\n  sendCacheControl: false, \u002F\u002F stored & served from cache, but no Cache-Control sent downstream\n});\n",[29,1398,1399,1411,1419,1427,1439],{"__ignoreMap":39},[43,1400,1401,1403,1405,1407,1409],{"class":45,"line":46},[43,1402,77],{"class":49},[43,1404,818],{"class":80},[43,1406,84],{"class":49},[43,1408,823],{"class":87},[43,1410,1063],{"class":53},[43,1412,1413,1415,1417],{"class":45,"line":67},[43,1414,280],{"class":53},[43,1416,175],{"class":80},[43,1418,194],{"class":53},[43,1420,1421,1423,1425],{"class":45,"line":74},[43,1422,293],{"class":53},[43,1424,957],{"class":80},[43,1426,194],{"class":53},[43,1428,1429,1432,1434,1436],{"class":45,"line":94},[43,1430,1431],{"class":53},"  sendCacheControl: ",[43,1433,296],{"class":80},[43,1435,178],{"class":53},[43,1437,1438],{"class":181},"\u002F\u002F stored & served from cache, but no Cache-Control sent downstream\n",[43,1440,1441],{"class":45,"line":122},[43,1442,525],{"class":53},[25,1444,1445,1446,1448],{},"This only governs ocache's own synthesis — a ",[29,1447,1302],{}," the handler sets explicitly is still preserved and sent.",[240,1450,1452,1453,1363],{"id":1451},"custom-cache-eligibility-shouldcache","Custom cache eligibility (",[29,1454,1455],{},"shouldCache",[25,1457,1458,1459,1116,1462,1465,1466,1116,1468,1470,1471,1116,1473,540,1475,1477,1478,1481],{},"The built-in response validation already rejects ",[29,1460,1461],{},"4xx",[29,1463,1464],{},"5xx"," statuses, ",[29,1467,1311],{},[29,1469,1315],{},", empty bodies, and responses missing ",[29,1472,781],{},[29,1474,784],{},[29,1476,1455],{}," to add your own rejection rule on top — for example to keep ",[29,1479,1480],{},"3xx"," redirects out of the cache:",[34,1483,1485],{"className":36,"code":1484,"language":38,"meta":39,"style":39},"const handler = defineCachedHandler(myHandler, {\n  maxAge: 60,\n  \u002F\u002F Return false to skip caching this response (it is still returned to the caller).\n  shouldCache: (res) => res.status \u003C 300 || res.status >= 400,\n});\n",[29,1486,1487,1499,1507,1512,1548],{"__ignoreMap":39},[43,1488,1489,1491,1493,1495,1497],{"class":45,"line":46},[43,1490,77],{"class":49},[43,1492,818],{"class":80},[43,1494,84],{"class":49},[43,1496,823],{"class":87},[43,1498,1063],{"class":53},[43,1500,1501,1503,1505],{"class":45,"line":67},[43,1502,280],{"class":53},[43,1504,175],{"class":80},[43,1506,194],{"class":53},[43,1508,1509],{"class":45,"line":74},[43,1510,1511],{"class":181},"  \u002F\u002F Return false to skip caching this response (it is still returned to the caller).\n",[43,1513,1514,1517,1519,1522,1524,1526,1529,1532,1535,1538,1540,1543,1546],{"class":45,"line":94},[43,1515,1516],{"class":87},"  shouldCache",[43,1518,321],{"class":53},[43,1520,1521],{"class":103},"res",[43,1523,113],{"class":53},[43,1525,116],{"class":49},[43,1527,1528],{"class":53}," res.status ",[43,1530,1531],{"class":49},"\u003C",[43,1533,1534],{"class":80}," 300",[43,1536,1537],{"class":49}," ||",[43,1539,1528],{"class":53},[43,1541,1542],{"class":49},">=",[43,1544,1545],{"class":80}," 400",[43,1547,194],{"class":53},[43,1549,1550],{"class":45,"line":122},[43,1551,525],{"class":53},[25,1553,1554,1556,1557,1560,1561,901],{},[29,1555,1455],{}," receives the serialized response entry, may be async, and is ",[1095,1558,1559],{},"ANDed"," with the built-in checks — it can only narrow what gets cached, never force-cache a response the built-ins reject. It gates both storing a fresh response and serving a stored one, and a throwing hook fails closed (treated as non-cacheable) and is reported via ",[29,1562,1563],{},"onError",[240,1565,1567],{"id":1566},"incremental-static-regeneration-isr","Incremental Static Regeneration (ISR)",[25,1569,1570,1571,1573],{},"you can reproduce a similar ISR behavior with ",[29,1572,777],{},": serve a cached page instantly, regenerate it in the background after it goes stale, and keep serving the last-good version until the refresh lands:",[34,1575,1577],{"className":36,"code":1576,"language":38,"meta":39,"style":39},"const page = defineCachedHandler(\n  async (event) => {\n    const html = await renderPage(event.url ?? new URL(event.req.url));\n    return new Response(html, { headers: { \"content-type\": \"text\u002Fhtml\" } });\n  },\n  {\n    swr: true, \u002F\u002F serve stale instantly, refresh in the background\n    maxAge: 60, \u002F\u002F \"revalidate\" window: fresh for 60s, then refresh on next request\n    \u002F\u002F no staleMaxAge → stale is served indefinitely until the refresh succeeds\n  },\n);\n",[29,1578,1579,1592,1606,1632,1653,1657,1661,1672,1683,1688,1692],{"__ignoreMap":39},[43,1580,1581,1583,1586,1588,1590],{"class":45,"line":46},[43,1582,77],{"class":49},[43,1584,1585],{"class":80}," page",[43,1587,84],{"class":49},[43,1589,823],{"class":87},[43,1591,91],{"class":53},[43,1593,1594,1596,1598,1600,1602,1604],{"class":45,"line":67},[43,1595,97],{"class":49},[43,1597,100],{"class":53},[43,1599,834],{"class":103},[43,1601,113],{"class":53},[43,1603,116],{"class":49},[43,1605,119],{"class":53},[43,1607,1608,1610,1613,1615,1617,1620,1623,1625,1627,1629],{"class":45,"line":74},[43,1609,125],{"class":49},[43,1611,1612],{"class":80}," html",[43,1614,84],{"class":49},[43,1616,133],{"class":49},[43,1618,1619],{"class":87}," renderPage",[43,1621,1622],{"class":53},"(event.url ",[43,1624,629],{"class":49},[43,1626,862],{"class":49},[43,1628,865],{"class":87},[43,1630,1631],{"class":53},"(event.req.url));\n",[43,1633,1634,1636,1638,1640,1643,1645,1647,1650],{"class":45,"line":94},[43,1635,145],{"class":49},[43,1637,862],{"class":49},[43,1639,893],{"class":87},[43,1641,1642],{"class":53},"(html, { headers: { ",[43,1644,915],{"class":60},[43,1646,918],{"class":53},[43,1648,1649],{"class":60},"\"text\u002Fhtml\"",[43,1651,1652],{"class":53}," } });\n",[43,1654,1655],{"class":45,"line":122},[43,1656,160],{"class":53},[43,1658,1659],{"class":45,"line":142},[43,1660,166],{"class":53},[43,1662,1663,1665,1667,1669],{"class":45,"line":157},[43,1664,954],{"class":53},[43,1666,957],{"class":80},[43,1668,178],{"class":53},[43,1670,1671],{"class":181},"\u002F\u002F serve stale instantly, refresh in the background\n",[43,1673,1674,1676,1678,1680],{"class":45,"line":163},[43,1675,172],{"class":53},[43,1677,175],{"class":80},[43,1679,178],{"class":53},[43,1681,1682],{"class":181},"\u002F\u002F \"revalidate\" window: fresh for 60s, then refresh on next request\n",[43,1684,1685],{"class":45,"line":169},[43,1686,1687],{"class":181},"    \u002F\u002F no staleMaxAge → stale is served indefinitely until the refresh succeeds\n",[43,1689,1690],{"class":45,"line":185},[43,1691,160],{"class":53},[43,1693,1694],{"class":45,"line":197},[43,1695,205],{"class":53},[25,1697,1698],{},"The two options that make it ISR-like:",[1201,1700,1701,1712],{},[1204,1702,1703,1708,1709,1711],{},[1095,1704,1705],{},[29,1706,1707],{},"swr: true"," turns on stale-while-revalidate: once an entry is older than ",[29,1710,547],{},", the next request gets the stale page immediately while a fresh render runs in the background.",[1204,1713,1714,1720,1721,1724,1725,1727,1728,1731],{},[1095,1715,1716,1717,901],{},"Omit ",[29,1718,1719],{},"staleMaxAge"," This is the important part. Leaving it unset means there's no point at which the entry becomes \"too old to serve\" — the last successful render is served forever until a refresh replaces it, exactly like ISR. (If instead you ",[1145,1722,1723],{},"set"," ",[29,1726,1719],{},", you get a hard cutoff: after ",[29,1729,1730],{},"maxAge + staleMaxAge"," the entry is dropped and the next request blocks on a fresh render.)",[25,1733,1734,1735,1738],{},"With this config the handler also emits ",[29,1736,1737],{},"Cache-Control: s-maxage=60, stale-while-revalidate",", so any shared\u002FCDN cache in front of it revalidates on the same schedule.",[25,1740,1741,1744,1745,1326,1748,1751],{},[1095,1742,1743],{},"On-demand revalidation"," (the equivalent of ",[29,1746,1747],{},"revalidatePath",[29,1749,1750],{},"revalidateTag",") uses the methods on the returned handler:",[34,1753,1755],{"className":36,"code":1754,"language":38,"meta":39,"style":39},"await page.expire(event); \u002F\u002F ISR-style: serve the stale page once more, refresh in the background\nawait page.invalidate(event); \u002F\u002F hard purge: next request blocks on a fresh render\n",[29,1756,1757,1774],{"__ignoreMap":39},[43,1758,1759,1762,1765,1768,1771],{"class":45,"line":46},[43,1760,1761],{"class":49},"await",[43,1763,1764],{"class":53}," page.",[43,1766,1767],{"class":87},"expire",[43,1769,1770],{"class":53},"(event); ",[43,1772,1773],{"class":181},"\u002F\u002F ISR-style: serve the stale page once more, refresh in the background\n",[43,1775,1776,1778,1780,1783,1785],{"class":45,"line":67},[43,1777,1761],{"class":49},[43,1779,1764],{"class":53},[43,1781,1782],{"class":87},"invalidate",[43,1784,1770],{"class":53},[43,1786,1787],{"class":181},"\u002F\u002F hard purge: next request blocks on a fresh render\n",[25,1789,1790,1791,1794,1795,1798],{},"Prefer ",[29,1792,1793],{},".expire()"," for the ISR feel — there's no blocking gap for visitors. Reach for ",[29,1796,1797],{},".invalidate()"," only when the next reader must get a guaranteed-fresh render.",[25,1800,1801,1804,1805,1808,1809,1811,1812,1815,1816,1819,1820,107],{},[1095,1802,1803],{},"Per-route revalidate windows."," If different pages need different refresh intervals (like Next's per-fetch ",[29,1806,1807],{},"revalidate","), use ",[29,1810,543],{}," to derive the window from the response — for example an ",[29,1813,1814],{},"x-revalidate"," header your handler sets. ",[29,1817,1818],{},"entry.value"," is the standard ",[29,1821,1822],{},"Response",[34,1824,1826],{"className":36,"code":1825,"language":38,"meta":39,"style":39},"const page = defineCachedHandler(\n  async (event) => {\n    const url = event.url ?? new URL(event.req.url);\n    const { html, revalidate } = await renderPage(url);\n    return new Response(html, {\n      headers: { \"content-type\": \"text\u002Fhtml\", \"x-revalidate\": String(revalidate) },\n    });\n  },\n  {\n    swr: true,\n    getMaxAge: (entry) => Number(entry.value.headers.get(\"x-revalidate\")) || 60,\n  },\n);\n",[29,1827,1828,1840,1854,1872,1898,1909,1932,1936,1940,1944,1952,1987,1991],{"__ignoreMap":39},[43,1829,1830,1832,1834,1836,1838],{"class":45,"line":46},[43,1831,77],{"class":49},[43,1833,1585],{"class":80},[43,1835,84],{"class":49},[43,1837,823],{"class":87},[43,1839,91],{"class":53},[43,1841,1842,1844,1846,1848,1850,1852],{"class":45,"line":67},[43,1843,97],{"class":49},[43,1845,100],{"class":53},[43,1847,834],{"class":103},[43,1849,113],{"class":53},[43,1851,116],{"class":49},[43,1853,119],{"class":53},[43,1855,1856,1858,1860,1862,1864,1866,1868,1870],{"class":45,"line":74},[43,1857,125],{"class":49},[43,1859,852],{"class":80},[43,1861,84],{"class":49},[43,1863,857],{"class":53},[43,1865,629],{"class":49},[43,1867,862],{"class":49},[43,1869,865],{"class":87},[43,1871,868],{"class":53},[43,1873,1874,1876,1879,1882,1884,1886,1889,1892,1894,1896],{"class":45,"line":94},[43,1875,125],{"class":49},[43,1877,1878],{"class":53}," { ",[43,1880,1881],{"class":80},"html",[43,1883,178],{"class":53},[43,1885,1807],{"class":80},[43,1887,1888],{"class":53}," } ",[43,1890,1891],{"class":49},"=",[43,1893,133],{"class":49},[43,1895,1619],{"class":87},[43,1897,139],{"class":53},[43,1899,1900,1902,1904,1906],{"class":45,"line":122},[43,1901,145],{"class":49},[43,1903,862],{"class":49},[43,1905,893],{"class":87},[43,1907,1908],{"class":53},"(html, {\n",[43,1910,1911,1913,1915,1917,1919,1921,1924,1926,1929],{"class":45,"line":142},[43,1912,912],{"class":53},[43,1914,915],{"class":60},[43,1916,918],{"class":53},[43,1918,1649],{"class":60},[43,1920,178],{"class":53},[43,1922,1923],{"class":60},"\"x-revalidate\"",[43,1925,918],{"class":53},[43,1927,1928],{"class":87},"String",[43,1930,1931],{"class":53},"(revalidate) },\n",[43,1933,1934],{"class":45,"line":157},[43,1935,929],{"class":53},[43,1937,1938],{"class":45,"line":163},[43,1939,160],{"class":53},[43,1941,1942],{"class":45,"line":169},[43,1943,166],{"class":53},[43,1945,1946,1948,1950],{"class":45,"line":185},[43,1947,954],{"class":53},[43,1949,957],{"class":80},[43,1951,194],{"class":53},[43,1953,1954,1956,1958,1960,1962,1964,1967,1970,1973,1975,1977,1980,1983,1985],{"class":45,"line":197},[43,1955,604],{"class":87},[43,1957,321],{"class":53},[43,1959,324],{"class":103},[43,1961,113],{"class":53},[43,1963,116],{"class":49},[43,1965,1966],{"class":87}," Number",[43,1968,1969],{"class":53},"(entry.value.headers.",[43,1971,1972],{"class":87},"get",[43,1974,233],{"class":53},[43,1976,1923],{"class":60},[43,1978,1979],{"class":53},")) ",[43,1981,1982],{"class":49},"||",[43,1984,632],{"class":80},[43,1986,194],{"class":53},[43,1988,1989],{"class":45,"line":202},[43,1990,160],{"class":53},[43,1992,1993],{"class":45,"line":208},[43,1994,205],{"class":53},[1338,1996,1997],{},[25,1998,1999,2000,2003,2004,2009,2010,2013,2014,2016,2017,2019,2020,2022],{},"\nTwo things differ from CDN managed ISR. ",[1095,2001,2002],{},"(1) Background refresh is coalesced per instance",", not globally — across multiple servers\u002Fserverless instances the origin can see one refresh per instance. Add a distributed lock in your ",[2005,2006,2008],"a",{"href":2007},"#custom-storage","custom storage"," if regeneration is expensive. ",[1095,2011,2012],{},"(2) Entries never auto-expire"," with ",[29,2015,1719],{}," omitted, so storage grows until you ",[29,2018,1797],{}," — or set a large ",[29,2021,1719],{}," to trade exact ISR semantics for eventual cleanup.",[20,2024,2026],{"id":2025},"cache-invalidation","Cache Invalidation",[25,2028,2029,2030,2032],{},"Cached functions have an ",[29,2031,1797],{}," method that removes cached entries across all base prefixes:",[34,2034,2036],{"className":36,"code":2035,"language":38,"meta":39,"style":39},"import { defineCachedFunction } from \"ocache\";\n\nconst getUser = defineCachedFunction(async (id: string) => db.users.find(id), {\n  name: \"getUser\",\n  maxAge: 60,\n  getKey: (id: string) => id,\n});\n\nconst user = await getUser(\"user-123\");\n\n\u002F\u002F Invalidate a specific entry\nawait getUser.invalidate(\"user-123\");\n\n\u002F\u002F Next call will re-invoke the function\nconst freshUser = await getUser(\"user-123\");\n",[29,2037,2038,2050,2054,2092,2101,2109,2128,2132,2136,2156,2160,2165,2180,2184,2189],{"__ignoreMap":39},[43,2039,2040,2042,2044,2046,2048],{"class":45,"line":46},[43,2041,50],{"class":49},[43,2043,54],{"class":53},[43,2045,57],{"class":49},[43,2047,61],{"class":60},[43,2049,64],{"class":53},[43,2051,2052],{"class":45,"line":67},[43,2053,71],{"emptyLinePlaceholder":70},[43,2055,2056,2058,2061,2063,2065,2067,2070,2072,2075,2077,2079,2081,2083,2086,2089],{"class":45,"line":74},[43,2057,77],{"class":49},[43,2059,2060],{"class":80}," getUser",[43,2062,84],{"class":49},[43,2064,88],{"class":87},[43,2066,233],{"class":53},[43,2068,2069],{"class":49},"async",[43,2071,100],{"class":53},[43,2073,2074],{"class":103},"id",[43,2076,107],{"class":49},[43,2078,110],{"class":80},[43,2080,113],{"class":53},[43,2082,116],{"class":49},[43,2084,2085],{"class":53}," db.users.",[43,2087,2088],{"class":87},"find",[43,2090,2091],{"class":53},"(id), {\n",[43,2093,2094,2096,2099],{"class":45,"line":94},[43,2095,267],{"class":53},[43,2097,2098],{"class":60},"\"getUser\"",[43,2100,194],{"class":53},[43,2102,2103,2105,2107],{"class":45,"line":122},[43,2104,280],{"class":53},[43,2106,175],{"class":80},[43,2108,194],{"class":53},[43,2110,2111,2113,2115,2117,2119,2121,2123,2125],{"class":45,"line":142},[43,2112,365],{"class":87},[43,2114,321],{"class":53},[43,2116,2074],{"class":103},[43,2118,107],{"class":49},[43,2120,110],{"class":80},[43,2122,113],{"class":53},[43,2124,116],{"class":49},[43,2126,2127],{"class":53}," id,\n",[43,2129,2130],{"class":45,"line":157},[43,2131,525],{"class":53},[43,2133,2134],{"class":45,"line":163},[43,2135,71],{"emptyLinePlaceholder":70},[43,2137,2138,2140,2143,2145,2147,2149,2151,2154],{"class":45,"line":169},[43,2139,77],{"class":49},[43,2141,2142],{"class":80}," user",[43,2144,84],{"class":49},[43,2146,133],{"class":49},[43,2148,2060],{"class":87},[43,2150,233],{"class":53},[43,2152,2153],{"class":60},"\"user-123\"",[43,2155,205],{"class":53},[43,2157,2158],{"class":45,"line":185},[43,2159,71],{"emptyLinePlaceholder":70},[43,2161,2162],{"class":45,"line":197},[43,2163,2164],{"class":181},"\u002F\u002F Invalidate a specific entry\n",[43,2166,2167,2169,2172,2174,2176,2178],{"class":45,"line":202},[43,2168,1761],{"class":49},[43,2170,2171],{"class":53}," getUser.",[43,2173,1782],{"class":87},[43,2175,233],{"class":53},[43,2177,2153],{"class":60},[43,2179,205],{"class":53},[43,2181,2182],{"class":45,"line":208},[43,2183,71],{"emptyLinePlaceholder":70},[43,2185,2186],{"class":45,"line":213},[43,2187,2188],{"class":181},"\u002F\u002F Next call will re-invoke the function\n",[43,2190,2191,2193,2196,2198,2200,2202,2204,2206],{"class":45,"line":219},[43,2192,77],{"class":49},[43,2194,2195],{"class":80}," freshUser",[43,2197,84],{"class":49},[43,2199,133],{"class":49},[43,2201,2060],{"class":87},[43,2203,233],{"class":53},[43,2205,2153],{"class":60},[43,2207,205],{"class":53},[25,2209,2210,2211,2214],{},"You can also use the standalone ",[29,2212,2213],{},"invalidateCache()"," when you don't have a reference to the cached function — just pass the same options:",[34,2216,2218],{"className":36,"code":2217,"language":38,"meta":39,"style":39},"import { invalidateCache } from \"ocache\";\n\nawait invalidateCache({\n  options: { name: \"getUser\", getKey: (id: string) => id },\n  args: [\"user-123\"],\n});\n",[29,2219,2220,2233,2237,2247,2273,2283],{"__ignoreMap":39},[43,2221,2222,2224,2227,2229,2231],{"class":45,"line":46},[43,2223,50],{"class":49},[43,2225,2226],{"class":53}," { invalidateCache } ",[43,2228,57],{"class":49},[43,2230,61],{"class":60},[43,2232,64],{"class":53},[43,2234,2235],{"class":45,"line":67},[43,2236,71],{"emptyLinePlaceholder":70},[43,2238,2239,2241,2244],{"class":45,"line":74},[43,2240,1761],{"class":49},[43,2242,2243],{"class":87}," invalidateCache",[43,2245,2246],{"class":53},"({\n",[43,2248,2249,2252,2254,2256,2258,2260,2262,2264,2266,2268,2270],{"class":45,"line":94},[43,2250,2251],{"class":53},"  options: { name: ",[43,2253,2098],{"class":60},[43,2255,178],{"class":53},[43,2257,1041],{"class":87},[43,2259,321],{"class":53},[43,2261,2074],{"class":103},[43,2263,107],{"class":49},[43,2265,110],{"class":80},[43,2267,113],{"class":53},[43,2269,116],{"class":49},[43,2271,2272],{"class":53}," id },\n",[43,2274,2275,2278,2280],{"class":45,"line":122},[43,2276,2277],{"class":53},"  args: [",[43,2279,2153],{"class":60},[43,2281,2282],{"class":53},"],\n",[43,2284,2285],{"class":45,"line":142},[43,2286,525],{"class":53},[25,2288,2289,2290,2293],{},"For advanced use cases, ",[29,2291,2292],{},".resolveKeys()"," returns the raw storage keys:",[34,2295,2297],{"className":36,"code":2296,"language":38,"meta":39,"style":39},"const keys = await getUser.resolveKeys(\"user-123\");\n\u002F\u002F [\"\u002Fcache:functions:getUser:user-123.json\"]\n",[29,2298,2299,2321],{"__ignoreMap":39},[43,2300,2301,2303,2306,2308,2310,2312,2315,2317,2319],{"class":45,"line":46},[43,2302,77],{"class":49},[43,2304,2305],{"class":80}," keys",[43,2307,84],{"class":49},[43,2309,133],{"class":49},[43,2311,2171],{"class":53},[43,2313,2314],{"class":87},"resolveKeys",[43,2316,233],{"class":53},[43,2318,2153],{"class":60},[43,2320,205],{"class":53},[43,2322,2323],{"class":45,"line":67},[43,2324,2325],{"class":181},"\u002F\u002F [\"\u002Fcache:functions:getUser:user-123.json\"]\n",[20,2327,2329],{"id":2328},"cache-expiration-swr-refresh","Cache Expiration (SWR refresh)",[25,2331,2332,2333,2335,2336,2338,2339,2341],{},"While ",[29,2334,1797],{}," removes an entry entirely (the next call must wait for a fresh value), ",[29,2337,1793],{}," only marks it as stale. With SWR enabled, stale values keep being served — still bounded by the originally configured ",[29,2340,1719],{}," window — and the next access triggers a background refresh:",[34,2343,2345],{"className":36,"code":2344,"language":38,"meta":39,"style":39},"\u002F\u002F Mark the entry stale: next call serves the stale value and refetches in the background\nawait getUser.expire(\"user-123\");\n",[29,2346,2347,2352],{"__ignoreMap":39},[43,2348,2349],{"class":45,"line":46},[43,2350,2351],{"class":181},"\u002F\u002F Mark the entry stale: next call serves the stale value and refetches in the background\n",[43,2353,2354,2356,2358,2360,2362,2364],{"class":45,"line":67},[43,2355,1761],{"class":49},[43,2357,2171],{"class":53},[43,2359,1767],{"class":87},[43,2361,233],{"class":53},[43,2363,2153],{"class":60},[43,2365,205],{"class":53},[25,2367,2368,2369,2372,2373,2375,2376,1326,2378,1326,2381,2383],{},"The standalone ",[29,2370,2371],{},"expireCache()"," works like ",[29,2374,2213],{}," — pass the same ",[29,2377,547],{},[29,2379,2380],{},"swr",[29,2382,1719],{}," options you cache with so the remaining storage TTL is preserved:",[34,2385,2387],{"className":36,"code":2386,"language":38,"meta":39,"style":39},"import { expireCache } from \"ocache\";\n\nawait expireCache({\n  options: { name: \"getUser\", getKey: (id: string) => id, maxAge: 60, staleMaxAge: 300 },\n  args: [\"user-123\"],\n});\n",[29,2388,2389,2402,2406,2415,2449,2457],{"__ignoreMap":39},[43,2390,2391,2393,2396,2398,2400],{"class":45,"line":46},[43,2392,50],{"class":49},[43,2394,2395],{"class":53}," { expireCache } ",[43,2397,57],{"class":49},[43,2399,61],{"class":60},[43,2401,64],{"class":53},[43,2403,2404],{"class":45,"line":67},[43,2405,71],{"emptyLinePlaceholder":70},[43,2407,2408,2410,2413],{"class":45,"line":74},[43,2409,1761],{"class":49},[43,2411,2412],{"class":87}," expireCache",[43,2414,2246],{"class":53},[43,2416,2417,2419,2421,2423,2425,2427,2429,2431,2433,2435,2437,2440,2442,2445,2447],{"class":45,"line":94},[43,2418,2251],{"class":53},[43,2420,2098],{"class":60},[43,2422,178],{"class":53},[43,2424,1041],{"class":87},[43,2426,321],{"class":53},[43,2428,2074],{"class":103},[43,2430,107],{"class":49},[43,2432,110],{"class":80},[43,2434,113],{"class":53},[43,2436,116],{"class":49},[43,2438,2439],{"class":53}," id, maxAge: ",[43,2441,175],{"class":80},[43,2443,2444],{"class":53},", staleMaxAge: ",[43,2446,944],{"class":80},[43,2448,924],{"class":53},[43,2450,2451,2453,2455],{"class":45,"line":122},[43,2452,2277],{"class":53},[43,2454,2153],{"class":60},[43,2456,2282],{"class":53},[43,2458,2459],{"class":45,"line":142},[43,2460,525],{"class":53},[20,2462,2464],{"id":2463},"multi-tier-caching","Multi-tier Caching",[25,2466,2467,2468,2471],{},"Use an array of ",[29,2469,2470],{},"base"," prefixes to enable multi-tier caching. On read, each prefix is tried in order and the first hit is used. On write, the entry is written to all prefixes:",[34,2473,2475],{"className":36,"code":2474,"language":38,"meta":39,"style":39},"const cachedFetch = defineCachedFunction(\n  async (url: string) => {\n    const res = await fetch(url);\n    return res.json();\n  },\n  {\n    maxAge: 60,\n    base: [\"\u002Ftmp\", \"\u002Fcache\"],\n  },\n);\n",[29,2476,2477,2489,2507,2521,2531,2535,2539,2547,2561,2565],{"__ignoreMap":39},[43,2478,2479,2481,2483,2485,2487],{"class":45,"line":46},[43,2480,77],{"class":49},[43,2482,81],{"class":80},[43,2484,84],{"class":49},[43,2486,88],{"class":87},[43,2488,91],{"class":53},[43,2490,2491,2493,2495,2497,2499,2501,2503,2505],{"class":45,"line":67},[43,2492,97],{"class":49},[43,2494,100],{"class":53},[43,2496,104],{"class":103},[43,2498,107],{"class":49},[43,2500,110],{"class":80},[43,2502,113],{"class":53},[43,2504,116],{"class":49},[43,2506,119],{"class":53},[43,2508,2509,2511,2513,2515,2517,2519],{"class":45,"line":74},[43,2510,125],{"class":49},[43,2512,128],{"class":80},[43,2514,84],{"class":49},[43,2516,133],{"class":49},[43,2518,136],{"class":87},[43,2520,139],{"class":53},[43,2522,2523,2525,2527,2529],{"class":45,"line":94},[43,2524,145],{"class":49},[43,2526,148],{"class":53},[43,2528,151],{"class":87},[43,2530,154],{"class":53},[43,2532,2533],{"class":45,"line":122},[43,2534,160],{"class":53},[43,2536,2537],{"class":45,"line":142},[43,2538,166],{"class":53},[43,2540,2541,2543,2545],{"class":45,"line":157},[43,2542,172],{"class":53},[43,2544,175],{"class":80},[43,2546,194],{"class":53},[43,2548,2549,2552,2555,2557,2559],{"class":45,"line":163},[43,2550,2551],{"class":53},"    base: [",[43,2553,2554],{"class":60},"\"\u002Ftmp\"",[43,2556,178],{"class":53},[43,2558,342],{"class":60},[43,2560,2282],{"class":53},[43,2562,2563],{"class":45,"line":169},[43,2564,160],{"class":53},[43,2566,2567],{"class":45,"line":185},[43,2568,205],{"class":53},[25,2570,2571],{},"This is useful for layered cache setups (e.g., fast local cache + shared remote cache) where you want reads to prefer the nearest tier while keeping all tiers populated on writes.",[20,2573,2575],{"id":2574},"custom-storage","Custom Storage",[25,2577,2578,2579,2582],{},"By default, ocache uses an in-memory ",[29,2580,2581],{},"Map","-based storage. You can provide a custom storage implementation:",[34,2584,2586],{"className":36,"code":2585,"language":38,"meta":39,"style":39},"import { setStorage } from \"ocache\";\nimport type { StorageInterface } from \"ocache\";\n\nconst redisStorage: StorageInterface = {\n  get: async (key) => {\n    return JSON.parse(await redis.get(key));\n  },\n  set: async (key, value, opts) => {\n    \u002F\u002F Setting null\u002Fundefined deletes the entry (used for cache invalidation)\n    if (value === null || value === undefined) {\n      await redis.del(key);\n      return;\n    }\n    await redis.set(key, JSON.stringify(value), opts?.ttl ? { EX: opts.ttl } : undefined);\n  },\n};\n\nsetStorage(redisStorage);\n",[29,2587,2588,2601,2617,2621,2637,2657,2681,2685,2714,2719,2745,2758,2765,2770,2803,2807,2812,2816],{"__ignoreMap":39},[43,2589,2590,2592,2595,2597,2599],{"class":45,"line":46},[43,2591,50],{"class":49},[43,2593,2594],{"class":53}," { setStorage } ",[43,2596,57],{"class":49},[43,2598,61],{"class":60},[43,2600,64],{"class":53},[43,2602,2603,2605,2608,2611,2613,2615],{"class":45,"line":67},[43,2604,50],{"class":49},[43,2606,2607],{"class":49}," type",[43,2609,2610],{"class":53}," { StorageInterface } ",[43,2612,57],{"class":49},[43,2614,61],{"class":60},[43,2616,64],{"class":53},[43,2618,2619],{"class":45,"line":74},[43,2620,71],{"emptyLinePlaceholder":70},[43,2622,2623,2625,2628,2630,2633,2635],{"class":45,"line":94},[43,2624,77],{"class":49},[43,2626,2627],{"class":80}," redisStorage",[43,2629,107],{"class":49},[43,2631,2632],{"class":87}," StorageInterface",[43,2634,84],{"class":49},[43,2636,119],{"class":53},[43,2638,2639,2642,2644,2646,2648,2651,2653,2655],{"class":45,"line":122},[43,2640,2641],{"class":87},"  get",[43,2643,918],{"class":53},[43,2645,2069],{"class":49},[43,2647,100],{"class":53},[43,2649,2650],{"class":103},"key",[43,2652,113],{"class":53},[43,2654,116],{"class":49},[43,2656,119],{"class":53},[43,2658,2659,2661,2664,2666,2669,2671,2673,2676,2678],{"class":45,"line":142},[43,2660,145],{"class":49},[43,2662,2663],{"class":80}," JSON",[43,2665,901],{"class":53},[43,2667,2668],{"class":87},"parse",[43,2670,233],{"class":53},[43,2672,1761],{"class":49},[43,2674,2675],{"class":53}," redis.",[43,2677,1972],{"class":87},[43,2679,2680],{"class":53},"(key));\n",[43,2682,2683],{"class":45,"line":157},[43,2684,160],{"class":53},[43,2686,2687,2690,2692,2694,2696,2698,2700,2703,2705,2708,2710,2712],{"class":45,"line":163},[43,2688,2689],{"class":87},"  set",[43,2691,918],{"class":53},[43,2693,2069],{"class":49},[43,2695,100],{"class":53},[43,2697,2650],{"class":103},[43,2699,178],{"class":53},[43,2701,2702],{"class":103},"value",[43,2704,178],{"class":53},[43,2706,2707],{"class":103},"opts",[43,2709,113],{"class":53},[43,2711,116],{"class":49},[43,2713,119],{"class":53},[43,2715,2716],{"class":45,"line":169},[43,2717,2718],{"class":181},"    \u002F\u002F Setting null\u002Fundefined deletes the entry (used for cache invalidation)\n",[43,2720,2721,2724,2727,2730,2733,2735,2738,2740,2742],{"class":45,"line":185},[43,2722,2723],{"class":49},"    if",[43,2725,2726],{"class":53}," (value ",[43,2728,2729],{"class":49},"===",[43,2731,2732],{"class":80}," null",[43,2734,1537],{"class":49},[43,2736,2737],{"class":53}," value ",[43,2739,2729],{"class":49},[43,2741,452],{"class":80},[43,2743,2744],{"class":53},") {\n",[43,2746,2747,2750,2752,2755],{"class":45,"line":197},[43,2748,2749],{"class":49},"      await",[43,2751,2675],{"class":53},[43,2753,2754],{"class":87},"del",[43,2756,2757],{"class":53},"(key);\n",[43,2759,2760,2763],{"class":45,"line":202},[43,2761,2762],{"class":49},"      return",[43,2764,64],{"class":53},[43,2766,2767],{"class":45,"line":208},[43,2768,2769],{"class":53},"    }\n",[43,2771,2772,2775,2777,2779,2782,2784,2786,2788,2791,2794,2797,2799,2801],{"class":45,"line":213},[43,2773,2774],{"class":49},"    await",[43,2776,2675],{"class":53},[43,2778,1723],{"class":87},[43,2780,2781],{"class":53},"(key, ",[43,2783,898],{"class":80},[43,2785,901],{"class":53},[43,2787,904],{"class":87},[43,2789,2790],{"class":53},"(value), opts?.ttl ",[43,2792,2793],{"class":49},"?",[43,2795,2796],{"class":53}," { EX: opts.ttl } ",[43,2798,107],{"class":49},[43,2800,452],{"class":80},[43,2802,205],{"class":53},[43,2804,2805],{"class":45,"line":219},[43,2806,160],{"class":53},[43,2808,2809],{"class":45,"line":522},[43,2810,2811],{"class":53},"};\n",[43,2813,2814],{"class":45,"line":986},[43,2815,71],{"emptyLinePlaceholder":70},[43,2817,2818,2821],{"class":45,"line":1000},[43,2819,2820],{"class":87},"setStorage",[43,2822,2823],{"class":53},"(redisStorage);\n",[25,2825,2826,2827,2830,2831,2834,2835,2838],{},"The built-in memory storage keeps at most ",[29,2828,2829],{},"10 000"," entries by default, evicting the least-recently-used entries once the ceiling is exceeded (LRU). Pass ",[29,2832,2833],{},"maxSize"," to change the ceiling, or ",[29,2836,2837],{},"Infinity"," to disable it and grow unbounded:",[34,2840,2842],{"className":36,"code":2841,"language":38,"meta":39,"style":39},"import { createMemoryStorage, setStorage } from \"ocache\";\n\nsetStorage(createMemoryStorage({ maxSize: 10_000 }));\n\n\u002F\u002F Opt out of the ceiling entirely (previous unbounded behavior)\nsetStorage(createMemoryStorage({ maxSize: Infinity }));\n",[29,2843,2844,2857,2861,2879,2883,2888],{"__ignoreMap":39},[43,2845,2846,2848,2851,2853,2855],{"class":45,"line":46},[43,2847,50],{"class":49},[43,2849,2850],{"class":53}," { createMemoryStorage, setStorage } ",[43,2852,57],{"class":49},[43,2854,61],{"class":60},[43,2856,64],{"class":53},[43,2858,2859],{"class":45,"line":67},[43,2860,71],{"emptyLinePlaceholder":70},[43,2862,2863,2865,2867,2870,2873,2876],{"class":45,"line":74},[43,2864,2820],{"class":87},[43,2866,233],{"class":53},[43,2868,2869],{"class":87},"createMemoryStorage",[43,2871,2872],{"class":53},"({ maxSize: ",[43,2874,2875],{"class":80},"10_000",[43,2877,2878],{"class":53}," }));\n",[43,2880,2881],{"class":45,"line":94},[43,2882,71],{"emptyLinePlaceholder":70},[43,2884,2885],{"class":45,"line":122},[43,2886,2887],{"class":181},"\u002F\u002F Opt out of the ceiling entirely (previous unbounded behavior)\n",[43,2889,2890,2892,2894,2896,2898,2900],{"class":45,"line":142},[43,2891,2820],{"class":87},[43,2893,233],{"class":53},[43,2895,2869],{"class":87},[43,2897,2872],{"class":53},[43,2899,2837],{"class":80},[43,2901,2878],{"class":53},[15,2903,2905],{"id":2904},"api","API",[20,2907,2909],{"id":2908},"cachedfunction",[29,2910,2911],{},"cachedFunction",[34,2913,2915],{"className":36,"code":2914,"language":38,"meta":39,"style":39},"const cachedFunction = defineCachedFunction;\n",[29,2916,2917],{"__ignoreMap":39},[43,2918,2919,2921,2924,2926],{"class":45,"line":46},[43,2920,77],{"class":49},[43,2922,2923],{"class":80}," cachedFunction",[43,2925,84],{"class":49},[43,2927,2928],{"class":53}," defineCachedFunction;\n",[25,2930,2931,2932,901],{},"Alias for ",[2005,2933,2935],{"href":2934},"#definecachedfunction",[29,2936,31],{},[2938,2939],"hr",{},[20,2941,2943],{"id":2942},"cachestatus",[29,2944,2945],{},"CacheStatus",[34,2947,2949],{"className":36,"code":2948,"language":38,"meta":39,"style":39},"type CacheStatus = \"hit\" | \"stale\" | \"revalidated\" | \"miss\";\n",[29,2950,2951],{"__ignoreMap":39},[43,2952,2953,2956,2959,2961,2964,2967,2970,2972,2975,2977,2980],{"class":45,"line":46},[43,2954,2955],{"class":49},"type",[43,2957,2958],{"class":87}," CacheStatus",[43,2960,84],{"class":49},[43,2962,2963],{"class":60}," \"hit\"",[43,2965,2966],{"class":49}," |",[43,2968,2969],{"class":60}," \"stale\"",[43,2971,2966],{"class":49},[43,2973,2974],{"class":60}," \"revalidated\"",[43,2976,2966],{"class":49},[43,2978,2979],{"class":60}," \"miss\"",[43,2981,64],{"class":53},[25,2983,2984],{},"How a cached value was served on a given call.",[1201,2986,2987,2993,2999,3005],{},[1204,2988,2989,2992],{},[29,2990,2991],{},"\"hit\""," — a fresh cached value was returned without re-resolving.",[1204,2994,2995,2998],{},[29,2996,2997],{},"\"stale\""," — a stale value was served while a background SWR refresh runs.",[1204,3000,3001,3004],{},[29,3002,3003],{},"\"revalidated\""," — a prior value existed but was expired\u002Finvalid, so it was\nre-resolved in the foreground (no stale value served) before returning.",[1204,3006,3007,3010],{},[29,3008,3009],{},"\"miss\""," — the value was resolved fresh on this call (nothing was cached).",[2938,3012],{},[20,3014,3016],{"id":3015},"creatememorystorage",[29,3017,2869],{},[34,3019,3021],{"className":36,"code":3020,"language":38,"meta":39,"style":39},"function createMemoryStorage(opts: MemoryStorageOptions =\n",[29,3022,3023],{"__ignoreMap":39},[43,3024,3025,3028,3031,3033,3035,3037,3040],{"class":45,"line":46},[43,3026,3027],{"class":49},"function",[43,3029,3030],{"class":87}," createMemoryStorage",[43,3032,233],{"class":53},[43,3034,2707],{"class":103},[43,3036,107],{"class":49},[43,3038,3039],{"class":87}," MemoryStorageOptions",[43,3041,3042],{"class":49}," =\n",[25,3044,3045,3046,3048],{},"Creates an in-memory storage backed by a ",[29,3047,2581],{}," with optional TTL support (in seconds) and LRU eviction.",[2938,3050],{},[20,3052,3054],{"id":3053},"definecachedfunction",[29,3055,31],{},[34,3057,3059],{"className":36,"code":3058,"language":38,"meta":39,"style":39},"function defineCachedFunction\u003CT, ArgsT extends unknown[] = any[]>(\n  fn: (...args: ArgsT) => T | Promise\u003CT>,\n  opts: CacheOptions\u003CT, ArgsT> =\n",[29,3060,3061,3094,3131],{"__ignoreMap":39},[43,3062,3063,3065,3067,3069,3072,3074,3077,3080,3083,3086,3088,3091],{"class":45,"line":46},[43,3064,3027],{"class":49},[43,3066,88],{"class":87},[43,3068,1531],{"class":53},[43,3070,3071],{"class":87},"T",[43,3073,178],{"class":53},[43,3075,3076],{"class":87},"ArgsT",[43,3078,3079],{"class":49}," extends",[43,3081,3082],{"class":80}," unknown",[43,3084,3085],{"class":53},"[] ",[43,3087,1891],{"class":49},[43,3089,3090],{"class":80}," any",[43,3092,3093],{"class":53},"[]>(\n",[43,3095,3096,3099,3101,3103,3105,3107,3109,3112,3114,3116,3119,3121,3124,3126,3128],{"class":45,"line":67},[43,3097,3098],{"class":87},"  fn",[43,3100,107],{"class":49},[43,3102,100],{"class":53},[43,3104,370],{"class":49},[43,3106,373],{"class":103},[43,3108,107],{"class":49},[43,3110,3111],{"class":87}," ArgsT",[43,3113,113],{"class":53},[43,3115,116],{"class":49},[43,3117,3118],{"class":87}," T",[43,3120,2966],{"class":49},[43,3122,3123],{"class":87}," Promise",[43,3125,1531],{"class":53},[43,3127,3071],{"class":87},[43,3129,3130],{"class":53},">,\n",[43,3132,3133,3136,3138,3141,3143,3145,3147,3149,3152],{"class":45,"line":74},[43,3134,3135],{"class":103},"  opts",[43,3137,107],{"class":49},[43,3139,3140],{"class":87}," CacheOptions",[43,3142,1531],{"class":53},[43,3144,3071],{"class":87},[43,3146,178],{"class":53},[43,3148,3076],{"class":87},[43,3150,3151],{"class":53},"> ",[43,3153,3154],{"class":49},"=\n",[25,3156,3157],{},"Wraps a function with caching support including TTL, SWR, integrity checks, and request deduplication.",[25,3159,3160],{},[1095,3161,3162],{},"Parameters:",[1201,3164,3165,3173],{},[1204,3166,3167,3172],{},[1095,3168,3169],{},[29,3170,3171],{},"fn"," — The function to cache.",[1204,3174,3175,3179],{},[1095,3176,3177],{},[29,3178,2707],{}," — Cache configuration options.",[25,3181,3182,3185,3186,3189],{},[1095,3183,3184],{},"Returns:"," — A cached function with a ",[29,3187,3188],{},".resolveKey(...args)"," method for cache key resolution.",[2938,3191],{},[20,3193,3195],{"id":3194},"definecachedhandler",[29,3196,777],{},[34,3198,3200],{"className":36,"code":3199,"language":38,"meta":39,"style":39},"function defineCachedHandler\u003CE extends HTTPEvent = HTTPEvent>(\n  handler: EventHandler\u003CE>,\n  opts: CachedEventHandlerOptions\u003CE> =\n",[29,3201,3202,3225,3241],{"__ignoreMap":39},[43,3203,3204,3206,3208,3210,3213,3215,3218,3220,3222],{"class":45,"line":46},[43,3205,3027],{"class":49},[43,3207,823],{"class":87},[43,3209,1531],{"class":53},[43,3211,3212],{"class":87},"E",[43,3214,3079],{"class":49},[43,3216,3217],{"class":87}," HTTPEvent",[43,3219,84],{"class":49},[43,3221,3217],{"class":87},[43,3223,3224],{"class":53},">(\n",[43,3226,3227,3230,3232,3235,3237,3239],{"class":45,"line":67},[43,3228,3229],{"class":103},"  handler",[43,3231,107],{"class":49},[43,3233,3234],{"class":87}," EventHandler",[43,3236,1531],{"class":53},[43,3238,3212],{"class":87},[43,3240,3130],{"class":53},[43,3242,3243,3245,3247,3250,3252,3254,3256],{"class":45,"line":74},[43,3244,3135],{"class":103},[43,3246,107],{"class":49},[43,3248,3249],{"class":87}," CachedEventHandlerOptions",[43,3251,1531],{"class":53},[43,3253,3212],{"class":87},[43,3255,3151],{"class":53},[43,3257,3154],{"class":49},[25,3259,3260],{},"Wraps an HTTP event handler with response caching.",[25,3262,3263,3264,178,3267,785,3269,3271,3272,3274],{},"Automatically generates cache keys from the URL path and variable headers,\nsets ",[29,3265,3266],{},"cache-control",[29,3268,781],{},[29,3270,784],{}," headers, and handles\n",[29,3273,788],{}," responses via conditional request headers.",[25,3276,3277],{},[1095,3278,3162],{},[1201,3280,3281,3289],{},[1204,3282,3283,3288],{},[1095,3284,3285],{},[29,3286,3287],{},"handler"," — The event handler to cache.",[1204,3290,3291,3295],{},[1095,3292,3293],{},[29,3294,2707],{}," — Cache and HTTP-specific configuration options.",[25,3297,3298,3300],{},[1095,3299,3184],{}," — A new event handler that serves cached responses when available.",[2938,3302],{},[20,3304,3306],{"id":3305},"eventhandler",[29,3307,3308],{},"EventHandler",[34,3310,3312],{"className":36,"code":3311,"language":38,"meta":39,"style":39},"type EventHandler\u003CE extends HTTPEvent = HTTPEvent> = (\n",[29,3313,3314],{"__ignoreMap":39},[43,3315,3316,3318,3320,3322,3324,3326,3328,3330,3332,3334,3336],{"class":45,"line":46},[43,3317,2955],{"class":49},[43,3319,3234],{"class":87},[43,3321,1531],{"class":53},[43,3323,3212],{"class":87},[43,3325,3079],{"class":49},[43,3327,3217],{"class":87},[43,3329,84],{"class":49},[43,3331,3217],{"class":87},[43,3333,3151],{"class":53},[43,3335,1891],{"class":49},[43,3337,3338],{"class":53}," (\n",[25,3340,3341,3342,3348],{},"Handler function that receives an ",[2005,3343,3345],{"href":3344},"#httpevent",[29,3346,3347],{},"HTTPEvent"," and returns a response value.",[2938,3350],{},[20,3352,3354],{"id":3353},"expirecache",[29,3355,3356],{},"expireCache",[34,3358,3360],{"className":36,"code":3359,"language":38,"meta":39,"style":39},"async function expireCache\u003CArgsT extends unknown[] = any[]>(\n  input:\n",[29,3361,3362,3387],{"__ignoreMap":39},[43,3363,3364,3366,3369,3371,3373,3375,3377,3379,3381,3383,3385],{"class":45,"line":46},[43,3365,2069],{"class":49},[43,3367,3368],{"class":49}," function",[43,3370,2412],{"class":87},[43,3372,1531],{"class":53},[43,3374,3076],{"class":87},[43,3376,3079],{"class":49},[43,3378,3082],{"class":80},[43,3380,3085],{"class":53},[43,3382,1891],{"class":49},[43,3384,3090],{"class":80},[43,3386,3093],{"class":53},[43,3388,3389,3392],{"class":45,"line":67},[43,3390,3391],{"class":103},"  input",[43,3393,3394],{"class":49},":\n",[25,3396,3397],{},"Expires cached entries for given arguments and cache options across all base prefixes,\nwithout removing them.",[25,3399,3400,3401,3407,3408,3410],{},"Unlike ",[2005,3402,3404],{"href":3403},"#invalidatecache",[29,3405,3406],{},"invalidateCache"," (which removes entries entirely), expired entries keep\nserving the stale value with SWR — still bounded by the originally configured\n",[29,3409,1719],{}," window — while the next access triggers a background refresh.\nWithout SWR, the next call re-resolves before returning.",[25,3412,3413,3414,1326,3416,3419,3420,1326,3422,1326,3424,3426],{},"Uses the same key derivation as ",[29,3415,31],{},[29,3417,3418],{},"resolveCacheKeys",".\nPass the same ",[29,3421,547],{},[29,3423,2380],{},[29,3425,1719],{}," options you cache with so the\nremaining storage TTL is preserved.",[25,3428,3429],{},[1095,3430,3162],{},[1201,3432,3433],{},[1204,3434,3435,3440,3441,3443,3444,3446],{},[1095,3436,3437],{},[29,3438,3439],{},"input"," — Object with ",[29,3442,242],{}," (cache options) and optional ",[29,3445,373],{}," (function arguments).",[25,3448,3449],{},[1095,3450,3451],{},"Example:",[34,3453,3455],{"className":36,"code":3454,"language":38,"meta":39,"style":39},"\u002F\u002F Mark a cached entry for background refresh on next access\nawait expireCache({\n  options: { name: \"fetchUser\", getKey: (id: string) => id, maxAge: 60, staleMaxAge: 300 },\n  args: [\"user-123\"],\n});\n",[29,3456,3457,3462,3470,3503,3511],{"__ignoreMap":39},[43,3458,3459],{"class":45,"line":46},[43,3460,3461],{"class":181},"\u002F\u002F Mark a cached entry for background refresh on next access\n",[43,3463,3464,3466,3468],{"class":45,"line":67},[43,3465,1761],{"class":49},[43,3467,2412],{"class":87},[43,3469,2246],{"class":53},[43,3471,3472,3474,3477,3479,3481,3483,3485,3487,3489,3491,3493,3495,3497,3499,3501],{"class":45,"line":74},[43,3473,2251],{"class":53},[43,3475,3476],{"class":60},"\"fetchUser\"",[43,3478,178],{"class":53},[43,3480,1041],{"class":87},[43,3482,321],{"class":53},[43,3484,2074],{"class":103},[43,3486,107],{"class":49},[43,3488,110],{"class":80},[43,3490,113],{"class":53},[43,3492,116],{"class":49},[43,3494,2439],{"class":53},[43,3496,175],{"class":80},[43,3498,2444],{"class":53},[43,3500,944],{"class":80},[43,3502,924],{"class":53},[43,3504,3505,3507,3509],{"class":45,"line":94},[43,3506,2277],{"class":53},[43,3508,2153],{"class":60},[43,3510,2282],{"class":53},[43,3512,3513],{"class":45,"line":122},[43,3514,525],{"class":53},[2938,3516],{},[20,3518,3520],{"id":3519},"invalidatecache",[29,3521,3406],{},[34,3523,3525],{"className":36,"code":3524,"language":38,"meta":39,"style":39},"async function invalidateCache\u003CArgsT extends unknown[] = any[]>(\n  input:\n",[29,3526,3527,3551],{"__ignoreMap":39},[43,3528,3529,3531,3533,3535,3537,3539,3541,3543,3545,3547,3549],{"class":45,"line":46},[43,3530,2069],{"class":49},[43,3532,3368],{"class":49},[43,3534,2243],{"class":87},[43,3536,1531],{"class":53},[43,3538,3076],{"class":87},[43,3540,3079],{"class":49},[43,3542,3082],{"class":80},[43,3544,3085],{"class":53},[43,3546,1891],{"class":49},[43,3548,3090],{"class":80},[43,3550,3093],{"class":53},[43,3552,3553,3555],{"class":45,"line":67},[43,3554,3391],{"class":103},[43,3556,3394],{"class":49},[25,3558,3559],{},"Invalidates (removes) cached entries for given arguments and cache options across all base prefixes.",[25,3561,3413,3562,1326,3564,901],{},[29,3563,31],{},[29,3565,3418],{},[25,3567,3568],{},[1095,3569,3162],{},[1201,3571,3572],{},[1204,3573,3574,3440,3578,3443,3580,3446],{},[1095,3575,3576],{},[29,3577,3439],{},[29,3579,242],{},[29,3581,373],{},[25,3583,3584],{},[1095,3585,3451],{},[34,3587,3589],{"className":36,"code":3588,"language":38,"meta":39,"style":39},"\u002F\u002F Invalidate a specific cached entry\nawait invalidateCache({\n  options: { name: \"fetchUser\", getKey: (id: string) => id },\n  args: [\"user-123\"],\n});\n",[29,3590,3591,3596,3604,3628,3636],{"__ignoreMap":39},[43,3592,3593],{"class":45,"line":46},[43,3594,3595],{"class":181},"\u002F\u002F Invalidate a specific cached entry\n",[43,3597,3598,3600,3602],{"class":45,"line":67},[43,3599,1761],{"class":49},[43,3601,2243],{"class":87},[43,3603,2246],{"class":53},[43,3605,3606,3608,3610,3612,3614,3616,3618,3620,3622,3624,3626],{"class":45,"line":74},[43,3607,2251],{"class":53},[43,3609,3476],{"class":60},[43,3611,178],{"class":53},[43,3613,1041],{"class":87},[43,3615,321],{"class":53},[43,3617,2074],{"class":103},[43,3619,107],{"class":49},[43,3621,110],{"class":80},[43,3623,113],{"class":53},[43,3625,116],{"class":49},[43,3627,2272],{"class":53},[43,3629,3630,3632,3634],{"class":45,"line":94},[43,3631,2277],{"class":53},[43,3633,2153],{"class":60},[43,3635,2282],{"class":53},[43,3637,3638],{"class":45,"line":122},[43,3639,525],{"class":53},[2938,3641],{},[20,3643,3645],{"id":3644},"resolvecachekeys",[29,3646,3418],{},[34,3648,3650],{"className":36,"code":3649,"language":38,"meta":39,"style":39},"async function resolveCacheKeys\u003CArgsT extends unknown[] = any[]>(\n  input:\n",[29,3651,3652,3677],{"__ignoreMap":39},[43,3653,3654,3656,3658,3661,3663,3665,3667,3669,3671,3673,3675],{"class":45,"line":46},[43,3655,2069],{"class":49},[43,3657,3368],{"class":49},[43,3659,3660],{"class":87}," resolveCacheKeys",[43,3662,1531],{"class":53},[43,3664,3076],{"class":87},[43,3666,3079],{"class":49},[43,3668,3082],{"class":80},[43,3670,3085],{"class":53},[43,3672,1891],{"class":49},[43,3674,3090],{"class":80},[43,3676,3093],{"class":53},[43,3678,3679,3681],{"class":45,"line":67},[43,3680,3391],{"class":103},[43,3682,3394],{"class":49},[25,3684,3685],{},"Resolves all cache storage keys (one per base prefix) for given arguments and cache options.",[25,3687,3413,3688,3690],{},[29,3689,31],{}," internally:",[1201,3692,3693,3703],{},[1204,3694,3695,3696,3699,3700,3702],{},"When ",[29,3697,3698],{},"opts.getKey"," is provided, it is called with ",[29,3701,373],{}," to produce the key segment.",[1204,3704,3705,3706,3708,3709,3712,3713,3715],{},"Otherwise, ",[29,3707,373],{}," are hashed with ",[29,3710,3711],{},"ohash"," (same default as ",[29,3714,31],{},").",[25,3717,3718,3719,178,3721,178,3724,785,3727,3729,3730,1326,3732,3734],{},"Pass the same ",[29,3720,1041],{},[29,3722,3723],{},"name",[29,3725,3726],{},"group",[29,3728,2470],{}," options you use in\n",[29,3731,31],{},[29,3733,777],{}," to get the exact storage keys.",[25,3736,3737],{},[1095,3738,3162],{},[1201,3740,3741],{},[1204,3742,3743,3440,3747,3443,3749,3446],{},[1095,3744,3745],{},[29,3746,3439],{},[29,3748,242],{},[29,3750,373],{},[25,3752,3753,3755],{},[1095,3754,3184],{}," — An array of storage key strings (one per base prefix).",[25,3757,3758],{},[1095,3759,3451],{},[34,3761,3763],{"className":36,"code":3762,"language":38,"meta":39,"style":39},"const keys = await resolveCacheKeys({\n  options: { name: \"fetchUser\", getKey: (id: string) => id },\n  args: [\"user-123\"],\n});\nfor (const key of keys) {\n  await useStorage().set(key, null); \u002F\u002F invalidate all tiers\n}\n",[29,3764,3765,3779,3803,3811,3815,3833,3857],{"__ignoreMap":39},[43,3766,3767,3769,3771,3773,3775,3777],{"class":45,"line":46},[43,3768,77],{"class":49},[43,3770,2305],{"class":80},[43,3772,84],{"class":49},[43,3774,133],{"class":49},[43,3776,3660],{"class":87},[43,3778,2246],{"class":53},[43,3780,3781,3783,3785,3787,3789,3791,3793,3795,3797,3799,3801],{"class":45,"line":67},[43,3782,2251],{"class":53},[43,3784,3476],{"class":60},[43,3786,178],{"class":53},[43,3788,1041],{"class":87},[43,3790,321],{"class":53},[43,3792,2074],{"class":103},[43,3794,107],{"class":49},[43,3796,110],{"class":80},[43,3798,113],{"class":53},[43,3800,116],{"class":49},[43,3802,2272],{"class":53},[43,3804,3805,3807,3809],{"class":45,"line":74},[43,3806,2277],{"class":53},[43,3808,2153],{"class":60},[43,3810,2282],{"class":53},[43,3812,3813],{"class":45,"line":94},[43,3814,525],{"class":53},[43,3816,3817,3820,3822,3824,3827,3830],{"class":45,"line":122},[43,3818,3819],{"class":49},"for",[43,3821,100],{"class":53},[43,3823,77],{"class":49},[43,3825,3826],{"class":80}," key",[43,3828,3829],{"class":49}," of",[43,3831,3832],{"class":53}," keys) {\n",[43,3834,3835,3838,3841,3844,3846,3848,3851,3854],{"class":45,"line":142},[43,3836,3837],{"class":49},"  await",[43,3839,3840],{"class":87}," useStorage",[43,3842,3843],{"class":53},"().",[43,3845,1723],{"class":87},[43,3847,2781],{"class":53},[43,3849,3850],{"class":80},"null",[43,3852,3853],{"class":53},"); ",[43,3855,3856],{"class":181},"\u002F\u002F invalidate all tiers\n",[43,3858,3859],{"class":45,"line":157},[43,3860,3861],{"class":53},"}\n",[2938,3863],{},[20,3865,3867],{"id":3866},"setstorage",[29,3868,2820],{},[34,3870,3872],{"className":36,"code":3871,"language":38,"meta":39,"style":39},"function setStorage(storage: StorageInterface): void\n",[29,3873,3874],{"__ignoreMap":39},[43,3875,3876,3878,3881,3883,3886,3888,3890,3892,3894],{"class":45,"line":46},[43,3877,3027],{"class":49},[43,3879,3880],{"class":87}," setStorage",[43,3882,233],{"class":53},[43,3884,3885],{"class":103},"storage",[43,3887,107],{"class":49},[43,3889,2632],{"class":87},[43,3891,1363],{"class":53},[43,3893,107],{"class":49},[43,3895,3896],{"class":80}," void\n",[25,3898,3899],{},"Sets a custom storage implementation to be used by all cached functions.",[2938,3901],{},[20,3903,3905],{"id":3904},"usestorage",[29,3906,3907],{},"useStorage",[34,3909,3911],{"className":36,"code":3910,"language":38,"meta":39,"style":39},"function useStorage(): StorageInterface\n",[29,3912,3913],{"__ignoreMap":39},[43,3914,3915,3917,3919,3922,3924],{"class":45,"line":46},[43,3916,3027],{"class":49},[43,3918,3840],{"class":87},[43,3920,3921],{"class":53},"()",[43,3923,107],{"class":49},[43,3925,3926],{"class":87}," StorageInterface\n",[25,3928,3929,3930,3932],{},"Returns the current storage instance. If none has been set via ",[29,3931,2820],{},", lazily initializes an in-memory storage.",[15,3934,3936],{"id":3935},"development","Development",[3938,3939,3940,3944],"details",{},[3941,3942,3943],"summary",{},"local development",[1201,3945,3946,3949,3958,3970,3976],{},[1204,3947,3948],{},"Clone this repository",[1204,3950,3951,3952],{},"Install latest LTS version of ",[2005,3953,3957],{"href":3954,"rel":3955},"https:\u002F\u002Fnodejs.org\u002Fen\u002F",[3956],"nofollow","Node.js",[1204,3959,3960,3961,3966,3967],{},"Enable ",[2005,3962,3965],{"href":3963,"rel":3964},"https:\u002F\u002Fgithub.com\u002Fnodejs\u002Fcorepack",[3956],"Corepack"," using ",[29,3968,3969],{},"corepack enable",[1204,3971,3972,3973],{},"Install dependencies using ",[29,3974,3975],{},"pnpm install",[1204,3977,3978,3979],{},"Run interactive tests using ",[29,3980,3981],{},"pnpm dev",[15,3983,3985],{"id":3984},"license","License",[25,3987,3988,3989,3994],{},"Published under the ",[2005,3990,3993],{"href":3991,"rel":3992},"https:\u002F\u002Fgithub.com\u002Funjs\u002Focache\u002Fblob\u002Fmain\u002FLICENSE",[3956],"MIT"," license 💛.",[3996,3997,3998],"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 .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 pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}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":39,"searchDepth":67,"depth":67,"links":4000},[4001,4009,4022,4023],{"id":17,"depth":67,"text":18,"children":4002},[4003,4004,4005,4006,4007,4008],{"id":22,"depth":74,"text":23},{"id":770,"depth":74,"text":771},{"id":2025,"depth":74,"text":2026},{"id":2328,"depth":74,"text":2329},{"id":2463,"depth":74,"text":2464},{"id":2574,"depth":74,"text":2575},{"id":2904,"depth":67,"text":2905,"children":4010},[4011,4012,4013,4014,4015,4016,4017,4018,4019,4020,4021],{"id":2908,"depth":74,"text":2911},{"id":2942,"depth":74,"text":2945},{"id":3015,"depth":74,"text":2869},{"id":3053,"depth":74,"text":31},{"id":3194,"depth":74,"text":777},{"id":3305,"depth":74,"text":3308},{"id":3353,"depth":74,"text":3356},{"id":3519,"depth":74,"text":3406},{"id":3644,"depth":74,"text":3418},{"id":3866,"depth":74,"text":2820},{"id":3904,"depth":74,"text":3907},{"id":3935,"depth":67,"text":3936},{"id":3984,"depth":67,"text":3985},"md",{"automd":70,"icon":8},{"icon":8},{"title":5,"description":39},"3k7wTbNNI51K8jO1mTLZLY6f8JZFVHKGA9AwAXvjKNY",[4030,4030],null,1783533023748]