asteasolutions / zod-to-openapi

A library that generates OpenAPI (Swagger) docs from Zod schemas
MIT License
993 stars 60 forks source link

Is there a way to define fields in the schema should be excluded from docs? (feature flagging fields) #171

Closed tigerabrodi closed 1 year ago

tigerabrodi commented 1 year ago

What are we trying to achieve?

We're trying to implement feature flagging into our API.

The fields and endpoints should exist (behavior & functionality).

However, if something is feature flagged, it should be excluded from the documentation, whether it'd be fields or an entire endpoint.

We figured out how to exclude entire endpoints, this focuses on excluding fields of an endpoint.

Question

Is there a way to define fields in the schema should be excluded from documentation when generating the docs?

We use OpenAPIRegistry to register what should be documented.

OpenApiGeneratorV31 to generate the docs.

Don't worry about defineRequestSchema in the image below, we do some minor custom stuff.

Is there a way to maybe have skip as one of the options in openapi({ })? Something like skipDocs? Then the field would be excluded from the docs during generation and isn't to be found in the generated openapi.json.

Screenshot 2023-09-12 at 11 01 56

Thoughts

Something else you would propose for dealing with this? 😄

Maybe skipDocs or some similar option could be a new feature.

I'm happy to contribute to the project too! 🙌

georgyangelov commented 1 year ago

Hi @narutosstudent , thanks for using the library and the suggestion. I'm converting this thread to a discussion since it's not really an issue.

I agree that there are cases where you don't want to expose docs for a particular field. At the same time, I'm wondering about the behavior when the field is required. For example, in your screenshot the field name is required, and if you skip it from the documentation - then that doesn't skip the validation later done when the Zod object is parsed (if input) or validated (if output), so it will throw an error if not provided. So if we add a skipDocs/hidden field it would really only work with nullable fields.

So there are two cases I see here for hiding fields:

  1. Internal-only fields that should be exposed but not have docs
  2. Versioning / feature flagging

However, for the second case I believe a better approach (that also handles required fields) is to dynamically switch the object itself instead of just hiding some of its properties. Something like this:

const ShareInputSchema = z.object({
  name: z.string()
});

const ShareWithDescriptionSchema = ShareInputSchema.extend({
  description: z.string()
})

export const CreateShareRequestSchema = defineRequestSchema.with({
  body: z.object({
    data: z.object({
      share: ( featureFlagEnabled ? ShareWithDescriptionSchema : ShareInputSchema ).openapi({ description: 'The share to create' })
    })
  })
})

This way the input validator/parser is also correctly expecting a description when the flag is enabled and ignoring it when it's disabled.