@hono/zod-openapi 0.18.3 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -52,6 +52,7 @@ const UserSchema = z
52
52
  ```
53
53
 
54
54
  > [!TIP]
55
+ >
55
56
  > `UserSchema` schema will be registered as `"#/components/schemas/User"` refs in the OpenAPI document.
56
57
  > If you want to register the schema as referenced components, use `.openapi()` method.
57
58
 
@@ -114,6 +115,71 @@ You can start your app just like you would with Hono. For Cloudflare Workers and
114
115
  export default app
115
116
  ```
116
117
 
118
+ > [!IMPORTANT]
119
+ > The request must have the proper `Content-Type` to ensure the validation. For example, if you want to validate a JSON body, the request must have the `Content-Type` to `application/json` in the request. Otherwise, the value of `c.req.valid('json')` will be `{}`.
120
+ >
121
+ > ```ts
122
+ > import { createRoute, z, OpenAPIHono } from '@hono/zod-openapi'
123
+ >
124
+ > const route = createRoute({
125
+ > method: 'post',
126
+ > path: '/books',
127
+ > request: {
128
+ > body: {
129
+ > content: {
130
+ > 'application/json': {
131
+ > schema: z.object({
132
+ > title: z.string(),
133
+ > }),
134
+ > },
135
+ > },
136
+ > },
137
+ > },
138
+ > responses: {
139
+ > 200: {
140
+ > description: 'Success message',
141
+ > },
142
+ > },
143
+ > })
144
+ >
145
+ > const app = new OpenAPIHono()
146
+ >
147
+ > app.openapi(route, (c) => {
148
+ > const validatedBody = c.req.valid('json')
149
+ > return c.json(validatedBody) // validatedBody is {}
150
+ > })
151
+ >
152
+ > const res = await app.request('/books', {
153
+ > method: 'POST',
154
+ > body: JSON.stringify({ title: 'foo' }),
155
+ > // The Content-Type header is lacking.
156
+ > })
157
+ >
158
+ > const data = await res.json()
159
+ > console.log(data) // {}
160
+ > ```
161
+ >
162
+ > If you want to force validation of requests that do not have the proper `Content-Type`, set the value of `request.body.required` to `true`.
163
+ >
164
+ > ```ts
165
+ > const route = createRoute({
166
+ > method: 'post',
167
+ > path: '/books',
168
+ > request: {
169
+ > body: {
170
+ > content: {
171
+ > 'application/json': {
172
+ > schema: z.object({
173
+ > title: z.string(),
174
+ > }),
175
+ > },
176
+ > },
177
+ > required: true, // <== add
178
+ > },
179
+ > },
180
+ > })
181
+ > ```
182
+
117
183
  ### Handling Validation Errors
118
184
 
119
185
  Validation errors can be handled as follows:
@@ -241,7 +307,10 @@ You can generate OpenAPI v3.1 spec using the following methods:
241
307
 
242
308
  ```ts
243
309
  app.doc31('/docs', { openapi: '3.1.0', info: { title: 'foo', version: '1' } }) // new endpoint
244
- app.getOpenAPI31Document({ openapi: '3.1.0', info: { title: 'foo', version: '1' } }) // schema object
310
+ app.getOpenAPI31Document({
311
+ openapi: '3.1.0',
312
+ info: { title: 'foo', version: '1' },
313
+ }) // schema object
245
314
  ```
246
315
 
247
316
  ### The Registry
@@ -285,10 +354,7 @@ const route = createRoute({
285
354
  request: {
286
355
  params: ParamsSchema,
287
356
  },
288
- middleware: [
289
- prettyJSON(),
290
- cache({ cacheName: 'my-cache' })
291
- ] as const, // Use `as const` to ensure TypeScript infers the middleware's Context.
357
+ middleware: [prettyJSON(), cache({ cacheName: 'my-cache' })] as const, // Use `as const` to ensure TypeScript infers the middleware's Context.
292
358
  responses: {
293
359
  200: {
294
360
  content: {
@@ -385,6 +451,17 @@ app.doc('/doc', (c) => ({
385
451
  }))
386
452
  ```
387
453
 
454
+ ### How to exclude a specific route from OpenAPI docs
455
+
456
+ You can use `hide` property as follows:
457
+
458
+ ```ts
459
+ const route = createRoute({
460
+ // ...
461
+ hide: true,
462
+ })
463
+ ```
464
+
388
465
  ## Limitations
389
466
 
390
467
  ### Combining with `Hono`
package/dist/index.d.mts CHANGED
@@ -4,14 +4,15 @@ import { RouteConfig as RouteConfig$1, ZodMediaTypeObject, OpenAPIRegistry, ZodR
4
4
  export { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
5
5
  import { MiddlewareHandler, TypedResponse, Env, ValidationTargets, Context, Input, Handler, Schema, Hono, ToSchema } from 'hono';
6
6
  import { MergePath, MergeSchemaPath } from 'hono/types';
7
- import { RemoveBlankRecord, SimplifyDeepArray, JSONValue, JSONParsed } from 'hono/utils/types';
8
7
  import { StatusCode, InfoStatusCode, SuccessStatusCode, RedirectStatusCode, ClientErrorStatusCode, ServerErrorStatusCode } from 'hono/utils/http-status';
8
+ import { RemoveBlankRecord, SimplifyDeepArray, JSONValue, JSONParsed } from 'hono/utils/types';
9
9
  import { ZodError, ZodType, z, ZodSchema } from 'zod';
10
10
  export { z } from 'zod';
11
11
 
12
12
  type MaybePromise<T> = Promise<T> | T;
13
13
  type RouteConfig = RouteConfig$1 & {
14
14
  middleware?: MiddlewareHandler | MiddlewareHandler[];
15
+ hide?: boolean;
15
16
  };
16
17
  type RequestTypes = {
17
18
  body?: ZodRequestBody;
@@ -169,7 +170,7 @@ declare class OpenAPIHono<E extends Env = Env, S extends Schema = {}, BasePath e
169
170
  * }
170
171
  *)
171
172
  */
172
- openapi: <R extends RouteConfig, I extends Input = InputTypeBase<R, "params", "param"> & InputTypeBase<R, "query", "query"> & InputTypeBase<R, "headers", "header"> & InputTypeBase<R, "cookies", "cookie"> & InputTypeForm<R> & InputTypeJson<R>, P extends string = ConvertPathType<R["path"]>>({ middleware: routeMiddleware, ...route }: R, handler: Handler<R['middleware'] extends MiddlewareHandler[] | MiddlewareHandler ? RouteMiddlewareParams<R>['env'] & E : E, P, I, R extends {
173
+ openapi: <R extends RouteConfig, I extends Input = InputTypeBase<R, "params", "param"> & InputTypeBase<R, "query", "query"> & InputTypeBase<R, "headers", "header"> & InputTypeBase<R, "cookies", "cookie"> & InputTypeForm<R> & InputTypeJson<R>, P extends string = ConvertPathType<R["path"]>>({ middleware: routeMiddleware, hide, ...route }: R, handler: Handler<R['middleware'] extends MiddlewareHandler[] | MiddlewareHandler ? RouteMiddlewareParams<R>['env'] & E : E, P, I, R extends {
173
174
  responses: {
174
175
  [statusCode: number]: {
175
176
  content: {
package/dist/index.d.ts CHANGED
@@ -4,14 +4,15 @@ import { RouteConfig as RouteConfig$1, ZodMediaTypeObject, OpenAPIRegistry, ZodR
4
4
  export { extendZodWithOpenApi } from '@asteasolutions/zod-to-openapi';
5
5
  import { MiddlewareHandler, TypedResponse, Env, ValidationTargets, Context, Input, Handler, Schema, Hono, ToSchema } from 'hono';
6
6
  import { MergePath, MergeSchemaPath } from 'hono/types';
7
- import { RemoveBlankRecord, SimplifyDeepArray, JSONValue, JSONParsed } from 'hono/utils/types';
8
7
  import { StatusCode, InfoStatusCode, SuccessStatusCode, RedirectStatusCode, ClientErrorStatusCode, ServerErrorStatusCode } from 'hono/utils/http-status';
8
+ import { RemoveBlankRecord, SimplifyDeepArray, JSONValue, JSONParsed } from 'hono/utils/types';
9
9
  import { ZodError, ZodType, z, ZodSchema } from 'zod';
10
10
  export { z } from 'zod';
11
11
 
12
12
  type MaybePromise<T> = Promise<T> | T;
13
13
  type RouteConfig = RouteConfig$1 & {
14
14
  middleware?: MiddlewareHandler | MiddlewareHandler[];
15
+ hide?: boolean;
15
16
  };
16
17
  type RequestTypes = {
17
18
  body?: ZodRequestBody;
@@ -169,7 +170,7 @@ declare class OpenAPIHono<E extends Env = Env, S extends Schema = {}, BasePath e
169
170
  * }
170
171
  *)
171
172
  */
172
- openapi: <R extends RouteConfig, I extends Input = InputTypeBase<R, "params", "param"> & InputTypeBase<R, "query", "query"> & InputTypeBase<R, "headers", "header"> & InputTypeBase<R, "cookies", "cookie"> & InputTypeForm<R> & InputTypeJson<R>, P extends string = ConvertPathType<R["path"]>>({ middleware: routeMiddleware, ...route }: R, handler: Handler<R['middleware'] extends MiddlewareHandler[] | MiddlewareHandler ? RouteMiddlewareParams<R>['env'] & E : E, P, I, R extends {
173
+ openapi: <R extends RouteConfig, I extends Input = InputTypeBase<R, "params", "param"> & InputTypeBase<R, "query", "query"> & InputTypeBase<R, "headers", "header"> & InputTypeBase<R, "cookies", "cookie"> & InputTypeForm<R> & InputTypeJson<R>, P extends string = ConvertPathType<R["path"]>>({ middleware: routeMiddleware, hide, ...route }: R, handler: Handler<R['middleware'] extends MiddlewareHandler[] | MiddlewareHandler ? RouteMiddlewareParams<R>['env'] & E : E, P, I, R extends {
173
174
  responses: {
174
175
  [statusCode: number]: {
175
176
  content: {
package/dist/index.js CHANGED
@@ -70,8 +70,10 @@ var OpenAPIHono = class _OpenAPIHono extends import_hono.Hono {
70
70
  * }
71
71
  *)
72
72
  */
73
- openapi = ({ middleware: routeMiddleware, ...route }, handler, hook = this.defaultHook) => {
74
- this.openAPIRegistry.registerPath(route);
73
+ openapi = ({ middleware: routeMiddleware, hide, ...route }, handler, hook = this.defaultHook) => {
74
+ if (!hide) {
75
+ this.openAPIRegistry.registerPath(route);
76
+ }
75
77
  const validators = [];
76
78
  if (route.request?.query) {
77
79
  const validator = (0, import_zod_validator.zValidator)("query", route.request.query, hook);
@@ -190,12 +192,22 @@ var OpenAPIHono = class _OpenAPIHono extends import_hono.Hono {
190
192
  case "route":
191
193
  return this.openAPIRegistry.registerPath({
192
194
  ...def.route,
193
- path: (0, import_url.mergePath)(pathForOpenAPI, def.route.path)
195
+ path: (0, import_url.mergePath)(
196
+ pathForOpenAPI,
197
+ // @ts-expect-error _basePath is private
198
+ app._basePath,
199
+ def.route.path
200
+ )
194
201
  });
195
202
  case "webhook":
196
203
  return this.openAPIRegistry.registerWebhook({
197
204
  ...def.webhook,
198
- path: (0, import_url.mergePath)(pathForOpenAPI, def.webhook.path)
205
+ path: (0, import_url.mergePath)(
206
+ pathForOpenAPI,
207
+ // @ts-expect-error _basePath is private
208
+ app._basePath,
209
+ def.webhook.path
210
+ )
199
211
  });
200
212
  case "schema":
201
213
  return this.openAPIRegistry.register(def.schema._def.openapi._internal.refId, def.schema);
package/dist/index.mjs CHANGED
@@ -48,8 +48,10 @@ var OpenAPIHono = class _OpenAPIHono extends Hono {
48
48
  * }
49
49
  *)
50
50
  */
51
- openapi = ({ middleware: routeMiddleware, ...route }, handler, hook = this.defaultHook) => {
52
- this.openAPIRegistry.registerPath(route);
51
+ openapi = ({ middleware: routeMiddleware, hide, ...route }, handler, hook = this.defaultHook) => {
52
+ if (!hide) {
53
+ this.openAPIRegistry.registerPath(route);
54
+ }
53
55
  const validators = [];
54
56
  if (route.request?.query) {
55
57
  const validator = zValidator("query", route.request.query, hook);
@@ -168,12 +170,22 @@ var OpenAPIHono = class _OpenAPIHono extends Hono {
168
170
  case "route":
169
171
  return this.openAPIRegistry.registerPath({
170
172
  ...def.route,
171
- path: mergePath(pathForOpenAPI, def.route.path)
173
+ path: mergePath(
174
+ pathForOpenAPI,
175
+ // @ts-expect-error _basePath is private
176
+ app._basePath,
177
+ def.route.path
178
+ )
172
179
  });
173
180
  case "webhook":
174
181
  return this.openAPIRegistry.registerWebhook({
175
182
  ...def.webhook,
176
- path: mergePath(pathForOpenAPI, def.webhook.path)
183
+ path: mergePath(
184
+ pathForOpenAPI,
185
+ // @ts-expect-error _basePath is private
186
+ app._basePath,
187
+ def.webhook.path
188
+ )
177
189
  });
178
190
  case "schema":
179
191
  return this.openAPIRegistry.register(def.schema._def.openapi._internal.refId, def.schema);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hono/zod-openapi",
3
- "version": "0.18.3",
3
+ "version": "0.19.0",
4
4
  "description": "A wrapper class of Hono which supports OpenAPI.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",