Customer: Use Case (3: Implementing NestJS Service)
Amalia Hajarani
Posted on November 30, 2023
Prerequisites
- Installed Node version of
v20.10.0
- Installed PostgreSQL version of
16
Initialize NestJS application
I'm assuming that you have already created project directories just like what I did in the first post.
-
Install nest cli globally using
command prompt
.
npm i -g @nestjs/cli
Open new
command prompt
from thenest-service
directory.-
Create new NestJS project by running command below. I choose
npm
as the package manager.
nest new .
-
Install these dependencies:
Dependency to work with .env file
npm i --save @nestjs/config
TypeOrm dependencies
npm install @nestjs/typeorm typeorm
PostgreSQL dependency
npm install pg
My
package.json
dependencies looks like:
"dependencies": { "@nestjs/common": "^10.0.0", "@nestjs/config": "^3.1.1", "@nestjs/core": "^10.0.0", "@nestjs/platform-express": "^10.0.0", "@nestjs/typeorm": "^10.0.1", "pg": "^8.11.3", "reflect-metadata": "^0.1.13", "rxjs": "^7.8.1", "typeorm": "^0.3.17" }
-
Create project directory skeleton that looks like this:
nest-service/ ├── src/ │ ├── config/ │ ├── controllers/ │ ├── entities/ │ ├── modules/ │ ├── services/ │ ├── app.controller.ts │ ├── app.module.ts │ ├── app.service.ts │ └── main.ts ├── .env └── package.json
-
My
.env
file looks like below. Makesure that you have correct and working port and credentials.
PORT=3002 DB_HOST=localhost DB_PORT=5432 DB_USERNAME=postgres DB_PASSWORD=password DB_NAME=customer
Creating configuration
Inside config
directory, create a file named database.config.ts
the content will look like this:
import { PostgresConnectionOptions } from "typeorm/driver/postgres/PostgresConnectionOptions";
import { ConfigService } from '@nestjs/config';
export const databaseConfig = async (configService: ConfigService): Promise<PostgresConnectionOptions> => ({
type: 'postgres',
host: configService.get<string>('DB_HOST'),
port: parseInt(configService.get<string>('DB_PORT')),
username: configService.get<string>('DB_USERNAME'),
password: configService.get<string>('DB_PASSWORD'),
database: configService.get<string>('DB_NAME'),
entities: ["dist/**/*.entity{.ts,.js}"],
synchronize: false,
});
creating entities
Now, let's move on to entities
directory. Create a file called Customer.enitity.ts
.
import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn } from "typeorm";
@Entity('customers')
export class Customer {
@PrimaryGeneratedColumn()
id: number;
@Column()
no: string;
@Column()
nama: string;
@Column()
alamat: string
@Column()
kota: string
@CreateDateColumn()
createdAt: Date
@UpdateDateColumn()
updatedAt: Date;
}
Creating services
In services we are going to create a file named customer.service.ts
and the content is looks like this:
import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { randomUUID } from "crypto";
import { Customer } from "src/entities/Customer.entity";
import { Repository } from "typeorm";
export interface CustomerInterface {
id?: string,
no?: string,
nama: string,
alamat: string,
kota: string
createdAt?: Date;
updatedAt?: Date;
};
@Injectable()
export class CustomersService {
constructor(
@InjectRepository(Customer)
private customerRepository: Repository<CustomerInterface>
) {}
create(customer: CustomerInterface): Promise<CustomerInterface> {
const customerBody = this.customerRepository.create(customer);
customerBody.no = randomUUID();
customerBody.createdAt = new Date();
customerBody.updatedAt = new Date();
return this.customerRepository.save(customerBody);
}
findAll(): Promise<CustomerInterface[]> {
return this.customerRepository.find();
}
findById(id: string): Promise<CustomerInterface> {
return this.customerRepository
.findOne({
where: {
id: id
}
});
}
update(id: string, data: CustomerInterface): Promise<any> {
return this.customerRepository
.createQueryBuilder()
.update()
.set({
nama: data.nama,
alamat: data.alamat,
kota: data.kota
})
.where('id = :id', { id })
.execute();
}
delete(id: string): Promise<any> {
return this.customerRepository
.createQueryBuilder()
.delete()
.from(Customer)
.where('id = :id', { id })
.execute();
}
}
Creating controllers
Let's create the controller for customer by making a file called customer.controller.ts
inside controllers
directory.
import { Body, Controller, Delete, Get, Param, Post, Put } from "@nestjs/common";
import { CustomerInterface, CustomersService } from "src/services/customer.service";
interface CreateCustomerDto {
nama: string,
alamat: string,
kota: string
};
@Controller('api/customers')
export class CustomersController {
constructor(private customerService: CustomersService) {}
@Post()
async create(@Body() createCustomerDto: CreateCustomerDto) {
const customer = await this.customerService.create(createCustomerDto);
if(!customer) {
return 'Error creating customer';
}
return 'Customer created successfully';
}
@Get()
async findAll() {
const customers: Array<CustomerInterface> = await this.customerService.findAll();
return customers;
}
@Get(':id')
async findByNama(@Param('id') id: string ) {
const customer: CustomerInterface = await this.customerService.findById(id);
return customer;
}
@Put(':id')
async update(@Param('id') id: string, @Body() body: CustomerInterface) {
const newCustomer: CustomerInterface = await this.customerService.update(id, body);
if(!newCustomer) {
return 'Error updating customer';
}
return 'Customer updated successfully';
}
@Delete(':id')
async remove(@Param('id') id: string) {
await this.customerService.delete(id);
return 'Successfully deleted customer with id' + id;
}
}
Creating module
Last, we need to pool our entity
, controller
, and service
at the module
. Create a file called customer.module.ts
inside modules
directory.
import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CustomersController } from 'src/controllers/customer.controller';
import { Customer } from 'src/entities/Customer.entity';
import { CustomersService } from 'src/services/customer.service';
@Module({
imports: [TypeOrmModule.forFeature([Customer])],
controllers: [CustomersController],
providers: [CustomersService]
})
export class CustomersModule {}
Configuring customer module in main module
In app.module.ts
file which located in root directory, we will configuring the things we've created like this:
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CustomersModule } from './modules/customer.module';
import { databaseConfig } from './config/database.config';
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true
}),
TypeOrmModule.forRootAsync({
imports: [ConfigModule],
inject: [ConfigService],
useFactory: async (configService: ConfigService) => await databaseConfig(configService),
}),
CustomersModule
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
Running application
- Back to
nest-service
root directory, open command prompt directed to the directory. - Run
npm run start
. It will take a little longer. - If it is running correctly you will see this log:
- Test your API endpoints using Postman or Thunder Client.
Posted on November 30, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.