typescript-express-starter 10.0.1 → 10.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/lib/mikro-orm/src/routes/auth.route.ts +2 -2
  2. package/lib/mikro-orm/src/routes/users.route.ts +2 -2
  3. package/lib/mongoose/src/routes/auth.route.ts +2 -2
  4. package/lib/mongoose/src/routes/users.route.ts +2 -2
  5. package/lib/node-postgres/.env.development.local +7 -0
  6. package/lib/node-postgres/.env.production.local +7 -0
  7. package/lib/node-postgres/.env.test.local +7 -0
  8. package/lib/node-postgres/.swcrc +0 -1
  9. package/lib/node-postgres/src/app.ts +0 -6
  10. package/lib/node-postgres/src/config/index.ts +1 -1
  11. package/lib/node-postgres/src/database/index.ts +6 -2
  12. package/lib/node-postgres/src/database/init.sql +11 -108
  13. package/lib/node-postgres/src/middlewares/auth.middleware.ts +12 -4
  14. package/lib/node-postgres/src/routes/auth.route.ts +2 -2
  15. package/lib/node-postgres/src/routes/users.route.ts +2 -2
  16. package/lib/node-postgres/src/services/auth.service.ts +66 -15
  17. package/lib/node-postgres/src/services/users.service.ts +103 -21
  18. package/lib/node-postgres/src/test/auth.test.ts +8 -3
  19. package/lib/node-postgres/src/test/users.test.ts +16 -15
  20. package/lib/node-postgres/tsconfig.json +0 -1
  21. package/lib/prisma/src/routes/auth.route.ts +2 -2
  22. package/lib/prisma/src/routes/users.route.ts +2 -2
  23. package/lib/routing-controllers/package.json +1 -1
  24. package/lib/routing-controllers/src/controllers/auth.controller.ts +2 -2
  25. package/lib/routing-controllers/src/controllers/users.controller.ts +2 -2
  26. package/lib/sequelize/src/routes/auth.route.ts +2 -2
  27. package/lib/sequelize/src/routes/users.route.ts +2 -2
  28. package/lib/typegoose/src/routes/auth.route.ts +2 -2
  29. package/lib/typegoose/src/routes/users.route.ts +2 -2
  30. package/lib/typeorm/.env.development.local +5 -5
  31. package/lib/typeorm/.env.production.local +5 -5
  32. package/lib/typeorm/.env.test.local +5 -5
  33. package/lib/typeorm/docker-compose.yml +8 -8
  34. package/lib/typeorm/src/config/index.ts +1 -1
  35. package/lib/typeorm/src/database/index.ts +6 -6
  36. package/lib/typeorm/src/routes/auth.route.ts +2 -2
  37. package/lib/typeorm/src/routes/users.route.ts +2 -2
  38. package/package.json +1 -1
  39. package/lib/node-postgres/src/models/users.model.ts +0 -9
@@ -15,8 +15,8 @@ export class AuthRoute implements Routes {
15
15
  }
16
16
 
17
17
  private initializeRoutes() {
18
- this.router.post(`${this.path}signup`, ValidationMiddleware(CreateUserDto, 'body'), this.auth.signUp);
19
- this.router.post(`${this.path}login`, ValidationMiddleware(CreateUserDto, 'body'), this.auth.logIn);
18
+ this.router.post(`${this.path}signup`, ValidationMiddleware(CreateUserDto), this.auth.signUp);
19
+ this.router.post(`${this.path}login`, ValidationMiddleware(CreateUserDto), this.auth.logIn);
20
20
  this.router.post(`${this.path}logout`, AuthMiddleware, this.auth.logOut);
21
21
  }
22
22
  }
@@ -16,8 +16,8 @@ export class UserRoute implements Routes {
16
16
  private initializeRoutes() {
17
17
  this.router.get(`${this.path}`, this.user.getUsers);
18
18
  this.router.get(`${this.path}/:id`, this.user.getUserById);
19
- this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto, 'body'), this.user.createUser);
20
- this.router.put(`${this.path}/:id`, ValidationMiddleware(CreateUserDto, 'body', true), this.user.updateUser);
19
+ this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto), this.user.createUser);
20
+ this.router.put(`${this.path}/:id`, ValidationMiddleware(CreateUserDto, true), this.user.updateUser);
21
21
  this.router.delete(`${this.path}/:id`, this.user.deleteUser);
22
22
  }
23
23
  }
@@ -15,8 +15,8 @@ export class AuthRoute implements Routes {
15
15
  }
16
16
 
17
17
  private initializeRoutes() {
18
- this.router.post(`${this.path}signup`, ValidationMiddleware(CreateUserDto, 'body'), this.auth.signUp);
19
- this.router.post(`${this.path}login`, ValidationMiddleware(CreateUserDto, 'body'), this.auth.logIn);
18
+ this.router.post(`${this.path}signup`, ValidationMiddleware(CreateUserDto), this.auth.signUp);
19
+ this.router.post(`${this.path}login`, ValidationMiddleware(CreateUserDto), this.auth.logIn);
20
20
  this.router.post(`${this.path}logout`, AuthMiddleware, this.auth.logOut);
21
21
  }
22
22
  }
@@ -16,8 +16,8 @@ export class UserRoute implements Routes {
16
16
  private initializeRoutes() {
17
17
  this.router.get(`${this.path}`, this.user.getUsers);
18
18
  this.router.get(`${this.path}/:id`, this.user.getUserById);
19
- this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto, 'body'), this.user.createUser);
20
- this.router.put(`${this.path}/:id`, ValidationMiddleware(CreateUserDto, 'body', true), this.user.updateUser);
19
+ this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto), this.user.createUser);
20
+ this.router.put(`${this.path}/:id`, ValidationMiddleware(CreateUserDto, true), this.user.updateUser);
21
21
  this.router.delete(`${this.path}/:id`, this.user.deleteUser);
22
22
  }
23
23
  }
@@ -11,3 +11,10 @@ LOG_DIR = ../logs
11
11
  # CORS
12
12
  ORIGIN = *
13
13
  CREDENTIALS = true
14
+
15
+ # DATABASE
16
+ POSTGRES_USER = root
17
+ POSTGRES_PASSWORD = password
18
+ POSTGRES_HOST = localhost
19
+ POSTGRES_PORT = 5432
20
+ POSTGRES_DB = dev
@@ -11,3 +11,10 @@ LOG_DIR = ../logs
11
11
  # CORS
12
12
  ORIGIN = your.domain.com
13
13
  CREDENTIALS = true
14
+
15
+ # DATABASE
16
+ POSTGRES_USER = root
17
+ POSTGRES_PASSWORD = password
18
+ POSTGRES_HOST = pg
19
+ POSTGRES_PORT = 5432
20
+ POSTGRES_DB = dev
@@ -11,3 +11,10 @@ LOG_DIR = ../logs
11
11
  # CORS
12
12
  ORIGIN = *
13
13
  CREDENTIALS = true
14
+
15
+ # DATABASE
16
+ POSTGRES_USER = root
17
+ POSTGRES_PASSWORD = password
18
+ POSTGRES_HOST = pg
19
+ POSTGRES_PORT = 5432
20
+ POSTGRES_DB = dev
@@ -28,7 +28,6 @@
28
28
  "@exceptions/*": ["exceptions/*"],
29
29
  "@interfaces/*": ["interfaces/*"],
30
30
  "@middlewares/*": ["middlewares/*"],
31
- "@models/*": ["models/*"],
32
31
  "@services/*": ["services/*"],
33
32
  "@utils/*": ["utils/*"]
34
33
  }
@@ -9,7 +9,6 @@ import morgan from 'morgan';
9
9
  import swaggerJSDoc from 'swagger-jsdoc';
10
10
  import swaggerUi from 'swagger-ui-express';
11
11
  import { NODE_ENV, PORT, LOG_FORMAT, ORIGIN, CREDENTIALS } from '@config';
12
- import { client } from '@database';
13
12
  import { Routes } from '@interfaces/routes.interface';
14
13
  import { ErrorMiddleware } from '@middlewares/error.middleware';
15
14
  import { logger, stream } from '@utils/logger';
@@ -24,7 +23,6 @@ export class App {
24
23
  this.env = NODE_ENV || 'development';
25
24
  this.port = PORT || 3000;
26
25
 
27
- this.connectToDatabase();
28
26
  this.initializeMiddlewares();
29
27
  this.initializeRoutes(routes);
30
28
  this.initializeSwagger();
@@ -44,10 +42,6 @@ export class App {
44
42
  return this.app;
45
43
  }
46
44
 
47
- private async connectToDatabase() {
48
- await client.connect();
49
- }
50
-
51
45
  private initializeMiddlewares() {
52
46
  this.app.use(morgan(LOG_FORMAT, { stream }));
53
47
  this.app.use(cors({ origin: ORIGIN, credentials: CREDENTIALS }));
@@ -3,4 +3,4 @@ config({ path: `.env.${process.env.NODE_ENV || 'development'}.local` });
3
3
 
4
4
  export const CREDENTIALS = process.env.CREDENTIALS === 'true';
5
5
  export const { NODE_ENV, PORT, SECRET_KEY, LOG_FORMAT, LOG_DIR, ORIGIN } = process.env;
6
- export const { DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_DATABASE } = process.env;
6
+ export const { POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB } = process.env;
@@ -1,6 +1,10 @@
1
1
  import { Client } from 'pg';
2
- import { DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_DATABASE } from '@config';
2
+ import { POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DB } from '@config';
3
3
 
4
4
  export const client = new Client({
5
- connectionString: `postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_DATABASE}`,
5
+ connectionString: `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}`,
6
6
  });
7
+
8
+ client.connect();
9
+
10
+ export default client;
@@ -1,110 +1,13 @@
1
- -- TABLE 존재할 경우 삭제
2
- DROP TABLE IF EXISTS teachers cascade;
3
- DROP TABLE IF EXISTS classes cascade;
4
- DROP TABLE IF EXISTS students cascade;
5
- DROP TABLE IF EXISTS classes_category cascade;
6
- DROP TABLE IF EXISTS enrolment cascade;
7
-
8
- -- ============
9
- -- 강사 테이블
10
- -- ============
11
- -- 강사 테이블 생성
12
- CREATE TABLE teachers(
13
- "teacherId" SERIAL PRIMARY KEY,
14
- -- 강사 ID
15
- "teacherName" VARCHAR(32) NOT NULL,
16
- -- 강사명
17
- "teacherAbout" VARCHAR(48) -- 강사 정보
18
- );
19
- -- 강사 데이터 생성
20
- INSERT INTO teachers(
21
- "teacherId",
22
- "teacherName",
23
- "teacherAbout"
24
- )
25
- VALUES (1, '조현영', '웹 개발 강사'),
26
- (2, '개복치개발자', '안드로이드 코틀린 강사'),
27
- (3, '이고잉', '생활코딩 운영진 겸 강사'),
28
- (4, '김태원', '파이썬 알고리즘 강사'),
29
- (5, '윤재성', 'Kotiln 기반 안드로이드 강사'),
30
- (6, '조훈', '쿠버네티스 강사'),
31
- (7, 'Rookiss', '얼리언 엔진 전문 강사'),
32
- (8, '유용한IT학습', 'SQLD 자격증 취득 강사'),
33
- (9, '김태민', '쿠버네티스 강사'),
34
- (10, '큰돌', '알고리즘 강사');
35
- SELECT SETVAL(
36
- '"teachers_teacherId_seq"',
37
- (
38
- SELECT max("teacherId")
39
- FROM teachers
40
- )
41
- );
42
- -- ===================
43
- -- 강의 카테고리 테이블
44
- -- ===================
45
- -- 강의 카테고리 테이블 생성
46
- CREATE TABLE classes_category(
47
- "categoryId" SERIAL PRIMARY KEY,
48
- -- 카테고리 ID
49
- "categoryName" VARCHAR(32) UNIQUE NOT NULL -- 카테고리 명
50
- );
51
- -- 강의 카테고리 데이터 생성
52
- INSERT INTO classes_category("categoryId", "categoryName")
53
- VALUES (1, '웹'),
54
- (2, '앱'),
55
- (3, '게임'),
56
- (4, '알고리즘'),
57
- (5, '인프라'),
58
- (6, '데이터베이스');
59
- SELECT SETVAL(
60
- '"classes_category_categoryId_seq"',
61
- (
62
- SELECT max("categoryId")
63
- FROM classes_category
64
- )
65
- );
66
- -- ============
67
- -- 강의 테이블
68
- -- ============
69
- -- 강의 테이블 생성
70
- CREATE TABLE classes(
71
- "classId" SERIAL PRIMARY KEY,
72
- -- 강의 ID
73
- "className" VARCHAR(32) UNIQUE NOT NULL,
74
- -- 강의명
75
- "classPrice" INTEGER NOT NULL DEFAULT 0,
76
- -- 가격
77
- "introduce" TEXT,
78
- -- 강의 소개
79
- "active" BOOLEAN NOT NULL DEFAULT false,
80
- -- 강의 활성화 (true: 공개, false, 비공개)
1
+ -- If Exists Table Drop
2
+ DROP TABLE IF EXISTS users cascade;
3
+ -- ================
4
+ -- TABLE [users]
5
+ -- ================
6
+ -- create users table
7
+ CREATE TABLE users(
8
+ "id" SERIAL PRIMARY KEY,
9
+ "email" VARCHAR(32) UNIQUE NOT NULL,
10
+ "password" VARCHAR(48) NOT NULL,
81
11
  "createdAt" TIMESTAMP WITHOUT TIME ZONE DEFAULT(NOW() AT TIME ZONE 'utc'),
82
- -- 강의 생성 일자
83
- "updatedAt" TIMESTAMP WITHOUT TIME ZONE,
84
- -- 강의 수정 일자
85
- "teacherId" INTEGER REFERENCES teachers("teacherId") ON DELETE CASCADE,
86
- -- 강사 ID
87
- "categoryId" INTEGER REFERENCES classes_category("categoryId") ON DELETE CASCADE -- 강사 ID
88
- );
89
- -- ==============
90
- -- 수강생 테이블
91
- -- ==============
92
- -- 수강생 테이블 생성
93
- CREATE TABLE students(
94
- "studentId" SERIAL PRIMARY KEY,
95
- -- 수강생 ID
96
- "email" VARCHAR(48) UNIQUE NOT NULL,
97
- -- 수강생 이메일
98
- "nickname" VARCHAR(32) NOT NULL -- 수강생 닉네임
99
- );
100
- -- ===============
101
- -- 수강신청 테이블
102
- -- ===============
103
- -- 수강신청 테이블 생성
104
- CREATE TABLE enrolment(
105
- "classId" INTEGER REFERENCES classes("classId") ON DELETE CASCADE,
106
- -- 강의 ID
107
- "studentId" INTEGER REFERENCES students("studentId") ON DELETE CASCADE,
108
- -- 수강생 ID
109
- "applicationAt" TIMESTAMP WITHOUT TIME ZONE DEFAULT(NOW() AT TIME ZONE 'utc') -- 신청 일자
12
+ "updatedAt" TIMESTAMP WITHOUT TIME ZONE
110
13
  );
@@ -1,9 +1,9 @@
1
1
  import { NextFunction, Response } from 'express';
2
2
  import { verify } from 'jsonwebtoken';
3
3
  import { SECRET_KEY } from '@config';
4
+ import pg from '@database';
4
5
  import { HttpException } from '@exceptions/httpException';
5
6
  import { DataStoredInToken, RequestWithUser } from '@interfaces/auth.interface';
6
- import { UserModel } from '@models/users.model';
7
7
 
8
8
  const getAuthorization = req => {
9
9
  const coockie = req.cookies['Authorization'];
@@ -21,10 +21,18 @@ export const AuthMiddleware = async (req: RequestWithUser, res: Response, next:
21
21
 
22
22
  if (Authorization) {
23
23
  const { id } = (await verify(Authorization, SECRET_KEY)) as DataStoredInToken;
24
- const findUser = UserModel.find(user => user.id === id);
24
+ const { rows, rowCount } = await pg.query(`
25
+ SELECT
26
+ "email",
27
+ "password"
28
+ FROM
29
+ users
30
+ WHERE
31
+ "id" = $1
32
+ `, id);
25
33
 
26
- if (findUser) {
27
- req.user = findUser;
34
+ if (rowCount) {
35
+ req.user = rows[0];
28
36
  next();
29
37
  } else {
30
38
  next(new HttpException(401, 'Wrong authentication token'));
@@ -14,8 +14,8 @@ export class AuthRoute implements Routes {
14
14
  }
15
15
 
16
16
  private initializeRoutes() {
17
- this.router.post('/signup', ValidationMiddleware(CreateUserDto, 'body'), this.auth.signUp);
18
- this.router.post('/login', ValidationMiddleware(CreateUserDto, 'body'), this.auth.logIn);
17
+ this.router.post('/signup', ValidationMiddleware(CreateUserDto), this.auth.signUp);
18
+ this.router.post('/login', ValidationMiddleware(CreateUserDto), this.auth.logIn);
19
19
  this.router.post('/logout', AuthMiddleware, this.auth.logOut);
20
20
  }
21
21
  }
@@ -16,8 +16,8 @@ export class UserRoute implements Routes {
16
16
  private initializeRoutes() {
17
17
  this.router.get(`${this.path}`, this.user.getUsers);
18
18
  this.router.get(`${this.path}/:id(\\d+)`, this.user.getUserById);
19
- this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto, 'body'), this.user.createUser);
20
- this.router.put(`${this.path}/:id(\\d+)`, ValidationMiddleware(CreateUserDto, 'body', true), this.user.updateUser);
19
+ this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto), this.user.createUser);
20
+ this.router.put(`${this.path}/:id(\\d+)`, ValidationMiddleware(CreateUserDto, true), this.user.updateUser);
21
21
  this.router.delete(`${this.path}/:id(\\d+)`, this.user.deleteUser);
22
22
  }
23
23
  }
@@ -2,10 +2,10 @@ import { hash, compare } from 'bcrypt';
2
2
  import { sign } from 'jsonwebtoken';
3
3
  import { Service } from 'typedi';
4
4
  import { SECRET_KEY } from '@config';
5
+ import pg from '@database';
5
6
  import { HttpException } from '@exceptions/httpException';
6
7
  import { DataStoredInToken, TokenData } from '@interfaces/auth.interface';
7
8
  import { User } from '@interfaces/users.interface';
8
- import { UserModel } from '@models/users.model';
9
9
 
10
10
  const createToken = (user: User): TokenData => {
11
11
  const dataStoredInToken: DataStoredInToken = { id: user.id };
@@ -21,32 +21,83 @@ const createCookie = (tokenData: TokenData): string => {
21
21
  @Service()
22
22
  export class AuthService {
23
23
  public async signup(userData: User): Promise<User> {
24
- const findUser: User = UserModel.find(user => user.email === userData.email);
25
- if (findUser) throw new HttpException(409, `This email ${userData.email} already exists`);
24
+ const { email, password } = userData;
26
25
 
27
- const hashedPassword = await hash(userData.password, 10);
28
- const createUserData: User = { id: UserModel.length + 1, ...userData, password: hashedPassword };
26
+ const { rows: findUser } = await pg.query(
27
+ `
28
+ SELECT EXISTS(
29
+ SELECT
30
+ "email"
31
+ FROM
32
+ users
33
+ WHERE
34
+ "email" = $1
35
+ )`,
36
+ [email],
37
+ );
38
+ if (findUser[0].exists) throw new HttpException(409, `This email ${userData.email} already exists`);
29
39
 
30
- return createUserData;
40
+ const hashedPassword = await hash(password, 10);
41
+ const { rows: signUpUserData } = await pg.query(
42
+ `
43
+ INSERT INTO
44
+ users(
45
+ "email",
46
+ "password"
47
+ )
48
+ VALUES ($1, $2)
49
+ RETURNING "email", "password"
50
+ `,
51
+ [email, hashedPassword],
52
+ );
53
+
54
+ return signUpUserData[0];
31
55
  }
32
56
 
33
57
  public async login(userData: User): Promise<{ cookie: string; findUser: User }> {
34
- const findUser: User = UserModel.find(user => user.email === userData.email);
35
- if (!findUser) throw new HttpException(409, `This email ${userData.email} was not found`);
58
+ const { email, password } = userData;
59
+
60
+ const { rows, rowCount } = await pg.query(
61
+ `
62
+ SELECT
63
+ "email",
64
+ "password"
65
+ FROM
66
+ users
67
+ WHERE
68
+ "email" = $1
69
+ `,
70
+ [email],
71
+ );
72
+ if (!rowCount) throw new HttpException(409, `This email ${email} was not found`);
36
73
 
37
- const isPasswordMatching: boolean = await compare(userData.password, findUser.password);
74
+ const isPasswordMatching: boolean = await compare(password, rows[0].password);
38
75
  if (!isPasswordMatching) throw new HttpException(409, "You're password not matching");
39
76
 
40
- const tokenData = createToken(findUser);
77
+ const tokenData = createToken(rows[0]);
41
78
  const cookie = createCookie(tokenData);
42
-
43
- return { cookie, findUser };
79
+ return { cookie, findUser: rows[0] };
44
80
  }
45
81
 
46
82
  public async logout(userData: User): Promise<User> {
47
- const findUser: User = UserModel.find(user => user.email === userData.email && user.password === userData.password);
48
- if (!findUser) throw new HttpException(409, "User doesn't exist");
83
+ const { email, password } = userData;
84
+
85
+ const { rows, rowCount } = await pg.query(
86
+ `
87
+ SELECT
88
+ "email",
89
+ "password"
90
+ FROM
91
+ users
92
+ WHERE
93
+ "email" = $1
94
+ AND
95
+ "password" = $2
96
+ `,
97
+ [email, password],
98
+ );
99
+ if (!rowCount) throw new HttpException(409, "User doesn't exist");
49
100
 
50
- return findUser;
101
+ return rows[0];
51
102
  }
52
103
  }
@@ -1,51 +1,133 @@
1
1
  import { hash } from 'bcrypt';
2
2
  import { Service } from 'typedi';
3
+ import pg from '@database';
3
4
  import { HttpException } from '@exceptions/httpException';
4
5
  import { User } from '@interfaces/users.interface';
5
- import { UserModel } from '@models/users.model';
6
6
 
7
7
  @Service()
8
8
  export class UserService {
9
9
  public async findAllUser(): Promise<User[]> {
10
- const users: User[] = UserModel;
11
- return users;
10
+ const { rows } = await pg.query(`
11
+ SELECT
12
+ *
13
+ FROM
14
+ users
15
+ `);
16
+ return rows;
12
17
  }
13
18
 
14
19
  public async findUserById(userId: number): Promise<User> {
15
- const findUser: User = UserModel.find(user => user.id === userId);
16
- if (!findUser) throw new HttpException(409, "User doesn't exist");
20
+ const { rows, rowCount } = await pg.query(
21
+ `
22
+ SELECT
23
+ *
24
+ FROM
25
+ users
26
+ WHERE
27
+ id = $1
28
+ `,
29
+ [userId],
30
+ );
31
+ if (!rowCount) throw new HttpException(409, "User doesn't exist");
17
32
 
18
- return findUser;
33
+ return rows[0];
19
34
  }
20
35
 
21
36
  public async createUser(userData: User): Promise<User> {
22
- const findUser: User = UserModel.find(user => user.email === userData.email);
23
- if (findUser) throw new HttpException(409, `This email ${userData.email} already exists`);
37
+ const { email, password } = userData;
24
38
 
25
- const hashedPassword = await hash(userData.password, 10);
26
- const createUserData: User = { id: UserModel.length + 1, ...userData, password: hashedPassword };
39
+ const { rows } = await pg.query(
40
+ `
41
+ SELECT EXISTS(
42
+ SELECT
43
+ "email"
44
+ FROM
45
+ users
46
+ WHERE
47
+ "email" = $1
48
+ )`,
49
+ [email],
50
+ );
51
+ if (rows[0].exists) throw new HttpException(409, `This email ${email} already exists`);
27
52
 
28
- return createUserData;
53
+ const hashedPassword = await hash(password, 10);
54
+ const { rows: createUserData } = await pg.query(
55
+ `
56
+ INSERT INTO
57
+ users(
58
+ "email",
59
+ "password"
60
+ )
61
+ VALUES ($1, $2)
62
+ RETURNING "email", "password"
63
+ `,
64
+ [email, hashedPassword],
65
+ );
66
+
67
+ return createUserData[0];
29
68
  }
30
69
 
31
70
  public async updateUser(userId: number, userData: User): Promise<User[]> {
32
- const findUser: User = UserModel.find(user => user.id === userId);
33
- if (!findUser) throw new HttpException(409, "User doesn't exist");
71
+ const { rows: findUser } = await pg.query(
72
+ `
73
+ SELECT EXISTS(
74
+ SELECT
75
+ "id"
76
+ FROM
77
+ users
78
+ WHERE
79
+ "id" = $1
80
+ )`,
81
+ [userId],
82
+ );
83
+ if (findUser[0].exists) throw new HttpException(409, "User doesn't exist");
34
84
 
35
- const hashedPassword = await hash(userData.password, 10);
36
- const updateUserData: User[] = UserModel.map((user: User) => {
37
- if (user.id === findUser.id) user = { id: userId, ...userData, password: hashedPassword };
38
- return user;
39
- });
85
+ const { email, password } = userData;
86
+ const hashedPassword = await hash(password, 10);
87
+ const { rows: updateUserData } = await pg.query(
88
+ `
89
+ UPDATE
90
+ users
91
+ SET
92
+ "email" = $2,
93
+ "password" = $3
94
+ WHERE
95
+ "id" = $1
96
+ RETURNING "email", "password"
97
+ `,
98
+ [userId, email, hashedPassword],
99
+ );
40
100
 
41
101
  return updateUserData;
42
102
  }
43
103
 
44
104
  public async deleteUser(userId: number): Promise<User[]> {
45
- const findUser: User = UserModel.find(user => user.id === userId);
46
- if (!findUser) throw new HttpException(409, "User doesn't exist");
105
+ const { rows: findUser } = await pg.query(
106
+ `
107
+ SELECT EXISTS(
108
+ SELECT
109
+ "id"
110
+ FROM
111
+ users
112
+ WHERE
113
+ "id" = $1
114
+ )`,
115
+ [userId],
116
+ );
117
+ if (findUser[0].exists) throw new HttpException(409, "User doesn't exist");
118
+
119
+ const { rows: deleteUserData } = await pg.query(
120
+ `
121
+ DELETE
122
+ FROM
123
+ users
124
+ WHERE
125
+ id = $1
126
+ RETURNING "email", "password"
127
+ `,
128
+ [userId],
129
+ );
47
130
 
48
- const deleteUserData: User[] = UserModel.filter(user => user.id !== findUser.id);
49
131
  return deleteUserData;
50
132
  }
51
133
  }
@@ -1,15 +1,17 @@
1
1
  import request from 'supertest';
2
2
  import { App } from '@/app';
3
+ import pg from '@database';
3
4
  import { CreateUserDto } from '@dtos/users.dto';
4
5
  import { AuthRoute } from '@routes/auth.route';
5
6
 
6
7
  afterAll(async () => {
7
8
  await new Promise<void>(resolve => setTimeout(() => resolve(), 500));
9
+ pg.end();
8
10
  });
9
11
 
10
12
  describe('Testing Auth', () => {
11
13
  describe('[POST] /signup', () => {
12
- it('response should have the Create userData', () => {
14
+ it('response should have the Create userData', async () => {
13
15
  const userData: CreateUserDto = {
14
16
  email: 'example@email.com',
15
17
  password: 'password',
@@ -17,7 +19,10 @@ describe('Testing Auth', () => {
17
19
  const authRoute = new AuthRoute();
18
20
  const app = new App([authRoute]);
19
21
 
20
- return request(app.getServer()).post('/signup').send(userData);
22
+ return await request(app.getServer())
23
+ .post('/signup')
24
+ .send(userData)
25
+ .expect(201);
21
26
  });
22
27
  });
23
28
 
@@ -31,7 +36,7 @@ describe('Testing Auth', () => {
31
36
  const authRoute = new AuthRoute();
32
37
  const app = new App([authRoute]);
33
38
 
34
- return request(app.getServer())
39
+ return await request(app.getServer())
35
40
  .post('/login')
36
41
  .send(userData)
37
42
  .expect('Set-Cookie', /^Authorization=.+/);
@@ -1,33 +1,35 @@
1
1
  import request from 'supertest';
2
- import App from '@/app';
2
+ import { App } from '@/app';
3
+ import pg from '@database';
3
4
  import { CreateUserDto } from '@dtos/users.dto';
4
- import { User } from '@interfaces/users.interface';
5
- import { UserModel } from '@models/users.model';
6
5
  import { UserRoute } from '@routes/users.route';
7
6
 
8
7
  afterAll(async () => {
9
8
  await new Promise<void>(resolve => setTimeout(() => resolve(), 500));
9
+ pg.end();
10
10
  });
11
11
 
12
12
  describe('Testing Users', () => {
13
13
  describe('[GET] /users', () => {
14
- it('response statusCode 200 / findAll', () => {
15
- const findUser: User[] = UserModel;
14
+ it('response statusCode 200 / findAll', async () => {
16
15
  const usersRoute = new UserRoute();
17
16
  const app = new App([usersRoute]);
18
17
 
19
- return request(app.getServer()).get(`${usersRoute.path}`).expect(200, { data: findUser, message: 'findAll' });
18
+ return await request(app.getServer()).get(`${usersRoute.path}`).expect(200);
20
19
  });
21
20
  });
22
21
 
23
22
  describe('[GET] /users/:id', () => {
24
- it('response statusCode 200 / findOne', () => {
25
- const userId = 1;
26
- const findUser: User = UserModel.find(user => user.id === userId);
23
+ it('response statusCode 200 / findOne', async () => {
27
24
  const usersRoute = new UserRoute();
28
25
  const app = new App([usersRoute]);
29
26
 
30
- return request(app.getServer()).get(`${usersRoute.path}/${userId}`).expect(200, { data: findUser, message: 'findOne' });
27
+ return await request(app.getServer())
28
+ .get(`${usersRoute.path}`)
29
+ .query({
30
+ userId: 1,
31
+ })
32
+ .expect(200);
31
33
  });
32
34
  });
33
35
 
@@ -40,7 +42,7 @@ describe('Testing Users', () => {
40
42
  const usersRoute = new UserRoute();
41
43
  const app = new App([usersRoute]);
42
44
 
43
- return request(app.getServer()).post(`${usersRoute.path}`).send(userData).expect(201);
45
+ return await request(app.getServer()).post(`${usersRoute.path}`).send(userData).expect(201);
44
46
  });
45
47
  });
46
48
 
@@ -54,18 +56,17 @@ describe('Testing Users', () => {
54
56
  const usersRoute = new UserRoute();
55
57
  const app = new App([usersRoute]);
56
58
 
57
- return request(app.getServer()).put(`${usersRoute.path}/${userId}`).send(userData).expect(200);
59
+ return await request(app.getServer()).put(`${usersRoute.path}/${userId}`).send(userData).expect(200);
58
60
  });
59
61
  });
60
62
 
61
63
  describe('[DELETE] /users/:id', () => {
62
- it('response statusCode 200 / deleted', () => {
64
+ it('response statusCode 200 / deleted', async () => {
63
65
  const userId = 1;
64
- const deleteUser: User[] = UserModel.filter(user => user.id !== userId);
65
66
  const usersRoute = new UserRoute();
66
67
  const app = new App([usersRoute]);
67
68
 
68
- return request(app.getServer()).delete(`${usersRoute.path}/${userId}`).expect(200, { data: deleteUser, message: 'deleted' });
69
+ return await request(app.getServer()).delete(`${usersRoute.path}/${userId}`).expect(200);
69
70
  });
70
71
  });
71
72
  });
@@ -29,7 +29,6 @@
29
29
  "@exceptions/*": ["exceptions/*"],
30
30
  "@interfaces/*": ["interfaces/*"],
31
31
  "@middlewares/*": ["middlewares/*"],
32
- "@models/*": ["models/*"],
33
32
  "@routes/*": ["routes/*"],
34
33
  "@services/*": ["services/*"],
35
34
  "@utils/*": ["utils/*"]
@@ -15,8 +15,8 @@ export class AuthRoute implements Routes {
15
15
  }
16
16
 
17
17
  private initializeRoutes() {
18
- this.router.post(`${this.path}signup`, ValidationMiddleware(CreateUserDto, 'body'), this.auth.signUp);
19
- this.router.post(`${this.path}login`, ValidationMiddleware(CreateUserDto, 'body'), this.auth.logIn);
18
+ this.router.post(`${this.path}signup`, ValidationMiddleware(CreateUserDto), this.auth.signUp);
19
+ this.router.post(`${this.path}login`, ValidationMiddleware(CreateUserDto), this.auth.logIn);
20
20
  this.router.post(`${this.path}logout`, AuthMiddleware, this.auth.logOut);
21
21
  }
22
22
  }
@@ -16,8 +16,8 @@ export class UserRoute implements Routes {
16
16
  private initializeRoutes() {
17
17
  this.router.get(`${this.path}`, this.user.getUsers);
18
18
  this.router.get(`${this.path}/:id(\\d+)`, this.user.getUserById);
19
- this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto, 'body'), this.user.createUser);
20
- this.router.put(`${this.path}/:id(\\d+)`, ValidationMiddleware(CreateUserDto, 'body', true), this.user.updateUser);
19
+ this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto), this.user.createUser);
20
+ this.router.put(`${this.path}/:id(\\d+)`, ValidationMiddleware(CreateUserDto, true), this.user.updateUser);
21
21
  this.router.delete(`${this.path}/:id(\\d+)`, this.user.deleteUser);
22
22
  }
23
23
  }
@@ -10,7 +10,7 @@
10
10
  "build": "swc src -d dist --source-maps --copy-files",
11
11
  "build:tsc": "tsc && tsc-alias",
12
12
  "test": "jest --forceExit --detectOpenHandles",
13
- "lint": "eslint --ignore-path .gitignore --ext .ts src/",
13
+ "lint": "eslint --ignore-path .gitignore --ext .ts src",
14
14
  "lint:fix": "npm run lint -- --fix",
15
15
  "deploy:prod": "npm run build && pm2 start ecosystem.config.js --only prod",
16
16
  "deploy:dev": "pm2 start ecosystem.config.js --only dev"
@@ -13,7 +13,7 @@ export class AuthController {
13
13
  public auth = Container.get(AuthService);
14
14
 
15
15
  @Post('/signup')
16
- @UseBefore(ValidationMiddleware(CreateUserDto, 'body'))
16
+ @UseBefore(ValidationMiddleware(CreateUserDto))
17
17
  @HttpCode(201)
18
18
  async signUp(@Body() userData: User) {
19
19
  const signUpUserData: User = await this.auth.signup(userData);
@@ -21,7 +21,7 @@ export class AuthController {
21
21
  }
22
22
 
23
23
  @Post('/login')
24
- @UseBefore(ValidationMiddleware(CreateUserDto, 'body'))
24
+ @UseBefore(ValidationMiddleware(CreateUserDto))
25
25
  async logIn(@Res() res: Response, @Body() userData: User) {
26
26
  const { cookie, findUser } = await this.auth.login(userData);
27
27
 
@@ -27,7 +27,7 @@ export class UserController {
27
27
 
28
28
  @Post('/users')
29
29
  @HttpCode(201)
30
- @UseBefore(ValidationMiddleware(CreateUserDto, 'body'))
30
+ @UseBefore(ValidationMiddleware(CreateUserDto))
31
31
  @OpenAPI({ summary: 'Create a new user' })
32
32
  async createUser(@Body() userData: User) {
33
33
  const createUserData: User = await this.user.createUser(userData);
@@ -35,7 +35,7 @@ export class UserController {
35
35
  }
36
36
 
37
37
  @Put('/users/:id')
38
- @UseBefore(ValidationMiddleware(CreateUserDto, 'body', true))
38
+ @UseBefore(ValidationMiddleware(CreateUserDto, true))
39
39
  @OpenAPI({ summary: 'Update a user' })
40
40
  async updateUser(@Param('id') userId: number, @Body() userData: User) {
41
41
  const updateUserData: User[] = await this.user.updateUser(userId, userData);
@@ -14,8 +14,8 @@ export class AuthRoute implements Routes {
14
14
  }
15
15
 
16
16
  private initializeRoutes() {
17
- this.router.post('/signup', ValidationMiddleware(CreateUserDto, 'body'), this.auth.signUp);
18
- this.router.post('/login', ValidationMiddleware(CreateUserDto, 'body'), this.auth.logIn);
17
+ this.router.post('/signup', ValidationMiddleware(CreateUserDto), this.auth.signUp);
18
+ this.router.post('/login', ValidationMiddleware(CreateUserDto), this.auth.logIn);
19
19
  this.router.post('/logout', AuthMiddleware, this.auth.logOut);
20
20
  }
21
21
  }
@@ -16,8 +16,8 @@ export class UserRoute implements Routes {
16
16
  private initializeRoutes() {
17
17
  this.router.get(`${this.path}`, this.user.getUsers);
18
18
  this.router.get(`${this.path}/:id(\\d+)`, this.user.getUserById);
19
- this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto, 'body'), this.user.createUser);
20
- this.router.put(`${this.path}/:id(\\d+)`, ValidationMiddleware(CreateUserDto, 'body', true), this.user.updateUser);
19
+ this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto), this.user.createUser);
20
+ this.router.put(`${this.path}/:id(\\d+)`, ValidationMiddleware(CreateUserDto, true), this.user.updateUser);
21
21
  this.router.delete(`${this.path}/:id(\\d+)`, this.user.deleteUser);
22
22
  }
23
23
  }
@@ -14,8 +14,8 @@ export class AuthRoute implements Routes {
14
14
  }
15
15
 
16
16
  private initializeRoutes() {
17
- this.router.post('/signup', ValidationMiddleware(CreateUserDto, 'body'), this.auth.signUp);
18
- this.router.post('/login', ValidationMiddleware(CreateUserDto, 'body'), this.auth.logIn);
17
+ this.router.post('/signup', ValidationMiddleware(CreateUserDto), this.auth.signUp);
18
+ this.router.post('/login', ValidationMiddleware(CreateUserDto), this.auth.logIn);
19
19
  this.router.post('/logout', AuthMiddleware, this.auth.logOut);
20
20
  }
21
21
  }
@@ -16,8 +16,8 @@ export class UserRoute implements Routes {
16
16
  private initializeRoutes() {
17
17
  this.router.get(`${this.path}`, this.user.getUsers);
18
18
  this.router.get(`${this.path}/:id`, this.user.getUserById);
19
- this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto, 'body'), this.user.createUser);
20
- this.router.put(`${this.path}/:id`, ValidationMiddleware(CreateUserDto, 'body', true), this.user.updateUser);
19
+ this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto), this.user.createUser);
20
+ this.router.put(`${this.path}/:id`, ValidationMiddleware(CreateUserDto, true), this.user.updateUser);
21
21
  this.router.delete(`${this.path}/:id`, this.user.deleteUser);
22
22
  }
23
23
  }
@@ -2,11 +2,11 @@
2
2
  PORT = 3000
3
3
 
4
4
  # DATABASE
5
- DB_USER = root
6
- DB_PASSWORD = password
7
- DB_HOST = localhost
8
- DB_PORT = 5432
9
- DB_DATABASE = dev
5
+ POSTGRES_USER = root
6
+ POSTGRES_PASSWORD = password
7
+ POSTGRES_HOST = localhost
8
+ POSTGRES_PORT = 5432
9
+ POSTGRES_DATABASE = dev
10
10
 
11
11
  # TOKEN
12
12
  SECRET_KEY = secretKey
@@ -2,11 +2,11 @@
2
2
  PORT = 3000
3
3
 
4
4
  # DATABASE
5
- DB_USER = root
6
- DB_PASSWORD = password
7
- DB_HOST = localhost
8
- DB_PORT = 5432
9
- DB_DATABASE = dev
5
+ POSTGRES_USER = root
6
+ POSTGRES_PASSWORD = password
7
+ POSTGRES_HOST = localhost
8
+ POSTGRES_PORT = 5432
9
+ POSTGRES_DATABASE = dev
10
10
 
11
11
  # TOKEN
12
12
  SECRET_KEY = secretKey
@@ -2,11 +2,11 @@
2
2
  PORT = 3000
3
3
 
4
4
  # DATABASE
5
- DB_USER = root
6
- DB_PASSWORD = password
7
- DB_HOST = localhost
8
- DB_PORT = 5432
9
- DB_DATABASE = dev
5
+ POSTGRES_USER = root
6
+ POSTGRES_PASSWORD = password
7
+ POSTGRES_HOST = localhost
8
+ POSTGRES_PORT = 5432
9
+ POSTGRES_DATABASE = dev
10
10
 
11
11
  # TOKEN
12
12
  SECRET_KEY = secretKey
@@ -20,11 +20,11 @@ services:
20
20
  ports:
21
21
  - "3000:3000"
22
22
  environment:
23
- DB_USER: root
24
- DB_PASSWORD: password
25
- DB_HOST: pg
26
- DB_PORT: 5432
27
- DB_DATABASE: dev
23
+ POSTGRES_USER: root
24
+ POSTGRES_PASSWORD: password
25
+ POSTGRES_HOST: pg
26
+ POSTGRES_PORT: 5432
27
+ POSTGRES_DATABASE: dev
28
28
  volumes:
29
29
  - ./:/app
30
30
  - /app/node_modules
@@ -40,9 +40,9 @@ services:
40
40
  container_name: pg
41
41
  image: postgres:14.5-alpine
42
42
  environment:
43
- DB_USER: root
44
- DB_PASSWORD: password
45
- DB_DATABASE: dev
43
+ POSTGRES_USER: root
44
+ POSTGRES_PASSWORD: password
45
+ POSTGRES_DB: dev
46
46
  ports:
47
47
  - "5432:5432"
48
48
  networks:
@@ -3,4 +3,4 @@ config({ path: `.env.${process.env.NODE_ENV || 'development'}.local` });
3
3
 
4
4
  export const CREDENTIALS = process.env.CREDENTIALS === 'true';
5
5
  export const { NODE_ENV, PORT, SECRET_KEY, LOG_FORMAT, LOG_DIR, ORIGIN } = process.env;
6
- export const { DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_DATABASE } = process.env;
6
+ export const { POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DATABASE } = process.env;
@@ -1,15 +1,15 @@
1
1
  import { join } from 'path';
2
2
  import { createConnection, ConnectionOptions } from 'typeorm';
3
- import { DB_USER, DB_PASSWORD, DB_HOST, DB_PORT, DB_DATABASE } from '@config';
3
+ import { POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST, POSTGRES_PORT, POSTGRES_DATABASE } from '@config';
4
4
 
5
5
  export const dbConnection = async () => {
6
6
  const dbConfig: ConnectionOptions = {
7
7
  type: 'postgres',
8
- username: DB_USER,
9
- password: DB_PASSWORD,
10
- host: DB_HOST,
11
- port: Number(DB_PORT),
12
- database: DB_DATABASE,
8
+ username: POSTGRES_USER,
9
+ password: POSTGRES_PASSWORD,
10
+ host: POSTGRES_HOST,
11
+ port: +POSTGRES_PORT,
12
+ database: POSTGRES_DATABASE,
13
13
  synchronize: true,
14
14
  logging: false,
15
15
  entities: [join(__dirname, '../**/*.entity{.ts,.js}')],
@@ -14,8 +14,8 @@ export class AuthRoute implements Routes {
14
14
  }
15
15
 
16
16
  private initializeRoutes() {
17
- this.router.post('/signup', ValidationMiddleware(CreateUserDto, 'body'), this.auth.signUp);
18
- this.router.post('/login', ValidationMiddleware(CreateUserDto, 'body'), this.auth.logIn);
17
+ this.router.post('/signup', ValidationMiddleware(CreateUserDto), this.auth.signUp);
18
+ this.router.post('/login', ValidationMiddleware(CreateUserDto), this.auth.logIn);
19
19
  this.router.post('/logout', AuthMiddleware, this.auth.logOut);
20
20
  }
21
21
  }
@@ -16,8 +16,8 @@ export class UserRoute implements Routes {
16
16
  private initializeRoutes() {
17
17
  this.router.get(`${this.path}`, this.user.getUsers);
18
18
  this.router.get(`${this.path}/:id(\\d+)`, this.user.getUserById);
19
- this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto, 'body'), this.user.createUser);
20
- this.router.put(`${this.path}/:id(\\d+)`, ValidationMiddleware(CreateUserDto, 'body', true), this.user.updateUser);
19
+ this.router.post(`${this.path}`, ValidationMiddleware(CreateUserDto), this.user.createUser);
20
+ this.router.put(`${this.path}/:id(\\d+)`, ValidationMiddleware(CreateUserDto, true), this.user.updateUser);
21
21
  this.router.delete(`${this.path}/:id(\\d+)`, this.user.deleteUser);
22
22
  }
23
23
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "typescript-express-starter",
3
- "version": "10.0.1",
3
+ "version": "10.2.1",
4
4
  "description": "Quick and Easy TypeScript Express Starter",
5
5
  "author": "AGUMON <ljlm0402@gmail.com>",
6
6
  "license": "MIT",
@@ -1,9 +0,0 @@
1
- import { User } from '@interfaces/users.interface';
2
-
3
- // password: password
4
- export const UserModel: User[] = [
5
- { id: 1, email: 'example1@email.com', password: '$2b$10$TBEfaCe1oo.2jfkBDWcj/usBj4oECsW2wOoDXpCa2IH9xqCpEK/hC' },
6
- { id: 2, email: 'example2@email.com', password: '$2b$10$TBEfaCe1oo.2jfkBDWcj/usBj4oECsW2wOoDXpCa2IH9xqCpEK/hC' },
7
- { id: 3, email: 'example3@email.com', password: '$2b$10$TBEfaCe1oo.2jfkBDWcj/usBj4oECsW2wOoDXpCa2IH9xqCpEK/hC' },
8
- { id: 4, email: 'example4@email.com', password: '$2b$10$TBEfaCe1oo.2jfkBDWcj/usBj4oECsW2wOoDXpCa2IH9xqCpEK/hC' },
9
- ];