TypeORM

beta Contributors are welcome

This tutorial provide two way to create connection:

  • The first one use @tsed/typeorm module to creation multiple connections with ,
  • The seconds use the new async provider feature introduced in v5.27 to create connection.

Additionally, this topic show you how you can use Entity from Typeorm with Ts.ED controller (on bottom of this page).

Solution with @tsed/typeorm

TIP

You can find a working example on TypeORM here.

Feature

Currently, @tsed/typeorm allows you:

  • Configure one or more TypeORM connections via the @ServerSettings configuration. All databases will be initialized when the server starts during the server's OnInit phase.
  • Use the Entity TypeORM as Model for Controllers, AJV Validation and Swagger.

Installation

To begin, install the TypeORM module for TS.ED:

npm install --save @tsed/typeorm
1

Then import @tsed/typeorm in your :

import {ServerLoader, ServerSettings} from "@tsed/common";
import "@tsed/typeorm"; // import typeorm ts.ed module

@ServerSettings({
  typeorm: [
    {
      name: "default",
      type: "postgres",
      // ...,

      entities: [
        `${__dirname}/entity/*{.ts,.js}`
      ],
      migrations: [
        `${__dirname}/migrations/*{.ts,.js}`
      ],
      subscribers: [
        `${__dirname}/subscriber/*{.ts,.js}`
      ]
    },
    {
      name: "mongo",
      type: "mongodb"
      // ...
    }
  ]
})
export class Server extends ServerLoader {

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

TypeORMService

TypeORMService let you to retrieve an instance of TypeORM Connection.

import {AfterRoutesInit, Injectable} from "@tsed/common";
import {TypeORMService} from "@tsed/typeorm";
import {Connection} from "typeorm";
import {User} from "../models/User";

@Injectable()
export class UsersService implements AfterRoutesInit {
  private connection: Connection;

  constructor(private typeORMService: TypeORMService) {

  }

  $afterRoutesInit() {
    this.connection = this.typeORMService.get("mongoose")!; // get connection by name
  }

  async create(user: User): Promise<User> {
    // do something
    // ...
    // Then save
    await this.connection.manager.save(user);
    console.log("Saved a new user with id: " + user.id);

    return user;
  }

  async find(): Promise<User[]> {
    const users = await this.connection.manager.find(User);
    console.log("Loaded users: ", users);

    return users;
  }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

For more information about TypeORM look his documentation here;

Solution with Async provider

This solution let you manage your connection and create provider around this with useAsyncFactory feature (See custom providers)

WARNING

@tsed/typeorm must not installed on your project but you have to install typeorm npm module instead.

Declare you connection as provider

import {Configuration, registerProvider} from "@tsed/di";
import {Connection, ConnectionOptions, getConnectionManager} from "typeorm";

export const CONNECTION = Symbol.for("CONNECTION"); // declare your own
export type CONNECTION = Connection; // Set alias types (optional)

registerProvider({
  provide: CONNECTION,
  deps: [Configuration],
  async useAsyncFactory(configuration: Configuration) {
    const settings = configuration.get<ConnectionOptions>("customSettings")!;

    const connection = getConnectionManager().create(settings!);
    await connection.connect();

    // Add hook to close connection when server is killed
    // @ts-ignore
    connection.$onDestroy = () => connection.close();

    return connection;
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

Inject connection in another service

import {Inject, Injectable} from "@tsed/di";
import {CONNECTION} from "./typeorm-async-provider";

@Injectable()
export class UserService {
  constructor(@Inject(CONNECTION) connection: CONNECTION) {

  }
}
1
2
3
4
5
6
7
8
9

Configure your connection

import {ServerLoader, ServerSettings} from "@tsed/common";
import "./connections/CONNECTION";

@ServerSettings({
  customConnection: {
    name: "default",
    type: "postgres",
    // ...,

    entities: [
      `${__dirname}/entity/*{.ts,.js}`
    ],
    migrations: [
      `${__dirname}/migrations/*{.ts,.js}`
    ],
    subscribers: [
      `${__dirname}/subscriber/*{.ts,.js}`
    ]
  }
})
export class Server extends ServerLoader {

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

Use Entity TypeORM with Controller

We need to define an Entity TypeORM like this and use Ts.ED Decorator to define the JSON Schema.

import {Maximum, MaxLength, Minimum, Property, Required} from "@tsed/common";
import {Column, Entity, PrimaryGeneratedColumn} from "typeorm";

@Entity()
export class User {

  @PrimaryGeneratedColumn()
  @Property()
  id: number;

  @Column()
  @MaxLength(100)
  @Required()
  firstName: string;

  @Column()
  @MaxLength(100)
  @Required()
  lastName: string;

  @Column()
  @Minimum(0)
  @Maximum(100)
  age: number;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

Now, the model is correctly defined and can be used with a Controller, AJV validation, Swagger and TypeORM.

We can use this model with a Controller like that:

import {BodyParams, Controller, Get, Post} from "@tsed/common";
import {User} from "../entities/User";
import {UsersService} from "../services/UsersService";

@Controller("/users")
export class UsersCtrl {
  constructor(private usersService: UsersService) {
  }

  @Post("/")
  create(@BodyParams() user: User): Promise<User> {
    return this.usersService.create(user);
  }

  @Get("/")
  getList(): Promise<User[]> {
    return this.usersService.find();
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19