[{"data":1,"prerenderedAt":2741},["ShallowReactive",2],{"navigation_docs":3,"-reference-migration":93,"-reference-migration-surround":2738},[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":90,"body":95,"description":2732,"extension":2733,"links":2734,"meta":2735,"navigation":1642,"path":91,"seo":2736,"stem":92,"__hash__":2737},"docs\u002F2.reference\u002F4.migration.md",{"type":96,"value":97,"toc":2709},"minimark",[98,102,107,123,131,152,300,324,327,373,376,416,423,429,475,575,582,675,704,708,711,764,772,776,803,807,850,942,946,967,970,995,1002,1012,1034,1048,1088,1100,1104,1107,1123,1127,1207,1213,1217,1355,1361,1365,1372,1376,1535,1538,1718,1735,1738,2174,2177,2412,2423,2427,2441,2546,2566,2577,2581,2632,2636,2655,2671,2688,2692,2705],[99,100,101],"p",{},"Each section lists every removed or renamed API with its replacement. Start with the section for the version you use now.",[103,104,106],"h2",{"id":105},"upgrade-from-020-alpha1-to-030-alpha1","Upgrade from 0.2.0-alpha.1 to 0.3.0-alpha.1",[99,108,109,113,114,118,119,122],{},[110,111,112],"strong",{},"Status."," ",[115,116,117],"code",{},"0.3.0-alpha.1"," is not released yet. This section collects its changes while they land on ",[115,120,121],{},"main",".",[124,125,127,128],"h3",{"id":126},"send-streams-with-responsesendstream","Send streams with ",[115,129,130],{},"Response.sendStream",[99,132,133,134,137,138,141,142,145,146,149,150,122],{},"A handler no longer returns a stream. It sends the stream with ",[115,135,136],{},"Response.sendStream(stream)"," as its last step and returns the ",[115,139,140],{},"Sent"," value that this gives. A handler that returns a ",[115,143,144],{},"kyo.Stream"," or a ",[115,147,148],{},"ZStream"," stops compiling, with a message that names ",[115,151,136],{},[153,154,155,171],"table",{},[156,157,158],"thead",{},[159,160,161,167],"tr",{},[162,163,164],"th",{},[115,165,166],{},"0.2.0-alpha.1",[162,168,169],{},[115,170,117],{},[172,173,174,203,237,258,271],"tbody",{},[159,175,176,188],{},[177,178,179,180,183,184,187],"td",{},"Kyo: return a ",[115,181,182],{},"kyo.Stream[String, S]"," (the ",[115,185,186],{},"ResponseBody.stream"," given)",[177,189,190,192,193,196,197,199,200,202],{},[115,191,136],{},", which gives ",[115,194,195],{},"Sent \u003C HandlerEffects","; return the ",[115,198,140],{},". The ",[115,201,186],{}," given is removed",[159,204,205,219],{},[177,206,207,208,183,211,214,215,218],{},"ZIO: return a ",[115,209,210],{},"ZStream[Any, E, String]",[115,212,213],{},"ZResponseBody.stream"," and ",[115,216,217],{},"infallibleStream"," givens)",[177,220,221,223,224,192,227,196,230,232,233,236],{},[115,222,136],{}," on ",[115,225,226],{},"dev.yuri4n.exts.zioh3.Response",[115,228,229],{},"ZIO[ZState[ResponseHead] & HandlerTransport, Throwable, Sent]",[115,231,140],{},". Both givens are removed, with ",[115,234,235],{},"StreamZResponseBody",", the public trait that held them",[159,238,239,244],{},[177,240,241],{},[115,242,243],{},"HandlerEffects = Async & Scope & Abort[Throwable] & Var[ResponseHead]",[177,245,246,249,250,253,254,257],{},[115,247,248],{},"HandlerEffects"," also has ",[115,251,252],{},"Env[Fetch & HandlerTransport]",", which h34s provides. Code that passes a program to ",[115,255,256],{},"KHandler.define"," compiles unchanged",[159,259,260,265],{},[177,261,262],{},[115,263,264],{},"HandlerEnv = ZState[ResponseHead] & Scope",[177,266,267,270],{},[115,268,269],{},"HandlerEnv = ZState[ResponseHead] & Scope & HandlerTransport & Fetch",", which h34s provides",[159,272,273,287],{},[177,274,275,276,279,280,283,284],{},"Test with ",[115,277,278],{},"Var.runTuple"," or ",[115,281,282],{},"ZIO.stateful"," and a ",[115,285,286],{},"Scope",[177,288,289,279,292,295,296,299],{},[115,290,291],{},"KHandler.test(handler)(request)",[115,293,294],{},"ZHandler.test(handler)(request)",", which give a ",[115,297,298],{},"TestResponse",". The manual provisioning no longer compiles: it lacks the transport, which only h34s can build",[99,301,302,303,306,307,310,311,314,315,317,318,320,321,323],{},"There is no ",[115,304,305],{},"ZHandler.sendStream",". ",[115,308,309],{},"0.1.0-alpha.1"," had one with another signature, ",[115,312,313],{},"ZHandler.sendStream[A: NativeConverter](stream: TaskStream[A]): TaskHandler[Unit]",", and ",[115,316,166],{}," removed it. If you upgrade from ",[115,319,309],{},", use ",[115,322,130],{}," with a stream of strings.",[99,325,326],{},"The wire behavior changes too:",[328,329,330,340,346,363],"ul",{},[331,332,333,113,336,339],"li",{},[110,334,335],{},"The head leaves at the call.",[115,337,338],{},"sendStream"," writes the head as your program set it when you call it, and over a socket it flushes it at once. Before, h34s wrote the head with the first element. Set the status and headers, validate input and acquire resources before the call: after it, the head is fixed, and a later change is not written.",[331,341,342,345],{},[110,343,344],{},"A failure before the first element no longer changes the status."," Before, it was rendered with the failure rule, for example as a 409 with an error body. Now h34s closes the connection, as it already did for a failure after the first element.",[331,347,348,354,355,358,359,362],{},[110,349,350,351,353],{},"A stream failure fails the ",[115,352,338],{}," step."," Your program, and a scope or transaction around the step, see the stream's error and can roll back. In Kyo, that scope is a ",[115,356,357],{},"Scope.run"," inside your handler: a finalizer of the request scope itself gets ",[115,360,361],{},"Absent",". The server logs the failure once. Before, the program never saw it.",[331,364,365,368,369,372],{},[110,366,367],{},"In-process calls stream."," A server-side ",[115,370,371],{},"$fetch"," to a streaming route answered an opaque 500 before. Now the caller gets the head first, then the elements.",[99,374,375],{},"To upgrade:",[377,378,379,392,395,413],"ol",{},[331,380,381,382,385,386,389,390,122],{},"Replace ",[115,383,384],{},".andThen(stream)"," (Kyo) or ",[115,387,388],{},"ZIO.succeed(stream)"," (ZIO) at the end of each streaming handler with ",[115,391,136],{},[331,393,394],{},"Move validation and resource acquisition before the call, if they ran inside the stream.",[331,396,397,398,279,401,404,405,408,409,122],{},"Update tests that read the head or body of a streaming handler: use ",[115,399,400],{},"KHandler.test",[115,402,403],{},"ZHandler.test",", and check ",[115,406,407],{},"TestResponse.Body.Streamed(elements)",". See ",[410,411,412],"a",{"href":52},"testing",[331,414,415],{},"Update clients that expected an error body for a stream that fails before its first element. They now see a successful status and an incomplete transfer.",[99,417,418,419,422],{},"See ",[410,420,421],{"href":48},"streaming"," for the details.",[124,424,426,427],{"id":425},"call-other-routes-with-fetch","Call other routes with ",[115,428,371],{},[99,430,431,433,434,436,437,214,440,443,444,447,448,447,451,447,454,214,457,460,461,464,465,468,469,214,472,122],{},[115,432,166],{}," removed the server-side ",[115,435,371],{},". It returns, with a new signature, in both runtimes: ",[115,438,439],{},"KHandler.$fetch",[115,441,442],{},"ZHandler.$fetch",", with the verbs ",[115,445,446],{},"raw",", ",[115,449,450],{},"text",[115,452,453],{},"as",[115,455,456],{},"get",[115,458,459],{},"post",". It answers a path that starts with ",[115,462,463],{},"\u002F"," in-process through Nitro, and forwards the incoming cookies and ",[115,466,467],{},"authorization"," only to such paths. See ",[410,470,23],{"href":471},"\u002Fguide\u002Fkyo#call-other-routes-with-fetch",[410,473,27],{"href":474},"\u002Fguide\u002Fzio#call-other-routes-with-fetch",[153,476,477,489],{},[156,478,479],{},[159,480,481,485],{},[162,482,483],{},[115,484,166],{},[162,486,487],{},[115,488,117],{},[172,490,491,536,550],{},[159,492,493,508],{},[177,494,495,496,498,499,501,502,214,504,507],{},"No server-side ",[115,497,371],{}," (",[115,500,309],{}," had ",[115,503,442],{},[115,505,506],{},"SH3Event.$fetch",")",[177,509,510,512,513,515,516,518,519,522,523,526,527,529,530,279,533],{},[115,511,439],{}," (Kyo, through ",[115,514,252],{},") and ",[115,517,442],{}," (ZIO, through the ",[115,520,521],{},"Fetch"," of ",[115,524,525],{},"HandlerEnv","). ",[115,528,446],{}," gives ",[115,531,532],{},"FetchResponse.Plain",[115,534,535],{},"FetchResponse.Streamed",[159,537,538,542],{},[177,539,540],{},[115,541,264],{},[177,543,544,546,547,257],{},[115,545,269],{},". Code that passes a program to ",[115,548,549],{},"ZHandler.define",[159,551,552,555],{},[177,553,554],{},"No test helper",[177,556,557,559,560,563,564,566,567,570,571,574],{},[115,558,294],{}," keeps working; ",[115,561,562],{},"ZHandler.test(handler)(request, fetch)"," answers ",[115,565,371],{}," calls, for example with ",[115,568,569],{},"Fetch.fake",", as ",[115,572,573],{},"KHandler.test(handler)(request, fetch)"," does",[99,576,577,578,581],{},"Keep three rules in mind. The first differs from Nuxt's ",[115,579,580],{},"event.$fetch",", which throws on an error status and retries a failed GET once:",[328,583,584,605,658],{},[331,585,586,113,589,591,592,447,594,447,596,214,598,600,601,604],{},[110,587,588],{},"Statuses do not throw, and nothing retries.",[115,590,446],{}," gives any status as a response. ",[115,593,450],{},[115,595,453],{},[115,597,456],{},[115,599,459],{}," fail with the typed ",[115,602,603],{},"FetchError.Status"," unless the status is 2xx.",[331,606,607,113,610,613,614,617,618,621,622,625,626,628,629,632,633,636,637,640,641,644,645,648,649,223,652,655,656,122],{},[110,608,609],{},"A streamed body is typed.",[115,611,612],{},"FetchResponse.Streamed.body"," is ",[115,615,616],{},"Stream[String, Async & Scope & Abort[FetchError]]"," in Kyo and ",[115,619,620],{},"ZStream[Any, FetchError, String]"," in ZIO. A body that breaks after its head fails with ",[115,623,624],{},"FetchError.BodyFailed(status, reason)",". In the unreleased ",[115,627,121],{}," before this change, the Kyo body was ",[115,630,631],{},"Stream[String, Async & Scope]",", and the failure was a panic: add ",[115,634,635],{},"Abort[FetchError]"," where you name that type. A ",[115,638,639],{},"Plain"," body whose read fails after the head is ",[115,642,643],{},"BodyFailed"," too (it was ",[115,646,647],{},"Failed","). A ",[115,650,651],{},"match",[115,653,654],{},"FetchError"," needs a case for the new ",[115,657,643],{},[331,659,660,113,663,666,667,670,671,674],{},[110,661,662],{},"The JSON is decoded as it arrives.",[115,664,665],{},"get[A]"," on an h34s route with the default options decodes ",[115,668,669],{},"{\"data\": ...}",", so ",[115,672,673],{},"A"," must model that envelope.",[99,676,677,680,681,447,684,687,688,691,692,694,695,697,698,701,702,122],{},[115,678,679],{},"FetchResponse.headers"," joins repeated values with ",[115,682,683],{},"\", \"",[115,685,686],{},"set-cookie"," included; ",[115,689,690],{},"headerValues(name)"," gives each ",[115,693,686],{}," value apart. In the unreleased ",[115,696,121],{}," before this change, ",[115,699,700],{},"headers"," kept only the last ",[115,703,686],{},[124,705,707],{"id":706},"mount-handlers-from-scala","Mount handlers from Scala",[99,709,710],{},"Mount your handlers from Scala, then delete the route files:",[377,712,713,720,731,749],{},[331,714,715,716,719],{},"Add ",[115,717,718],{},".at(Route.get(\"\u002Fapi\u002Fnotes\"))"," (with the route and method of the file) to each exported handler.",[331,721,722,723,726,727,730],{},"Remove ",[115,724,725],{},"entries"," from ",[115,728,729],{},"h34s.config.mjs",", or keep them for outputs that still have route files.",[331,732,733,734,737,738,741,742,745,746,306],{},"Link with ",[115,735,736],{},"h34s-scala dev",". It prints the routes it found and writes ",[115,739,740],{},"h34s-routes.json",", the ",[115,743,744],{},".d.ts"," files and ",[115,747,748],{},"h34s-models.d.ts",[331,750,751,752,755,756,759,760,763],{},"Delete the ",[115,753,754],{},"server\u002Fapi"," files that re-export the linked modules, and the hand-written ",[115,757,758],{},"declare module"," types for them. A route file and ",[115,761,762],{},".at"," for the same route register the handler twice.",[99,765,766,767,122],{},"Route files keep working if you want to move later. See ",[410,768,769,770],{"href":20},"routes and typed ",[115,771,371],{},[124,773,775],{"id":774},"non-finite-numbers-are-an-opaque-500","Non-finite numbers are an opaque 500",[99,777,778,779,782,783,447,786,789,790,214,792,794,795,798,799,802],{},"A value body that contains ",[115,780,781],{},"NaN"," or an infinite number (",[115,784,785],{},"Double",[115,787,788],{},"Float",") is now the opaque 500. ",[115,791,309],{},[115,793,166],{}," sent these numbers as ",[115,796,797],{},"null",". If a value can be non-finite, return an ",[115,800,801],{},"Option"," or a string for it instead.",[124,804,806],{"id":805},"json-reads-require-a-content-type","JSON reads require a content type",[99,808,809,812,813,306,816,819,820,823,824,827,828,831,832,835,836,838,839,279,842,845,846,849],{},[115,810,811],{},"HandlerOptions.requireJsonContentType"," now defaults to ",[115,814,815],{},"true",[115,817,818],{},"request.body.json[A]"," answers 415 (",[115,821,822],{},"Request body must be JSON",") for a request that has a body but no ",[115,825,826],{},"Content-Type",". A request without a body needs no content type: ",[115,829,830],{},"json[Option[A]]"," still gives ",[115,833,834],{},"None"," and a model still answers 422. In ",[115,837,166],{},", a body without a content type was read as JSON. Requests with ",[115,840,841],{},"application\u002Fjson",[115,843,844],{},"application\u002F*+json"," behave as before, and ",[115,847,848],{},"text()"," never checks the content type.",[377,851,852,900,907,921],{},[331,853,854,855,857,858,861,862,864,865,279,868,871,872,875,876,879,880,883,884,886,887,890,891,498,894,897,898,122],{},"Check your clients. ",[115,856,371],{}," with an object body and ",[115,859,860],{},"curl --json"," send ",[115,863,841],{},". A ",[115,866,867],{},"fetch",[115,869,870],{},"navigator.sendBeacon"," with a byte body (",[115,873,874],{},"Blob"," without a type, ",[115,877,878],{},"ArrayBuffer",", typed array) and no ",[115,881,882],{},"content-type"," header sends no content type; these clients now get 415. Clients that send another content type, such as ",[115,885,867],{}," with a string body (",[115,888,889],{},"text\u002Fplain",") or ",[115,892,893],{},"curl -d",[115,895,896],{},"application\u002Fx-www-form-urlencoded","), already got 415 in ",[115,899,166],{},[331,901,902,903,906],{},"Make each client send ",[115,904,905],{},"content-type: application\u002Fjson",". This is the recommended fix.",[331,908,909,910,913,914,916,917,122],{},"If a client cannot send it, keep the old behavior for that handler only: ",[115,911,912],{},"KHandler.define(HandlerOptions(requireJsonContentType = false))(program)",", or the same options with ",[115,915,549],{},". Do not do this for a cookie-authenticated handler that changes state; see ",[410,918,920],{"href":919},"\u002Fguide\u002Fkyo#cross-site-requests","cross-site requests",[331,922,923,924,927,928,931,932,306,935,937,938,941],{},"In unit tests, add ",[115,925,926],{},"headers = Map(\"content-type\" -> \"application\u002Fjson\")"," to each ",[115,929,930],{},"Request.fake"," with a body that you read with ",[115,933,934],{},"json[A]",[115,936,930],{}," follows the same default; pass ",[115,939,940],{},"requireJsonContentType = false"," to test a handler that turns the option off.",[124,943,945],{"id":944},"a-dying-zio-finalizer-keeps-the-response","A dying ZIO finalizer keeps the response",[99,947,948,949,951,952,955,956,959,960,963,964,966],{},"In ",[115,950,166],{},", a ZIO finalizer that died after a value or ",[115,953,954],{},"Unit"," program turned the response into an opaque 500, and after a safe failure it replaced the approved error with the opaque 500. Now the ZIO adapter behaves like Kyo: it logs ",[115,957,958],{},"h34s: a ZIO finalizer failed"," with ",[115,961,962],{},"Cause.prettyPrint"," on the server, and the client gets the response that your program produced. This also applies to a streaming handler, before and after it calls ",[115,965,130],{},". Streamed bodies already behaved this way.",[99,968,969],{},"You do not need to change code that compiles. Check your handlers if you relied on the old 500:",[377,971,972,986,989],{},[331,973,974,975,447,978,981,982,985],{},"Find cleanup in ",[115,976,977],{},"ZIO.acquireRelease",[115,979,980],{},"ZIO.addFinalizer"," or a scoped ",[115,983,984],{},"ZLayer"," that must succeed for the response to be correct, for example a commit in a finalizer.",[331,987,988],{},"Move that step into the program, before the value is returned. A failure there follows the failure rule as before.",[331,990,991,992,994],{},"Watch the server log for ",[115,993,958],{}," to see finalizers that fail.",[99,996,997,998,1001],{},"The rule applies to the request scope. A release that dies inside your own ",[115,999,1000],{},"ZIO.scoped"," block, or inside a scoped layer that you provide inside the handler, fails the program under ZIO's rules and answers 500, as before.",[124,1003,1005,1008,1009],{"id":1004},"h34s-scala-runs-sbt-in-sbtroot",[115,1006,1007],{},"h34s-scala"," runs sbt in ",[115,1010,1011],{},"sbtRoot",[99,1013,1014,1016,1017,1019,1020,1022,1023,1025,1026,1029,1030,122],{},[115,1015,729],{}," has a new optional key, ",[115,1018,1011],{},": the directory of your sbt build, relative to the config file. Its default is the config file's directory. ",[115,1021,1007],{}," runs sbt there; in ",[115,1024,166],{},", it ran sbt in the application root (",[115,1027,1028],{},"--root","). The outputs stay relative to the application root. See ",[410,1031,1033],{"href":1032},"\u002Fguide\u002Fnpm-tooling#point-the-cli-at-your-sbt-build","npm tooling",[99,1035,1036,1037,1039,1040,1043,1044,1047],{},"Nothing changes when ",[115,1038,729],{}," sits next to your ",[115,1041,1042],{},"build.sbt",", the usual setup. Check your scripts if they pass ",[115,1045,1046],{},"--config"," with a file in another directory:",[377,1049,1050,1067],{},[331,1051,1052,1053,1055,1056,1059,1060,1063,1064,1066],{},"Set ",[115,1054,1011],{}," in that file to the directory of your sbt build, relative to the file. For example, ",[115,1057,1058],{},"sbtRoot: '..'"," for a config in ",[115,1061,1062],{},"config\u002Fh34s.config.mjs"," of an app whose ",[115,1065,1042],{}," is in the app root.",[331,1068,1069,1070,1073,1074,1077,1078,1080,1081,1084,1085,1087],{},"Run your ",[115,1071,1072],{},"scala:fast"," script, or ",[115,1075,1076],{},"h34s-scala dev --config \u003Cyour file>",". If the directory has no ",[115,1079,1042],{}," and no ",[115,1082,1083],{},"project\u002F"," directory, the command now stops before sbt starts, with an error that names ",[115,1086,1011],{},", the directory and the config file.",[99,1089,1090,726,1093,1096,1097,1099],{},[115,1091,1092],{},"loadConfig",[115,1094,1095],{},"@yuri4n\u002Fh34s-nuxt\u002Fbuild"," now returns a copy of the config with ",[115,1098,1011],{}," as an absolute path.",[103,1101,1103],{"id":1102},"upgrade-from-010-alpha1-to-020-alpha1","Upgrade from 0.1.0-alpha.1 to 0.2.0-alpha.1",[99,1105,1106],{},"The Kyo core refactor changes the module graph, the handler shape and the wire format. This section lists every removed or renamed API with its replacement. Work through it in order: toolchain, dependencies, handlers, clients.",[99,1108,1109,1111,1112,199,1120,1122],{},[110,1110,112],{}," The new API is ",[410,1113,1117,1119],{"href":1114,"rel":1115},"https:\u002F\u002Fgithub.com\u002Fyuri4n\u002Fh34s\u002Freleases\u002Ftag\u002Fv0.2.0-alpha.1",[1116],"nofollow",[115,1118,166],{},", which is published",[115,1121,309],{}," artifacts stay published and unchanged, so you can upgrade when you are ready.",[124,1124,1126],{"id":1125},"_1-update-the-toolchain","1. Update the toolchain",[153,1128,1129,1140],{},[156,1130,1131],{},[159,1132,1133,1135,1137],{},[162,1134],{},[162,1136,309],{},[162,1138,1139],{},"Now",[172,1141,1142,1153,1164,1175,1186,1196],{},[159,1143,1144,1147,1150],{},[177,1145,1146],{},"Scala",[177,1148,1149],{},"3.5.2 for native and ZIO modules, 3.9.0 for Kyo",[177,1151,1152],{},"3.9.0 for every module",[159,1154,1155,1158,1161],{},[177,1156,1157],{},"Build JDK",[177,1159,1160],{},"21 was enough for ZIO-only builds",[177,1162,1163],{},"25 for every build (Kyo 1.0.0-RC7 macros)",[159,1165,1166,1169,1172],{},[177,1167,1168],{},"ZIO",[177,1170,1171],{},"2.1.23",[177,1173,1174],{},"2.1.26 (pinned by kyo-zio 1.0.0-RC7)",[159,1176,1177,1180,1183],{},[177,1178,1179],{},"zio-json",[177,1181,1182],{},"as resolved",[177,1184,1185],{},"0.7.44",[159,1187,1188,1191,1194],{},[177,1189,1190],{},"Kyo",[177,1192,1193],{},"1.0.0-RC7",[177,1195,1193],{},[159,1197,1198,1201,1204],{},[177,1199,1200],{},"Scala.js, NativeConverter, h3",[177,1202,1203],{},"1.22.0, 0.9.0, 1.15.4",[177,1205,1206],{},"unchanged",[99,1208,1052,1209,1212],{},[115,1210,1211],{},"scalaVersion := \"3.9.0\""," and run sbt with JDK 25. Production still runs on Node only.",[124,1214,1216],{"id":1215},"_2-update-dependencies","2. Update dependencies",[153,1218,1219,1229],{},[156,1220,1221],{},[159,1222,1223,1226],{},[162,1224,1225],{},"Module",[162,1227,1228],{},"Change",[172,1230,1231,1244,1269,1287,1303,1317,1331,1346],{},[159,1232,1233,1238],{},[177,1234,1235],{},[115,1236,1237],{},"zio-js-ext",[177,1239,1240,1243],{},[110,1241,1242],{},"Removed."," It was an empty package. Delete the dependency",[159,1245,1246,1251],{},[177,1247,1248],{},[115,1249,1250],{},"nuxthub-ext",[177,1252,1253,113,1255,214,1258,1261,1262,1265,1266],{},[110,1254,1242],{},[115,1256,1257],{},"HubKv",[115,1259,1260],{},"NativeKvSetOptions"," are gone; storage comes from ",[115,1263,1264],{},"KHubKv.mount"," \u002F ",[115,1267,1268],{},"ZHubKv.mount",[159,1270,1271,1276],{},[177,1272,1273],{},[115,1274,1275],{},"zio-h3-schema-ext",[177,1277,1278,1280,1281,959,1284,1286],{},[110,1279,1242],{}," Use ",[115,1282,1283],{},"native-converter-zio-schema-ext",[115,1285,818],{}," (step 3)",[159,1288,1289,1294],{},[177,1290,1291],{},[115,1292,1293],{},"native-converter-kyo-schema-ext",[177,1295,1296,1299,1300],{},[110,1297,1298],{},"New."," Kyo Schema bridge: ",[115,1301,1302],{},"derives Schema, NativeSchema",[159,1304,1305,1310],{},[177,1306,1307],{},[115,1308,1309],{},"zio-h3-ext",[177,1311,1312,1313,1316],{},"Now depends on ",[115,1314,1315],{},"kyo-h3-ext"," and kyo-zio. ZIO applications get Kyo transitively",[159,1318,1319,1324],{},[177,1320,1321],{},[115,1322,1323],{},"zio-nuxthub-ext",[177,1325,1312,1326,214,1329],{},[115,1327,1328],{},"kyo-nuxthub-ext",[115,1330,1309],{},[159,1332,1333,1340],{},[177,1334,1335,447,1338],{},[115,1336,1337],{},"native-converter-zio-ext",[115,1339,1283],{},[177,1341,1342,1343],{},"Now depend on ",[115,1344,1345],{},"h3-ext",[159,1347,1348,1352],{},[177,1349,1350],{},[115,1351,1345],{},[177,1353,1354],{},"No longer exposes ScalablyTyped-generated h3 facades. The facades are internal",[99,1356,1357,1358,122],{},"A ZIO application now pulls Kyo's dependency graph, including scala-java-locales' full currency database. If you do not need currency data, exclude it as described in ",[410,1359,23],{"href":1360},"\u002Fguide\u002Fkyo#choose-locale-data-in-your-build",[124,1362,1364],{"id":1363},"_3-rewrite-handlers","3. Rewrite handlers",[99,1366,1367,1368,1371],{},"The handler is now a function from an immutable ",[115,1369,1370],{},"Request"," snapshot to the body. There is no event object in the environment, and no API changes the native response while your program runs.",[1373,1374,1190],"h4",{"id":1375},"kyo",[153,1377,1378,1386],{},[156,1379,1380],{},[159,1381,1382,1384],{},[162,1383,309],{},[162,1385,1139],{},[172,1387,1388,1404,1426,1439,1460,1474,1492,1510,1522],{},[159,1389,1390,1399],{},[177,1391,1392,1395,1396],{},[115,1393,1394],{},"KHandler.define(program)"," with a by-name ",[115,1397,1398],{},"A \u003C HandlerEffects",[177,1400,1401],{},[115,1402,1403],{},"KHandler.define(request => program)",[159,1405,1406,1411],{},[177,1407,1408],{},[115,1409,1410],{},"KHandler.define[A: NativeConverter]",[177,1412,1413,1416,1417,1420,1421,214,1423,1425],{},[115,1414,1415],{},"KHandler.define[B: ResponseBody]","; any ",[115,1418,1419],{},"NativeConverter"," value, ",[115,1422,954],{},[115,1424,182],{}," are bodies",[159,1427,1428,1435],{},[177,1429,1430,959,1432],{},[115,1431,248],{},[115,1433,1434],{},"Env[KH3Event]",[177,1436,1437],{},[115,1438,243],{},[159,1440,1441,1452],{},[177,1442,1443,447,1446,447,1449],{},[115,1444,1445],{},"KH3Event",[115,1447,1448],{},"KHandler.getEvent",[115,1450,1451],{},"rawEvent",[177,1453,1454,1456,1457,1459],{},[110,1455,1242],{}," Use the ",[115,1458,1370],{}," argument",[159,1461,1462,1470],{},[177,1463,1464,447,1467],{},[115,1465,1466],{},"KHandler.readBody[A]",[115,1468,1469],{},"KH3Event.readBody[A]",[177,1471,1472],{},[115,1473,818],{},[159,1475,1476,1484],{},[177,1477,1478,447,1481],{},[115,1479,1480],{},"KHandler.setResponseStatus(code)",[115,1482,1483],{},"KH3Event.setResponseStatus",[177,1485,1486,279,1489],{},[115,1487,1488],{},"Response.status(Status.Created)",[115,1490,1491],{},"Response.status(Status.unsafe(code))",[159,1493,1494,1499],{},[177,1495,1496],{},[115,1497,1498],{},"dev.yuri4n.exts.kyoh3.SafeError",[177,1500,1501,1502,1504,1505,214,1507],{},"Same name, now defined in ",[115,1503,1345],{}," and re-exported. It adds ",[115,1506,700],{},[115,1508,1509],{},"errors",[159,1511,1512,1517],{},[177,1513,1514],{},[115,1515,1516],{},"KHubKv(native)",[177,1518,1519],{},[115,1520,1521],{},"KHubKv.mount(base)",[159,1523,1524,1529],{},[177,1525,1526],{},[115,1527,1528],{},"CommonEvHandler",[177,1530,1531,1534],{},[115,1532,1533],{},"EventHandler"," (the old alias is deprecated)",[99,1536,1537],{},"Before and after:",[1539,1540,1545],"pre",{"className":1541,"code":1542,"language":1543,"meta":1544,"style":1544},"language-scala shiki shiki-themes github-light github-light github-dark","\u002F\u002F 0.1.0-alpha.1\nval personalizedGreeting = AppHandler.define:\n    for\n      input    \u003C- KHandler.readBody[GreetingRequest]\n      greeting \u003C- Env.use[Greetings](_.greet(input.name))\n    yield greeting\n\n\u002F\u002F Now\nval personalizedGreeting: EventHandler = AppHandler.define: request =>\n    for\n      input    \u003C- request.body.json[GreetingRequest]\n      greeting \u003C- Env.use[Greetings](_.greet(input.name))\n    yield greeting\n","scala","",[115,1546,1547,1556,1581,1587,1608,1628,1637,1644,1650,1677,1682,1696,1711],{"__ignoreMap":1544},[1548,1549,1552],"span",{"class":1550,"line":1551},"line",1,[1548,1553,1555],{"class":1554},"sCsY4","\u002F\u002F 0.1.0-alpha.1\n",[1548,1557,1559,1563,1567,1570,1574,1578],{"class":1550,"line":1558},2,[1548,1560,1562],{"class":1561},"s8jYJ","val",[1548,1564,1566],{"class":1565},"sP4rz"," personalizedGreeting",[1548,1568,1569],{"class":1561}," =",[1548,1571,1573],{"class":1572},"snPdu"," AppHandler",[1548,1575,1577],{"class":1576},"sxrX7",".define",[1548,1579,1580],{"class":1561},":\n",[1548,1582,1584],{"class":1550,"line":1583},3,[1548,1585,1586],{"class":1561},"    for\n",[1548,1588,1590,1593,1596,1599,1602,1605],{"class":1550,"line":1589},4,[1548,1591,1592],{"class":1576},"      input    ",[1548,1594,1595],{"class":1561},"\u003C-",[1548,1597,1598],{"class":1572}," KHandler",[1548,1600,1601],{"class":1576},".readBody[",[1548,1603,1604],{"class":1572},"GreetingRequest",[1548,1606,1607],{"class":1576},"]\n",[1548,1609,1611,1614,1616,1619,1622,1625],{"class":1550,"line":1610},5,[1548,1612,1613],{"class":1576},"      greeting ",[1548,1615,1595],{"class":1561},[1548,1617,1618],{"class":1572}," Env",[1548,1620,1621],{"class":1576},".use[",[1548,1623,1624],{"class":1572},"Greetings",[1548,1626,1627],{"class":1576},"](_.greet(input.name))\n",[1548,1629,1631,1634],{"class":1550,"line":1630},6,[1548,1632,1633],{"class":1561},"    yield",[1548,1635,1636],{"class":1576}," greeting\n",[1548,1638,1640],{"class":1550,"line":1639},7,[1548,1641,1643],{"emptyLinePlaceholder":1642},true,"\n",[1548,1645,1647],{"class":1550,"line":1646},8,[1548,1648,1649],{"class":1554},"\u002F\u002F Now\n",[1548,1651,1653,1655,1657,1660,1663,1665,1667,1669,1671,1674],{"class":1550,"line":1652},9,[1548,1654,1562],{"class":1561},[1548,1656,1566],{"class":1565},[1548,1658,1659],{"class":1561},":",[1548,1661,1662],{"class":1572}," EventHandler",[1548,1664,1569],{"class":1561},[1548,1666,1573],{"class":1572},[1548,1668,1577],{"class":1576},[1548,1670,1659],{"class":1561},[1548,1672,1673],{"class":1576}," request ",[1548,1675,1676],{"class":1561},"=>\n",[1548,1678,1680],{"class":1550,"line":1679},10,[1548,1681,1586],{"class":1561},[1548,1683,1685,1687,1689,1692,1694],{"class":1550,"line":1684},11,[1548,1686,1592],{"class":1576},[1548,1688,1595],{"class":1561},[1548,1690,1691],{"class":1576}," request.body.json[",[1548,1693,1604],{"class":1572},[1548,1695,1607],{"class":1576},[1548,1697,1699,1701,1703,1705,1707,1709],{"class":1550,"line":1698},12,[1548,1700,1613],{"class":1576},[1548,1702,1595],{"class":1561},[1548,1704,1618],{"class":1572},[1548,1706,1621],{"class":1576},[1548,1708,1624],{"class":1572},[1548,1710,1627],{"class":1576},[1548,1712,1714,1716],{"class":1550,"line":1713},13,[1548,1715,1633],{"class":1561},[1548,1717,1636],{"class":1576},[99,1719,1720,1721,1724,1725,1728,1729,408,1732,122],{},"Your ",[115,1722,1723],{},"AppHandler.define"," now takes ",[115,1726,1727],{},"Request => B \u003C (HandlerEffects & ...)"," and calls ",[115,1730,1731],{},"KHandler.define(options)(request => ...)",[410,1733,23],{"href":1734},"\u002Fguide\u002Fkyo#compose-services-in-your-apphandler",[1373,1736,1168],{"id":1737},"zio",[153,1739,1740,1748],{},[156,1741,1742],{},[159,1743,1744,1746],{},[162,1745,309],{},[162,1747,1139],{},[172,1749,1750,1768,1787,1817,1835,1853,1876,1894,1909,1921,1946,1964,1977,2000,2018,2036,2054,2078,2114,2126,2148],{},[159,1751,1752,1760],{},[177,1753,1754,959,1757],{},[115,1755,1756],{},"ZHandler.define(program)",[115,1758,1759],{},"ZIO[SH3Event & Scope & R, E, A]",[177,1761,1762,959,1765],{},[115,1763,1764],{},"ZHandler.define(request => program)",[115,1766,1767],{},"ZIO[HandlerEnv, ErrorResponse | Throwable, B]",[159,1769,1770,1778],{},[177,1771,1772,447,1775],{},[115,1773,1774],{},"SH3Event",[115,1776,1777],{},"ZHandler.getEvent",[177,1779,1780,1456,1782,1784,1785],{},[110,1781,1242],{},[115,1783,1370],{}," argument; ",[115,1786,264],{},[159,1788,1789,1809],{},[177,1790,1791,447,1794,447,1797,447,1800,447,1803,447,1806],{},[115,1792,1793],{},"ZHandler[R, E, A]",[115,1795,1796],{},"Handler",[115,1798,1799],{},"TaskHandler",[115,1801,1802],{},"URHandler",[115,1804,1805],{},"UHandler",[115,1807,1808],{},"RHandler",[177,1810,1811,1812,1814,1815],{},"Same names, now over ",[115,1813,525],{}," instead of ",[115,1816,1774],{},[159,1818,1819,1830],{},[177,1820,1821,447,1824,447,1827],{},[115,1822,1823],{},"ZHandler.readBody[A]",[115,1825,1826],{},"readBody[A](strict)",[115,1828,1829],{},"SH3Event.readBody",[177,1831,1832,1834],{},[115,1833,818],{},". Parsing is always strict; a non-JSON content type is a 415",[159,1836,1837,1845],{},[177,1838,1839,447,1842],{},[115,1840,1841],{},"ZHandler.getQuery",[115,1843,1844],{},"getQuery[T](using Conversion)",[177,1846,1847,447,1850],{},[115,1848,1849],{},"request.query",[115,1851,1852],{},"request.queryAll",[159,1854,1855,1863],{},[177,1856,1857,447,1860],{},[115,1858,1859],{},"ZHandler.getRouterParams",[115,1861,1862],{},"getRouterParam(name)",[177,1864,1865,447,1868,1871,1872,1875],{},[115,1866,1867],{},"request.routerParams",[115,1869,1870],{},"request.routerParam(name)",", or ",[115,1873,1874],{},"request.param(name)"," (400 when absent)",[159,1877,1878,1886],{},[177,1879,1880,447,1883],{},[115,1881,1882],{},"GetRouterParamsError",[115,1884,1885],{},"SH3Event.MissingRouterParamError",[177,1887,1888,1890,1891],{},[110,1889,1242],{}," A missing parameter is ",[115,1892,1893],{},"HttpError(400, \"Missing router parameter: \u003Cname>\")",[159,1895,1896,1901],{},[177,1897,1898],{},[115,1899,1900],{},"SH3Event.parseCookies",[177,1902,1903,447,1906],{},[115,1904,1905],{},"request.cookies",[115,1907,1908],{},"request.cookie(name)",[159,1910,1911,1916],{},[177,1912,1913],{},[115,1914,1915],{},"ZHandler.setResponseStatus(code)",[177,1917,1918],{},[115,1919,1920],{},"Response.status(...)",[159,1922,1923,1931],{},[177,1924,1925,447,1928],{},[115,1926,1927],{},"ZHandler.sendStream(stream)",[115,1929,1930],{},"SH3Event.sendStream",[177,1932,1933,1934,1936,1937,1939,1940,1942,1943],{},"Return the ",[115,1935,148],{}," as the body. Elements are strings now: ",[115,1938,338],{}," converted each element with its ",[115,1941,1419],{},", which Node cannot write. Encode values yourself, for example ",[115,1944,1945],{},"stream.map(_.toJson + \"\\n\")",[159,1947,1948,1956],{},[177,1949,1950,447,1953],{},[115,1951,1952],{},"respondWith",[115,1954,1955],{},"respondWithZIO",[177,1957,1958,1960,1961],{},[110,1959,1242],{}," Return the body; set the head with ",[115,1962,1963],{},"Response.*",[159,1965,1966,1972],{},[177,1967,1968,447,1970],{},[115,1969,442],{},[115,1971,506],{},[177,1973,1974,1976],{},[110,1975,1242],{}," Call your service directly, or use an HTTP client",[159,1978,1979,1991],{},[177,1980,1981,1984,1985,214,1988],{},[115,1982,1983],{},"mkHandler",", top-level ",[115,1986,1987],{},"defineEventHandler(h)",[115,1989,1990],{},"defineEventHandler(runtime, h)",[177,1992,1993,1995,1996,1999],{},[115,1994,549],{},". Put a ",[115,1997,1998],{},"given Runtime[Any]"," in scope for a custom runtime",[159,2001,2002,2007],{},[177,2003,2004],{},[115,2005,2006],{},"ZIOH3.Console",[177,2008,2009,2011,2012,279,2015],{},[110,2010,1242],{}," Use ZIO's ",[115,2013,2014],{},"Console",[115,2016,2017],{},"ZIO.log",[159,2019,2020,2031],{},[177,2021,2022,447,2025,447,2028],{},[115,2023,2024],{},"taskStreamToReadableStream",[115,2026,2027],{},"taskStreamToReadableStreamReader",[115,2029,2030],{},"streamconversion",[177,2032,2033,2035],{},[110,2034,1242],{}," Streams are bodies now",[159,2037,2038,2047],{},[177,2039,2040,2043,2044],{},[115,2041,2042],{},"fromNative_"," extension on ",[115,2045,2046],{},"js.Any",[177,2048,2049,2051,2052],{},[110,2050,1242],{}," Decode request bodies with ",[115,2053,818],{},[159,2055,2056,2061],{},[177,2057,2058],{},[115,2059,2060],{},"ErrorResponse(errors)",[177,2062,2063,2066,2067,2070,2071,2074,2075],{},[115,2064,2065],{},"ErrorResponse(errors, status = 400)",". A one-field pattern match needs ",[115,2068,2069],{},"_","; its ",[115,2072,2073],{},"JsonEncoder"," output now has ",[115,2076,2077],{},"status",[159,2079,2080,2094],{},[177,2081,2082,2083,959,2086,447,2089,447,2091],{},"ZIO ",[115,2084,2085],{},"SafeError",[115,2087,2088],{},"val message",[115,2090,2077],{},[115,2092,2093],{},"maybeUnderlying",[177,2095,2096,2097,498,2099,447,2102,447,2104,447,2106,526,2108,2110,2111,2113],{},"The shared ",[115,2098,2085],{},[115,2100,2101],{},"message",[115,2103,2077],{},[115,2105,700],{},[115,2107,1509],{},[115,2109,2093],{}," is gone; a ",[115,2112,2088],{}," still works",[159,2115,2116,2121],{},[177,2117,2118],{},[115,2119,2120],{},"ZHubKv(native)",[177,2122,2123],{},[115,2124,2125],{},"ZHubKv.mount(base)",[159,2127,2128,2137],{},[177,2129,2130,447,2133,2136],{},[115,2131,2132],{},"ZHandler.readBodyWithSchema[A]",[115,2134,2135],{},"InvalidBody"," (zio-h3-schema)",[177,2138,2139,2141,2142,2144,2145],{},[115,2140,1302],{}," on the model, then ",[115,2143,818],{},"; failures are ",[115,2146,2147],{},"InvalidInput",[159,2149,2150,2156],{},[177,2151,2152,2155],{},[115,2153,2154],{},"NativeSchema(schema).converter"," returned a converter that failed with a generic error",[177,2157,2158,2159,2161,2162,2165,2166,2169,2170,2173],{},"It now throws ",[115,2160,2147],{}," with entries; ",[115,2163,2164],{},"Codec"," gains ",[115,2167,2168],{},"validate","; ",[115,2171,2172],{},"derives NativeSchema"," is new",[99,2175,2176],{},"Before and after, from the demo's Notes route:",[1539,2178,2180],{"className":1541,"code":2179,"language":1543,"meta":1544,"style":1544},"\u002F\u002F 0.1.0-alpha.1\nval createNote = AppHandler.define:\n    for\n      input \u003C- ZHandler.readBodyWithSchema[CreateNote]\n      note  \u003C- ZIO.serviceWithZIO[Notes](_.create(input.text))\n      _     \u003C- ZHandler.setResponseStatus(201)\n    yield note\n\n\u002F\u002F Now\nval create: Request => ZIO[HandlerEnv & Notes, Throwable, Note] = request =>\n  for\n    input \u003C- request.body.json[CreateNote]\n    note  \u003C- ZIO.serviceWithZIO[Notes](_.create(input.text))\n    _     \u003C- Response.status(Status.Created)\n  yield note\n\nval createNote: EventHandler = AppHandler.define(create)\n",[115,2181,2182,2186,2201,2205,2223,2242,2261,2268,2272,2276,2324,2329,2342,2357,2381,2389,2394],{"__ignoreMap":1544},[1548,2183,2184],{"class":1550,"line":1551},[1548,2185,1555],{"class":1554},[1548,2187,2188,2190,2193,2195,2197,2199],{"class":1550,"line":1558},[1548,2189,1562],{"class":1561},[1548,2191,2192],{"class":1565}," createNote",[1548,2194,1569],{"class":1561},[1548,2196,1573],{"class":1572},[1548,2198,1577],{"class":1576},[1548,2200,1580],{"class":1561},[1548,2202,2203],{"class":1550,"line":1583},[1548,2204,1586],{"class":1561},[1548,2206,2207,2210,2212,2215,2218,2221],{"class":1550,"line":1589},[1548,2208,2209],{"class":1576},"      input ",[1548,2211,1595],{"class":1561},[1548,2213,2214],{"class":1572}," ZHandler",[1548,2216,2217],{"class":1576},".readBodyWithSchema[",[1548,2219,2220],{"class":1572},"CreateNote",[1548,2222,1607],{"class":1576},[1548,2224,2225,2228,2230,2233,2236,2239],{"class":1550,"line":1610},[1548,2226,2227],{"class":1576},"      note  ",[1548,2229,1595],{"class":1561},[1548,2231,2232],{"class":1572}," ZIO",[1548,2234,2235],{"class":1576},".serviceWithZIO[",[1548,2237,2238],{"class":1572},"Notes",[1548,2240,2241],{"class":1576},"](_.create(input.text))\n",[1548,2243,2244,2247,2249,2251,2254,2258],{"class":1550,"line":1630},[1548,2245,2246],{"class":1576},"      _     ",[1548,2248,1595],{"class":1561},[1548,2250,2214],{"class":1572},[1548,2252,2253],{"class":1576},".setResponseStatus(",[1548,2255,2257],{"class":2256},"sBjJW","201",[1548,2259,2260],{"class":1576},")\n",[1548,2262,2263,2265],{"class":1550,"line":1639},[1548,2264,1633],{"class":1561},[1548,2266,2267],{"class":1576}," note\n",[1548,2269,2270],{"class":1550,"line":1646},[1548,2271,1643],{"emptyLinePlaceholder":1642},[1548,2273,2274],{"class":1550,"line":1652},[1548,2275,1649],{"class":1554},[1548,2277,2278,2280,2283,2285,2288,2291,2293,2296,2298,2301,2304,2306,2309,2311,2314,2317,2320,2322],{"class":1550,"line":1679},[1548,2279,1562],{"class":1561},[1548,2281,2282],{"class":1565}," create",[1548,2284,1659],{"class":1561},[1548,2286,2287],{"class":1572}," Request",[1548,2289,2290],{"class":1561}," =>",[1548,2292,2232],{"class":1572},[1548,2294,2295],{"class":1576},"[",[1548,2297,525],{"class":1572},[1548,2299,2300],{"class":1561}," &",[1548,2302,2303],{"class":1572}," Notes",[1548,2305,447],{"class":1576},[1548,2307,2308],{"class":1572},"Throwable",[1548,2310,447],{"class":1576},[1548,2312,2313],{"class":1572},"Note",[1548,2315,2316],{"class":1576},"] ",[1548,2318,2319],{"class":1561},"=",[1548,2321,1673],{"class":1576},[1548,2323,1676],{"class":1561},[1548,2325,2326],{"class":1550,"line":1684},[1548,2327,2328],{"class":1561},"  for\n",[1548,2330,2331,2334,2336,2338,2340],{"class":1550,"line":1698},[1548,2332,2333],{"class":1576},"    input ",[1548,2335,1595],{"class":1561},[1548,2337,1691],{"class":1576},[1548,2339,2220],{"class":1572},[1548,2341,1607],{"class":1576},[1548,2343,2344,2347,2349,2351,2353,2355],{"class":1550,"line":1713},[1548,2345,2346],{"class":1576},"    note  ",[1548,2348,1595],{"class":1561},[1548,2350,2232],{"class":1572},[1548,2352,2235],{"class":1576},[1548,2354,2238],{"class":1572},[1548,2356,2241],{"class":1576},[1548,2358,2360,2363,2365,2368,2371,2374,2376,2379],{"class":1550,"line":2359},14,[1548,2361,2362],{"class":1576},"    _     ",[1548,2364,1595],{"class":1561},[1548,2366,2367],{"class":1572}," Response",[1548,2369,2370],{"class":1576},".status(",[1548,2372,2373],{"class":1572},"Status",[1548,2375,122],{"class":1576},[1548,2377,2378],{"class":1572},"Created",[1548,2380,2260],{"class":1576},[1548,2382,2384,2387],{"class":1550,"line":2383},15,[1548,2385,2386],{"class":1561},"  yield",[1548,2388,2267],{"class":1576},[1548,2390,2392],{"class":1550,"line":2391},16,[1548,2393,1643],{"emptyLinePlaceholder":1642},[1548,2395,2397,2399,2401,2403,2405,2407,2409],{"class":1550,"line":2396},17,[1548,2398,1562],{"class":1561},[1548,2400,2192],{"class":1565},[1548,2402,1659],{"class":1561},[1548,2404,1662],{"class":1572},[1548,2406,1569],{"class":1561},[1548,2408,1573],{"class":1572},[1548,2410,2411],{"class":1576},".define(create)\n",[99,2413,2414,2416,2417,2419,2420,122],{},[115,2415,2220],{}," now uses ",[115,2418,2172],{}," with its ZIO Schema in the companion. See ",[410,2421,2422],{"href":40},"schemas",[124,2424,2426],{"id":2425},"_4-update-your-clients","4. Update your clients",[99,2428,2429,2430,2432,2433,2435,2436,2440],{},"The wire format changed. Update your ",[115,2431,867],{}," code, and remove the TypeScript interfaces you wrote for these bodies: the generated declarations type ",[115,2434,371],{}," (see ",[410,2437,769,2438],{"href":20},[115,2439,371],{},"):",[153,2442,2443,2455],{},[156,2444,2445],{},[159,2446,2447,2450,2452],{},[162,2448,2449],{},"Response",[162,2451,309],{},[162,2453,2454],{},"Now (default options)",[172,2456,2457,2470,2485,2502,2522],{},[159,2458,2459,2462,2465],{},[177,2460,2461],{},"A value",[177,2463,2464],{},"The value as is",[177,2466,2467],{},[115,2468,2469],{},"{\"data\": \u003Cvalue>}",[159,2471,2472,2476,2482],{},[177,2473,2474],{},[115,2475,954],{},[177,2477,2478,2481],{},[115,2479,2480],{},"undefined"," (h3 decided the status)",[177,2483,2484],{},"204 with no body",[159,2486,2487,2490,2495],{},[177,2488,2489],{},"A stream",[177,2491,2492,2493],{},"Through ",[115,2494,338],{},[177,2496,2497,2498,2501],{},"The stream of strings as the body, as UTF-8 text; ",[115,2499,2500],{},"text\u002Fplain; charset=utf-8"," unless you set a content type",[159,2503,2504,2507,2512],{},[177,2505,2506],{},"A safe error",[177,2508,2509],{},[115,2510,2511],{},"{\"errors\": [\"message\"]}",[177,2513,2514,2517,2518,2521],{},[115,2515,2516],{},"{\"errors\": [{\"message\": \"...\"}]}",", with ",[115,2519,2520],{},"path"," for schema entries",[159,2523,2524,2527,2537],{},[177,2525,2526],{},"An internal error",[177,2528,2529,2532,2533,2536],{},[115,2530,2531],{},"{\"errors\": [\"Internal server error\"]}",", plus top-level ",[115,2534,2535],{},"debug"," in development",[177,2538,2539,2542,2543],{},[115,2540,2541],{},"{\"errors\": [{\"message\": \"Internal server error\"}]}","; in development or debug mode the entry carries ",[115,2544,2545],{},"debug.cause",[99,2547,2548,2549,864,2552,2555,2556,2558,2559,2561,2562,2565],{},"To keep the old success shape for a handler, pass ",[115,2550,2551],{},"HandlerOptions(success = SuccessEnvelope.Raw)",[115,2553,2554],{},"Raw"," string is sent as ",[115,2557,2500],{}," and any other value as JSON text with ",[115,2560,841],{},", unless you set a content type; h3 no longer guesses (it sent strings as ",[115,2563,2564],{},"text\u002Fhtml","). There is no option for the old string-array errors.",[99,2567,2568,2569,2572,2573,2576],{},"Body problems now have their own statuses: 415 for a non-JSON content type, 413 for a body above the limit (1 MiB by default), 400 for invalid JSON, and 422 for a body that does not match the converter or schema. The old schema reader answered 422 for invalid JSON and ",[115,2570,2571],{},"Request body does not match schema"," for every rejection. A plain ",[115,2574,2575],{},"readBody"," failure used to be an opaque 500.",[124,2578,2580],{"id":2579},"_5-move-configuration-and-storage-into-scala","5. Move configuration and storage into Scala",[328,2582,2583,2606,2620],{},[331,2584,2585,2586,1265,2589,2592,2593,2596,2597,214,2600,408,2603,122],{},"Read Nuxt runtime config with ",[115,2587,2588],{},"RuntimeConfig",[115,2590,2591],{},"ZRuntimeConfig"," instead of reading environment variables yourself. The demo moved from Ciris and ",[115,2594,2595],{},"MY_APP_DB_*"," to ",[115,2598,2599],{},"runtimeConfig.database",[115,2601,2602],{},"NUXT_DATABASE_*",[410,2604,2605],{"href":32},"configuration",[331,2607,2608,2609,2612,2613,279,2615,408,2617,122],{},"Replace application-side ",[115,2610,2611],{},"@JSImport(\"@nuxthub\u002Fkv\", \"kv\")"," objects with ",[115,2614,1521],{},[115,2616,2125],{},[410,2618,2619],{"href":56},"Nitro storage",[331,2621,2622,2623,279,2626,408,2629,122],{},"Replace per-request database connections with an application pool in ",[115,2624,2625],{},"Shared",[115,2627,2628],{},"ZShared",[410,2630,2631],{"href":36},"lifetimes",[124,2633,2635],{"id":2634},"_6-check-the-nuxt-module","6. Check the Nuxt module",[99,2637,2638,2639,2642,2643,2646,2647,2650,2651,2654],{},"Keep ",[115,2640,2641],{},"@yuri4n\u002Fh34s-nuxt"," in ",[115,2644,2645],{},"modules",". Its Nitro plugin is now ",[115,2648,2649],{},"runtime\u002Fh34s.mjs"," and supplies the development and debug flags, runtime config, storage and the close hook. The module registers it for you. If you registered ",[115,2652,2653],{},"runtime\u002Fdevelopment.mjs"," yourself, remove that entry; the old file still re-exports the new plugin for one release.",[99,2656,2657,2658,670,2661,2664,2665,2667,2668,122],{},"The module also declares ",[115,2659,2660],{},"runtimeConfig.h34s.debug: false",[115,2662,2663],{},"NUXT_H34S_DEBUG=true"," turns on diagnostics at runtime. Nuxt's own ",[115,2666,2535],{}," option does not turn them on. Keep debug mode off in production; see ",[410,2669,2670],{"href":60},"debugging",[99,2672,2673,2674,199,2677,2679,2680,214,2682,2684,2685,122],{},"Use the package version that matches your Scala libraries: ",[115,2675,2676],{},"@yuri4n\u002Fh34s-nuxt@0.2.0-alpha.1",[115,2678,309],{}," package lacks the new plugin records, and ",[115,2681,2588],{},[115,2683,1264],{}," then fail with ",[115,2686,2687],{},"ConfigError",[124,2689,2691],{"id":2690},"roll-back","Roll back",[99,2693,2694,2695,2697,2698,2701,2702,2704],{},"To stay on the old API, keep your dependencies at ",[115,2696,309],{},", Scala 3.5.2 for ZIO code, and ",[115,2699,2700],{},"@yuri4n\u002Fh34s-nuxt@0.1.0-alpha.1",". Both stay published. Do not mix modules from the two versions in one application: their ",[115,2703,2085],{}," types and module graphs differ.",[2706,2707,2708],"style",{},"html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s8jYJ, html code.shiki .s8jYJ{--shiki-light:#D73A49;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sP4rz, html code.shiki .sP4rz{--shiki-light:#E36209;--shiki-default:#E36209;--shiki-dark:#FFAB70}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 .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 .sBjJW, html code.shiki .sBjJW{--shiki-light:#005CC5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":1544,"searchDepth":1558,"depth":1558,"links":2710},[2711,2723],{"id":105,"depth":1558,"text":106,"children":2712},[2713,2715,2717,2718,2719,2720,2721],{"id":126,"depth":1583,"text":2714},"Send streams with Response.sendStream",{"id":425,"depth":1583,"text":2716},"Call other routes with $fetch",{"id":706,"depth":1583,"text":707},{"id":774,"depth":1583,"text":775},{"id":805,"depth":1583,"text":806},{"id":944,"depth":1583,"text":945},{"id":1004,"depth":1583,"text":2722},"h34s-scala runs sbt in sbtRoot",{"id":1102,"depth":1558,"text":1103,"children":2724},[2725,2726,2727,2728,2729,2730,2731],{"id":1125,"depth":1583,"text":1126},{"id":1215,"depth":1583,"text":1216},{"id":1363,"depth":1583,"text":1364},{"id":2425,"depth":1583,"text":2426},{"id":2579,"depth":1583,"text":2580},{"id":2634,"depth":1583,"text":2635},{"id":2690,"depth":1583,"text":2691},"Every removed or renamed API with its replacement, the new wire format, and the new toolchain.","md",null,{},{"title":90,"description":2732},"0a4WAfc5MrUVNfVPmyAoBDOpBCzY72qQDO5Fx2zMqfw",[2739,2734],{"title":86,"path":87,"stem":88,"description":2740,"children":-1},"Tested profiles with their evidence, kept apart into locally verified, CI-validated and untested combinations.",1792533383165]