Description
Consider this real-world code example:
/**
* A message batch, as received from and sent to the server in the context of re-signing messages.
* This type is generic over `T`, where `T` represents the content of the actual message. This
* means, that the specific message content depends on the concrete implementation or extension
* of the polyproto protocol.
*/
model MessageBatch<T> {
@doc("The ID-Cert that the following messages' signatures correspond to.")
idCert: string,
@doc("The actual message.")
messages: {
@doc("Signature of the whole message")
signature: string,
@doc("Arbitrary content `T`. This depends on the specific implementation or extension of the protocol.")
content: T
}[];
}
generates the following OpenAPI3 spec for a dummy route:
/.p2/core/v1/dummy:
post:
operationId: Unregistered_dummy
parameters: []
responses:
'204':
description: 'There is no content to send for this request, but the headers may be useful. '
tags:
- Migration - Registration not required
requestBody:
required: true
content:
application/json:
schema:
type: object
required:
- idCert
- messages
properties:
idCert:
type: string
description: The ID-Cert that the following messages' signatures correspond to.
messages:
type: array
items:
type: object
properties:
signature:
type: string
description: Signature of the whole message
content:
type: string
description: Arbitrary content `T`. This depends on the specific implementation or extension of the protocol.
required:
- signature
- content
description: The actual message.
description: |-
A message batch, as received from and sent to the server in the context of re-signing messages.
This type is generic over `T`, where `T` represents the content of the actual message. This
means, that the specific message content depends on the concrete implementation or extension
of the polyproto protocol.
security:
- BearerAuth: []
The issue at hand here has to do with the fact that generic TypeSpec models do not generate OpenAPI schemas. This is somewhat understandable, as OpenAPI3 likely does not have a way to represent generic type arguments. However, all of my documentation for the TypeSpec model is lost in the compilation process, as it does not make it into the OpenAPI documentation/specification at all. Off the top of my head, I can think of two solutions for this problem:
1. Compile time monomorphization of generics
Say I have the above MessageBatch<T>
model. For the sake of explanation, we assume that the T
parameter is used in two different ways within my route definitions or other model definitions:
T
=string
T
=uint32
Through monomorphization, TypeSpec could generate the following OpenAPI3 schemas:
MessageBatchString
and MessageBatchUint32
This way, the documentation I meticulously added to my TypeSpec model does not get lost and the model still translates to an OpenAPI3 schema in some way. In my opinion, this is better than completely "losing"/"missing out" on the entire schema.
2. Add the documentation of the generic type to every usage field in OpenAPI3 schema
This solution is perhaps simpler than the first proposal.
Assume, again, that I have the MessageBatch<T>
model with two different T
parameters within my project, where T
= string
and T
= uint32
.
With this proposal, the TypeSpec model would not be translated to an OpenAPI schema. Instead, the documentation of the MessageType
(and, if applicable, the T
generic parameter as well) would be copy-pasted into every occurrence of MessageType
in the generated OpenAPI3 specification.
This way, every occurrence of MessageType
in the generated OpenAPI3 schema would have documentation attached to it, making things easier for TypeSpec developers and those intending to use the OpenAPI3 schema to preview it in SwaggerUI or generate client/server code from it.
Checklist
- Follow our Code of Conduct
- Read the docs.
- Check that there isn't already an issue that request the same feature to avoid creating a duplicate.