Introduction#
It's a way to generate a dedicated endpoint for an entity property.
Let's say you have a User
entity that owns a collection of articles
. Rather than exposing the articles
in the
/users
route and have a lot of unnecessary nested data, you might want to directly access the article
list with only
the properties you want for that route scope
.
Usage#
By decorating the articles
property with the @Subresource decorator, you generates 3
routes :
GET:/users/:userId/articles
, which will list allarticles
of the givenuser
POST:/users/:userId/articles
, which will allow you to join anarticle
to thisuser
(a newarticle
is inserted if noarticle
.id is given !)DELETE:/users/:userId/articles/:articleId
, which will allow you to remove the relation between the givenuser
/article
Let's implement that :
For an entity to be used as a Subresource, it must have an EntityRouter
registered. And if you don't want to generates CRUD routes, you can just provide no arguments to
@EntityRoute
just like the example above.
Of course, you can customize your Subresource using SubresourceOptions as optional second argument.
Option key | Type | Default | Description |
---|---|---|---|
operations | SubresourceOperation | ["create", "list", "details", "delete"] | Defines which routes should be generated for this subresource |
maxDepth | number | undefined | Restrict the depth of subresources nesting allow from this one |
canHaveNested | boolean | true | Allow this subresource to have nested child subresources |
canBeNested | boolean | true | Allow this subresource to be used as a child subresource |
- By just specifying "create" as
SubresourceOperation
, only thePOST:/users/:userId/articles
would be generated. You get the idea, this works the same for others operations. - A single relation should use the
details
SubresourceOperation
whereas a collection should use thelist
SubresourceOperation
.
Nesting#
Subresources are nestable by default, so you could have a GET:/users/:userId/articles/comments
by making
Article.comments
a subresource as well. And if you're crazy enough, nothing stops you from nesting further with a
GET:/users/:userId/articles/comments/upvotes
, etc.
The defaultEntityRouteOptions
(passed to the
makers
) has a defaultSubresourceMaxDepthLvl: 2
.
Max depth#
You can control the max depth using the maxDepth key of SubresourceOptions. Each
maxDepth is independant from each other. If no max depth is defined, it will fallback to the
defaultSubresourceMaxDepthLvl
of EntityRouteOptions
, and if somehow no
defaultSubresourceMaxDepthLvl
is defined, it will default to 2.
Circular#
Circular subresources are disabled by default. You can allow this behavior using the allowCircular
key of
SubresourceOptions.
Example: Let's say a user
has articles
, these articles
have both a writers
(linking back to the User
entity)
and also have a relatedArticles
subresources.
By allowing circular subresources (and with the appropriates max depths configured), the route
GET:/users/articles/writers
would be generated.
With single relations#
The example above and most use-cases of subresources will be for collection relation
(OneToMany
/ManyToMany
).
But sometimes you might want a single relation
(OneToOne
/ManyToOne
)
to be a subresource.
There is actually no difference in usage between single/collection subresources but here's an example for the sake of it.
Let's say you have a User
entity that is linked with a config
relation. Rather than exposing the config
in the
/users
route and have a lot of unnecessary nested data, you might want to directly access the config with only the
properties you want for that route scope
.
By decorating the config
property with the @Subresource decorator, you generates 3 routes
:
GET:/users/:userId/config
, which will show you theconfig
of the givenuser
POST:/users/:userId/config
, which will allow you to join aconfig
to thisuser
(a newconfig
is inserted if noconfig
.id is given !)DELETE:/users/:userId/config
, which will allow you to remove the relation between the givenuser
/config
Format in response#
With the EntityRouteOptions
key shouldSetSubresourcesIriOnItem
, the corresponding
subresources IRI are added for each items having subresources (without exposing them through
@Groups
).
The defaultEntityRouteOptions
(passed to the
makers
) has a shouldSetSubresourcesIriOnItem: true
.
With subresource IRI#
Using the same example from above with User/Article, here's how that would look like :
The articles
property will have its subresource IRI displayed in the responses :
With relation exposed#
When exposing the articles
property on user.details
, the response will differ :
With nested property exposed#
And if you exposed properties from that subresource relation (with @Groups
):
This is how the response would look like with User.articles.title
exposed :
Metadata#
You can retrieve the RouteSubresourcesMeta
registered by an
@EntityRoute
decorator by using the
getRouteSubresourcesMetadata
function.