API with Nest js and sequelize - part 2
Model Synchronization
A model can be synchronized with the database using the model.sync(options). It returns promise and is as asynchronous function.
Sequelize will perform the necessary sql query in the database to create or update table.
import { Sequelize } from 'sequelize-typescript';
import { databaseConfig } from './database.config';
import { Portfolio } from 'src/portfolio/entities/portfolio.entity';
export const databaseProviders = [{
provide: "SEQUELIZE",
useFactory: async () => {
let config;
switch (process.env.NODE_ENV) {
case "development":
config = databaseConfig.development;
break;
case "test":
config = databaseConfig.test;
break;
case "production":
config = databaseConfig.production;
break;
default:
config = databaseConfig.development;
}
const sequelize = new Sequelize(config);
sequelize.addModels([Portfolio]);
await sequelize.sync({ alter: true });
return sequelize;
},
}];
Here we have used the sync() method.
model.sync() : Creates the table if it does not exist else do nothing
model.sync({force:true}) : Drops the existing table and create a new one.
model.sync({alter:true}) : Updates the table like adding/removing new columns, changing datatypes.
In the part 1, we completed the project setup. We covered the database configuration. And we have completed the C of CRUD. Here we will sell four operations.
portfolio.controller.ts
import { Controller, Get, Post, Body, Patch, Param, Delete } from '@nestjs/common';
import { PortfolioService } from './portfolio.service';
import { CreatePortfolioDto } from './dto/create-portfolio.dto';
import { UpdatePortfolioDto } from './dto/update-portfolio.dto';
import { get } from 'http';
@Controller('portfolio')
export class PortfolioController {
constructor(private readonly portfolioService: PortfolioService) {}
@Post()
create(@Body() createPortfolioDto: CreatePortfolioDto) {
return this.portfolioService.create(createPortfolioDto);
}
@Get()
findAll() {
return this.portfolioService.findAll();
}
@Get(':id')
findOne(@Param('id') id: string) {
return this.portfolioService.findOne(+id);
}
@Patch(':id')
update(@Param('id') id: string, @Body() updatePortfolioDto: UpdatePortfolioDto) {
return this.portfolioService.update(+id, updatePortfolioDto);
}
@Delete(':id')
remove(@Param('id') id: string) {
return this.portfolioService.remove(+id);
}
}
portfolio.service.ts
Here we are injecting the sequelize model Portfolio, named as portfolioRepository.
import { Inject, Injectable } from '@nestjs/common';
import { CreatePortfolioDto } from './dto/create-portfolio.dto';
import { UpdatePortfolioDto } from './dto/update-portfolio.dto';
import { Portfolio } from './entities/portfolio.entity';
@Injectable()
export class PortfolioService {
constructor(@Inject("PORTFOLIO_REPOSITORY") private readonly portfolioRepository: typeof Portfolio) { }
async create(createPortfolioDto: CreatePortfolioDto) : Promise<Portfolio> {
return await this.portfolioRepository.create<Portfolio>(createPortfolioDto)
}
async findAll() {
return await this.portfolioRepository.findAll();
}
async findOne(id: number) {
return await this.portfolioRepository.findOne({
where:{
id
}
})
}
async update(id: number, updatePortfolioDto: UpdatePortfolioDto) {
return await this.portfolioRepository.update(updatePortfolioDto,{
where:{id:id}
});
}
async remove(id: number) {
return await this.portfolioRepository.destroy({
where:{id:id}
});
}
}
portfolio.provider.ts
As configured here, "PORTFOLIO_REPOSITORY" is just a Portfolio model here.
import { Portfolio } from "./entities/portfolio.entity";
export const portfolioProviders = [{
provide: "PORTFOLIO_REPOSITORY",
useValue: Portfolio,
}];
portfolio.modules.ts
We need to bind controller, service, provider within one module. We group those related class into one module and expose them as one module , Portfolio module.
import { Module } from '@nestjs/common';
import { PortfolioService } from './portfolio.service';
import { PortfolioController } from './portfolio.controller';
import { portfolioProviders } from './portfolio.providers';
@Module({
controllers: [PortfolioController],
providers: [PortfolioService, ...portfolioProviders],
exports:[PortfolioService]
})
export class PortfolioModule {}
One of the advantage of creating module is to prevent scattering different related classes like controller, provider, services, dto, entitiy, model into various location. But to place them together in one folder under one module.
The second advantage is that, now we can expose all these class using their module.
app.modules.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { PortfolioModule } from './portfolio/portfolio.module';
import { DatabaseModule } from './database/database.module';
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot({
envFilePath:
process.env.NODE_ENV === 'production'
? ['.env.production']
: ['.env.development'],
isGlobal: true,
}),
PortfolioModule,
DatabaseModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Here in the main module named app.module.ts, the portfolioModule is registered.
We used the sequelize methods to perform the crud operation. The methods are simple and self-explanatory. Anyone who has worked with any other ORM like Entiryframework can easily relate.
Create
await this.portfolioRepository.create<Portfolio>(createPortfolioDto)
Read
await this.portfolioRepository.findAll();
await this.portfolioRepository.findOne({
where:{
id
}
})
Update
await this.portfolioRepository.update(updatePortfolioDto,{
where:{id:id}
});
Delete
await this.portfolioRepository.destroy({
where:{id:id}
});
Swagger
We configure it in the main.ts file
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const config = new DocumentBuilder().setTitle('portfolio-api').build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('/api', app, document);
app.enableCors({
origin: '*',
});
await app.listen(3030);
}
bootstrap();
Note that the app.listen(portNumber) should be after the swagger configuration.
And that's it. Just with this much work you can get swagger UI in the baseurl/api location
Don't forget to install before using
npm i @nestjs/swagger