# TypeORM Contributors are welcome

# Features

Currently, @tsed/typeorm allows you to:

  • Configure one or more TypeORM connections via the @Configuration 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.
  • Declare a connection with asyncProvider or automatically by server configuration.

# Installation

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

npm install --save @tsed/typeorm
npm install --save typeorm
1
2

Then import @tsed/typeorm in your Server:

import {Configuration} from "@tsed/di";
import "@tsed/platform-express";
import "@tsed/typeorm"; // !!! IMPORTANT TO ADD THIS !!!

@Configuration({
  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 {

}
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

WARNING

Don't forget to import the TypeORM module in the Server. Ts.ED need it to load correctly the TypeORM DI, entities and repositories!

# TypeORMService

TypeORMService lets you retrieve an instance of TypeORM Connection.

import {AfterRoutesInit} from "@tsed/common";
import {Injectable} from "@tsed/di";
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
36

For more information about TypeORM, look its documentation here (opens new window);

# Declare your connection as provider

It is also possible to create your connection with the useAsyncFactory feature (See custom providers) This approach allows you to inject your connection as a Service to another one.

To create a new connection, declare your custom provider as follows:

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

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

const CONNECTION_NAME = "default"; // change the name according to your server configuration

registerProvider({
  provide: CONNECTION,
  deps: [Configuration],
  async useAsyncFactory(configuration: Configuration) {
    const settings = configuration.get<ConnectionOptions[]>("typeorm")!;
    const connectionOptions = settings.find(o => o.name === CONNECTION_NAME);

    return createConnection(connectionOptions!);
  }
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Then inject your connection to another service or provide like this:

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

# 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/schema";
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

Now, the model is correctly defined and can be used with a Controller, AJV validation, Swagger and TypeORM (opens new window).

We can use this model with a Controller like that:

import {BodyParams} from "@tsed/platform-params";
import {Get, Post} from "@tsed/schema";
import {Controller} from "@tsed/di";
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
20
21

# EntityRepository

You can create a custom repository which should contain methods to work with your database. Usually custom repositories are created for a single entity and contain their specific queries. For example, let's say we want to have a method called findByName(firstName: string, lastName: string) which will search for users by a given first and last names. The best place for this method is in Repository, so we could call it like userRepository.findByName(...). You can achieve this using custom repositories.

@tsed/typeorm plugin configures the DI so that repositories declared for TypeORM can be injected into a Ts.ED controller or service.

The first way to create a custom repository is to extend Repository. Example:

import {Repository, EntityRepository} from "typeorm";
import {User} from "../entity/User";

@EntityRepository(User)
export class UserRepository extends Repository<User> {
  findByName(firstName: string, lastName: string) {
    return this.findOne({ firstName, lastName });
  }
}
1
2
3
4
5
6
7
8
9

Then inject your repository to another service:

import {Inject, Injectable} from "@tsed/di";
import {UseConnection} from "@tsed/typeorm";
import {UserRepository} from "./repository/UserRepository";

@Injectable()
export class OtherService {
  @Inject()
  @UseConnection("db2")
  userRepository2: UserRepository;

  constructor(public userRepository: UserRepository,
              @UseConnection("db3") public userRepository3: UserRepository) {

  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

TIP

Use UseConnection decorator to select which database connection the injected repository should be used (require Ts.ED v5.58.0+).

# Author

    # Maintainers Help wanted

      Last Updated: 1/27/2022, 2:23:22 PM

      Other topics