Repository: unjs/h3
Pull request #735 (2024-04-19 15:28:57)

docs: fix zod example
<!---
☝️ PR title should follow conventional commits (https://conventionalcommits.org) 
-->

### 🔗 Linked issue

<!-- Please ensure there is an open issue and mention its number as #123 -->

### ❓ Type of change

<!-- What types of changes does your code introduce? Put an `x` in all the boxes that apply. -->

- [x] 📖 Documentation (updates to the documentation, readme, or JSdoc annotations)
- [ ] 🐞 Bug fix (a non-breaking change that fixes an issue)
- [ ] 👌 Enhancement (improving an existing functionality like performance)
- [ ] ✨ New feature (a non-breaking change that adds functionality)
- [ ] 🧹 Chore (updates to the build process or auxiliary tools and libraries)
- [ ] ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

### 📚 Description

Examples using Zod should be passing a callback to the `validated` reader functions instead of the schema object. This PR aligns the examples to be consistent with `readValidatedBody` (https://h3.unjs.io/utils/request#readvalidatedbodyevent-validate).

<!-- Describe your changes in detail -->
<!-- Why is this change required? What problem does it solve? -->
<!-- If it resolves an open issue, please link to the issue here. For example "Resolves #1337" -->

### 📝 Checklist

<!-- Put an `x` in all the boxes that apply. -->
<!-- If your change requires a documentation PR, please link it appropriately -->
<!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! -->

- [ ] I have linked an issue or discussion.
- [X] I have updated the documentation accordingly.



Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a9a9724..04caeb9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -116,7 +116,7 @@ All notable changes to this project will be documented in this file. See [standa
 
 - **release:** V1.10.0 ([ae91fc8](https://github.com/unjs/h3/commit/ae91fc8))
 - Update lockfile ([1f9393d](https://github.com/unjs/h3/commit/1f9393d))
-- Rename vitest config file to supress warn ([8345c1f](https://github.com/unjs/h3/commit/8345c1f))
+- Rename vitest config file to suppress warn ([8345c1f](https://github.com/unjs/h3/commit/8345c1f))
 - Update lockfile ([87119a1](https://github.com/unjs/h3/commit/87119a1))
 
 ### ✅ Tests
@@ -223,7 +223,7 @@ All notable changes to this project will be documented in this file. See [standa
 
 ### 🩹 Fixes
 
-- **getRequestProtocol:** Conditionaly check `connection?.encrypted` ([#532](https://github.com/unjs/h3/pull/532))
+- **getRequestProtocol:** Conditionally check `connection?.encrypted` ([#532](https://github.com/unjs/h3/pull/532))
 
 ### 🏡 Chore
 
@@ -361,7 +361,7 @@ All notable changes to this project will be documented in this file. See [standa
 ### 🚀 Enhancements
 
 - **app:** Handle bigint return types ([#474](https://github.com/unjs/h3/pull/474))
-- Preserve and make error cause accessable ([#479](https://github.com/unjs/h3/pull/479))
+- Preserve and make error cause accessible ([#479](https://github.com/unjs/h3/pull/479))
 - Platform agnostic `serveStatic` utility ([#480](https://github.com/unjs/h3/pull/480))
 - **app:** `onRequest`, `onBeforeResponse` and `onAfterResponse` global hooks ([#482](https://github.com/unjs/h3/pull/482))
 - `plain` and `web` adapters ([#483](https://github.com/unjs/h3/pull/483))
@@ -369,11 +369,11 @@ All notable changes to this project will be documented in this file. See [standa
 ### 🩹 Fixes
 
 - **app:** Handle directly `node.res.end()` returned value ([7b18fa0](https://github.com/unjs/h3/commit/7b18fa0))
-- **stream:** Improve node.js redable stream check ([cdd2680](https://github.com/unjs/h3/commit/cdd2680))
-- **proxy:** Merge overriden headers with different case ([#476](https://github.com/unjs/h3/pull/476))
+- **stream:** Improve node.js readable stream check ([cdd2680](https://github.com/unjs/h3/commit/cdd2680))
+- **proxy:** Merge overridden headers with different case ([#476](https://github.com/unjs/h3/pull/476))
 - **readbody:** Accept additional options for urlencoded header ([#437](https://github.com/unjs/h3/pull/437))
 - **app:** Throw error when trying to return function or symbol as response ([6e58103](https://github.com/unjs/h3/commit/6e58103))
-- **app:** Use default error handler if `onError` does not handles reponse ([#478](https://github.com/unjs/h3/pull/478))
+- **app:** Use default error handler if `onError` does not handles response ([#478](https://github.com/unjs/h3/pull/478))
 - **proxyRequest:** Only attempt to read body if incoming request can contain body ([a26579f](https://github.com/unjs/h3/commit/a26579f))
 - **app:** Make sure resolved val is also not undefined before calling hooks ([cfe397e](https://github.com/unjs/h3/commit/cfe397e))
 
@@ -440,7 +440,7 @@ All notable changes to this project will be documented in this file. See [standa
 - Split `set-cookie` value when handling web responses ([#445](https://github.com/unjs/h3/pull/445))
 - **defineLazyEventHandler:** Infer return type ([#442](https://github.com/unjs/h3/pull/442))
 - **proxy:** Respect `fetchOptions.method` over incoming request method ([#441](https://github.com/unjs/h3/pull/441))
-- Append `set-cookie` headers in web reponse ([#453](https://github.com/unjs/h3/pull/453))
+- Append `set-cookie` headers in web response ([#453](https://github.com/unjs/h3/pull/453))
 - **proxy:** Avoid decoding request body as utf8 ([#440](https://github.com/unjs/h3/pull/440))
 - **readMultipartFormData:** Handle utf8 encoding for `name` and `filename` ([#416](https://github.com/unjs/h3/pull/416))
 - **event:** Do not remove double slashes from query ([#462](https://github.com/unjs/h3/pull/462))
@@ -1032,7 +1032,7 @@ All notable changes to this project will be documented in this file. See [standa
 
 ### Bug Fixes
 
-- add `params` to compatiblity layer for `req` ([63dd55c](https://github.com/unjs/h3/commit/63dd55c629b6a36021c6799365c05512e4b04b6f))
+- add `params` to compatibility layer for `req` ([63dd55c](https://github.com/unjs/h3/commit/63dd55c629b6a36021c6799365c05512e4b04b6f))
 
 ### [0.5.5](https://github.com/unjs/h3/compare/v0.5.4...v0.5.5) (2022-04-04)
 
@@ -1063,7 +1063,7 @@ All notable changes to this project will be documented in this file. See [standa
 
 - add `[h3]` prefix to console error ([2f4859c](https://github.com/unjs/h3/commit/2f4859c9210e1eb79fc1681942af5a9678e2e8c0))
 - improve `writableEnded` guard ([ba5084c](https://github.com/unjs/h3/commit/ba5084c7fce225e09536003f025ff9f46f005e03))
-- make console error for thrown unkown errors ([1552219](https://github.com/unjs/h3/commit/1552219cdbd515a47ad9f6b51d4ba6f31ffea0b4))
+- make console error for thrown unknown errors ([1552219](https://github.com/unjs/h3/commit/1552219cdbd515a47ad9f6b51d4ba6f31ffea0b4))
 - skip built-in error handler if `onError` provided ([2c25aa1](https://github.com/unjs/h3/commit/2c25aa10e6d872ba87926e97f77fffcc96f4d203))
 
 ### [0.5.1](https://github.com/unjs/h3/compare/v0.5.0...v0.5.1) (2022-03-29)
@@ -1193,7 +1193,7 @@ All notable changes to this project will be documented in this file. See [standa
 
 ### Features
 
-- automatically promisify legacyMiddlware with `use` ([2805d4c](https://github.com/unjs/h3/commit/2805d4cc42d22c22c7798a41514aca5cceeb8e19)), closes [#27](https://github.com/unjs/h3/issues/27)
+- automatically promisify legacyMiddleware with `use` ([2805d4c](https://github.com/unjs/h3/commit/2805d4cc42d22c22c7798a41514aca5cceeb8e19)), closes [#27](https://github.com/unjs/h3/issues/27)
 - handle returned errors (closes [#28](https://github.com/unjs/h3/issues/28)) ([991fcff](https://github.com/unjs/h3/commit/991fcff606b659035d5a23bd4ae97d3750e730cd))
 
 ### [0.2.12](https://github.com/unjs/h3/compare/v0.2.11...v0.2.12) (2021-07-02)
@@ -1330,7 +1330,7 @@ All notable changes to this project will be documented in this file. See [standa
 
 ### Bug Fixes
 
-- don't log 404 ([541ede0](https://github.com/unjs/h3/commit/541ede03edc6526b953c8a0bb7f31f0dc5fc21d3))
+- don't log 404 ([541edge0](https://github.com/unjs/h3/commit/541ede03edc6526b953c8a0bb7f31f0dc5fc21d3))
 
 ### [0.0.7](https://github.com/unjs/h3/compare/v0.0.6...v0.0.7) (2020-11-19)
 
diff --git a/docs/1.guide/1.index.md b/docs/1.guide/1.index.md
index fac5408..6079861 100644
--- a/docs/1.guide/1.index.md
+++ b/docs/1.guide/1.index.md
@@ -74,7 +74,7 @@ Now it is time to add our first endpoint. In h3, request handlers can be defined
 defineEventHandler((event) => {});
 ```
 
-What is beautiful in h3 is that all you have to do to make a reponse, is to simply return it! Responses can be simple string, JSON objects, data buffers, streams or standard [Web Response](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response).
+What is beautiful in h3 is that all you have to do to make a response, is to simply return it! Responses can be simple string, JSON objects, data buffers, streams or standard [Web Response](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response).
 
 ```ts
 return { message: "⚡️ Tadaa!" };
diff --git a/docs/1.guide/2.app.md b/docs/1.guide/2.app.md
index 461d1d6..1094a5a 100644
--- a/docs/1.guide/2.app.md
+++ b/docs/1.guide/2.app.md
@@ -110,7 +110,7 @@ If all handlers get called and no response is returned, h3 will end the request
 
 > [!NOTE]
 > Using an empty `return` or `return undefined` make a [`404 Not Found`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/404) status response.
-> Also using `return null` will make a [`204 No Content`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204) status reponse.
+> Also using `return null` will make a [`204 No Content`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/204) status response.
 
 > [!TIP]
 > Use `return {}` or `return ""` or `return true` to make an explicit response.
diff --git a/docs/1.guide/2.event-handler.md b/docs/1.guide/2.event-handler.md
index 28650f3..b189f8b 100644
--- a/docs/1.guide/2.event-handler.md
+++ b/docs/1.guide/2.event-handler.md
@@ -102,7 +102,7 @@ app.use(
   defineEventHandler((event) => {
     throw createError({
       status: 400,
-      message: "An error occured",
+      message: "An error occurred",
     });
   }),
 );
@@ -113,7 +113,7 @@ This will end the request with `400 - Bad Request` status code and the following
 ```json
 {
   "status": 400,
-  "message": "An error occured"
+  "message": "An error occurred"
 }
 ```
 
@@ -159,7 +159,7 @@ This is useful to define some one-time logic such as configuration, class initia
 Event handlers that don't return any value act as middleware. They can be used to add side effects to your application such as logging, caching, etc or to modify the request or response.
 
 > [!TIP]
-> Middleware pattern is **not recommanded** for h3 in general. Side effects can affect global application performance and make tracing logic harder.
+> Middleware pattern is **not recommended** for h3 in general. Side effects can affect global application performance and make tracing logic harder.
 > Instead use h3 composables and object syntax hooks.
 
 Similar to normal event handlers, you can define middleware using `defineEventHandler` or `eventHandler` utilities:
diff --git a/docs/1.guide/4.event.md b/docs/1.guide/4.event.md
index 83bd455..cca683a 100644
--- a/docs/1.guide/4.event.md
+++ b/docs/1.guide/4.event.md
@@ -79,7 +79,7 @@ Access tp the normalized request [Headers](https://developer.mozilla.org/en-US/d
 ### `event.context`
 
 The context is an object that contains arbitrary information about the request.
-You can store your custom properies inside `event.context` to share across composable utils.
+You can store your custom properties inside `event.context` to share across composable utils.
 
 ### `event.handled`
 
diff --git a/docs/1.guide/6.websocket.md b/docs/1.guide/6.websocket.md
index 9e5e21d..5f9603c 100644
--- a/docs/1.guide/6.websocket.md
+++ b/docs/1.guide/6.websocket.md
@@ -9,7 +9,7 @@ icon: cib:socket-io
 H3 natively supports runtime agnostic [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) API using [CrossWS](https://crossws.unjs.io/).
 
 ::tip
-You can define WebSocket handlers in your exisiting [Event Handlers](/guide/event-handler) to define multiple websocket handlers, dynamically matched with your same route defenitions!
+You can define WebSocket handlers in your existing [Event Handlers](/guide/event-handler) to define multiple websocket handlers, dynamically matched with your same route definitions!
 ::
 
 :read-more{title="WebSocket in MDN" to="https://developer.mozilla.org/en-US/docs/Web/API/WebSocket"}
diff --git a/docs/2.utils/1.request.md b/docs/2.utils/1.request.md
index 6dca648..c3b8ae0 100644
--- a/docs/2.utils/1.request.md
+++ b/docs/2.utils/1.request.md
@@ -202,12 +202,8 @@ export default defineEventHandler((event) => {
 ```ts
 import { z } from "zod";
 export default defineEventHandler((event) => {
-  const query = getValidatedQuery(
-    event,
-    z.object({
-      key: z.string(),
-    }),
-  );
+  const objectSchema = z.object({ key: z.string() });
+  const query = getValidatedQuery(event, objectSchema.safeParse);
 });
 ```
 
@@ -234,12 +230,8 @@ export default defineEventHandler((event) => {
 ```ts
 import { z } from "zod";
 export default defineEventHandler((event) => {
-  const params = getValidatedRouterParams(
-    event,
-    z.object({
-      key: z.string(),
-    }),
-  );
+  const objectSchema = z.object({ key: z.string() });
+  const params = getValidatedRouterParams(event, objectSchema.safeParse);
 });
 ```
 
diff --git a/docs/2.utils/2.reponse.md b/docs/2.utils/2.response.md
similarity index 97%
rename from docs/2.utils/2.reponse.md
rename to docs/2.utils/2.response.md
index 75fd608..70cc375 100644
--- a/docs/2.utils/2.reponse.md
+++ b/docs/2.utils/2.response.md
@@ -152,11 +152,11 @@ export default defineEventHandler((event) => {
 
 Directly send a response to the client.
 
-**Note:** This function should be used only when you want to send a response directly without using the `h3` event. Normaly you can directly `return` a value inside event handlers.
+**Note:** This function should be used only when you want to send a response directly without using the `h3` event. Normally you can directly `return` a value inside event handlers.
 
 ### `sendIterable(event, iterable)`
 
-Iterate a source of chunks and send back each chunk in order. Supports mixing async work toghether with emitting chunks.
+Iterate a source of chunks and send back each chunk in order. Supports mixing async work together with emitting chunks.
 
 Each chunk must be a string or a buffer.
 
diff --git a/docs/3.adapters/3.plain.md b/docs/3.adapters/3.plain.md
index ae0b35b..bbc30af 100644
--- a/docs/3.adapters/3.plain.md
+++ b/docs/3.adapters/3.plain.md
@@ -6,10 +6,10 @@ icon: material-symbols-light:data-object
 
 > Run h3 servers into any unknown runtime!
 
-There might be cases where your runtime is nither Node.js or Web compatible. Using plain adapter you can have an object input/output interface.
+There might be cases where your runtime is neither Node.js or Web compatible. Using plain adapter you can have an object input/output interface.
 
 > [!NOTE]
-> This can be also be particulary useful for testing your server or running inside lambda-like environments.
+> This can be also be particularly useful for testing your server or running inside lambda-like environments.
 
 ## Usage
 
diff --git a/docs/4.examples/serve-static-assets.md b/docs/4.examples/serve-static-assets.md
index d18c78b..a5c76ac 100644
--- a/docs/4.examples/serve-static-assets.md
+++ b/docs/4.examples/serve-static-assets.md
@@ -1,6 +1,6 @@
 # Serve Static Assets
 
-> Serve static assets such as HMTL, images, CSS, JavaScript, etc.
+> Serve static assets such as HTML, images, CSS, JavaScript, etc.
 
 h3 can serve static assets such as HTML, images, CSS, JavaScript, etc.
 
diff --git a/package.json b/package.json
index 44f0259..3da84a2 100644
--- a/package.json
+++ b/package.json
@@ -35,7 +35,7 @@
     "crossws": "^0.2.4",
     "defu": "^6.1.4",
     "destr": "^2.0.3",
-    "iron-webcrypto": "^1.1.0",
+    "iron-webcrypto": "^1.1.1",
     "ohash": "^1.1.3",
     "radix3": "^1.1.2",
     "ufo": "^1.5.3",
@@ -52,7 +52,7 @@
     "automd": "^0.3.7",
     "changelogen": "^0.5.5",
     "connect": "^3.7.0",
-    "eslint": "^9.0.0",
+    "eslint": "^9.1.1",
     "eslint-config-unjs": "^0.3.0-rc.6",
     "express": "^4.19.2",
     "get-port": "^7.1.0",
@@ -66,7 +66,7 @@
     "typescript": "^5.4.5",
     "unbuild": "^2.0.0",
     "vitest": "^1.5.0",
-    "zod": "^3.22.4"
+    "zod": "^3.23.3"
   },
-  "packageManager": "pnpm@9.0.1"
+  "packageManager": "pnpm@9.0.5"
 }
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 3b33aea..bae8e15 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -21,8 +21,8 @@ importers:
         specifier: ^2.0.3
         version: 2.0.3
       iron-webcrypto:
-        specifier: ^1.1.0
-        version: 1.1.0
+        specifier: ^1.1.1
+        version: 1.1.1
       ohash:
         specifier: ^1.1.3
         version: 1.1.3
@@ -67,11 +67,11 @@ importers:
         specifier: ^3.7.0
         version: 3.7.0
       eslint:
-        specifier: ^9.0.0
-        version: 9.0.0
+        specifier: ^9.1.1
+        version: 9.1.1
       eslint-config-unjs:
         specifier: ^0.3.0-rc.6
-        version: 0.3.0-rc.6(eslint@9.0.0)(typescript@5.4.5)
+        version: 0.3.0-rc.6(eslint@9.1.1)(typescript@5.4.5)
       express:
         specifier: ^4.19.2
         version: 4.19.2
@@ -109,8 +109,8 @@ importers:
         specifier: ^1.5.0
         version: 1.5.0(@types/node@20.12.7)
       zod:
-        specifier: ^3.22.4
-        version: 3.22.4
+        specifier: ^3.23.3
+        version: 3.23.3
 
   examples:
     dependencies:
@@ -551,8 +551,12 @@ packages:
     resolution: {integrity: sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  '@humanwhocodes/config-array@0.12.3':
-    resolution: {integrity: sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g==}
+  '@eslint/js@9.1.1':
+    resolution: {integrity: sha512-5WoDz3Y19Bg2BnErkZTp0en+c/i9PvgFS7MBe1+m60HjFr0hrphlAGp4yzI7pxpt4xShln4ZyYp4neJm8hmOkQ==}
+    engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+  '@humanwhocodes/config-array@0.13.0':
+    resolution: {integrity: sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==}
     engines: {node: '>=10.10.0'}
 
   '@humanwhocodes/module-importer@1.0.1':
@@ -562,6 +566,10 @@ packages:
   '@humanwhocodes/object-schema@2.0.3':
     resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
 
+  '@humanwhocodes/retry@0.2.3':
+    resolution: {integrity: sha512-X38nUbachlb01YMlvPFojKoiXq+LzZvuSce70KPMPdeM1Rj03k4dR7lDslhbqXn3Ang4EU3+EAmwEAsbrjHW3g==}
+    engines: {node: '>=18.18'}
+
   '@istanbuljs/schema@0.1.3':
     resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==}
     engines: {node: '>=8'}
@@ -1758,8 +1766,8 @@ packages:
     resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
 
-  eslint@9.0.0:
-    resolution: {integrity: sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q==}
+  eslint@9.1.1:
+    resolution: {integrity: sha512-b4cRQ0BeZcSEzPpY2PjFY70VbO32K7BStTGtBsnIGdTSEEQzBi8hPBcGQmTG2zUvFr9uLe0TK42bw8YszuHEqg==}
     engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
     hasBin: true
 
@@ -2178,6 +2186,9 @@ packages:
   iron-webcrypto@1.1.0:
     resolution: {integrity: sha512-5vgYsCakNlaQub1orZK5QmNYhwYtcllTkZBp5sfIaCqY93Cf6l+v2rtE+E4TMbcfjxDMCdrO8wmp7+ZvhDECLA==}
 
+  iron-webcrypto@1.1.1:
+    resolution: {integrity: sha512-5xGwQUWHQSy039rFr+5q/zOmj7GP0Ypzvo34Ep+61bPIhaLduEDp/PvLGlU3awD2mzWUR0weN2vJ1mILydFPEg==}
+
   is-alphabetical@1.0.4:
     resolution: {integrity: sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg==}
 
@@ -3817,8 +3828,8 @@ packages:
     resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==}
     engines: {node: '>=12.20'}
 
-  zod@3.22.4:
-    resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}
+  zod@3.23.3:
+    resolution: {integrity: sha512-tPvq1B/2Yu/dh2uAIH2/BhUlUeLIUvAjr6dpL/75I0pCYefHgjhXk1o1Kob3kTU8C7yU1j396jFHlsVWFi9ogg==}
 
 snapshots:
 
@@ -4139,9 +4150,9 @@ snapshots:
   '@esbuild/win32-x64@0.20.2':
     optional: true
 
-  '@eslint-community/eslint-utils@4.4.0(eslint@9.0.0)':
+  '@eslint-community/eslint-utils@4.4.0(eslint@9.1.1)':
     dependencies:
-      eslint: 9.0.0
+      eslint: 9.1.1
       eslint-visitor-keys: 3.4.3
 
   '@eslint-community/regexpp@4.10.0': {}
@@ -4176,7 +4187,9 @@ snapshots:
 
   '@eslint/js@9.0.0': {}
 
-  '@humanwhocodes/config-array@0.12.3':
+  '@eslint/js@9.1.1': {}
+
+  '@humanwhocodes/config-array@0.13.0':
     dependencies:
       '@humanwhocodes/object-schema': 2.0.3
       debug: 4.3.4
@@ -4188,6 +4201,8 @@ snapshots:
 
   '@humanwhocodes/object-schema@2.0.3': {}
 
+  '@humanwhocodes/retry@0.2.3': {}
+
   '@istanbuljs/schema@0.1.3': {}
 
   '@jest/schemas@29.6.3':
@@ -4464,16 +4479,16 @@ snapshots:
 
   '@types/unist@2.0.10': {}
 
-  '@typescript-eslint/eslint-plugin@7.7.0(@typescript-eslint/parser@7.7.0(eslint@9.0.0)(typescript@5.4.5))(eslint@9.0.0)(typescript@5.4.5)':
+  '@typescript-eslint/eslint-plugin@7.7.0(@typescript-eslint/parser@7.7.0(eslint@9.1.1)(typescript@5.4.5))(eslint@9.1.1)(typescript@5.4.5)':
     dependencies:
       '@eslint-community/regexpp': 4.10.0
-      '@typescript-eslint/parser': 7.7.0(eslint@9.0.0)(typescript@5.4.5)
+      '@typescript-eslint/parser': 7.7.0(eslint@9.1.1)(typescript@5.4.5)
       '@typescript-eslint/scope-manager': 7.7.0
-      '@typescript-eslint/type-utils': 7.7.0(eslint@9.0.0)(typescript@5.4.5)
-      '@typescript-eslint/utils': 7.7.0(eslint@9.0.0)(typescript@5.4.5)
+      '@typescript-eslint/type-utils': 7.7.0(eslint@9.1.1)(typescript@5.4.5)
+      '@typescript-eslint/utils': 7.7.0(eslint@9.1.1)(typescript@5.4.5)
       '@typescript-eslint/visitor-keys': 7.7.0
       debug: 4.3.4
-      eslint: 9.0.0
+      eslint: 9.1.1
       graphemer: 1.4.0
       ignore: 5.3.1
       natural-compare: 1.4.0
@@ -4484,14 +4499,14 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/parser@7.7.0(eslint@9.0.0)(typescript@5.4.5)':
+  '@typescript-eslint/parser@7.7.0(eslint@9.1.1)(typescript@5.4.5)':
     dependencies:
       '@typescript-eslint/scope-manager': 7.7.0
       '@typescript-eslint/types': 7.7.0
       '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.4.5)
       '@typescript-eslint/visitor-keys': 7.7.0
       debug: 4.3.4
-      eslint: 9.0.0
+      eslint: 9.1.1
     optionalDependencies:
       typescript: 5.4.5
     transitivePeerDependencies:
@@ -4502,12 +4517,12 @@ snapshots:
       '@typescript-eslint/types': 7.7.0
       '@typescript-eslint/visitor-keys': 7.7.0
 
-  '@typescript-eslint/type-utils@7.7.0(eslint@9.0.0)(typescript@5.4.5)':
+  '@typescript-eslint/type-utils@7.7.0(eslint@9.1.1)(typescript@5.4.5)':
     dependencies:
       '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.4.5)
-      '@typescript-eslint/utils': 7.7.0(eslint@9.0.0)(typescript@5.4.5)
+      '@typescript-eslint/utils': 7.7.0(eslint@9.1.1)(typescript@5.4.5)
       debug: 4.3.4
-      eslint: 9.0.0
+      eslint: 9.1.1
       ts-api-utils: 1.3.0(typescript@5.4.5)
     optionalDependencies:
       typescript: 5.4.5
@@ -4531,15 +4546,15 @@ snapshots:
     transitivePeerDependencies:
       - supports-color
 
-  '@typescript-eslint/utils@7.7.0(eslint@9.0.0)(typescript@5.4.5)':
+  '@typescript-eslint/utils@7.7.0(eslint@9.1.1)(typescript@5.4.5)':
     dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0)
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.1)
       '@types/json-schema': 7.0.15
       '@types/semver': 7.5.8
       '@typescript-eslint/scope-manager': 7.7.0
       '@typescript-eslint/types': 7.7.0
       '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.4.5)
-      eslint: 9.0.0
+      eslint: 9.1.1
       semver: 7.6.0
     transitivePeerDependencies:
       - supports-color
@@ -5608,34 +5623,34 @@ snapshots:
 
   escape-string-regexp@4.0.0: {}
 
-  eslint-config-unjs@0.3.0-rc.6(eslint@9.0.0)(typescript@5.4.5):
+  eslint-config-unjs@0.3.0-rc.6(eslint@9.1.1)(typescript@5.4.5):
     dependencies:
       '@eslint/js': 9.0.0
-      eslint: 9.0.0
-      eslint-plugin-markdown: 4.0.1(eslint@9.0.0)
-      eslint-plugin-unicorn: 52.0.0(eslint@9.0.0)
+      eslint: 9.1.1
+      eslint-plugin-markdown: 4.0.1(eslint@9.1.1)
+      eslint-plugin-unicorn: 52.0.0(eslint@9.1.1)
       globals: 15.0.0
       typescript: 5.4.5
-      typescript-eslint: 7.7.0(eslint@9.0.0)(typescript@5.4.5)
+      typescript-eslint: 7.7.0(eslint@9.1.1)(typescript@5.4.5)
     transitivePeerDependencies:
       - supports-color
 
-  eslint-plugin-markdown@4.0.1(eslint@9.0.0):
+  eslint-plugin-markdown@4.0.1(eslint@9.1.1):
     dependencies:
-      eslint: 9.0.0
+      eslint: 9.1.1
       mdast-util-from-markdown: 0.8.5
     transitivePeerDependencies:
       - supports-color
 
-  eslint-plugin-unicorn@52.0.0(eslint@9.0.0):
+  eslint-plugin-unicorn@52.0.0(eslint@9.1.1):
     dependencies:
       '@babel/helper-validator-identifier': 7.22.20
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0)
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.1)
       '@eslint/eslintrc': 2.1.4
       ci-info: 4.0.0
       clean-regexp: 1.0.0
       core-js-compat: 3.37.0
-      eslint: 9.0.0
+      eslint: 9.1.1
       esquery: 1.5.0
       indent-string: 4.0.0
       is-builtin-module: 3.2.1
@@ -5658,14 +5673,15 @@ snapshots:
 
   eslint-visitor-keys@4.0.0: {}
 
-  eslint@9.0.0:
+  eslint@9.1.1:
     dependencies:
-      '@eslint-community/eslint-utils': 4.4.0(eslint@9.0.0)
+      '@eslint-community/eslint-utils': 4.4.0(eslint@9.1.1)
       '@eslint-community/regexpp': 4.10.0
       '@eslint/eslintrc': 3.0.2
-      '@eslint/js': 9.0.0
-      '@humanwhocodes/config-array': 0.12.3
+      '@eslint/js': 9.1.1
+      '@humanwhocodes/config-array': 0.13.0
       '@humanwhocodes/module-importer': 1.0.1
+      '@humanwhocodes/retry': 0.2.3
       '@nodelib/fs.walk': 1.2.8
       ajv: 6.12.6
       chalk: 4.1.2
@@ -5681,7 +5697,6 @@ snapshots:
       file-entry-cache: 8.0.0
       find-up: 5.0.0
       glob-parent: 6.0.2
-      graphemer: 1.4.0
       ignore: 5.3.1
       imurmurhash: 0.1.4
       is-glob: 4.0.3
@@ -6201,6 +6216,8 @@ snapshots:
 
   iron-webcrypto@1.1.0: {}
 
+  iron-webcrypto@1.1.1: {}
+
   is-alphabetical@1.0.4: {}
 
   is-alphanumerical@1.0.4:
@@ -7614,12 +7631,12 @@ snapshots:
 
   typedarray@0.0.6: {}
 
-  typescript-eslint@7.7.0(eslint@9.0.0)(typescript@5.4.5):
+  typescript-eslint@7.7.0(eslint@9.1.1)(typescript@5.4.5):
     dependencies:
-      '@typescript-eslint/eslint-plugin': 7.7.0(@typescript-eslint/parser@7.7.0(eslint@9.0.0)(typescript@5.4.5))(eslint@9.0.0)(typescript@5.4.5)
-      '@typescript-eslint/parser': 7.7.0(eslint@9.0.0)(typescript@5.4.5)
-      '@typescript-eslint/utils': 7.7.0(eslint@9.0.0)(typescript@5.4.5)
-      eslint: 9.0.0
+      '@typescript-eslint/eslint-plugin': 7.7.0(@typescript-eslint/parser@7.7.0(eslint@9.1.1)(typescript@5.4.5))(eslint@9.1.1)(typescript@5.4.5)
+      '@typescript-eslint/parser': 7.7.0(eslint@9.1.1)(typescript@5.4.5)
+      '@typescript-eslint/utils': 7.7.0(eslint@9.1.1)(typescript@5.4.5)
+      eslint: 9.1.1
     optionalDependencies:
       typescript: 5.4.5
     transitivePeerDependencies:
@@ -7853,4 +7870,4 @@ snapshots:
 
   yocto-queue@1.0.0: {}
 
-  zod@3.22.4: {}
+  zod@3.23.3: {}
diff --git a/src/app.ts b/src/app.ts
index 6bd5ad2..2a8d6fe 100644
--- a/src/app.ts
+++ b/src/app.ts
@@ -136,7 +136,7 @@ export function createAppEventHandler(stack: Stack, options: AppOptions) {
   const spacing = options.debug ? 2 : undefined;
 
   return eventHandler(async (event) => {
-    // Keep original incoming url accessable
+    // Keep original incoming url accessible
     event.node.req.originalUrl =
       event.node.req.originalUrl || event.node.req.url || "/";
 
diff --git a/src/utils/cache.ts b/src/utils/cache.ts
index a33baa1..5039fae 100644
--- a/src/utils/cache.ts
+++ b/src/utils/cache.ts
@@ -10,7 +10,7 @@ export interface CacheConditions {
 /**
  * Check request caching headers (`If-Modified-Since`) and add caching headers (Last-Modified, Cache-Control)
  * Note: `public` cache control will be added by default
- * @returns `true` when cache headers are matching. When `true` is returned, no reponse should be sent anymore
+ * @returns `true` when cache headers are matching. When `true` is returned, no response should be sent anymore
  */
 export function handleCacheHeaders(
   event: H3Event,
diff --git a/src/utils/internal/iteratable.ts b/src/utils/internal/iterable.ts
similarity index 100%
rename from src/utils/internal/iteratable.ts
rename to src/utils/internal/iterable.ts
diff --git a/src/utils/response.ts b/src/utils/response.ts
index d945460..023820e 100644
--- a/src/utils/response.ts
+++ b/src/utils/response.ts
@@ -12,7 +12,7 @@ import {
   coerceIterable,
   IterationSource,
   IteratorSerializer,
-} from "./internal/iteratable";
+} from "./internal/iterable";
 
 const defer =
   typeof setImmediate === "undefined" ? (fn: () => any) => fn() : setImmediate;
@@ -21,7 +21,7 @@ const defer =
  * Directly send a response to the client.
  *
  * **Note:** This function should be used only when you want to send a response directly without using the `h3` event.
- * Normaly you can directly `return` a value inside event handlers.
+ * Normally you can directly `return` a value inside event handlers.
  */
 export function send(event: H3Event, data?: any, type?: string): Promise<void> {
   if (type) {
@@ -545,7 +545,7 @@ export function sendWebResponse(
 
 /**
  * Iterate a source of chunks and send back each chunk in order.
- * Supports mixing async work toghether with emitting chunks.
+ * Supports mixing async work together with emitting chunks.
  *
  * Each chunk must be a string or a buffer.
  *


Test patch:
diff --git a/test/iterable.test.ts b/test/iterable.test.ts
new file mode 100644
index 0000000..b3d998a
--- /dev/null
+++ b/test/iterable.test.ts
@@ -0,0 +1,154 @@
+import { ReadableStream } from "node:stream/web";
+import supertest, { SuperTest, Test } from "supertest";
+import { describe, it, expect, beforeEach, vi } from "vitest";
+import {
+  createApp,
+  App,
+  toNodeListener,
+  eventHandler,
+  sendIterable,
+} from "../src";
+import { serializeIterableValue } from "../src/utils/internal/iterable";
+
+describe("iterable", () => {
+  let app: App;
+  let request: SuperTest<Test>;
+
+  beforeEach(() => {
+    app = createApp({ debug: false });
+    request = supertest(toNodeListener(app));
+  });
+
+  describe("serializeIterableValue", () => {
+    const exampleDate: Date = new Date(Date.UTC(2015, 6, 21, 3, 24, 54, 888));
+    it.each([
+      { value: "Hello, world!", output: "Hello, world!" },
+      { value: 123, output: "123" },
+      { value: 1n, output: "1" },
+      { value: true, output: "true" },
+      { value: false, output: "false" },
+      { value: undefined, output: undefined },
+      { value: null, output: "null" },
+      { value: exampleDate, output: JSON.stringify(exampleDate) },
+      { value: { field: 1 }, output: '{"field":1}' },
+      { value: [1, 2, 3], output: "[1,2,3]" },
+      { value: () => {}, output: undefined },
+      {
+        value: Buffer.from("Hello, world!"),
+        output: Buffer.from("Hello, world!"),
+      },
+      { value: Uint8Array.from([1, 2, 3]), output: Uint8Array.from([1, 2, 3]) },
+    ])("$value => $output", ({ value, output }) => {
+      const serialized = serializeIterableValue(value);
+      expect(serialized).toStrictEqual(output);
+    });
+  });
+
+  describe("sendIterable", () => {
+    it("sends empty body for an empty iterator", async () => {
+      app.use(eventHandler((event) => sendIterable(event, [])));
+      const result = await request.get("/");
+      expect(result.header["content-length"]).toBe("0");
+      expect(result.text).toBe("");
+    });
+
+    it("concatenates iterated values", async () => {
+      app.use(eventHandler((event) => sendIterable(event, ["a", "b", "c"])));
+      const result = await request.get("/");
+      expect(result.text).toBe("abc");
+    });
+
+    describe("iterable support", () => {
+      it.each([
+        { type: "Array", iterable: ["the-value"] },
+        { type: "Set", iterable: new Set(["the-value"]) },
+        {
+          type: "Map.keys()",
+          iterable: new Map([["the-value", "unused"]]).keys(),
+        },
+        {
+          type: "Map.values()",
+          iterable: new Map([["unused", "the-value"]]).values(),
+        },
+        {
+          type: "Iterator object",
+          iterable: { next: () => ({ value: "the-value", done: true }) },
+        },
+        {
+          type: "AsyncIterator object",
+          iterable: {
+            next: () => Promise.resolve({ value: "the-value", done: true }),
+          },
+        },
+        {
+          type: "Generator (yield)",
+          iterable: (function* () {
+            yield "the-value";
+          })(),
+        },
+        {
+          type: "Generator (return)",
+          // eslint-disable-next-line require-yield
+          iterable: (function* () {
+            return "the-value";
+          })(),
+        },
+        {
+          type: "Generator (yield*)",
+          iterable: (function* () {
+            // prettier-ignore
+            yield * ["the-value"];
+          })(),
+        },
+        {
+          type: "AsyncGenerator",
+          iterable: (async function* () {
+            await Promise.resolve();
+            yield "the-value";
+          })(),
+        },
+        {
+          type: "ReadableStream (push-mode)",
+          iterable: new ReadableStream({
+            start(controller) {
+              controller.enqueue("the-value");
+              controller.close();
+            },
+          }),
+        },
+        {
+          type: "ReadableStream (pull-mode)",
+          iterable: new ReadableStream({
+            pull(controller) {
+              controller.enqueue("the-value");
+              controller.close();
+            },
+          }),
+        },
+      ])("$type", async ({ iterable }) => {
+        app.use(eventHandler((event) => sendIterable(event, iterable)));
+        const response = await request.get("/");
+        expect(response.text).toBe("the-value");
+      });
+    });
+
+    describe("serializer argument", () => {
+      it("is called for every value", async () => {
+        const iterable = [1, "2", { field: 3 }, null];
+        const serializer = vi.fn(() => "x");
+
+        app.use(
+          eventHandler((event) =>
+            sendIterable(event, iterable, { serializer }),
+          ),
+        );
+        const response = await request.get("/");
+        expect(response.text).toBe("x".repeat(iterable.length));
+        expect(serializer).toBeCalledTimes(4);
+        for (const [i, obj] of iterable.entries()) {
+          expect.soft(serializer).toHaveBeenNthCalledWith(i + 1, obj);
+        }
+      });
+    });
+  });
+});
diff --git a/test/iteratable.test.ts b/test/iteratable.test.ts
index 03d2d7c..68a5b3d 100644
--- a/test/iteratable.test.ts
+++ b/test/iteratable.test.ts
@@ -8,7 +8,7 @@ import {
   eventHandler,
   sendIterable,
 } from "../src";
-import { serializeIterableValue } from "../src/utils/internal/iteratable";
+import { serializeIterableValue } from "../src/utils/internal/iterable";
 
 describe("iteratable", () => {
   let app: App;
diff --git a/test/proxy.test.ts b/test/proxy.test.ts
index d5872fd..82c1c39 100644
--- a/test/proxy.test.ts
+++ b/test/proxy.test.ts
@@ -90,9 +90,9 @@ describe("", () => {
         eventHandler((event) => {
           return proxyRequest(event, url + "/debug", {
             fetch,
-            headers: { "x-custom1": "overriden" },
+            headers: { "x-custom1": "overridden" },
             fetchOptions: {
-              headers: { "x-custom2": "overriden" },
+              headers: { "x-custom2": "overridden" },
             },
           });
         }),
@@ -112,8 +112,8 @@ describe("", () => {
       const { headers, ...data } = result;
       expect(headers["content-type"]).toEqual("text/custom");
 
-      expect(headers["x-custom1"]).toEqual("overriden");
-      expect(headers["x-custom2"]).toEqual("overriden");
+      expect(headers["x-custom1"]).toEqual("overridden");
+      expect(headers["x-custom2"]).toEqual("overridden");
       expect(headers["x-custom3"]).toEqual("user");
 
       expect(data).toMatchInlineSnapshot(`
diff --git a/test/resolve.test.ts b/test/resolve.test.ts
index 50e4a4d..8340bd1 100644
--- a/test/resolve.test.ts
+++ b/test/resolve.test.ts
@@ -16,7 +16,7 @@ describe("Event handler resolver", () => {
   const router = createRouter();
   app.use(router);
 
-  // Middlware
+  // Middleware
   app.use(testHandlers[0]);
   app.use("/", testHandlers[1]);
 
diff --git a/test/utils.test.ts b/test/utils.test.ts
index f4b719b..c55e6a1 100644
--- a/test/utils.test.ts
+++ b/test/utils.test.ts
@@ -16,7 +16,7 @@ import {
   getRequestFingerprint,
   sendIterable,
 } from "../src";
-import { serializeIterableValue } from "../src/utils/internal/iteratable";
+import { serializeIterableValue } from "../src/utils/internal/iterable";
 
 describe("", () => {
   let app: App;