-
Notifications
You must be signed in to change notification settings - Fork 67
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
feat: add ability to define securitySchemes under components #25
feat: add ability to define securitySchemes under components #25
Conversation
@@ -345,6 +354,11 @@ export class OpenAPIGenerator { | |||
: simpleSchema; | |||
} | |||
|
|||
private generateSecuritySchema(name: string, schema: SecuritySchemeObject): SecuritySchemeObject { | |||
this.securitySchemaRefs[name] = schema; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From what I see you're aiming to provide a pure object definition for the components.securitySchemes
property, right? If that is the case I see no reason for putting this through the registry and binding it into the generation logic. I'll try and showcase a different approach.
// Note I think this would look better in a class/factory but a function is easier to shwocase. We can just export this as
// some sort of helper function from `zod-to-openapi`.
function generateSecuritySchemes<T extends Record<string, SecuritySchemeObject>>(securitySchemes: T) {
return {
securitySchemes,
addSecurityScheme: (key: keyof T, val: string[] = []) => ({[key]: val}),
}
}
const generator = new OpenAPIGenerator(rootRegistry.definitions);
const Security = generateSecuritySchemes({bearerAuth: {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
}})
registry.registerPath({
path: '/units',
method: 'get',
security: [
Security.addSecurityScheme('bearerAuth'),
],
responses: {
200: {
mediaType: 'application/json',
schema: Unit.array().openapi({description: 'Array of all units'})
}
}
})
generator.generateDocument({
// the generic stuff
components: {
securitySchemes: Security.securitySchemes
}
});
In order to make this work we would only need to make sure the config is being merged correctly in generateDocument
. I feel like it is not wrong to provide support for manually added components (if someone wants to do that).
@viktor-ku @georgyangelov what do you think. I'd also love to here any possible benefits of getting it through the registry, since I wrote this on the fly and haven't tested particular cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's certainly reasonable, however I think that registry could serve a bit more than just a zod schema handler. The registry just sounds like a convenient way to just add stuff to it like security schemas and it would just know what to do with it.
Maybe it's better to rename it from registry.registerSecuritySchema
to like registry.addSecuritySchema
implying that there is nothing to generate, just add to the registry?
And then I don't believe it's necessary to have additional boilerplate around generateDocument
, I believe the registry is therefore capable of handling exactly that: knowing when to add something to the components and then doing it.
@viktor-ku Thank you for taking the time to open a PR, it's much appreciated! On the topic @AGalabov raised, on one hand, from a user point of view it would be nice to have the same way of registering OpenAPI stuff as with Zod schemas. On the other, something like the following is pretty simple as well (which is not currently possible): registry.registerPath({
path: '/units',
method: 'get',
security: [
bearerAuth: [],
],
responses: { ... }
})
generator.generateDocument({
...,
components: {
securitySchemes: {
bearerAuth: { type: 'http', scheme: 'bearer', bearerFormat: 'JWT' }
}
}
}); I believe the concern here is purely from a maintenance point of view - if we start supporting one type of (let's call it) raw openapi object, then it'll make sense to support all of them, which I'm not sure we want to have to do, especially if they are special-cased. So what do you both think about:
This way the implementation for all the components would be the same and we won't need to support all types separately. As a bonus there could still be Something like this, which is your code, just some comments on the reusable version. We can add both since the const registry = new OpenAPIRegistry();
// Will call registry.registerComponent('securitySchemes', 'bearerAuth', { ... })
const bearerAuth = registry.registerSecurityScheme('bearerAuth', {
type: 'http',
scheme: 'bearer',
bearerFormat: 'JWT',
})
registry.registerPath({
path: '/units',
method: 'get',
security: [
// Same as just specifying `{ [bearerAuth.name]: [] }`
bearerAuth.security()
],
responses: { ... }
}) So to sum up, my suggestion is to just make the implementation a bit more general so that any raw components are supported, then specialize just the |
I like all of this and also the latter code sample. |
@viktor-ku Could you make the change in this PR? Otherwise I'll refactor later but I won't have the time this week |
@georgyangelov sorry I've moved to trpc now, I won't have time this week either. |
I've created a separate PR for the more generic version: #28 Viktor, thank you again for sparking the discussion here |
Hi, there is a small change that I missed when using this package: having to define my securitySchemes (as of v3 of open api)
I hope you too find it useful and it'll get merged shortly.
Any feedback would be appreciated!
Thanks