feat(zod-openapi): support "status code" (#519)
* feat(zod-openapi): support "status code" * add changeset and tweak * fixed lock filepull/520/head
parent
fb81f4ea4a
commit
b03484ba05
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
'@hono/zod-openapi': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat(zod-openapi): support "status code"
|
Binary file not shown.
|
@ -51,8 +51,7 @@ const UserSchema = z
|
||||||
.openapi('User')
|
.openapi('User')
|
||||||
```
|
```
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP] > `UserSchema` schema will be registered as `"#/components/schemas/User"` refs in the OpenAPI document.
|
||||||
> `UserSchema` schema will be registered as `"#/components/schemas/User"` refs in the OpenAPI document.
|
|
||||||
> If you want to register the schema as referenced components, use `.openapi()` method.
|
> If you want to register the schema as referenced components, use `.openapi()` method.
|
||||||
|
|
||||||
Next, create a route:
|
Next, create a route:
|
||||||
|
@ -88,11 +87,14 @@ const app = new OpenAPIHono()
|
||||||
|
|
||||||
app.openapi(route, (c) => {
|
app.openapi(route, (c) => {
|
||||||
const { id } = c.req.valid('param')
|
const { id } = c.req.valid('param')
|
||||||
return c.json({
|
return c.json(
|
||||||
id,
|
{
|
||||||
age: 20,
|
id,
|
||||||
name: 'Ultra-man',
|
age: 20,
|
||||||
})
|
name: 'Ultra-man',
|
||||||
|
},
|
||||||
|
200 // You should specify the status code even if it is 200.
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// The OpenAPI documentation will be available at /doc
|
// The OpenAPI documentation will be available at /doc
|
||||||
|
@ -157,11 +159,14 @@ app.openapi(
|
||||||
route,
|
route,
|
||||||
(c) => {
|
(c) => {
|
||||||
const { id } = c.req.valid('param')
|
const { id } = c.req.valid('param')
|
||||||
return c.json({
|
return c.json(
|
||||||
id,
|
{
|
||||||
age: 20,
|
id,
|
||||||
name: 'Ultra-man',
|
age: 20,
|
||||||
})
|
name: 'Ultra-man',
|
||||||
|
},
|
||||||
|
200
|
||||||
|
)
|
||||||
},
|
},
|
||||||
// Hook
|
// Hook
|
||||||
(result, c) => {
|
(result, c) => {
|
||||||
|
@ -213,7 +218,7 @@ app.openapi(
|
||||||
createBookRoute,
|
createBookRoute,
|
||||||
(c) => {
|
(c) => {
|
||||||
const { title } = c.req.valid('json')
|
const { title } = c.req.valid('json')
|
||||||
return c.json({ title })
|
return c.json({ title }, 200)
|
||||||
},
|
},
|
||||||
(result, c) => {
|
(result, c) => {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
@ -234,8 +239,8 @@ app.openapi(
|
||||||
You can generate OpenAPI v3.1 spec using the following methods:
|
You can generate OpenAPI v3.1 spec using the following methods:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
app.doc31('/docs', {openapi: '3.1.0'}) // new endpoint
|
app.doc31('/docs', { openapi: '3.1.0' }) // new endpoint
|
||||||
app.getOpenAPI31Document({openapi: '3.1.0'}) // raw json
|
app.getOpenAPI31Document({ openapi: '3.1.0' }) // raw json
|
||||||
```
|
```
|
||||||
|
|
||||||
### The Registry
|
### The Registry
|
||||||
|
@ -279,10 +284,7 @@ const route = createRoute({
|
||||||
request: {
|
request: {
|
||||||
params: ParamsSchema,
|
params: ParamsSchema,
|
||||||
},
|
},
|
||||||
middleware: [
|
middleware: [prettyJSON(), cache({ cacheName: 'my-cache' })],
|
||||||
prettyJSON(),
|
|
||||||
cache({ cacheName: 'my-cache' })
|
|
||||||
],
|
|
||||||
responses: {
|
responses: {
|
||||||
200: {
|
200: {
|
||||||
content: {
|
content: {
|
||||||
|
@ -305,10 +307,13 @@ import { hc } from 'hono/client'
|
||||||
|
|
||||||
const appRoutes = app.openapi(route, (c) => {
|
const appRoutes = app.openapi(route, (c) => {
|
||||||
const data = c.req.valid('json')
|
const data = c.req.valid('json')
|
||||||
return c.json({
|
return c.json(
|
||||||
id: data.id,
|
{
|
||||||
message: 'Success',
|
id: data.id,
|
||||||
})
|
message: 'Success',
|
||||||
|
},
|
||||||
|
200
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const client = hc<typeof appRoutes>('http://localhost:8787/')
|
const client = hc<typeof appRoutes>('http://localhost:8787/')
|
||||||
|
@ -337,9 +342,9 @@ eg. Bearer Auth
|
||||||
Register the security scheme:
|
Register the security scheme:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
app.openAPIRegistry.registerComponent("securitySchemes", "Bearer", {
|
app.openAPIRegistry.registerComponent('securitySchemes', 'Bearer', {
|
||||||
type: "http",
|
type: 'http',
|
||||||
scheme: "bearer",
|
scheme: 'bearer',
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -361,7 +366,7 @@ const route = createRoute({
|
||||||
You can access the context in `app.doc` as follows:
|
You can access the context in `app.doc` as follows:
|
||||||
|
|
||||||
```ts
|
```ts
|
||||||
app.doc('/doc', c => ({
|
app.doc('/doc', (c) => ({
|
||||||
openapi: '3.0.0',
|
openapi: '3.0.0',
|
||||||
info: {
|
info: {
|
||||||
version: '1.0.0',
|
version: '1.0.0',
|
||||||
|
|
|
@ -37,12 +37,12 @@
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/honojs/middleware",
|
"homepage": "https://github.com/honojs/middleware",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"hono": ">=3.11.3",
|
"hono": ">=4.3.6",
|
||||||
"zod": "3.*"
|
"zod": "3.*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cloudflare/workers-types": "^4.20240117.0",
|
"@cloudflare/workers-types": "^4.20240117.0",
|
||||||
"hono": "^4.2.2",
|
"hono": "^4.3.6",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"openapi3-ts": "^4.1.2",
|
"openapi3-ts": "^4.1.2",
|
||||||
"tsup": "^8.0.1",
|
"tsup": "^8.0.1",
|
||||||
|
|
|
@ -27,7 +27,8 @@ import type {
|
||||||
TypedResponse,
|
TypedResponse,
|
||||||
} from 'hono'
|
} from 'hono'
|
||||||
import type { MergePath, MergeSchemaPath } from 'hono/types'
|
import type { MergePath, MergeSchemaPath } from 'hono/types'
|
||||||
import type { RemoveBlankRecord } from 'hono/utils/types'
|
import { StatusCode } from 'hono/utils/http-status'
|
||||||
|
import type { Prettify, RemoveBlankRecord } from 'hono/utils/types'
|
||||||
import { mergePath } from 'hono/utils/url'
|
import { mergePath } from 'hono/utils/url'
|
||||||
import type { AnyZodObject, ZodSchema, ZodError } from 'zod'
|
import type { AnyZodObject, ZodSchema, ZodError } from 'zod'
|
||||||
import { z, ZodType } from 'zod'
|
import { z, ZodType } from 'zod'
|
||||||
|
@ -132,19 +133,23 @@ type InputTypeQuery<R extends RouteConfig> = InputTypeBase<R, 'query', 'query'>
|
||||||
type InputTypeHeader<R extends RouteConfig> = InputTypeBase<R, 'headers', 'header'>
|
type InputTypeHeader<R extends RouteConfig> = InputTypeBase<R, 'headers', 'header'>
|
||||||
type InputTypeCookie<R extends RouteConfig> = InputTypeBase<R, 'cookies', 'cookie'>
|
type InputTypeCookie<R extends RouteConfig> = InputTypeBase<R, 'cookies', 'cookie'>
|
||||||
|
|
||||||
type OutputType<R extends RouteConfig> = R['responses'] extends Record<infer _, infer C>
|
type ExtractContent<T> = T extends {
|
||||||
? C extends ResponseConfig
|
[K in keyof T]: infer A
|
||||||
? C['content'] extends ZodContentObject
|
}
|
||||||
? IsJson<keyof C['content']> extends never
|
? A extends Record<'schema', ZodSchema>
|
||||||
? {}
|
? z.infer<A['schema']>
|
||||||
: C['content'][keyof C['content']] extends Record<'schema', ZodSchema>
|
: never
|
||||||
? z.infer<C['content'][keyof C['content']]['schema']>
|
: never
|
||||||
: {}
|
|
||||||
: {}
|
|
||||||
: {}
|
|
||||||
: {}
|
|
||||||
|
|
||||||
export type Hook<T, E extends Env, P extends string, O> = (
|
export type RouteConfigToTypedResponse<R extends RouteConfig> = {
|
||||||
|
[Status in keyof R['responses'] & StatusCode]: IsJson<
|
||||||
|
keyof R['responses'][Status]['content']
|
||||||
|
> extends never
|
||||||
|
? TypedResponse<{}, Status, string>
|
||||||
|
: TypedResponse<ExtractContent<R['responses'][Status]['content']>, Status, 'json'>
|
||||||
|
}[keyof R['responses'] & StatusCode]
|
||||||
|
|
||||||
|
export type Hook<T, E extends Env, P extends string, R> = (
|
||||||
result:
|
result:
|
||||||
| {
|
| {
|
||||||
success: true
|
success: true
|
||||||
|
@ -155,25 +160,12 @@ export type Hook<T, E extends Env, P extends string, O> = (
|
||||||
error: ZodError
|
error: ZodError
|
||||||
},
|
},
|
||||||
c: Context<E, P>
|
c: Context<E, P>
|
||||||
) =>
|
) => R
|
||||||
| TypedResponse<O>
|
|
||||||
| Promise<TypedResponse<T>>
|
|
||||||
| Response
|
|
||||||
| Promise<Response>
|
|
||||||
| void
|
|
||||||
| Promise<void>
|
|
||||||
|
|
||||||
type ConvertPathType<T extends string> = T extends `${infer Start}/{${infer Param}}${infer Rest}`
|
type ConvertPathType<T extends string> = T extends `${infer Start}/{${infer Param}}${infer Rest}`
|
||||||
? `${Start}/:${Param}${ConvertPathType<Rest>}`
|
? `${Start}/:${Param}${ConvertPathType<Rest>}`
|
||||||
: T
|
: T
|
||||||
|
|
||||||
type HandlerTypedResponse<O> = TypedResponse<O> | Promise<TypedResponse<O>>
|
|
||||||
type HandlerAllResponse<O> =
|
|
||||||
| Response
|
|
||||||
| Promise<Response>
|
|
||||||
| TypedResponse<O>
|
|
||||||
| Promise<TypedResponse<O>>
|
|
||||||
|
|
||||||
export type OpenAPIHonoOptions<E extends Env> = {
|
export type OpenAPIHonoOptions<E extends Env> = {
|
||||||
defaultHook?: Hook<any, E, any, any>
|
defaultHook?: Hook<any, E, any, any>
|
||||||
}
|
}
|
||||||
|
@ -196,15 +188,15 @@ export type RouteHandler<
|
||||||
// If response type is defined, only TypedResponse is allowed.
|
// If response type is defined, only TypedResponse is allowed.
|
||||||
R extends {
|
R extends {
|
||||||
responses: {
|
responses: {
|
||||||
[statusCode: string]: {
|
[statusCode: number]: {
|
||||||
content: {
|
content: {
|
||||||
[mediaType: string]: ZodMediaTypeObject
|
[mediaType: string]: ZodMediaTypeObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
? HandlerTypedResponse<OutputType<R>>
|
? RouteConfigToTypedResponse<R>
|
||||||
: HandlerAllResponse<OutputType<R>>
|
: RouteConfigToTypedResponse<R> | Response | Promise<Response>
|
||||||
>
|
>
|
||||||
|
|
||||||
export type RouteHook<
|
export type RouteHook<
|
||||||
|
@ -217,7 +209,12 @@ export type RouteHook<
|
||||||
InputTypeForm<R> &
|
InputTypeForm<R> &
|
||||||
InputTypeJson<R>,
|
InputTypeJson<R>,
|
||||||
P extends string = ConvertPathType<R['path']>
|
P extends string = ConvertPathType<R['path']>
|
||||||
> = Hook<I, E, P, OutputType<R>>
|
> = Hook<
|
||||||
|
I,
|
||||||
|
E,
|
||||||
|
P,
|
||||||
|
RouteConfigToTypedResponse<R> | Response | Promise<Response> | void | Promise<void>
|
||||||
|
>
|
||||||
|
|
||||||
export type OpenAPIObjectConfigure<E extends Env, P extends string> =
|
export type OpenAPIObjectConfigure<E extends Env, P extends string> =
|
||||||
| OpenAPIObjectConfig
|
| OpenAPIObjectConfig
|
||||||
|
@ -237,6 +234,37 @@ export class OpenAPIHono<
|
||||||
this.defaultHook = init?.defaultHook
|
this.defaultHook = init?.defaultHook
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {RouteConfig} route - The route definition which you create with `createRoute()`.
|
||||||
|
* @param {Handler} handler - The handler. If you want to return a JSON object, you should specify the status code with `c.json()`.
|
||||||
|
* @param {Hook} hook - Optional. The hook method defines what it should do after validation.
|
||||||
|
* @example
|
||||||
|
* app.openapi(
|
||||||
|
* route,
|
||||||
|
* (c) => {
|
||||||
|
* // ...
|
||||||
|
* return c.json(
|
||||||
|
* {
|
||||||
|
* age: 20,
|
||||||
|
* name: 'Young man',
|
||||||
|
* },
|
||||||
|
* 200 // You should specify the status code even if it's 200.
|
||||||
|
* )
|
||||||
|
* },
|
||||||
|
* (result, c) => {
|
||||||
|
* if (!result.success) {
|
||||||
|
* return c.json(
|
||||||
|
* {
|
||||||
|
* code: 400,
|
||||||
|
* message: 'Custom Message',
|
||||||
|
* },
|
||||||
|
* 400
|
||||||
|
* )
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*)
|
||||||
|
*/
|
||||||
openapi = <
|
openapi = <
|
||||||
R extends RouteConfig,
|
R extends RouteConfig,
|
||||||
I extends Input = InputTypeParam<R> &
|
I extends Input = InputTypeParam<R> &
|
||||||
|
@ -255,20 +283,27 @@ export class OpenAPIHono<
|
||||||
// If response type is defined, only TypedResponse is allowed.
|
// If response type is defined, only TypedResponse is allowed.
|
||||||
R extends {
|
R extends {
|
||||||
responses: {
|
responses: {
|
||||||
[statusCode: string]: {
|
[statusCode: number]: {
|
||||||
content: {
|
content: {
|
||||||
[mediaType: string]: ZodMediaTypeObject
|
[mediaType: string]: ZodMediaTypeObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
? HandlerTypedResponse<OutputType<R>>
|
? RouteConfigToTypedResponse<R>
|
||||||
: HandlerAllResponse<OutputType<R>>
|
: RouteConfigToTypedResponse<R> | Response | Promise<Response>
|
||||||
>,
|
>,
|
||||||
hook: Hook<I, E, P, OutputType<R>> | undefined = this.defaultHook
|
hook:
|
||||||
|
| Hook<
|
||||||
|
I,
|
||||||
|
E,
|
||||||
|
P,
|
||||||
|
RouteConfigToTypedResponse<R> | Response | Promise<Response> | void | Promise<void>
|
||||||
|
>
|
||||||
|
| undefined = this.defaultHook
|
||||||
): OpenAPIHono<
|
): OpenAPIHono<
|
||||||
E,
|
E,
|
||||||
S & ToSchema<R['method'], MergePath<BasePath, P>, I['in'], OutputType<R>>,
|
S & ToSchema<R['method'], MergePath<BasePath, P>, I, RouteConfigToTypedResponse<R>>,
|
||||||
BasePath
|
BasePath
|
||||||
> => {
|
> => {
|
||||||
this.openAPIRegistry.registerPath(route)
|
this.openAPIRegistry.registerPath(route)
|
||||||
|
@ -357,7 +392,7 @@ export class OpenAPIHono<
|
||||||
try {
|
try {
|
||||||
const document = this.getOpenAPIDocument(config)
|
const document = this.getOpenAPIDocument(config)
|
||||||
return c.json(document)
|
return c.json(document)
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
return c.json(e, 500)
|
return c.json(e, 500)
|
||||||
}
|
}
|
||||||
}) as any
|
}) as any
|
||||||
|
@ -372,7 +407,7 @@ export class OpenAPIHono<
|
||||||
try {
|
try {
|
||||||
const document = this.getOpenAPI31Document(config)
|
const document = this.getOpenAPI31Document(config)
|
||||||
return c.json(document)
|
return c.json(document)
|
||||||
} catch (e) {
|
} catch (e: any) {
|
||||||
return c.json(e, 500)
|
return c.json(e, 500)
|
||||||
}
|
}
|
||||||
}) as any
|
}) as any
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import type { RouteConfig } from '@asteasolutions/zod-to-openapi'
|
import type { RouteConfig } from '@asteasolutions/zod-to-openapi'
|
||||||
import type { Context } from 'hono'
|
import type { Context, TypedResponse } from 'hono'
|
||||||
import { hc } from 'hono/client'
|
import { hc } from 'hono/client'
|
||||||
import { describe, it, expect, expectTypeOf } from 'vitest'
|
import { describe, it, expect, expectTypeOf } from 'vitest'
|
||||||
import { OpenAPIHono, createRoute, z } from '../src/index'
|
import { OpenAPIHono, createRoute, z, RouteConfigToTypedResponse } from '../src/index'
|
||||||
|
import { Expect, Equal } from 'hono/utils/types'
|
||||||
|
|
||||||
describe('Constructor', () => {
|
describe('Constructor', () => {
|
||||||
it('Should not require init object', () => {
|
it('Should not require init object', () => {
|
||||||
|
@ -104,11 +105,14 @@ describe('Basic - params', () => {
|
||||||
route,
|
route,
|
||||||
(c) => {
|
(c) => {
|
||||||
const { id } = c.req.valid('param')
|
const { id } = c.req.valid('param')
|
||||||
return c.json({
|
return c.json(
|
||||||
id,
|
{
|
||||||
age: 20,
|
id,
|
||||||
name: 'Ultra-man',
|
age: 20,
|
||||||
})
|
name: 'Ultra-man',
|
||||||
|
},
|
||||||
|
200 // You should specify the status code even if it's 200.
|
||||||
|
)
|
||||||
},
|
},
|
||||||
(result, c) => {
|
(result, c) => {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
@ -663,9 +667,24 @@ describe('Input types', () => {
|
||||||
app.openapi(route, (c) => {
|
app.openapi(route, (c) => {
|
||||||
return c.json({
|
return c.json({
|
||||||
id: '123', // should be number
|
id: '123', // should be number
|
||||||
message: 'Success',
|
age: 42,
|
||||||
|
sex: 'male' as const,
|
||||||
|
name: 'Success',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// @ts-expect-error it should throw an error if the status code is wrong
|
||||||
|
app.openapi(route, (c) => {
|
||||||
|
return c.json(
|
||||||
|
{
|
||||||
|
id: 123,
|
||||||
|
age: 42,
|
||||||
|
sex: 'male' as const,
|
||||||
|
name: 'Success',
|
||||||
|
},
|
||||||
|
404
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Routers', () => {
|
describe('Routers', () => {
|
||||||
|
@ -976,7 +995,7 @@ describe('With hc', () => {
|
||||||
// use the defaultHook
|
// use the defaultHook
|
||||||
app.openapi(createPostRoute, (c) => {
|
app.openapi(createPostRoute, (c) => {
|
||||||
const { title } = c.req.valid('json')
|
const { title } = c.req.valid('json')
|
||||||
return c.json({ title })
|
return c.json({ title }, 200)
|
||||||
})
|
})
|
||||||
|
|
||||||
// use a routeHook
|
// use a routeHook
|
||||||
|
@ -984,7 +1003,7 @@ describe('With hc', () => {
|
||||||
createBookRoute,
|
createBookRoute,
|
||||||
(c) => {
|
(c) => {
|
||||||
const { title } = c.req.valid('json')
|
const { title } = c.req.valid('json')
|
||||||
return c.json({ title })
|
return c.json({ title }, 200)
|
||||||
},
|
},
|
||||||
(result, c) => {
|
(result, c) => {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
|
@ -1389,3 +1408,84 @@ describe('Middleware', () => {
|
||||||
expect(res.headers.get('x-foo')).toBe('bar')
|
expect(res.headers.get('x-foo')).toBe('bar')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('RouteConfigToTypedResponse', () => {
|
||||||
|
const ParamsSchema = z.object({
|
||||||
|
id: z
|
||||||
|
.string()
|
||||||
|
.min(4)
|
||||||
|
.openapi({
|
||||||
|
param: {
|
||||||
|
name: 'id',
|
||||||
|
in: 'path',
|
||||||
|
},
|
||||||
|
example: '12345',
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
const UserSchema = z
|
||||||
|
.object({
|
||||||
|
name: z.string().openapi({
|
||||||
|
example: 'John Doe',
|
||||||
|
}),
|
||||||
|
age: z.number().openapi({
|
||||||
|
example: 42,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.openapi('User')
|
||||||
|
|
||||||
|
const ErrorSchema = z
|
||||||
|
.object({
|
||||||
|
ok: z.boolean().openapi({
|
||||||
|
example: false,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
.openapi('Error')
|
||||||
|
|
||||||
|
it('Should return types correctly', () => {
|
||||||
|
const route = {
|
||||||
|
method: 'post' as any,
|
||||||
|
path: '/users/{id}',
|
||||||
|
request: {
|
||||||
|
params: ParamsSchema,
|
||||||
|
},
|
||||||
|
responses: {
|
||||||
|
200: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: UserSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Get the user',
|
||||||
|
},
|
||||||
|
400: {
|
||||||
|
content: {
|
||||||
|
'application/json': {
|
||||||
|
schema: ErrorSchema,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
description: 'Error!',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Actual = RouteConfigToTypedResponse<typeof route>
|
||||||
|
|
||||||
|
type Expected =
|
||||||
|
| TypedResponse<
|
||||||
|
{
|
||||||
|
name: string
|
||||||
|
age: number
|
||||||
|
},
|
||||||
|
200,
|
||||||
|
'json'
|
||||||
|
>
|
||||||
|
| TypedResponse<
|
||||||
|
{
|
||||||
|
ok: boolean
|
||||||
|
},
|
||||||
|
400,
|
||||||
|
'json'
|
||||||
|
>
|
||||||
|
type verify = Expect<Equal<Expected, Actual>>
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
|
@ -594,7 +594,7 @@ __metadata:
|
||||||
"@asteasolutions/zod-to-openapi": "npm:^7.0.0"
|
"@asteasolutions/zod-to-openapi": "npm:^7.0.0"
|
||||||
"@cloudflare/workers-types": "npm:^4.20240117.0"
|
"@cloudflare/workers-types": "npm:^4.20240117.0"
|
||||||
"@hono/zod-validator": "npm:0.2.1"
|
"@hono/zod-validator": "npm:0.2.1"
|
||||||
hono: "npm:^4.2.2"
|
hono: "npm:^4.3.6"
|
||||||
jest: "npm:^29.7.0"
|
jest: "npm:^29.7.0"
|
||||||
openapi3-ts: "npm:^4.1.2"
|
openapi3-ts: "npm:^4.1.2"
|
||||||
tsup: "npm:^8.0.1"
|
tsup: "npm:^8.0.1"
|
||||||
|
@ -602,7 +602,7 @@ __metadata:
|
||||||
vitest: "npm:^1.4.0"
|
vitest: "npm:^1.4.0"
|
||||||
zod: "npm:^3.22.1"
|
zod: "npm:^3.22.1"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
hono: ">=3.11.3"
|
hono: ">=4.3.6"
|
||||||
zod: 3.*
|
zod: 3.*
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
@ -2379,10 +2379,10 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"hono@npm:^4.2.2":
|
"hono@npm:^4.3.6":
|
||||||
version: 4.2.2
|
version: 4.3.6
|
||||||
resolution: "hono@npm:4.2.2"
|
resolution: "hono@npm:4.3.6"
|
||||||
checksum: 4f423ff808c105341d2802192abe9070c5f6fc4a45da51842a5f5f2111b4c333ef4aea2720a585e16996944cc0cedf68657c57df1d150f1382f21fc18e814b42
|
checksum: 2e27eb1e90b392a5884af573179d29e3f717f5e803c2b90f1383488f42bc986810e8e714d5bb1205935fda1d3e9944b3262aed88e852ea44d0e13d799474fa5b
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|
18
yarn.lock
18
yarn.lock
|
@ -2153,7 +2153,7 @@ __metadata:
|
||||||
"@asteasolutions/zod-to-openapi": "npm:^7.0.0"
|
"@asteasolutions/zod-to-openapi": "npm:^7.0.0"
|
||||||
"@cloudflare/workers-types": "npm:^4.20240117.0"
|
"@cloudflare/workers-types": "npm:^4.20240117.0"
|
||||||
"@hono/zod-validator": "npm:0.2.1"
|
"@hono/zod-validator": "npm:0.2.1"
|
||||||
hono: "npm:^4.2.2"
|
hono: "npm:^4.3.6"
|
||||||
jest: "npm:^29.7.0"
|
jest: "npm:^29.7.0"
|
||||||
openapi3-ts: "npm:^4.1.2"
|
openapi3-ts: "npm:^4.1.2"
|
||||||
tsup: "npm:^8.0.1"
|
tsup: "npm:^8.0.1"
|
||||||
|
@ -2161,7 +2161,7 @@ __metadata:
|
||||||
vitest: "npm:^1.4.0"
|
vitest: "npm:^1.4.0"
|
||||||
zod: "npm:^3.22.1"
|
zod: "npm:^3.22.1"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
hono: ">=3.11.3"
|
hono: ">=4.3.6"
|
||||||
zod: 3.*
|
zod: 3.*
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
@ -9605,13 +9605,6 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"hono@npm:^4.2.2":
|
|
||||||
version: 4.2.2
|
|
||||||
resolution: "hono@npm:4.2.2"
|
|
||||||
checksum: 4f423ff808c105341d2802192abe9070c5f6fc4a45da51842a5f5f2111b4c333ef4aea2720a585e16996944cc0cedf68657c57df1d150f1382f21fc18e814b42
|
|
||||||
languageName: node
|
|
||||||
linkType: hard
|
|
||||||
|
|
||||||
"hono@npm:^4.2.3":
|
"hono@npm:^4.2.3":
|
||||||
version: 4.2.3
|
version: 4.2.3
|
||||||
resolution: "hono@npm:4.2.3"
|
resolution: "hono@npm:4.2.3"
|
||||||
|
@ -9640,6 +9633,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"hono@npm:^4.3.6":
|
||||||
|
version: 4.3.6
|
||||||
|
resolution: "hono@npm:4.3.6"
|
||||||
|
checksum: 2e27eb1e90b392a5884af573179d29e3f717f5e803c2b90f1383488f42bc986810e8e714d5bb1205935fda1d3e9944b3262aed88e852ea44d0e13d799474fa5b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"hosted-git-info@npm:^2.1.4":
|
"hosted-git-info@npm:^2.1.4":
|
||||||
version: 2.8.9
|
version: 2.8.9
|
||||||
resolution: "hosted-git-info@npm:2.8.9"
|
resolution: "hosted-git-info@npm:2.8.9"
|
||||||
|
|
Loading…
Reference in New Issue