[{"data":1,"prerenderedAt":1039},["ShallowReactive",2],{"navigation_docs":3,"-guide-storage":93,"-guide-storage-surround":1034},[4,71],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":70},"Guide","i-lucide-book-open","\u002Fguide","1.guide",[10,14,18,22,26,30,34,38,42,46,50,54,58,62,66],{"title":11,"path":12,"stem":13},"Getting started","\u002Fguide\u002Fgetting-started","1.guide\u002F01.getting-started",{"title":15,"path":16,"stem":17},"Adoption paths","\u002Fguide\u002Fadoption","1.guide\u002F02.adoption",{"title":19,"path":20,"stem":21},"Routes and typed $fetch","\u002Fguide\u002Froutes","1.guide\u002F02.routes",{"title":23,"path":24,"stem":25},"Kyo handlers","\u002Fguide\u002Fkyo","1.guide\u002F03.kyo",{"title":27,"path":28,"stem":29},"ZIO handlers","\u002Fguide\u002Fzio","1.guide\u002F04.zio",{"title":31,"path":32,"stem":33},"Configuration and secrets","\u002Fguide\u002Fconfiguration","1.guide\u002F05.configuration",{"title":35,"path":36,"stem":37},"Application and request lifetimes","\u002Fguide\u002Flifetimes","1.guide\u002F06.lifetimes",{"title":39,"path":40,"stem":41},"Schemas","\u002Fguide\u002Fschema","1.guide\u002F07.schema",{"title":43,"path":44,"stem":45},"PostgreSQL","\u002Fguide\u002Fdatabase","1.guide\u002F08.database",{"title":47,"path":48,"stem":49},"Streaming and cancellation","\u002Fguide\u002Fstreaming","1.guide\u002F09.streaming",{"title":51,"path":52,"stem":53},"Testing","\u002Fguide\u002Ftesting","1.guide\u002F10.testing",{"title":55,"path":56,"stem":57},"Nitro storage and NuxtHub KV","\u002Fguide\u002Fstorage","1.guide\u002F11.storage",{"title":59,"path":60,"stem":61},"Debug Scala handlers","\u002Fguide\u002Fdebugging","1.guide\u002F12.debugging",{"title":63,"path":64,"stem":65},"npm build tooling","\u002Fguide\u002Fnpm-tooling","1.guide\u002F13.npm-tooling",{"title":67,"path":68,"stem":69},"Set up h34s with a coding assistant","\u002Fguide\u002Fagent-setup","1.guide\u002F14.agent-setup",false,{"title":72,"icon":73,"path":74,"stem":75,"children":76,"page":70},"Reference","i-lucide-library","\u002Freference","2.reference",[77,81,85,89],{"title":78,"path":79,"stem":80},"Architecture","\u002Freference\u002Farchitecture","2.reference\u002F1.architecture",{"title":82,"path":83,"stem":84},"Releases","\u002Freference\u002Freleases","2.reference\u002F2.releases",{"title":86,"path":87,"stem":88},"Compatibility","\u002Freference\u002Fcompatibility","2.reference\u002F3.compatibility",{"title":90,"path":91,"stem":92},"Migration guide","\u002Freference\u002Fmigration","2.reference\u002F4.migration",{"id":94,"title":55,"body":95,"description":1028,"extension":1029,"links":1030,"meta":1031,"navigation":391,"path":56,"seo":1032,"stem":57,"__hash__":1033},"docs\u002F1.guide\u002F11.storage.md",{"type":96,"value":97,"toc":1021},"minimark",[98,119,151,214,221,226,241,332,339,342,346,357,440,443,637,640,784,811,827,831,936,940,943,974,978,1017],[99,100,101,102,106,107,110,111,114,115,118],"p",{},"Use key-value storage from Scala without JavaScript. ",[103,104,105],"code",{},"KHubKv.mount(base)"," (Kyo) and ",[103,108,109],{},"ZHubKv.mount(base)"," (ZIO) open a Nitro storage mount: the same storage that Nitro's ",[103,112,113],{},"useStorage(base)"," returns. You do not import ",[103,116,117],{},"@nuxthub\u002Fkv"," or pass a native object.",[99,120,121,125,126,129,130,133,134,137,138,141,142,145,146,150],{},[122,123,124],"strong",{},"Status."," ",[103,127,128],{},"mount"," is new in ",[103,131,132],{},"0.2.0-alpha.1",". It replaces the ",[103,135,136],{},"KHubKv(native)"," and ",[103,139,140],{},"ZHubKv(native)"," constructors of ",[103,143,144],{},"0.1.0-alpha.1","; see the ",[147,148,149],"a",{"href":91},"migration guide",".",[152,153,154,170],"table",{},[155,156,157],"thead",{},[158,159,160,164,167],"tr",{},[161,162,163],"th",{},"Module",[161,165,166],{},"API",[161,168,169],{},"Depends on",[171,172,173,194],"tbody",{},[158,174,175,181,191],{},[176,177,178],"td",{},[103,179,180],{},"kyo-nuxthub-ext",[176,182,183,186,187,190],{},[103,184,185],{},"KHubKv"," (package ",[103,188,189],{},"dev.yuri4n.exts.kyonuxthub",")",[176,192,193],{},"the Kyo core",[158,195,196,201,209],{},[176,197,198],{},[103,199,200],{},"zio-nuxthub-ext",[176,202,203,186,206,190],{},[103,204,205],{},"ZHubKv",[103,207,208],{},"dev.yuri4n.exts.zionuxthub",[176,210,211,213],{},[103,212,180],{}," and the ZIO adapter",[99,215,216,217,220],{},"Neither module needs a schema. The h34s Nitro plugin, which the ",[103,218,219],{},"@yuri4n\u002Fh34s-nuxt"," module registers, supplies the storage.",[222,223,225],"h2",{"id":224},"choose-a-mount","Choose a mount",[99,227,228,229,232,233,236,237,240],{},"A mount is a named part of Nitro storage with its own driver. Configure mounts in ",[103,230,231],{},"nuxt.config.ts"," with Nitro's ",[103,234,235],{},"storage"," option, or let a module such as NuxtHub add them. For example, a Redis-backed ",[103,238,239],{},"cache"," mount:",[242,243,248],"pre",{"className":244,"code":245,"language":246,"meta":247,"style":247},"language-ts shiki shiki-themes github-light github-light github-dark","export default defineNuxtConfig({\n  modules: ['@yuri4n\u002Fh34s-nuxt'],\n  nitro: {\n    storage: {\n      cache: { driver: 'redis', url: process.env.REDIS_URL },\n    },\n  },\n})\n","ts","",[103,249,250,270,283,289,295,314,320,326],{"__ignoreMap":247},[251,252,255,259,262,266],"span",{"class":253,"line":254},"line",1,[251,256,258],{"class":257},"s8jYJ","export",[251,260,261],{"class":257}," default",[251,263,265],{"class":264},"snPdu"," defineNuxtConfig",[251,267,269],{"class":268},"sxrX7","({\n",[251,271,273,276,280],{"class":253,"line":272},2,[251,274,275],{"class":268},"  modules: [",[251,277,279],{"class":278},"sIIMD","'@yuri4n\u002Fh34s-nuxt'",[251,281,282],{"class":268},"],\n",[251,284,286],{"class":253,"line":285},3,[251,287,288],{"class":268},"  nitro: {\n",[251,290,292],{"class":253,"line":291},4,[251,293,294],{"class":268},"    storage: {\n",[251,296,298,301,304,307,311],{"class":253,"line":297},5,[251,299,300],{"class":268},"      cache: { driver: ",[251,302,303],{"class":278},"'redis'",[251,305,306],{"class":268},", url: process.env.",[251,308,310],{"class":309},"sBjJW","REDIS_URL",[251,312,313],{"class":268}," },\n",[251,315,317],{"class":253,"line":316},6,[251,318,319],{"class":268},"    },\n",[251,321,323],{"class":253,"line":322},7,[251,324,325],{"class":268},"  },\n",[251,327,329],{"class":253,"line":328},8,[251,330,331],{"class":268},"})\n",[99,333,334,335,338],{},"Keep connection URLs and passwords out of committed files; read them from the environment as shown. ",[103,336,337],{},"mount(\"\")"," opens the root storage, which sees every mount.",[99,340,341],{},"NuxtHub: whether NuxtHub 0.10.8 exposes its KV as a Nitro storage mount has not been verified. The bindings were tested with Unstorage 1.17.3's memory driver, the driver NuxtHub 0.10.8 generates for local KV. Check the mount name in your NuxtHub setup before you rely on it.",[222,343,345],{"id":344},"open-and-use-a-mount","Open and use a mount",[99,347,348,349,352,353,356],{},"Models need only a ",[103,350,351],{},"NativeConverter"," (or a ",[147,354,355],{"href":40},"schema","):",[242,358,362],{"className":359,"code":360,"language":361,"meta":247,"style":247},"language-scala shiki shiki-themes github-light github-light github-dark","import org.getshaka.nativeconverter.NativeConverter\n\nfinal case class Profile(name: String, visits: Int) derives NativeConverter\n","scala",[103,363,364,387,393],{"__ignoreMap":247},[251,365,366,369,372,374,377,379,382,384],{"class":253,"line":254},[251,367,368],{"class":257},"import",[251,370,371],{"class":264}," org",[251,373,150],{"class":268},[251,375,376],{"class":264},"getshaka",[251,378,150],{"class":268},[251,380,381],{"class":264},"nativeconverter",[251,383,150],{"class":268},[251,385,386],{"class":264},"NativeConverter\n",[251,388,389],{"class":253,"line":272},[251,390,392],{"emptyLinePlaceholder":391},true,"\n",[251,394,395,398,401,404,407,410,414,417,420,423,426,428,431,434,437],{"class":253,"line":285},[251,396,397],{"class":257},"final",[251,399,400],{"class":257}," case",[251,402,403],{"class":257}," class",[251,405,406],{"class":264}," Profile",[251,408,409],{"class":268},"(",[251,411,413],{"class":412},"sP4rz","name",[251,415,416],{"class":268},": ",[251,418,419],{"class":264},"String",[251,421,422],{"class":268},", ",[251,424,425],{"class":412},"visits",[251,427,416],{"class":268},[251,429,430],{"class":264},"Int",[251,432,433],{"class":268},") ",[251,435,436],{"class":257},"derives",[251,438,439],{"class":264}," NativeConverter\n",[99,441,442],{},"Kyo:",[242,444,446],{"className":359,"code":445,"language":361,"meta":247,"style":247},"import dev.yuri4n.exts.kyonuxthub.KHubKv\nimport kyo.*\n\nval visit: Option[Profile] \u003C (Async & Abort[Throwable]) =\n  for\n    cache   \u003C- KHubKv.mount(\"cache\")\n    _       \u003C- cache.set(\"profiles:42\", Profile(\"Yuri\", 1), ttlSeconds = Some(300.0))\n    profile \u003C- cache.get[Profile](\"profiles:42\")\n  yield profile\n",[103,447,448,475,487,491,540,545,565,609,628],{"__ignoreMap":247},[251,449,450,452,455,457,460,462,465,467,470,472],{"class":253,"line":254},[251,451,368],{"class":257},[251,453,454],{"class":264}," dev",[251,456,150],{"class":268},[251,458,459],{"class":264},"yuri4n",[251,461,150],{"class":268},[251,463,464],{"class":264},"exts",[251,466,150],{"class":268},[251,468,469],{"class":264},"kyonuxthub",[251,471,150],{"class":268},[251,473,474],{"class":264},"KHubKv\n",[251,476,477,479,482,484],{"class":253,"line":272},[251,478,368],{"class":257},[251,480,481],{"class":264}," kyo",[251,483,150],{"class":268},[251,485,486],{"class":264},"*\n",[251,488,489],{"class":253,"line":285},[251,490,392],{"emptyLinePlaceholder":391},[251,492,493,496,499,502,505,508,511,514,517,520,523,526,529,531,534,537],{"class":253,"line":291},[251,494,495],{"class":257},"val",[251,497,498],{"class":412}," visit",[251,500,501],{"class":257},":",[251,503,504],{"class":264}," Option",[251,506,507],{"class":268},"[",[251,509,510],{"class":264},"Profile",[251,512,513],{"class":268},"] ",[251,515,516],{"class":257},"\u003C",[251,518,519],{"class":268}," (",[251,521,522],{"class":264},"Async",[251,524,525],{"class":257}," &",[251,527,528],{"class":264}," Abort",[251,530,507],{"class":268},[251,532,533],{"class":264},"Throwable",[251,535,536],{"class":268},"]) ",[251,538,539],{"class":257},"=\n",[251,541,542],{"class":253,"line":297},[251,543,544],{"class":257},"  for\n",[251,546,547,550,553,556,559,562],{"class":253,"line":316},[251,548,549],{"class":268},"    cache   ",[251,551,552],{"class":257},"\u003C-",[251,554,555],{"class":264}," KHubKv",[251,557,558],{"class":268},".mount(",[251,560,561],{"class":278},"\"cache\"",[251,563,564],{"class":268},")\n",[251,566,567,570,572,575,578,580,582,584,587,589,592,595,598,601,603,606],{"class":253,"line":322},[251,568,569],{"class":268},"    _       ",[251,571,552],{"class":257},[251,573,574],{"class":268}," cache.set(",[251,576,577],{"class":278},"\"profiles:42\"",[251,579,422],{"class":268},[251,581,510],{"class":264},[251,583,409],{"class":268},[251,585,586],{"class":278},"\"Yuri\"",[251,588,422],{"class":268},[251,590,591],{"class":309},"1",[251,593,594],{"class":268},"), ttlSeconds ",[251,596,597],{"class":257},"=",[251,599,600],{"class":264}," Some",[251,602,409],{"class":268},[251,604,605],{"class":309},"300.0",[251,607,608],{"class":268},"))\n",[251,610,611,614,616,619,621,624,626],{"class":253,"line":328},[251,612,613],{"class":268},"    profile ",[251,615,552],{"class":257},[251,617,618],{"class":268}," cache.get[",[251,620,510],{"class":264},[251,622,623],{"class":268},"](",[251,625,577],{"class":278},[251,627,564],{"class":268},[251,629,631,634],{"class":253,"line":630},9,[251,632,633],{"class":257},"  yield",[251,635,636],{"class":268}," profile\n",[99,638,639],{},"ZIO:",[242,641,643],{"className":359,"code":642,"language":361,"meta":247,"style":247},"import dev.yuri4n.exts.zionuxthub.ZHubKv\nimport zio.*\n\nval visit: Task[Option[Profile]] =\n  for\n    cache   \u003C- ZHubKv.mount(\"cache\")\n    _       \u003C- cache.set(\"profiles:42\", Profile(\"Yuri\", 1), ttlSeconds = Some(300.0))\n    profile \u003C- cache.get[Profile](\"profiles:42\")\n  yield profile\n",[103,644,645,669,680,684,709,713,728,762,778],{"__ignoreMap":247},[251,646,647,649,651,653,655,657,659,661,664,666],{"class":253,"line":254},[251,648,368],{"class":257},[251,650,454],{"class":264},[251,652,150],{"class":268},[251,654,459],{"class":264},[251,656,150],{"class":268},[251,658,464],{"class":264},[251,660,150],{"class":268},[251,662,663],{"class":264},"zionuxthub",[251,665,150],{"class":268},[251,667,668],{"class":264},"ZHubKv\n",[251,670,671,673,676,678],{"class":253,"line":272},[251,672,368],{"class":257},[251,674,675],{"class":264}," zio",[251,677,150],{"class":268},[251,679,486],{"class":264},[251,681,682],{"class":253,"line":285},[251,683,392],{"emptyLinePlaceholder":391},[251,685,686,688,690,692,695,697,700,702,704,707],{"class":253,"line":291},[251,687,495],{"class":257},[251,689,498],{"class":412},[251,691,501],{"class":257},[251,693,694],{"class":264}," Task",[251,696,507],{"class":268},[251,698,699],{"class":264},"Option",[251,701,507],{"class":268},[251,703,510],{"class":264},[251,705,706],{"class":268},"]] ",[251,708,539],{"class":257},[251,710,711],{"class":253,"line":297},[251,712,544],{"class":257},[251,714,715,717,719,722,724,726],{"class":253,"line":316},[251,716,549],{"class":268},[251,718,552],{"class":257},[251,720,721],{"class":264}," ZHubKv",[251,723,558],{"class":268},[251,725,561],{"class":278},[251,727,564],{"class":268},[251,729,730,732,734,736,738,740,742,744,746,748,750,752,754,756,758,760],{"class":253,"line":322},[251,731,569],{"class":268},[251,733,552],{"class":257},[251,735,574],{"class":268},[251,737,577],{"class":278},[251,739,422],{"class":268},[251,741,510],{"class":264},[251,743,409],{"class":268},[251,745,586],{"class":278},[251,747,422],{"class":268},[251,749,591],{"class":309},[251,751,594],{"class":268},[251,753,597],{"class":257},[251,755,600],{"class":264},[251,757,409],{"class":268},[251,759,605],{"class":309},[251,761,608],{"class":268},[251,763,764,766,768,770,772,774,776],{"class":253,"line":328},[251,765,613],{"class":268},[251,767,552],{"class":257},[251,769,618],{"class":268},[251,771,510],{"class":264},[251,773,623],{"class":268},[251,775,577],{"class":278},[251,777,564],{"class":268},[251,779,780,782],{"class":253,"line":630},[251,781,633],{"class":257},[251,783,636],{"class":268},[99,785,786,787,422,790,422,793,422,796,137,799,802,803,806,807,810],{},"Both APIs offer ",[103,788,789],{},"get[A](key)",[103,791,792],{},"set[A](key, value, ttlSeconds = None)",[103,794,795],{},"has(key)",[103,797,798],{},"delete(key)",[103,800,801],{},"keys(base = None)",". Kyo operations are ",[103,804,805],{},"A \u003C (Async & Abort[Throwable])","; ZIO operations are ",[103,808,809],{},"Task[A]",". Each run calls the storage again.",[99,812,813,815,816,819,820,823,824,826],{},[103,814,128],{}," fails with ",[103,817,818],{},"ConfigError"," when the h34s plugin is not installed (",[103,821,822],{},"h34s Nitro plugin is not installed",") or when the mount is not available. An unhandled ",[103,825,818],{}," is an opaque 500.",[222,828,830],{"id":829},"know-the-storage-contract","Know the storage contract",[832,833,834,853,871,892,909,930],"ul",{},[835,836,837,840,841,844,845,848,849,852],"li",{},[122,838,839],{},"Missing values."," A missing key and a stored ",[103,842,843],{},"null"," are both ",[103,846,847],{},"None",". Use ",[103,850,851],{},"has"," when the difference matters.",[835,854,855,858,859,862,863,866,867,870],{},[122,856,857],{},"Conversion."," Values are converted directly to native values; the driver serializes them for its backend. A stored value that the converter rejects fails ",[103,860,861],{},"get"," with ",[103,864,865],{},"StoredValueError",", a typed failure that names only the failing path (",[103,868,869],{},"root.count",", or a schema path), never the key or the stored value: keys are often session ids, and values can hold tokens. It is server data, so an unhandled one is an opaque 500, never a 422, even when a schema converter rejected it. It is not treated as a missing key.",[835,872,873,876,877,422,880,883,884,887,888,891],{},[122,874,875],{},"Top-level strings."," Unstorage's default serialization can turn a stored top-level string such as ",[103,878,879],{},"\"42\"",[103,881,882],{},"\"true\""," or ",[103,885,886],{},"\"null\""," into another JavaScript type (a ",[103,889,890],{},"Secret(\"12345\")"," comes back as a number and fails to decode). Store objects (a case class) for typed records.",[835,893,894,125,897,900,901,904,905,908],{},[122,895,896],{},"TTL.",[103,898,899],{},"ttlSeconds"," is forwarded as ",[103,902,903],{},"{ ttl: seconds }",". Expiry depends on the driver. The memory driver and NuxtHub's fs-lite driver ignore it, so a successful ",[103,906,907],{},"set"," does not prove that a key expires.",[835,910,911,914,915,918,919,921,922,925,926,929],{},[122,912,913],{},"Keys."," Keys follow Unstorage normalization: ",[103,916,917],{},"\u002F"," becomes ",[103,920,501],{},". ",[103,923,924],{},"keys(Some(\"profiles\"))"," lists keys under ",[103,927,928],{},"profiles:",". The order depends on the driver.",[835,931,932,935],{},[122,933,934],{},"Cancellation."," Storage calls cannot be cancelled. Interrupting a waiting fiber does not cancel or roll back a write that already started.",[222,937,939],{"id":938},"invalidate-cached-data","Invalidate cached data",[99,941,942],{},"h34s adds no cache abstraction. Common patterns with these operations:",[832,944,945,955,965],{},[835,946,947,950,951,954],{},[122,948,949],{},"Delete on write."," After you change the source data, ",[103,952,953],{},"delete"," the cached key in the same handler.",[835,956,957,960,961,964],{},[122,958,959],{},"Generation keys."," Store a generation number under one key and include it in every cached key (",[103,962,963],{},"catalogue:v7:page:1","). Increment it to invalidate everything at once; old keys expire through the driver's TTL.",[835,966,967,970,971,973],{},[122,968,969],{},"Short TTLs."," For data that may be slightly stale, set ",[103,972,899],{}," and accept the delay. Check that your driver supports TTL first.",[222,975,977],{"id":976},"what-is-tested","What is tested",[99,979,980,983,984,987,988,990,991,993,994,137,997,1000,1001,137,1003,1006,1007,1009,1010,1012,1013,1016],{},[103,981,982],{},"KHubKvSuite"," (15 tests) and ",[103,985,986],{},"ZHubKvSpec"," (14 tests) on macOS x86_64 with Node 24.19.0: ",[103,989,128],{}," through a fake h34s startup record, ",[103,992,818],{}," without the plugin or the mount, round trips with Unstorage 1.17.3's memory driver, ",[103,995,996],{},"false",[103,998,999],{},"0"," as stored values, ",[103,1002,843],{},[103,1004,1005],{},"undefined"," as ",[103,1008,847],{},", lazy operations, exact TTL forwarding, JavaScript errors and rejected Promises in the failure channel, value-free ",[103,1011,865],{},"s for shape and schema mismatches (an opaque 500 in a handler), a ",[103,1014,1015],{},"SafeError"," from an encoder that stays unapproved, upstream string deserialization, and interruption during a write. No test starts Nuxt, NuxtHub or a cloud service.",[1018,1019,1020],"style",{},"html pre.shiki code .s8jYJ, html code.shiki .s8jYJ{--shiki-light:#D73A49;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .snPdu, html code.shiki .snPdu{--shiki-light:#6F42C1;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sxrX7, html code.shiki .sxrX7{--shiki-light:#24292E;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sIIMD, html code.shiki .sIIMD{--shiki-light:#032F62;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sBjJW, html code.shiki .sBjJW{--shiki-light:#005CC5;--shiki-default:#005CC5;--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 .sP4rz, html code.shiki .sP4rz{--shiki-light:#E36209;--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":247,"searchDepth":272,"depth":272,"links":1022},[1023,1024,1025,1026,1027],{"id":224,"depth":272,"text":225},{"id":344,"depth":272,"text":345},{"id":829,"depth":272,"text":830},{"id":938,"depth":272,"text":939},{"id":976,"depth":272,"text":977},"Open a Nitro storage mount from Scala with KHubKv.mount or ZHubKv.mount, with no native objects.","md",null,{},{"title":55,"description":1028},"IQ4mQIR4jaEnpgnNuQcZPDHoC8hw_lF5wlzUYZWBz1o",[1035,1037],{"title":51,"path":52,"stem":53,"description":1036,"children":-1},"Test handler functions with Request.fake and KHandler.test or ZHandler.test, without h3, Nitro or a server.",{"title":59,"path":60,"stem":61,"description":1038,"children":-1},"See error causes in development or debug mode, keep production opaque, and map Nitro's JavaScript back to Scala.",1792533383165]