SQL
To reduce a boilerplate necessary to start the adventure with the databases, Nest comes with the ready to use @nestjs/typeorm package.
We have selected TypeORM because it is definitely the most mature Object Relational Mapper (ORM) available in the node.js world.
Since it's written in TypeScript, it works pretty well with the Nest framework.
Firstly, we need to install all of the required dependencies:
$ npm install --save @nestjs/typeorm typeorm mysql
Notice In this chapter we'll use a MySQL database, but TypeORM provides a support for a lot of different ones such as PostgreSQL, SQLite, and even MongoDB (NoSQL).
Once the installation process is completed, we can import the TypeOrmModule into the root ApplicationModule.
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [
TypeOrmModule.forRoot({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'root',
database: 'test',
entities: [__dirname + '/../**/*.entity{.ts,.js}'],
synchronize: true,
}),
],
})
export class ApplicationModule {}
The forRoot() method accepts the same configuration object as createConnection() from the TypeORM package.
Futhermore, instead of passing anything to the forRoot(), we can create an ormconfig.json file in the project root directory.
{
"type": "mysql",
"host": "localhost",
"port": 3306,
"username": "root",
"password": "root",
"database": "test",
"entities": ["src/**/**.entity{.ts,.js}"],
"synchronize": true
}
Now we can simply leave the parenthesis empty:
app.module.ts
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [TypeOrmModule.forRoot()],
})
export class ApplicationModule {}
Afterwards, the Connection and EntityManager will be available to inject across entire project (without importing any module elsewhere), for example in this way:
import { Connection } from 'typeorm';
@Module({
imports: [TypeOrmModule.forRoot(), PhotoModule],
})
export class ApplicationModule {
constructor(private readonly connection: Connection) {}
}
import { Connection } from 'typeorm';
@Dependencies(Connection)
@Module({
imports: [TypeOrmModule.forRoot(), PhotoModule],
})
export class ApplicationModule {
constructor(connection) {
this.connection = connection;
}
}
Repository pattern
The TypeORM supports the repository design pattern, so each entity has its own Repository. These repositories can be obtained from the database connection.
Firstly, we need at least one entity. We're gonna reuse the Photo entity from the offical documentation.
import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';
@Entity()
export class Photo {
@PrimaryGeneratedColumn()
id: number;
@Column({ length: 500 })
name: string;
@Column('text')
description: string;
@Column()
filename: string;
@Column('int')
views: number;
@Column()
isPublished: boolean;
}
The Photo entity belongs to the photo directory.
This directory represents the PhotoModule. It's your decision where you gonna keep your model files. From my point of view, the best way's to hold them nearly their domain, in the appropriate module directory.
Let's have a look at the PhotoModule:
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { PhotoService } from './photo.service';
import { PhotoController } from './photo.controller';
import { Photo } from './photo.entity';
@Module({
imports: [TypeOrmModule.forFeature([Photo])],
components: [PhotoService],
controllers: [PhotoController],
})
export class PhotoModule {}
This module uses forFeature() method to define which repositories shall be registered in the current scope.
Now we can inject the PhotoRepository to the PhotoService using the @InjectRepository() decorator:
import { Component, Inject } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Photo } from './photo.entity';
@Component()
export class PhotoService {
constructor(
@InjectRepository(Photo)
private readonly photoRepository: Repository<Photo>,
) {}
async findAll(): Promise<Photo[]> {
return await this.photoRepository.find();
}
}
import { Component, Dependencies } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Photo } from './photo.entity';
@Component()
@Dependencies(InjectRepository(Photo))
export class PhotoService {
constructor(photoRepository) {
this.photoRepository = photoRepository;
}
async findAll() {
return await this.photoRepository.find();
}
}
That's all. The full source code's available here.
Hint Don't forget to import thePhotoModuleinto the rootApplicationModule.