fastify / fastify-swagger

Swagger documentation generator for Fastify
MIT License
941 stars 209 forks source link

fix: multiple alternative security objects in route schema #817

Closed beryxz closed 2 months ago

beryxz commented 2 months ago

Fixes #816

Update the security property of FastifySchema to allow multiple security objects in a route schema.

Checklist

Uzlopak commented 2 months ago

please add some unit tests

beryxz commented 2 months ago

Are these unit tests what you had in mind?

Uzlopak commented 2 months ago

To be honest, I dont see any code change in the lib folder. So this is only about typings?

beryxz commented 2 months ago

Yes, it's only about updating the type of the security property in the FastifySchema interface. The linked issue has some more detailed information.

jdagerydnnsoft commented 2 months ago

When this fix will be release?...

beryxz commented 2 months ago

As @climba03003 rightly pointed out, I also think my changes are invalid, and this issue/PR should be closed.

I looked into my problem more thoroughly, and it was not actually caused by Fastify or Typebox but by a lack of explicit typing on my end.

To give a simplified context:

const app = fastify().withTypeProvider<TypeBoxTypeProvider>();

// FastifyRequestTypebox & FastifyReplyTypebox defined as in the official README

export const SomeOperationSchema = {
    summary: 'Do some operation',
    security: [{ bearer_token: [] }, { api_key: [] }],
    response: {
        204: NoContentResponse
    },
};

async function some_operation(
    request: FastifyRequestTypebox<typeof SomeOperationSchema>,
    reply: FastifyReplyTypebox<typeof SomeOperationSchema>,
) {
    return reply.status(204).send();
}

app.get('/', { schema: SomeOperationSchema }, some_operation);

This approach didn't work as the dynamic result of typeof SomeOperationSchema doesn't satisfy the FastifySchema type:

[{ bearer_token: [] }, { api_key: [] }]

gets parsed as

({ bearer_token: never[]; test?: undefined; } | { test: never[]; bearer_token?: undefined; })[]

thus, not matching the security property type defined in FastifySchema.

I tried fixing this by explicitly setting the type of the route schema:

- export const SomeOperationSchema = {
+ export const SomeOperationSchema: FastifySchema = {

but this seems to break the typing of everything else.


What would be an appropriate solution?

climba03003 commented 2 months ago

I am closing this PR because it is related to how TypeScript works and coding styles.

What would be an appropriate solution?

  1. Place it all together to allows TypeScript infer.
import Swagger from '@fastify/swagger'
import Fastify from 'fastify'

const fastify = Fastify()

await fastify.register(Swagger)

fastify.get('/', {
  schema: {
    security: [{ api_key: [] }, { bearer: [] }]
  }
}, () => { })
  1. Make use of as const to bypass TypeScript auto reflection for array.
import Swagger from '@fastify/swagger'
import Fastify from 'fastify'

const fastify = Fastify()

await fastify.register(Swagger)

const schema = {
  security: [{ api_key: [] }, { bearer: [] }]
} as const

fastify.get('/', {
  schema
}, () => { })