entity-routes logo
Docs

Examples#

Code examples below have been shortened with only relevants parts.

Basic operations#

Given a User entity described here.

#
typescript
1@EntityRoute({ path: "/users", operations: ["create", "update", "details", "list", "delete"] })
2@Entity()
3export class User extends AbstractEntity {
4 @Column()
5 name: string;
7 @Column()
8 birthDate: Date;
10 @Column()
11 email: string;

Let's say we want to expose the user name through basic CRUD_OPERATIONS for any context.

#
typescript
1class User {
2 @Groups("basic")
3 name: string;
4}

But we would also like to expose it for any route scope, on a custom operation (which is matching a custom route action with the same operation).

#
typescript
1// You could decorate it with another @Groups
2class User {
3 @Groups("basic")
4 @Groups(["admin_custom"])
5 name: string;
6}
8// or write all the operations yourself and get the same result
9class User {
10 @Groups(["create", "update", "list", "details", "admin_custom"])
11 name: string;

And finally, we want to expose it precisely on the article context on customList operation.

#
typescript
1// You can just decorate it with yet another @Groups, you get the idea.
2class User {
3 @Groups("basic")
4 @Groups(["admin_custom"])
5 @Groups({ article: ["customList"] })
6 name: string;
7}

Relations#

IRI#

Given a User entity described here.

#
typescript
1@EntityRoute({ path: "/users", operations: ["create", "update", "details", "list", "delete"] })
2@Entity()
3export class User extends AbstractEntity {
4 @Column()
5 name: string;
7 @ManyToOne(() => Role)
8 role: Role;
9}

And a Role entity described here.

#
typescript
1@EntityRoute()
2@Entity()
3export class Role extends AbstractEntity {
4 @Column()
5 title: string;
6}

Remember, since every entities should extend from the GenericEntity interface and always have the id property exposed, you can expose your relations IRI by just decorating the relation with @Groups on the parent entity.

#
typescript
1class User extends AbstractEntity {
2 @Groups({ user: ["details"] })
3 @ManyToOne(() => Role)
4 role: Role;
5}

If no other properties than id are exposed on role for the user.details route scope, you will end up with a response such as :

#
json
1{
2 "@context": {
3 "operation": "details",
4 "entity": "user"
5 },
6 "id": 1,
7 "name": "Alex",
8 "role": "/api/role/1"
9}

Nested property#

To expose a nested property, you need to decorate with @Groups both the relation (on the parent entity) and the property (of the relation) with the same route scope.

For this example, let's expose the user's role.title property for the details route (GET:/user/xxx route).

#
typescript
1class User extends AbstractEntity {
2 @Groups({ user: ["details"] })
3 @ManyToOne(() => Role)
4 role: Role;
5}
#
typescript
1class Role extends AbstractEntity {
2 @Groups({ user: ["details"] })
3 @Column()
4 title: string;
5}

That's it ! The user details route (GET:/user/1) will contain a role object with a title property inside :

#
json
1{
2 "@context": {
3 "operation": "details",
4 "entity": "user"
5 },
6 "id": 1,
7 "name": "Alex",
8 "role": {
9 "id": 1,
10 "title": "Admin"
11 }

This works the exact same way with a property that is a collection (OneToMany/ManyToMany) instead of a single relation (OneToOne/ManyToOne).

Still, for the sake of it let's have an example using User/Articles entities. Let's expose the user's articles.title property for the list route (GET:/user/xxx route).

#
typescript
1class User extends AbstractEntity {
2 @Groups({ user: ["details"] })
3 @Subresource(() => Article)
4 @OneToMany(() => Article, (article) => article.author)
5 articles: Article[];
6}
#
typescript
1class Article extends AbstractEntity {
2 @Groups({ user: ["details"] })
3 @Column()
4 title: string;
6 @Column()
7 content: string;
9 @ManyToOne(() => User, (user) => user.articles)
10 author: User;

And you would end up with this kind of response :

#
json
1{
2 "@context": {
3 "operation": "details",
4 "entity": "user"
5 },
6 "articles": [
7 {
8 "id": 1,
9 "title": "First article"
10 }
11 ],
12 "id": 1,
13 "name": "Alex"

Of course, if you hadn't exposed the articles.title property while keeping user.articles exposed, you would only have the articles IRI returned :

#
json
1{
2 "@context": {
3 "operation": "details",
4 "entity": "user"
5 },
6 "articles": ["/api/article/1"],
7 "id": 1,
8 "name": "Alex"
9}
Prev
Computed property
Next
Introduction