Replies: 3 comments 2 replies
-
Seems that the most correct is to specify each schema with an const UserSchema = t.Object({
name: t.String()
}, {
$id: "User"
}) And then put this schema object directly into Single: response: t.Object({
user: t.Ref(UserSchema)
}) Multiple: response: t.Object({
users: t.Array(t.Ref(UserSchema))
}) This seems to generate the following OpenAPI document: Show
Components section: "components": {
"schemas": {
"User": {
"$id": "User",
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": [
"name"
]
}
}
} Paths section: "paths": {
"/users/": {
"get": {
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": {
"users": { "type": "array", "items": { "$ref": "User" } }
},
"required": ["users"]
}
}
}
}
},
"operationId": "getUsers",
"summary": "Get all users"
}
},
"/users/{id}": {
"get": {
"parameters": [
{
"anyOf": [
{ "format": "numeric", "default": 0, "type": "string" },
{ "type": "number" }
],
"schema": {},
"in": "path",
"name": "id",
"required": true
}
],
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"type": "object",
"properties": { "user": { "$ref": "User" } },
"required": ["user"]
}
}
}
}
},
"operationId": "getUsersById",
"summary": "Get a user"
}
}
} It won't show the name of the schema up front, but it does correctly refer to it, so I guess that's just a SwaggerUI feature. The identification can be made with the This seems to be the best I can come up with for now. |
Beta Was this translation helpful? Give feedback.
-
This is a really big problem. I've tried using Elysia several times, but it seems like there's no way to work with lists/arrays. Likewise, I've tried various options, defining types via PS the manual configuration works fine, for example: const UserResponse = t.Object({ /* ... */ }, { $id: 'UserResponse' });
// the full link to the schema:
const UsersResponse = t.Array(t.Ref('#/components/schemas/UserResponse'), { $id: 'UsersResponse' });
app
.model({
UserResponse,
UsersResponse,
})
.get('/users', () => /* ... */, { response: { defualt: 'UsersResponse' }, /* ... */ })
.get('/users/:id', () => /* ... */, { response: { default: 'UserResponse' }, /* ... */ }) |
Beta Was this translation helpful? Give feedback.
-
Since I posted this, I came across a different, albeit more manual, solution that seems mostly okay. Mentioned here. I think this was made possible in a more recent version of Elysia, as I had to upgrade my dependencies for it to work. The important part is that the const PetSchema = t.Object(
{
name: t.String(),
animal: t.String(),
},
{
$id: "#/components/schemas/Pet",
}
); An array version would be like this: const PetsSchema = t.Array(t.Ref(PetSchema)); Register the (singular) schema: .model({
Pet: PetSchema
}) To refer to the singular schema, you can do it normally by just doing I think there's a fair bit of room for DX improvement here though. |
Beta Was this translation helpful? Give feedback.
-
In regards to Swagger documentation, being able to use
.model
is very nice as it also generates schema components. However, I find myself wanting to re-use some of these schemas, but wrapped in an array. Essentially I want to mix pre-defined components with one-off schemas per route.How should this be achieved?
Assume I register a schema like so:
What I have tried so far, and their issues:
1. Register an array version in .model
With this, I register both the singular and the array version as 2 separate schemas.
Problem:
This will register both as schemas in the components section for SwaggerUI, which I find to be redundant, since they are more or less the same schema.
2. Manually import the schema only for the routes that require the array version
With this, I register only the singular schema, and manually import the schema only for the routes that need it in a different way
Problem:
This mixes the implementations based on whether I want a single or multiple items, since the single item will still be configured using
response: "User"
.3. Just use .model for documentation rather than auto-complete.
With this, I only register the schemas with .model, but never refer to any of them by name in the routes, instead importing the same schemas.
Problem:
This loses out on the benefit of having the auto-complete suggestions and the entire feature of registering schemas by their string name. It also makes Swagger unable to detect that it is the same schema, instead thinking it is a separate object with the same shape.
Referring to registered schema by name:
Referring to re-import of the schema object:
What I would want ideally is to do something like this (I don't think this is currently possible, but please correct me):
Is there maybe something that will solve this using
t.Ref
or so?Beta Was this translation helpful? Give feedback.
All reactions