Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use generator with nitro openapi #2912

Open
maximersetec opened this issue Dec 2, 2024 · 7 comments
Open

Use generator with nitro openapi #2912

maximersetec opened this issue Dec 2, 2024 · 7 comments

Comments

@maximersetec
Copy link

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?
@OskarLebuda
Copy link

OskarLebuda commented Dec 4, 2024

@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.

@AkarinServer
Copy link

AkarinServer commented Dec 5, 2024

@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.

@AkarinServer
Copy link

@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.

#2870
#2641
#2490
#2274

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.

@OskarLebuda
Copy link

@AkarinServer I will try to dive into it :)

@OskarLebuda
Copy link

OskarLebuda commented Dec 5, 2024

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.

@maximersetec
Copy link
Author

maximersetec commented Dec 5, 2024 via email

@xMaxximum
Copy link

I found a solution in my case: I create a new api route that fetches me _openapi.json and modifies or adds elements from my generator. I can show you this in a future post if you're interested, but the idea was to be able to modify directly without going through a wrapper that fetches Envoyé à partir de Outlook pour Androidhttps://aka.ms/AAb9ysg

________________________________ From: Oskar Lebuda @.> Sent: Thursday, December 5, 2024 7:46:48 PM To: nitrojs/nitro @.> Cc: RAMOS Maxime @.>; Mention @.> Subject: Re: [nitrojs/nitro] Use generator with nitro openapi (Issue #2912) Ok @AkarinServerhttps://github.com/AkarinServer @maximersetechttps://github.com/maximersetec I found the reason of that. Without core changes this couldn't be done unfortunately 😢 Let me tell you why. defineRouteMeta is transformed using AST as a rollup plugin for nitro. There is the transform: https://github.com/nitrojs/nitro/blob/v2/src/rollup/plugins/handlers-meta.ts#L58 This code takes defineRouteMeta expression statement and creates an object from that. The output code is injected into bundled code and looks like this: export default {"openAPI":{"summary":"Login","requestBody":{"content":{"application/json":{"schema":{"type":"object"}}}}}}; Then this code is injected into index.mjs file right here: https://github.com/nitrojs/nitro/blob/v2/src/rollup/plugins/handlers.ts#L102 The AST could export that variables as additional export from file, but this is way to much changes then I thought before. I have some ideas for that but @pi0https://github.com/pi0 should looks at that and told if it's worth. — Reply to this email directly, view it on GitHub<#2912 (comment)>, or unsubscribehttps://github.com/notifications/unsubscribe-auth/BNEYQNQCSKMWWCY3LIKW3P32ECNRRAVCNFSM6AAAAABS23E3VCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKMRRGE2TQMBXGI. You are receiving this because you were mentioned.Message ID: @.***>

Hello, could you show me how you did this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants