Use generator with nitro openapi
maximersetec opened this issue · comments
Describe the feature
Question
Is it possible to configure Nitro OpenAPI to use a generator from @asteasolutions/zod-to-openapi
to automatically add OpenAPI objects to one or more routes?
Example Code
import { extendZodWithOpenApi, OpenApiGeneratorV3 } from '@asteasolutions/zod-to-openapi';
import { z } from 'zod';
extendZodWithOpenApi(z);
const fieldDefinitions = {
'title': {
label: 'Project name',
placeholder: 'Project name',
validation: z
.string()
.min(1, "Project name is required")
.openapi({ description: 'Project name' }),
},
'case-number': {
label: 'Case-number',
placeholder: 'Case-number',
validation: z
.string()
.min(1, "Case-number is required")
.openapi({ description: 'Case-number' }),
},
'case-manager': {
label: 'Case-manager',
placeholder: 'Case-manager',
validation: z
.string()
.min(1, "Case-manager is required")
.openapi({ description: 'Case-manager' }),
},
'contributor': {
label: 'Contributor',
placeholder: 'Contributor',
validation: z
.string()
.min(1, "Contributor is required")
.openapi({ description: 'Project contributor' }),
},
};
export const metadataSchema = z
.object(
Object.fromEntries(
Object.entries(fieldDefinitions).map(([key, { validation }]) => [
key,
validation,
])
)
)
.openapi('Metadata');
export const formFields = Object.entries(fieldDefinitions).map(
([key, { label, placeholder }]) => ({
id: key,
label,
type: 'text',
placeholder,
})
);
const generator = new OpenApiGeneratorV3([metadataSchema]);
### Additional information
- [ ] Would you be willing to help implement this feature?
@maximersetec Can you provide a simple repo with @asteasolutions/zod-to-openapi
usage? I don't know this tool at all so would be grateful for some example.
@maximersetec Can you provide a simple repo with
@asteasolutions/zod-to-openapi
usage? I don't know this tool at all so would be grateful for some example.
Actually what he has used (I mean that Zod or something) is not important. The important thing is, we need dynamic variables work in DefineRouteMeta. Now in DefineRouteMeta, it only accept static string. For example:
defineRouteMeta({
openAPI: {
description: 'Handle AT Protocol OAuth callback'
}
})
This will work. Because is doesn't contains any variables.
However if:
let des = 'Handle AT Protocol OAuth callback';
defineRouteMeta({
openAPI: {
description: des
}
})
Or even:
let routeMeta = {
openAPI: {
description: 'Handle AT Protocol OAuth callback'
}
}
defineRouteMeta(routeMeta)
In both situation, they won't work because of variables.
@maximersetec Can you provide a simple repo with
@asteasolutions/zod-to-openapi
usage? I don't know this tool at all so would be grateful for some example.
import { z } from 'zod'
import { createSchema, extendZodWithOpenApi } from 'zod-openapi'
extendZodWithOpenApi(z)
const TestLoginDto = z.object({
username: z.string().openapi({ description: 'Username' }),
password: z.string().openapi({ description: 'Password' }),
})
const { schema: TestLoginSchema } = createSchema(TestLoginDto)
defineRouteMeta({
openAPI: {
summary: 'Login',
requestBody: {
content: {
'application/json': {
schema: TestLoginSchema,
},
},
},
},
})
For your information, I have copied an example that I use in another issue.
Acutally, with this issue, there are 5 issues that are requiring for dynamic DefineRouteMeta function. That's why I said this function is very necessary.
@AkarinServer I will try to dive into it :)
Ok, @AkarinServer @maximersetec, I found the root cause of this issue. Unfortunately, this can't be resolved without core changes 😢 Let me explain why.
The defineRouteMeta
function is transformed using AST as a Rollup plugin for Nitro. Here's the transformation:
https://github.com/nitrojs/nitro/blob/v2/src/rollup/plugins/handlers-meta.ts#L58
This code takes the defineRouteMeta
expression statement and generates an object from it. The resulting code is injected into the bundled output and looks like this:
export default {"openAPI":{"summary":"Login","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}}}};
This code is then injected into the index.mjs
file here:
https://github.com/nitrojs/nitro/blob/v2/src/rollup/plugins/handlers.ts#L102
The AST could export these variables as additional exports from the file, but this would require significantly more changes than I initially anticipated. I have some ideas for how to approach this, but @pi0 should take a look and decide if it's worth pursuing.