TypeScript Express Postgres Relationships
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity({ name: 'users' })
class UserEntity {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public name?: string;
@Column()
public email?: string;
@Column()
public password?: string;
}
export default UserEntity;
One-To-One
import { Column, Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
import AddressEntity from '../address/address.entity';
@Entity({ name: 'user' })
class UserEntity {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public name?: string;
@Column()
public email?: string;
@Column()
public password?: string;
@OneToOne(() => AddressEntity)
@JoinColumn()
public address?: AddressEntity;
}
export default UserEntity;
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
@Entity({name: 'address'})
class AddressEntity {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public street?: string;
@Column()
public city?: string;
@Column()
public country?: string;
}
export default AddressEntity;
Inverse relationship
import { Column, Entity, JoinColumn, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
import AddressEntity from '../address/address.entity';
@Entity({ name: 'user' })
class UserEntity {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public name?: string;
@Column()
public email?: string;
@Column()
public password?: string;
@OneToOne(() => AddressEntity, (address: AddressEntity) => address.user)
@JoinColumn()
public address?: AddressEntity;
}
export default UserEntity;
import UserEntity from '../../entities/user/user.entity';
import { Column, Entity, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
@Entity({name: 'address'})
class AddressEntity {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public street?: string;
@Column()
public city?: string;
@Column()
public country?: string;
@OneToOne(() => UserEntity, (user: UserEntity) => user.address)
public user?: UserEntity
}
export default AddressEntity;
export async function getAllAddresses(
request: express.Request,
response: express.Response
) {
const addressRepository = await getRepository(AddressEntity);
const addresses = await addressRepository.find({relations: ["user"]});
response.send(addresses);
}
import * as express from "express";
import Controller from "../../interfaces/controller.interface";
import * as addressService from "../../service/address/address.service";
class AddressController implements Controller {
public path = "/address";
public router = express.Router();
private addressService = addressService;
constructor() {
this.initializeRoutes();
}
private initializeRoutes() {
this.router.get(this.path, this.getAllAddresses);
}
private getAllAddresses = (
request: express.Request,
response: express.Response
) => {
this.addressService.getAllAddresses(request, response);
};
}
export default AddressController;
import express from "express";
import PostNotFoundException from "../../exceptions/PostNotFoundException";
import RequestWithUser from "../../interfaces/requestWithUser.interface";
import NotAuthorizedException from "../../exceptions/NotAuthorizedException";
import { getRepository } from "../../utils/connectedToDatabase";
import AddressEntity from "../../entities/address/address.entity";
import UserEntity from "../../entities/user/user.entity";
export async function createUser(
request: RequestWithUser,
response: express.Response
) {
const usertRepository = await getRepository(UserEntity);
const user = new UserEntity();
user.name = 'John Doe';
user.email = 'jo@host';
user.password = '123';
const address = new AddressEntity();
address.street = 'street';
address.city = 'city';
address.country = 'country';
user.address = address;
const createdUser = await usertRepository.save(user);
response.send(createdUser);
}
export async function getUserById(
request: express.Request,
response: express.Response,
next: express.NextFunction
) {
const id = request.params.id;
const userRepository = await getRepository(UserEntity);
const user = await userRepository.findOneBy({ id });
if (user) {
response.send(user);
} else {
next(new PostNotFoundException(id));
}
}
import * as express from "express";
import Controller from "../../interfaces/controller.interface";
import validationMiddleware from "../../middleware/validation.middleware";
import CreatePostDto from "../../dto/posts/post.dto";
import authMiddleware from '../../middleware/auth.middleware';
import RequestWithUser from '../../interfaces/requestWithUser.interface';
import * as userService from "../../service/user/user.service";
class UserController implements Controller {
public path = "/users";
public router = express.Router();
private userService = userService;
constructor() {
this.initializeRoutes();
}
private initializeRoutes() {
this.router.get(`${this.path}/:id`, this.getUserById);
this.router.post(
this.path,
this.createUser as any
);
}
private getUserById = (
request: express.Request,
response: express.Response,
next: express.NextFunction
) => {
this.userService.getUserById(request, response, next);
};
private createUser = (
request: RequestWithUser,
response: express.Response
) => {
this.userService.createUser(request, response);
};
}
export default UserController;
import 'dotenv/config';
import 'reflect-metadata';
import App from './app';
import PostsController from './controller/posts/post.controller';
import UserController from './controller/user/user.controller';
(async () => {
const app = new App(
[
new PostsController(),
new UserController(),
],
);
app.listen();
})();


One-To-Many and Many-To-One
import { Column, Entity, JoinColumn, OneToMany, OneToOne, PrimaryGeneratedColumn } from 'typeorm';
import AddressEntity from '../address/address.entity';
import PostEntity from '../../entities/post/post.entity';
@Entity({ name: 'user' })
class UserEntity {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public name?: string;
@Column()
public email?: string;
@Column()
public password?: string;
@OneToOne(() => AddressEntity, (address: AddressEntity) => address.user, {
cascade: true,
eager: true,
})
@JoinColumn()
public address?: AddressEntity;
@OneToMany(() => PostEntity, (post: PostEntity) => post.author)
public posts?: PostEntity[];
}
export default UserEntity;
import UserEntity from "../../entities/user/user.entity";
import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
@Entity({ name: "post" })
class PostEntity {
@PrimaryGeneratedColumn()
public id?: number;
@Column()
public title!: string;
@Column()
public content!: string;
@ManyToOne(() => UserEntity, (author: UserEntity) => author.posts)
public author?: UserEntity;
}
export default PostEntity;
export async function createPost(
request: RequestWithUser,
response: express.Response
) {
const postData: Post = request.body;
const postRepository = await getRepository(PostEntity);
const userRepository = await getRepository(UserEntity);
const user = await userRepository.findOneBy({ id: request.user.id });
if (!user) {
throw new NotAuthorizedException();
}
const postEntity = new PostEntity();
postEntity.author = user;
postEntity.title = postData.title;
postEntity.content = postData.content;
const createdPost = await postRepository.save(postEntity);
response.send(createdPost);
}
Many-To-Many
import UserEntity from "../../entities/user/user.entity";
import { Column, Entity, JoinTable, ManyToMany, ManyToOne, PrimaryGeneratedColumn } from "typeorm";
import CategoryEntity from '../category/category.entiry';
@Entity({ name: "post" })
class PostEntity {
@PrimaryGeneratedColumn()
public id?: number;
@Column()
public title!: string;
@Column()
public content!: string;
@ManyToOne(() => UserEntity, (author: UserEntity) => author.posts)
public author?: UserEntity;
@ManyToMany(() => CategoryEntity, (category: CategoryEntity) => category.posts)
@JoinTable()
categories?: CategoryEntity[];
}
export default PostEntity;
import PostEntity from '../../entities/post/post.entity';
import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from 'typeorm';
@Entity({name: 'category'})
class CategoryEntity {
@PrimaryGeneratedColumn()
public id!: string;
@Column()
public name!: string;
@Column()
public pid!: string;
@ManyToMany(() => PostEntity, (post: PostEntity) => post.categories)
public posts?: PostEntity[];
}
export default CategoryEntity;
import express from "express";
import PostNotFoundException from "../../exceptions/PostNotFoundException";
import RequestWithUser from "../../interfaces/requestWithUser.interface";
import NotAuthorizedException from "../../exceptions/NotAuthorizedException";
import { getRepository } from "../../utils/connectedToDatabase";
import CreateCategoryDto from "dto/category/category.dto";
import CategoryEntity from "../../entities/category/category.entiry";
export async function createCategory(
request: RequestWithUser,
response: express.Response
) {
const categoryData: CreateCategoryDto = request.body;
const categoryRepository = await getRepository(CategoryEntity);
const categoryEntity = new CategoryEntity();
categoryEntity.name = categoryData.name;
categoryEntity.pid = categoryData.pid!;
const createdCategory = await categoryRepository.save(categoryEntity);
response.send(createdCategory);
}
export async function getAllCategories(
request: express.Request,
response: express.Response
) {
const categoryRepository = await getRepository(CategoryEntity);
const addresses = await categoryRepository.find();
response.send(addresses);
}
export async function getCategoryById(
request: express.Request,
response: express.Response,
next: express.NextFunction
) {
const id = request.params.id;
const categoryRepository = await getRepository(CategoryEntity);
const category = await categoryRepository.findOneBy({ id });
if (category) {
response.send(category);
} else {
next(new PostNotFoundException(id));
}
}
export async function modifyCategory(
request: express.Request,
response: express.Response,
next: express.NextFunction
) {
const id = request.params.id;
const catigoryData: CreateCategoryDto = request.body;
const categoryRepository = await getRepository(CategoryEntity);
const category = await categoryRepository.findOneBy({ id });
if (category) {
category.name = catigoryData.name;
category.pid = catigoryData.pid!;
await categoryRepository.save(category);
response.send(category);
} else {
next(new PostNotFoundException(id));
}
}
export async function deleteCategory(
request: express.Request,
response: express.Response,
next: express.NextFunction
) {
const id = request.params.id;
const postRepository = await getRepository(CategoryEntity);
const post = await postRepository.delete(id);
console.log("delete post: ", post);
if (post) {
response.send(200);
} else {
next(new PostNotFoundException(id));
}
}
import * as express from "express";
import Controller from "../../interfaces/controller.interface";
import validationMiddleware from "../../middleware/validation.middleware";
import authMiddleware from '../../middleware/auth.middleware';
import RequestWithUser from '../../interfaces/requestWithUser.interface';
import * as categoryService from "../../service/category/category.service";
class CategoryController implements Controller {
public path = "/categories";
public router = express.Router();
private categoryService = categoryService;
constructor() {
this.initializeRoutes();
}
private initializeRoutes() {
this.router.get(this.path, this.getAllCategories);
this.router.get(`${this.path}/:id`, this.getCategoryById);
this.router.patch(`${this.path}/:id`, this.modifyCategory);
this.router.delete(`${this.path}/:id`, this.deleteCategory);
this.router.post(
this.path,
this.createCategory as any
);
}
private getAllCategories = (
request: express.Request,
response: express.Response
) => {
this.categoryService.getAllCategories(request, response);
};
private getCategoryById = (
request: express.Request,
response: express.Response,
next: express.NextFunction
) => {
this.categoryService.getCategoryById(request, response, next);
};
private modifyCategory = (
request: express.Request,
response: express.Response,
next: express.NextFunction
) => {
this.categoryService.modifyCategory(request, response, next);
};
private createCategory = (
request: RequestWithUser,
response: express.Response
) => {
this.categoryService.createCategory(request, response);
};
private deleteCategory = (
request: express.Request,
response: express.Response,
next: express.NextFunction
) => {
this.categoryService.deleteCategory(request, response, next);
};
}
export default CategoryController;
import { IsString } from 'class-validator';
class CreateCategoryDto {
@IsString()
public name!: string;
@IsString()
public pid?: string;
}
export default CreateCategoryDto;
import 'dotenv/config';
import 'reflect-metadata';
import App from './app';
import PostsController from './controller/posts/post.controller';
import UserController from './controller/user/user.controller';
import CategoryController from './controller/category/category.controller';
(async () => {
const app = new App(
[
new PostsController(),
new UserController(),
new CategoryController()
],
);
app.listen();
})();


source