Create Nest.js Entities
In this part of the tutorial, we shall be creating TypeORM entities in Nest.js. Entities are code representations of database objects, usually tables and views. They allow us to perform database operations, such as CRUD operations, but without having to write SQL code. Before we create the entities we shall generate modules for our resources that will be stored within a modules directory. In our application, we shall be using the repository design pattern, where each entity will have its own repository.
Generate modules for the various resources
We’ll create separate modules for each of our resources using the nest.s CLI, and store the modules in their respective directories.
Within the project root run:
nest g module modules/orders
nest g module modules/products
nest g module modules/customers
Create the entities
Under the respective modules, we shall store our entities within a models directory like so:
Customer entity:
import { Exclude } from 'class-transformer';
import { Order } from '../../orders/models/order';
import {
Column,
CreateDateColumn,
Entity,
OneToMany,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity('customers')
export class Customer {
constructor(intialData: Partial<Customer> = null) {
if (intialData !== null) {
Object.assign(this, intialData);
}
}
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ type: 'varchar' })
name: string;
@Column({ type: 'varchar' })
email: string;
@Column({ name: 'phone_number', type: 'varchar' })
phoneNumber: string;
@Exclude()
@Column({ name: 'password_digest', type: 'varchar' })
password: string;
@CreateDateColumn({
name: 'created_at',
type: 'timestamptz',
default: 'now()',
readonly: true,
})
createdAt: string;
@UpdateDateColumn({
name: 'updated_at',
type: 'timestamptz',
default: 'now()',
})
updatedAt: string;
@OneToMany(() => Order, (order) => order.customer)
orders: Order[];
}
Product entity:
import { OrderItem } from 'src/modules/orders/models/order-item';
import {
Column,
CreateDateColumn,
Entity,
OneToMany,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity()
export class Product {
constructor(intialData: Partial<Product> = null) {
if (intialData !== null) {
Object.assign(this, intialData);
}
}
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ type: 'varchar' })
name: string;
@Column({ name: 'unit_price', type: 'numeric' })
unitPrice: number;
@Column({ name: 'is_discontinued', type: 'boolean' })
isDiscontinued: boolean;
@Column({ type: 'text' })
description: string;
@Column({ type: 'varchar' })
image: string;
@CreateDateColumn({
name: 'created_at',
type: 'timestamptz',
default: 'now()',
readonly: true,
})
createdAt: string;
@UpdateDateColumn({
name: 'updated_at',
type: 'timestamptz',
default: 'now()',
})
updatedAt: string;
@OneToMany(() => OrderItem, (orderItem) => orderItem.product)
orderItems: OrderItem[];
}
Order entity:
import { Customer } from '../../customers/models/customer';
import {
Column,
CreateDateColumn,
Entity,
JoinColumn,
ManyToOne,
OneToMany,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
import { OrderItem } from './order-item';
@Entity()
export class Order {
constructor(intialData: Partial<Order> = null) {
if (intialData !== null) {
Object.assign(this, intialData);
}
}
@PrimaryGeneratedColumn('uuid')
id: string;
@Column({ name: 'customer_id', type: 'uuid' })
customerId: string;
@Column({ name: 'total_amount', type: 'numeric' })
totalAmount: number;
@CreateDateColumn({
name: 'created_at',
type: 'timestamptz',
default: 'now()',
readonly: true,
})
createdAt: string;
@UpdateDateColumn({
name: 'updated_at',
type: 'timestamptz',
default: 'now()',
})
updatedAt: string;
@ManyToOne(() => Customer, (customer) => customer.orders)
@JoinColumn({ name: 'customer_id', referencedColumnName: 'id' })
customer: Customer;
@OneToMany(() => OrderItem, (orderItem) => orderItem.order)
orderItems: OrderItem[];
}
Order item entity:
import { Product } from '../../products/models/product';
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm';
import { Order } from './order';
@Entity()
export class OrderItem {
constructor(intialData: Partial<OrderItem> = null) {
if (intialData !== null) {
Object.assign(this, intialData);
}
}
@PrimaryColumn({ name: 'order_id', type: 'uuid' })
orderId: string;
@PrimaryColumn({ name: 'product_id', type: 'uuid' })
productId: string;
@Column({ name: 'unit_price', type: 'numeric' })
unitPrice: number;
@Column({ type: 'numeric' })
quantity: number;
@ManyToOne(() => Product, (product) => product.orderItems)
@JoinColumn({ name: 'product_id', referencedColumnName: 'id' })
product: Product;
@ManyToOne(() => Order, (order) => order.orderItems)
@JoinColumn({ name: 'order_id', referencedColumnName: 'id' })
order: Order;
}
In all the above entities, I have also modelled the 1 to many, as well as many to 1 relationships that we had in our entity relationship diagram.
SOURCES
- TypeORM Entities Documentation: https://typeorm.io/entities
- TypeORM Repository Documentation: https://typeorm.io/working-with-repository
- Nest.js Documentation: https://docs.nestjs.com/techniques/database