feat(zod-openapi): Support for other json content-types such as application/vnd.api+json, application/problem+json, etc. (#645)
* Support other json content-types * Run changesetpull/647/head
parent
2b54aa037a
commit
f38a6166f6
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@hono/zod-openapi': minor
|
||||
---
|
||||
|
||||
Support other json content-types such as application/vnd.api+json, application/problem+json, etc.
|
|
@ -55,10 +55,12 @@ type RequestTypes = {
|
|||
}
|
||||
|
||||
type IsJson<T> = T extends string
|
||||
? T extends `application/json${infer _Rest}`
|
||||
? 'json'
|
||||
? T extends `application/${infer Start}json${infer _End}`
|
||||
? Start extends '' | `${string}+` | `vnd.${string}+`
|
||||
? 'json'
|
||||
: never
|
||||
: never
|
||||
: never
|
||||
: never
|
||||
|
||||
type IsForm<T> = T extends string
|
||||
? T extends
|
||||
|
@ -385,7 +387,7 @@ export class OpenAPIHono<
|
|||
if (!(schema instanceof ZodType)) {
|
||||
continue
|
||||
}
|
||||
if (mediaType.startsWith('application/json')) {
|
||||
if (/^application\/([a-z-\.]+\+)?json/.test(mediaType)) {
|
||||
const validator = zValidator('json', schema, hook as any)
|
||||
validators.push(validator as any)
|
||||
}
|
||||
|
|
|
@ -422,74 +422,157 @@ describe('JSON', () => {
|
|||
})
|
||||
.openapi('Post')
|
||||
|
||||
const route = createRoute({
|
||||
method: 'post',
|
||||
path: '/posts',
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: RequestSchema,
|
||||
describe('Content-Type application/json', () => {
|
||||
const route = createRoute({
|
||||
method: 'post',
|
||||
path: '/posts',
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: RequestSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: PostSchema,
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: PostSchema,
|
||||
},
|
||||
},
|
||||
description: 'Post a post',
|
||||
},
|
||||
description: 'Post a post',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const app = new OpenAPIHono()
|
||||
|
||||
app.openapi(route, (c) => {
|
||||
const { id, title } = c.req.valid('json')
|
||||
return c.json({
|
||||
id,
|
||||
title,
|
||||
})
|
||||
})
|
||||
|
||||
it('Should return 200 response with correct contents', async () => {
|
||||
const req = new Request('http://localhost/posts', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
const app = new OpenAPIHono()
|
||||
|
||||
app.openapi(route, (c) => {
|
||||
const {id, title} = c.req.valid('json')
|
||||
return c.json({
|
||||
id,
|
||||
title,
|
||||
})
|
||||
})
|
||||
|
||||
it('Should return 200 response with correct contents', async () => {
|
||||
const req = new Request('http://localhost/posts', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
id: 123,
|
||||
title: 'Good title',
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
|
||||
const res = await app.request(req)
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toEqual({
|
||||
id: 123,
|
||||
title: 'Good title',
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
const res = await app.request(req)
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toEqual({
|
||||
id: 123,
|
||||
title: 'Good title',
|
||||
it('Should return 400 response with correct contents', async () => {
|
||||
const req = new Request('http://localhost/posts', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
})
|
||||
const res = await app.request(req)
|
||||
expect(res.status).toBe(400)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should return 400 response with correct contents', async () => {
|
||||
const req = new Request('http://localhost/posts', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
describe('Content-Type application/vnd.api+json', () => {
|
||||
const route = createRoute({
|
||||
method: 'post',
|
||||
path: '/posts',
|
||||
request: {
|
||||
body: {
|
||||
content: {
|
||||
'application/vnd.api+json': {
|
||||
schema: RequestSchema,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
responses: {
|
||||
200: {
|
||||
content: {
|
||||
'application/json': {
|
||||
schema: PostSchema,
|
||||
},
|
||||
},
|
||||
description: 'Post a post',
|
||||
},
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
})
|
||||
const res = await app.request(req)
|
||||
expect(res.status).toBe(400)
|
||||
|
||||
const app = new OpenAPIHono()
|
||||
|
||||
app.openapi(route, (c) => {
|
||||
const {id, title} = c.req.valid('json')
|
||||
return c.json({
|
||||
id,
|
||||
title,
|
||||
})
|
||||
})
|
||||
|
||||
it('Should return 200 response with correct contents', async () => {
|
||||
const req = new Request('http://localhost/posts', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
id: 123,
|
||||
title: 'Good title',
|
||||
}),
|
||||
headers: {
|
||||
'Content-Type': 'application/vnd.api+json',
|
||||
},
|
||||
})
|
||||
|
||||
const res = await app.request(req)
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
expect(await res.json()).toEqual({
|
||||
id: 123,
|
||||
title: 'Good title',
|
||||
})
|
||||
})
|
||||
|
||||
it('Should return 400 response with correct contents for empty request data', async () => {
|
||||
const req = new Request('http://localhost/posts', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/vnd.api+json',
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
})
|
||||
const res = await app.request(req)
|
||||
expect(res.status).toBe(400)
|
||||
})
|
||||
|
||||
it('Should return 400 response with correct contents for non application/vnd.api+json request', async () => {
|
||||
const req = new Request('http://localhost/posts', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({}),
|
||||
})
|
||||
const res = await app.request(req)
|
||||
expect(res.status).toBe(400)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
// application/vnd.api+json
|
||||
describe('Form', () => {
|
||||
const RequestSchema = z.object({
|
||||
id: z.string().openapi({}),
|
||||
|
|
Loading…
Reference in New Issue