diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 5359085..0000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: npm publish - -on: - release: - types: - - created - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout source code - uses: actions/checkout@v1 - - - name: Setup nodejs - uses: actions/setup-node@v1 - with: - node-version: 12 - registry-url: https://registry.npmjs.org/ - - - name: Publish npm - run: npm publish --access public - working-directory: ./typescript-express-starter - env: - NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} diff --git a/.gitignore b/.gitignore deleted file mode 100644 index b609d07..0000000 --- a/.gitignore +++ /dev/null @@ -1,107 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# Diagnostic reports (https://nodejs.org/api/report.html) -report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json - -# Runtime data -pids -*.pid -*.seed -*.pid.lock - -# Directory for instrumented libs generated by jscoverage/JSCover -lib-cov - -# Coverage directory used by tools like istanbul -coverage -*.lcov - -# nyc test coverage -.nyc_output - -# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) -.grunt - -# Bower dependency directory (https://bower.io/) -bower_components - -# node-waf configuration -.lock-wscript - -# Compiled binary addons (https://nodejs.org/api/addons.html) -build/Release - -# Dependency directories -node_modules/ -jspm_packages/ - -# TypeScript v1 declaration files -typings/ - -# TypeScript cache -*.tsbuildinfo - -# Optional npm cache directory -.npm - -# Optional eslint cache -.eslintcache - -# Microbundle cache -.rpt2_cache/ -.rts2_cache_cjs/ -.rts2_cache_es/ -.rts2_cache_umd/ - -# Optional REPL history -.node_repl_history - -# Output of 'npm pack' -*.tgz - -# Yarn Integrity file -.yarn-integrity - -# dotenv environment variables file -# .env -# .env.test - -# parcel-bundler cache (https://parceljs.org/) -.cache - -# Next.js build output -.next - -# Nuxt.js build / generate output -.nuxt -dist - -# Gatsby files -.cache/ -# Comment in the public line in if your project uses Gatsby and *not* Next.js -# https://nextjs.org/blog/next-9-1#public-directory-support -# public - -# vuepress build output -.vuepress/dist - -# Serverless directories -.serverless/ - -# FuseBox cache -.fusebox/ - -# DynamoDB Local files -.dynamodb/ - -# TernJS port file -.tern-port - -# Package-lock json file -package-lock.json diff --git a/LICENSE b/LICENSE deleted file mode 100644 index bfec98f..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 아구몬 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index 1629388..0000000 --- a/README.md +++ /dev/null @@ -1,135 +0,0 @@ -logo - -[Express](https://www.npmjs.com/package/express) with [TypeScript's](https://www.npmjs.com/package/typescript) application generator. - -NPM Version -Package License -NPM Downloads - -
- -## 🧐 What is it? - -Creates a new typescript express application. -application is configured to use TypeScript instead of plain JavaScript. - -## 🤔 Why typescript-express-starter? - -Node Js is great for the rapid development of web-projects, but is often neglected because of the lack of -type safety. TypeScript solves this issue and (along with its linter file) can even make your code -more robust than some other static languages like Java. - -## ⚙️ Installation - -```sh -$ npm install -g typescript-express-starter -``` - -## 🚀 Quick Start - -The quickest way to get started is use npx and pass in the name of the project you want to create. -If you don't specify a project name, the default _typescript-express-starter_ will be used instead. - -### 1. Create the app - -```bash -$ npx typescript-express-starter "project name" -``` - -Choose the template you want. We will create more templates later. - -### 2. Select a templates - -example - -Start your typescript-express-starter app in development mode at `http://localhost:3000/` - -```bash -$ cd "project name" && npm run start -``` - -## 🎠 Available commands for the server. - -- Run the Server in production mode : `npm run start`. -- Run the Server in development mode : `npm run dev`. -- Run all unit-tests: `npm run test`. -- Check for linting errors: `npm run lint`. - -You may need to install [nodemon](https://www.npmjs.com/package/nodemon) separately if you do not currently have it installed on your machine. - -## ⛑ Code Structure (default) - -```bash -│ -├── /src -│ ├── /controllers -│ │ ├── auth.controller.ts -│ │ ├── index.controller.ts -│ │ └── users.controller.ts -│ │ -│ ├── /dtos -│ │ └── user.dto.ts -│ │ -│ ├── /exceptions -│ │ └── HttpException.ts -│ │ -│ ├── /interfaces -│ │ ├── auth.interface.ts -│ │ ├── routes.interface.ts -│ │ └── user.interface.ts -│ │ -│ ├── /middlewares -│ │ ├── auth.middleware.ts -│ │ ├── error.middleware.ts -│ │ └── validation.middleware.ts -│ │ -│ ├── /models -│ │ └── users.model.ts -│ │ -│ ├── /routes -│ │ ├── auth.route.ts -│ │ ├── index.route.ts -│ │ └── users.route.ts -│ │ -│ ├── /services -│ │ ├── auth.service.ts -│ │ └── user.service.ts -│ │ -│ ├── /tests -│ │ ├── auth.test.ts -│ │ ├── index.test.ts -│ │ └── users.test.ts -│ │ -│ ├── /utils -│ │ ├── util.ts -│ │ └── vaildateEnv.ts -│ │ -│ ├── app.ts -│ └── server.ts -│ -├── .env -├── .gitignore -├── jest.config.js -├── package-lock.json -├── package.json -├── tsconfig.json -└── tslint.json -``` - -## 💳 License - -[MIT](LICENSE) - -## 🤝 Contributors - -* Jeongwon Kim [https://github.com/swtpumpkin](https://github.com/swtpumpkin) - -* Lloyd Park [https://github.com/yeondam88](https://github.com/yeondam88) - -* BitYoungjae [https://github.com/BitYoungjae](https://github.com/BitYoungjae) - -* strama4 [https://github.com/strama4](https://github.com/strama4) - -* João Silva [https://github.com/joaopms](https://github.com/joaopms) - -* sonbyungjun [https://github.com/sonbyungjun](https://github.com/sonbyungjun) diff --git a/cli.gif b/cli.gif new file mode 100644 index 0000000..cb61906 Binary files /dev/null and b/cli.gif differ diff --git a/typescript-express-starter.jpg b/logo.jpg similarity index 100% rename from typescript-express-starter.jpg rename to logo.jpg diff --git a/newLogo.png b/newLogo.png new file mode 100644 index 0000000..be30d2b Binary files /dev/null and b/newLogo.png differ diff --git a/typescript-express-starter.gif b/typescript-express-starter.gif deleted file mode 100644 index 3a1ee94..0000000 Binary files a/typescript-express-starter.gif and /dev/null differ diff --git a/typescript-express-starter/LICENSE b/typescript-express-starter/LICENSE deleted file mode 100644 index bfec98f..0000000 --- a/typescript-express-starter/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 아구몬 - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/typescript-express-starter/README.md b/typescript-express-starter/README.md deleted file mode 100644 index 1629388..0000000 --- a/typescript-express-starter/README.md +++ /dev/null @@ -1,135 +0,0 @@ -logo - -[Express](https://www.npmjs.com/package/express) with [TypeScript's](https://www.npmjs.com/package/typescript) application generator. - -NPM Version -Package License -NPM Downloads - -
- -## 🧐 What is it? - -Creates a new typescript express application. -application is configured to use TypeScript instead of plain JavaScript. - -## 🤔 Why typescript-express-starter? - -Node Js is great for the rapid development of web-projects, but is often neglected because of the lack of -type safety. TypeScript solves this issue and (along with its linter file) can even make your code -more robust than some other static languages like Java. - -## ⚙️ Installation - -```sh -$ npm install -g typescript-express-starter -``` - -## 🚀 Quick Start - -The quickest way to get started is use npx and pass in the name of the project you want to create. -If you don't specify a project name, the default _typescript-express-starter_ will be used instead. - -### 1. Create the app - -```bash -$ npx typescript-express-starter "project name" -``` - -Choose the template you want. We will create more templates later. - -### 2. Select a templates - -example - -Start your typescript-express-starter app in development mode at `http://localhost:3000/` - -```bash -$ cd "project name" && npm run start -``` - -## 🎠 Available commands for the server. - -- Run the Server in production mode : `npm run start`. -- Run the Server in development mode : `npm run dev`. -- Run all unit-tests: `npm run test`. -- Check for linting errors: `npm run lint`. - -You may need to install [nodemon](https://www.npmjs.com/package/nodemon) separately if you do not currently have it installed on your machine. - -## ⛑ Code Structure (default) - -```bash -│ -├── /src -│ ├── /controllers -│ │ ├── auth.controller.ts -│ │ ├── index.controller.ts -│ │ └── users.controller.ts -│ │ -│ ├── /dtos -│ │ └── user.dto.ts -│ │ -│ ├── /exceptions -│ │ └── HttpException.ts -│ │ -│ ├── /interfaces -│ │ ├── auth.interface.ts -│ │ ├── routes.interface.ts -│ │ └── user.interface.ts -│ │ -│ ├── /middlewares -│ │ ├── auth.middleware.ts -│ │ ├── error.middleware.ts -│ │ └── validation.middleware.ts -│ │ -│ ├── /models -│ │ └── users.model.ts -│ │ -│ ├── /routes -│ │ ├── auth.route.ts -│ │ ├── index.route.ts -│ │ └── users.route.ts -│ │ -│ ├── /services -│ │ ├── auth.service.ts -│ │ └── user.service.ts -│ │ -│ ├── /tests -│ │ ├── auth.test.ts -│ │ ├── index.test.ts -│ │ └── users.test.ts -│ │ -│ ├── /utils -│ │ ├── util.ts -│ │ └── vaildateEnv.ts -│ │ -│ ├── app.ts -│ └── server.ts -│ -├── .env -├── .gitignore -├── jest.config.js -├── package-lock.json -├── package.json -├── tsconfig.json -└── tslint.json -``` - -## 💳 License - -[MIT](LICENSE) - -## 🤝 Contributors - -* Jeongwon Kim [https://github.com/swtpumpkin](https://github.com/swtpumpkin) - -* Lloyd Park [https://github.com/yeondam88](https://github.com/yeondam88) - -* BitYoungjae [https://github.com/BitYoungjae](https://github.com/BitYoungjae) - -* strama4 [https://github.com/strama4](https://github.com/strama4) - -* João Silva [https://github.com/joaopms](https://github.com/joaopms) - -* sonbyungjun [https://github.com/sonbyungjun](https://github.com/sonbyungjun) diff --git a/typescript-express-starter/bin/cli.js b/typescript-express-starter/bin/cli.js deleted file mode 100644 index 0175444..0000000 --- a/typescript-express-starter/bin/cli.js +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env node - -/***************************************************************** - * Create new typescript-express-starter project. - * created by Lim Kyungmin, 12/18/2019 - *****************************************************************/ - -const path = require('path'); -const tsExpressStarter = require('../lib/typescript-express-starter'); -const destination = getDest(process.argv[2]); - -function getDest(destFolder) { - destFolder = destFolder || 'typescript-express-starter'; - return path.join(process.cwd(), destFolder); -}; - -tsExpressStarter(destination); diff --git a/typescript-express-starter/lib/default/.env b/typescript-express-starter/lib/default/.env deleted file mode 100644 index 993b87e..0000000 --- a/typescript-express-starter/lib/default/.env +++ /dev/null @@ -1,2 +0,0 @@ -JWT_SECRET=jwt_secret -PORT=3000 diff --git a/typescript-express-starter/lib/default/.gitignore b/typescript-express-starter/lib/default/.gitignore deleted file mode 100644 index 09ea094..0000000 --- a/typescript-express-starter/lib/default/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -# compiled output -/dist -/node_modules - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# OS -.DS_Store - -# Tests -/coverage -/.nyc_output - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json diff --git a/typescript-express-starter/lib/default/jest.config.js b/typescript-express-starter/lib/default/jest.config.js deleted file mode 100644 index 3f878c4..0000000 --- a/typescript-express-starter/lib/default/jest.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testEnvironment: "node" -}; diff --git a/typescript-express-starter/lib/default/package.json b/typescript-express-starter/lib/default/package.json deleted file mode 100644 index c356818..0000000 --- a/typescript-express-starter/lib/default/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "typescript-express-starter", - "version": "0.0.0", - "scripts": { - "start": "cross-env NODE_ENV=production ts-node --transpile-only src/server.ts", - "dev": "cross-env NODE_ENV=development nodemon --watch src --delay 1 --exec 'ts-node' src/server.ts", - "test": "jest --forceExit --detectOpenHandles", - "lint": "tslint -p tsconfig.json -c tslint.json" - } -} diff --git a/typescript-express-starter/lib/default/src/app.ts b/typescript-express-starter/lib/default/src/app.ts deleted file mode 100644 index bb95300..0000000 --- a/typescript-express-starter/lib/default/src/app.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as cookieParser from 'cookie-parser'; -import * as cors from 'cors'; -import * as express from 'express'; -import * as helmet from 'helmet'; -import * as hpp from 'hpp'; -import * as logger from 'morgan'; -import Routes from './interfaces/routes.interface'; -import errorMiddleware from './middlewares/error.middleware'; - -class App { - public app: express.Application; - public port: (string | number); - public env: boolean; - - constructor(routes: Routes[]) { - this.app = express(); - this.port = process.env.PORT || 3000; - this.env = process.env.NODE_ENV === 'production' ? true : false; - - this.initializeMiddlewares(); - this.initializeRoutes(routes); - this.initializeErrorHandling(); - } - - public listen() { - this.app.listen(this.port, () => { - console.log(`🚀 App listening on the port ${this.port}`); - }); - } - - public getServer() { - return this.app; - } - - private initializeMiddlewares() { - if (this.env) { - this.app.use(hpp()); - this.app.use(helmet()); - this.app.use(logger('combined')); - this.app.use(cors({ origin: 'your.domain.com', credentials: true })); - } else { - this.app.use(logger('dev')); - this.app.use(cors({ origin: true, credentials: true })); - } - - this.app.use(express.json()); - this.app.use(express.urlencoded({ extended: true })); - this.app.use(cookieParser()); - } - - private initializeRoutes(routes: Routes[]) { - routes.forEach((route) => { - this.app.use('/', route.router); - }); - } - - private initializeErrorHandling() { - this.app.use(errorMiddleware); - } -} - -export default App; diff --git a/typescript-express-starter/lib/default/src/controllers/auth.controller.ts b/typescript-express-starter/lib/default/src/controllers/auth.controller.ts deleted file mode 100644 index 4cc3124..0000000 --- a/typescript-express-starter/lib/default/src/controllers/auth.controller.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; -import { CreateUserDto } from '../dtos/users.dto'; -import { RequestWithUser } from '../interfaces/auth.interface'; -import { User } from '../interfaces/users.interface'; -import AuthService from '../services/auth.service'; - -class AuthController { - public authService = new AuthService(); - - public signUp = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const signUpUserData: User = await this.authService.signup(userData); - res.status(201).json({ data: signUpUserData, message: 'signup' }); - } catch (error) { - next(error); - } - } - - public logIn = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const { cookie, findUser } = await this.authService.login(userData); - res.setHeader('Set-Cookie', [cookie]); - res.status(200).json({ data: findUser, message: 'login' }); - } catch (error) { - next(error); - } - } - - public logOut = async (req: RequestWithUser, res: Response, next: NextFunction) => { - const userData: User = req.user; - - try { - const logOutUserData: User = await this.authService.logout(userData); - res.setHeader('Set-Cookie', ['Authorization=; Max-age=0']); - res.status(200).json({ data: logOutUserData, message: 'logout' }); - } catch (error) { - next(error); - } - } -} - -export default AuthController; diff --git a/typescript-express-starter/lib/default/src/controllers/index.controller.ts b/typescript-express-starter/lib/default/src/controllers/index.controller.ts deleted file mode 100644 index 8b1915b..0000000 --- a/typescript-express-starter/lib/default/src/controllers/index.controller.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; - -class IndexController { - - public index = (req: Request, res: Response, next: NextFunction) => { - try { - res.sendStatus(200); - } catch (error) { - next(error); - } - } -} - -export default IndexController; diff --git a/typescript-express-starter/lib/default/src/controllers/users.controller.ts b/typescript-express-starter/lib/default/src/controllers/users.controller.ts deleted file mode 100644 index 1751da4..0000000 --- a/typescript-express-starter/lib/default/src/controllers/users.controller.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; -import { CreateUserDto } from '../dtos/users.dto'; -import { User } from '../interfaces/users.interface'; -import userService from '../services/users.service'; - -class UsersController { - public userService = new userService(); - - public getUsers = async (req: Request, res: Response, next: NextFunction) => { - try { - const findAllUsersData: User[] = await this.userService.findAllUser(); - res.status(200).json({ data: findAllUsersData, message: 'findAll' }); - } catch (error) { - next(error); - } - } - - public getUserById = async (req: Request, res: Response, next: NextFunction) => { - const userId: number = Number(req.params.id); - - try { - const findOneUserData: User = await this.userService.findUserById(userId); - res.status(200).json({ data: findOneUserData, message: 'findOne' }); - } catch (error) { - next(error); - } - } - - public createUser = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const createUserData: User = await this.userService.createUser(userData); - res.status(201).json({ data: createUserData, message: 'created' }); - } catch (error) { - next(error); - } - } - - public updateUser = async (req: Request, res: Response, next: NextFunction) => { - const userId: number = Number(req.params.id); - const userData: User = req.body; - - try { - const updateUserData: User[] = await this.userService.updateUser(userId, userData); - res.status(200).json({ data: updateUserData, message: 'updated' }); - } catch (error) { - next(error); - } - } - - public deleteUser = async (req: Request, res: Response, next: NextFunction) => { - const userId : number = Number(req.params.id); - - try { - const deleteUserData: User[] = await this.userService.deleteUser(userId); - res.status(200).json({ data: deleteUserData, message: 'deleted' }); - } catch (error) { - next(error); - } - } -} - -export default UsersController; diff --git a/typescript-express-starter/lib/default/src/dtos/users.dto.ts b/typescript-express-starter/lib/default/src/dtos/users.dto.ts deleted file mode 100644 index e769e68..0000000 --- a/typescript-express-starter/lib/default/src/dtos/users.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IsEmail, IsString } from 'class-validator'; - -export class CreateUserDto { - @IsEmail() - public email: string; - - @IsString() - public password: string; -} diff --git a/typescript-express-starter/lib/default/src/exceptions/HttpException.ts b/typescript-express-starter/lib/default/src/exceptions/HttpException.ts deleted file mode 100644 index 435ab80..0000000 --- a/typescript-express-starter/lib/default/src/exceptions/HttpException.ts +++ /dev/null @@ -1,12 +0,0 @@ -class HttpException extends Error { - public status: number; - public message: string; - - constructor(status: number, message: string) { - super(message); - this.status = status; - this.message = message; - } -} - -export default HttpException; diff --git a/typescript-express-starter/lib/default/src/interfaces/auth.interface.ts b/typescript-express-starter/lib/default/src/interfaces/auth.interface.ts deleted file mode 100644 index 15ff6db..0000000 --- a/typescript-express-starter/lib/default/src/interfaces/auth.interface.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Request } from 'express'; -import { User } from './users.interface'; - -export interface DataStoredInToken { - id: number; -} - -export interface TokenData { - token: string; - expiresIn: number; -} - -export interface RequestWithUser extends Request { - user: User; -} diff --git a/typescript-express-starter/lib/default/src/interfaces/routes.interface.ts b/typescript-express-starter/lib/default/src/interfaces/routes.interface.ts deleted file mode 100644 index 3b4eb1f..0000000 --- a/typescript-express-starter/lib/default/src/interfaces/routes.interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Router } from 'express'; - -interface Route { - path: string; - router: Router; -} - -export default Route; diff --git a/typescript-express-starter/lib/default/src/interfaces/users.interface.ts b/typescript-express-starter/lib/default/src/interfaces/users.interface.ts deleted file mode 100644 index 7b9654c..0000000 --- a/typescript-express-starter/lib/default/src/interfaces/users.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface User { - id: number; - email: string; - password: string; -} diff --git a/typescript-express-starter/lib/default/src/middlewares/auth.middleware.ts b/typescript-express-starter/lib/default/src/middlewares/auth.middleware.ts deleted file mode 100644 index 2174709..0000000 --- a/typescript-express-starter/lib/default/src/middlewares/auth.middleware.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { NextFunction, Response } from 'express'; -import * as jwt from 'jsonwebtoken'; -import HttpException from '../exceptions/HttpException'; -import { DataStoredInToken, RequestWithUser } from '../interfaces/auth.interface'; -import userModel from '../models/users.model'; - -function authMiddleware(req: RequestWithUser, res: Response, next: NextFunction) { - const cookies = req.cookies; - - if (cookies && cookies.Authorization) { - const secret = process.env.JWT_SECRET; - - try { - const verificationResponse = jwt.verify(cookies.Authorization, secret) as DataStoredInToken; - const userId = verificationResponse.id; - const findUser = userModel.find(user => user.id === userId); - - if (findUser) { - req.user = findUser; - next(); - } else { - next(new HttpException(401, 'Wrong authentication token')); - } - } catch (error) { - next(new HttpException(401, 'Wrong authentication token')); - } - } else { - next(new HttpException(404, 'Authentication token missing')); - } -} - -export default authMiddleware; diff --git a/typescript-express-starter/lib/default/src/middlewares/error.middleware.ts b/typescript-express-starter/lib/default/src/middlewares/error.middleware.ts deleted file mode 100644 index dab7eb8..0000000 --- a/typescript-express-starter/lib/default/src/middlewares/error.middleware.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; -import HttpException from '../exceptions/HttpException'; - -function errorMiddleware(error: HttpException, req: Request, res: Response, next: NextFunction) { - const status: number = error.status || 500; - const message: string = error.message || 'Something went wrong'; - - console.error('[ERROR] ', status, message); - - res.status(status).json({ message }); -} - -export default errorMiddleware; diff --git a/typescript-express-starter/lib/default/src/middlewares/validation.middleware.ts b/typescript-express-starter/lib/default/src/middlewares/validation.middleware.ts deleted file mode 100644 index fbf86c7..0000000 --- a/typescript-express-starter/lib/default/src/middlewares/validation.middleware.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { plainToClass } from 'class-transformer'; -import { validate, ValidationError } from 'class-validator'; -import { RequestHandler } from 'express'; -import HttpException from '../exceptions/HttpException'; - -function validationMiddleware(type: any, skipMissingProperties = false): RequestHandler { - return (req, res, next) => { - validate(plainToClass(type, req.body), { skipMissingProperties }) - .then((errors: ValidationError[]) => { - if (errors.length > 0) { - const message = errors.map((error: ValidationError) => Object.values(error.constraints)).join(', '); - next(new HttpException(400, message)); - } else { - next(); - } - }); - }; -} - -export default validationMiddleware; diff --git a/typescript-express-starter/lib/default/src/models/users.model.ts b/typescript-express-starter/lib/default/src/models/users.model.ts deleted file mode 100644 index dede70f..0000000 --- a/typescript-express-starter/lib/default/src/models/users.model.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { User } from '../interfaces/users.interface'; - -// password: q1w2e3r4 -const userModel: User[] = [ - { id: 1, email: 'lim@gmail.com', password: '$2b$10$hmrwtGwC.QlfWt6YWaT3S.FP9CarS3.V9n3Qr.d9y2ovcan0oxs56' }, - { id: 2, email: 'kim@gmail.com', password: '$2b$10$hmrwtGwC.QlfWt6YWaT3S.FP9CarS3.V9n3Qr.d9y2ovcan0oxs56' }, - { id: 3, email: 'park@gmail.com', password: '$2b$10$hmrwtGwC.QlfWt6YWaT3S.FP9CarS3.V9n3Qr.d9y2ovcan0oxs56' }, - { id: 4, email: 'choi@gmail.com', password: '$2b$10$hmrwtGwC.QlfWt6YWaT3S.FP9CarS3.V9n3Qr.d9y2ovcan0oxs56' }, -]; - -export default userModel; diff --git a/typescript-express-starter/lib/default/src/routes/auth.route.ts b/typescript-express-starter/lib/default/src/routes/auth.route.ts deleted file mode 100644 index 99d5908..0000000 --- a/typescript-express-starter/lib/default/src/routes/auth.route.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Router } from 'express'; -import AuthController from '../controllers/auth.controller'; -import { CreateUserDto } from '../dtos/users.dto'; -import Route from '../interfaces/routes.interface'; -import authMiddleware from '../middlewares/auth.middleware'; -import validationMiddleware from '../middlewares/validation.middleware'; - -class AuthRoute implements Route { - public path = '/auth'; - public router = Router(); - public authController = new AuthController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.post(`${this.path}/signup`, validationMiddleware(CreateUserDto), this.authController.signUp); - this.router.post(`${this.path}/login`, validationMiddleware(CreateUserDto), this.authController.logIn); - this.router.post(`${this.path}/logout`, authMiddleware, this.authController.logOut); - } -} - -export default AuthRoute; diff --git a/typescript-express-starter/lib/default/src/routes/index.route.ts b/typescript-express-starter/lib/default/src/routes/index.route.ts deleted file mode 100644 index c84e380..0000000 --- a/typescript-express-starter/lib/default/src/routes/index.route.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Router } from 'express'; -import IndexController from '../controllers/index.controller'; -import Route from '../interfaces/routes.interface'; - -class IndexRoute implements Route { - public path = '/'; - public router = Router(); - public indexController = new IndexController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.get(`${this.path}`, this.indexController.index); - } -} - -export default IndexRoute; diff --git a/typescript-express-starter/lib/default/src/routes/users.route.ts b/typescript-express-starter/lib/default/src/routes/users.route.ts deleted file mode 100644 index 5473833..0000000 --- a/typescript-express-starter/lib/default/src/routes/users.route.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Router } from 'express'; -import UsersController from '../controllers/users.controller'; -import { CreateUserDto } from '../dtos/users.dto'; -import Route from '../interfaces/routes.interface'; -import validationMiddleware from '../middlewares/validation.middleware'; - -class UsersRoute implements Route { - public path = '/users'; - public router = Router(); - public usersController = new UsersController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.get(`${this.path}`, this.usersController.getUsers); - this.router.get(`${this.path}/:id(\\d+)`, this.usersController.getUserById); - this.router.post(`${this.path}`, validationMiddleware(CreateUserDto), this.usersController.createUser); - this.router.put(`${this.path}/:id(\\d+)`, validationMiddleware(CreateUserDto, true), this.usersController.updateUser); - this.router.delete(`${this.path}/:id(\\d+)`, this.usersController.deleteUser); - } -} - -export default UsersRoute; diff --git a/typescript-express-starter/lib/default/src/server.ts b/typescript-express-starter/lib/default/src/server.ts deleted file mode 100644 index 12b1d31..0000000 --- a/typescript-express-starter/lib/default/src/server.ts +++ /dev/null @@ -1,16 +0,0 @@ -import 'dotenv/config'; -import App from './app'; -import AuthRoute from './routes/auth.route'; -import IndexRoute from './routes/index.route'; -import UsersRoute from './routes/users.route'; -import validateEnv from './utils/validateEnv'; - -validateEnv(); - -const app = new App([ - new IndexRoute(), - new UsersRoute(), - new AuthRoute(), -]); - -app.listen(); diff --git a/typescript-express-starter/lib/default/src/services/auth.service.ts b/typescript-express-starter/lib/default/src/services/auth.service.ts deleted file mode 100644 index 1ebaf0d..0000000 --- a/typescript-express-starter/lib/default/src/services/auth.service.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import * as jwt from 'jsonwebtoken'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { DataStoredInToken, TokenData } from '../interfaces/auth.interface'; -import { User } from '../interfaces/users.interface'; -import userModel from '../models/users.model'; -import { isEmptyObject } from '../utils/util'; - -class AuthService { - public users = userModel; - - public async signup(userData: CreateUserDto): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = this.users.find(user => user.email === userData.email); - if (findUser) throw new HttpException(409, `You're email ${userData.email} already exists`); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const createUserData: User = { id: (this.users.length + 1), ...userData, password: hashedPassword }; - - return createUserData; - } - - public async login(userData: CreateUserDto): Promise<{ cookie: string, findUser: User }> { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = this.users.find(user => user.email === userData.email); - if (!findUser) throw new HttpException(409, `You're email ${userData.email} not found`); - - const isPasswordMatching: boolean = await bcrypt.compare(userData.password, findUser.password); - if (!isPasswordMatching) throw new HttpException(409, "You're password not matching"); - - const tokenData = this.createToken(findUser); - const cookie = this.createCookie(tokenData); - - return { cookie, findUser }; - } - - public async logout(userData: User): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = this.users.find(user => user.password === userData.password); - if (!findUser) throw new HttpException(409, "You're not user"); - - return findUser; - } - - public createToken(user: User): TokenData { - const dataStoredInToken: DataStoredInToken = { id: user.id }; - const secret: string = process.env.JWT_SECRET; - const expiresIn: number = 60 * 60; - - return { expiresIn, token: jwt.sign(dataStoredInToken, secret, { expiresIn }) }; - } - - public createCookie(tokenData: TokenData): string { - return `Authorization=${tokenData.token}; HttpOnly; Max-Age=${tokenData.expiresIn};`; - } -} - -export default AuthService; diff --git a/typescript-express-starter/lib/default/src/services/users.service.ts b/typescript-express-starter/lib/default/src/services/users.service.ts deleted file mode 100644 index 9d8f462..0000000 --- a/typescript-express-starter/lib/default/src/services/users.service.ts +++ /dev/null @@ -1,59 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { User } from '../interfaces/users.interface'; -import userModel from '../models/users.model'; -import { isEmptyObject } from '../utils/util'; - -class UserService { - public users = userModel; - - public async findAllUser(): Promise { - const users: User[] = this.users; - return users; - } - - public async findUserById(userId: number): Promise { - const findUser: User = this.users.find(user => user.id === userId); - if (!findUser) throw new HttpException(409, "You're not user"); - - return findUser; - } - - public async createUser(userData: CreateUserDto): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = this.users.find(user => user.email === userData.email); - if (findUser) throw new HttpException(409, `You're email ${userData.email} already exists`); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const createUserData: User = { id: (this.users.length + 1), ...userData, password: hashedPassword }; - - return createUserData; - } - - public async updateUser(userId: number, userData: User): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = this.users.find(user => user.id === userId); - if (!findUser) throw new HttpException(409, "You're not user"); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const updateUserData: User[] = this.users.map((user: User) => { - if (user.id === findUser.id) user = { id: userId, ...userData, password: hashedPassword }; - return user; - }); - - return updateUserData; - } - - public async deleteUser(userId: number): Promise { - const findUser: User = this.users.find(user => user.id === userId); - if (!findUser) throw new HttpException(409, "You're not user"); - - const deleteUserData: User[] = this.users.filter(user => user.id !== findUser.id); - return deleteUserData; - } -} - -export default UserService; diff --git a/typescript-express-starter/lib/default/src/tests/auth.test.ts b/typescript-express-starter/lib/default/src/tests/auth.test.ts deleted file mode 100644 index 0f33d73..0000000 --- a/typescript-express-starter/lib/default/src/tests/auth.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import * as request from 'supertest'; -import App from '../app'; -import AuthRoute from '../routes/auth.route'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { TokenData } from '../interfaces/auth.interface'; -import AuthService from '../services/auth.service'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing Auth', () => { - describe('[POST] /signup', () => { - it('response should have the Create userData', () => { - const userData: CreateUserDto = { - email: 'lkm@gmail.com', - password: 'q1w2e3r4', - }; - const authRoute = new AuthRoute(); - const app = new App([authRoute]); - - return request(app.getServer()) - .post(`${authRoute.path}/signup`) - .send(userData); - }); - }); - - describe('[POST] /login', () => { - it('response should have the Set-Cookie header with the Authorization token', async () => { - const userData: CreateUserDto = { - email: 'lim@gmail.com', - password: 'q1w2e3r4', - }; - process.env.JWT_SECRET = 'jwt_secret'; - const authRoute = new AuthRoute(); - const app = new App([authRoute]); - - return request(app.getServer()) - .post(`${authRoute.path}/login`) - .send(userData) - .expect('Set-Cookie', /^Authorization=.+/); - }); - }); - - describe('[POST] /logout', () => { - it('logout Set-Cookie Authorization=; Max-age=0', () => { - const authRoute = new AuthRoute(); - const app = new App([authRoute]); - - return request(app.getServer()) - .post(`${authRoute.path}/logout`) - .expect('Set-Cookie', /^Authorization=\;/); - }); - }); -}); - -// describe('Testing AuthService', () => { -// describe('when creating a cookie', () => { -// it('should return a string', () => { -// const tokenData: TokenData = { -// token: '', -// expiresIn: 1, -// }; - -// const authService = new AuthService(); - -// expect(typeof authService.createCookie(tokenData)) -// .toEqual('string'); -// }); -// }); - -// describe('when registering a user', () => { -// describe('if the email is already token', () => { -// it('should throw an error', async () => { -// const userData: CreateUserDto = { -// email: 'lkm@gmail.com', -// password: 'q1w2e3r4', -// }; - -// const authService = new AuthService(); - -// authService.users.find = jest -// .fn() -// .mockReturnValue(Promise.resolve(userData)); - -// await expect(authService.signup(userData)) -// .rejects -// .toMatchObject(new HttpException(400, `User with email ${userData.email} already exists`)); -// }); -// }); - -// describe('if the email is not token', () => { -// it('should not throw an error', async () => { -// const userData: CreateUserDto = { -// email: 'lkm@gmail.com', -// password: 'q1w2e3r4', -// }; -// process.env.JWT_SECRET = 'jwt_secret'; - -// const authService = new AuthService(); - -// authService.users.find = jest -// .fn() -// .mockReturnValue(Promise.resolve(undefined)); - -// authService.users = jest -// .fn() -// .mockReturnValue({ _id: 0, ...userData }); - -// await expect(authService.signup(userData)) -// .resolves -// .toBeDefined(); -// }); -// }); -// }); -// }); diff --git a/typescript-express-starter/lib/default/src/tests/index.test.ts b/typescript-express-starter/lib/default/src/tests/index.test.ts deleted file mode 100644 index ea4089a..0000000 --- a/typescript-express-starter/lib/default/src/tests/index.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as request from 'supertest'; -import App from '../app'; -import IndexRoute from '../routes/index.route'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing Index', () => { - describe('[GET] /', () => { - it('response statusCode 200', () => { - const indexRoute = new IndexRoute(); - const app = new App([indexRoute]); - - return request(app.getServer()) - .get(`${indexRoute.path}`) - .expect(200); - }); - }); -}); diff --git a/typescript-express-starter/lib/default/src/tests/users.test.ts b/typescript-express-starter/lib/default/src/tests/users.test.ts deleted file mode 100644 index 9eb1e4a..0000000 --- a/typescript-express-starter/lib/default/src/tests/users.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import * as request from 'supertest'; -import App from '../app'; -import { User } from '../interfaces/users.interface'; -import userModel from '../models/users.model'; -import UserRoute from '../routes/users.route'; -import { CreateUserDto } from 'dtos/users.dto'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing Users', () => { - describe('[GET] /users', () => { - it('response statusCode 200 / findAll', () => { - const findUser: User[] = userModel; - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .get(`${usersRoute.path}`) - .expect(200, { data: findUser, message: 'findAll' }); - }); - }); - - describe('[GET] /users/:id', () => { - it('response statusCode 200 / findOne', () => { - const userId: number = 1; - const findUser: User = userModel.find(user => user.id === userId); - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .get(`${usersRoute.path}/${userId}`) - .expect(200, { data: findUser, message: 'findOne' }); - }); - }); - - describe('[POST] /users', () => { - it('response statusCode 201 / created', async () => { - const userData: CreateUserDto = { - email: 'lkm@gmail.com', - password: 'q1w2e3r4', - }; - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .post(`${usersRoute.path}`) - .send(userData) - .expect(201); - }); - }); - - describe('[PUT] /users/:id', () => { - it('response statusCode 200 / updated', async () => { - const userId: number = 1; - const userData: CreateUserDto = { - email: 'lim@gmail.com', - password: '1q2w3e4r', - }; - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .put(`${usersRoute.path}/${userId}`) - .send(userData) - .expect(200); - }); - }); - - describe('[DELETE] /users/:id', () => { - it('response statusCode 200 / deleted', () => { - const userId = 1; - const deleteUser: User[] = userModel.filter(user => user.id !== userId); - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .delete(`${usersRoute.path}/${userId}`) - .expect(200, { data: deleteUser, message: 'deleted' }); - }); - }); -}); diff --git a/typescript-express-starter/lib/default/src/utils/util.ts b/typescript-express-starter/lib/default/src/utils/util.ts deleted file mode 100644 index 64a65b9..0000000 --- a/typescript-express-starter/lib/default/src/utils/util.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const isEmptyObject = (obj: object): boolean => { - return !Object.keys(obj).length; -}; diff --git a/typescript-express-starter/lib/default/src/utils/validateEnv.ts b/typescript-express-starter/lib/default/src/utils/validateEnv.ts deleted file mode 100644 index 3a6286c..0000000 --- a/typescript-express-starter/lib/default/src/utils/validateEnv.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { cleanEnv, port, str } from 'envalid'; - -function validateEnv() { - cleanEnv(process.env, { - NODE_ENV: str(), - JWT_SECRET: str(), - PORT: port(), - }); -} - -export default validateEnv; diff --git a/typescript-express-starter/lib/default/tsconfig.json b/typescript-express-starter/lib/default/tsconfig.json deleted file mode 100644 index 9a37fa1..0000000 --- a/typescript-express-starter/lib/default/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "compilerOptions": { - "sourceMap": true, - "target": "es2017", - "outDir": "./dist", - "baseUrl": "./src", - "alwaysStrict": true, - "noImplicitAny": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "allowSyntheticDefaultImports": true, - "moduleResolution": "node", - "typeRoots": ["./node_modules/@types"] - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules"] - } - \ No newline at end of file diff --git a/typescript-express-starter/lib/default/tslint.json b/typescript-express-starter/lib/default/tslint.json deleted file mode 100644 index 4b3cf8d..0000000 --- a/typescript-express-starter/lib/default/tslint.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "defaultSeverity": "error", - "extends": ["tslint:recommended", "tslint-config-airbnb"], - "jsRules": { - "no-unused-expression": true - }, - "rules": { - "max-line-length": [true, 150], - "prefer-template": false, - "interface-name": [true, "never-prefix"], - "import-name": false, - "no-console": false, - "object-literal-sort-keys": false, - "disable-next-line": ["align", "no-trailing-whitespace"], - "max-classes-per-file": true, - "no-parameter-reassignment": false - }, - "rulesDirectory": [] - } - \ No newline at end of file diff --git a/typescript-express-starter/lib/mongoose/.env b/typescript-express-starter/lib/mongoose/.env deleted file mode 100644 index 91d59db..0000000 --- a/typescript-express-starter/lib/mongoose/.env +++ /dev/null @@ -1,6 +0,0 @@ -MONGO_USER=root -MONGO_PASSWORD=password -MONGO_PATH=@localhost:27017 -MONGO_DATABASE=mongoose -JWT_SECRET=jwt_secret -PORT=3000 diff --git a/typescript-express-starter/lib/mongoose/.gitignore b/typescript-express-starter/lib/mongoose/.gitignore deleted file mode 100644 index 09ea094..0000000 --- a/typescript-express-starter/lib/mongoose/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -# compiled output -/dist -/node_modules - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# OS -.DS_Store - -# Tests -/coverage -/.nyc_output - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json diff --git a/typescript-express-starter/lib/mongoose/docker-compose.yml b/typescript-express-starter/lib/mongoose/docker-compose.yml deleted file mode 100644 index fed1e8c..0000000 --- a/typescript-express-starter/lib/mongoose/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: '3.1' - -services: - mongo: - image: mongo:latest - container_name: mongo - environment: - MONGO_INITDB_ROOT_USERNAME: root - MONGO_INITDB_ROOT_PASSWORD: password - MONGO_INITDB_DATABASE: mongoose - ports: - - 27017:27017 diff --git a/typescript-express-starter/lib/mongoose/jest.config.js b/typescript-express-starter/lib/mongoose/jest.config.js deleted file mode 100644 index 3f878c4..0000000 --- a/typescript-express-starter/lib/mongoose/jest.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testEnvironment: "node" -}; diff --git a/typescript-express-starter/lib/mongoose/package.json b/typescript-express-starter/lib/mongoose/package.json deleted file mode 100644 index c356818..0000000 --- a/typescript-express-starter/lib/mongoose/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "typescript-express-starter", - "version": "0.0.0", - "scripts": { - "start": "cross-env NODE_ENV=production ts-node --transpile-only src/server.ts", - "dev": "cross-env NODE_ENV=development nodemon --watch src --delay 1 --exec 'ts-node' src/server.ts", - "test": "jest --forceExit --detectOpenHandles", - "lint": "tslint -p tsconfig.json -c tslint.json" - } -} diff --git a/typescript-express-starter/lib/mongoose/src/app.ts b/typescript-express-starter/lib/mongoose/src/app.ts deleted file mode 100644 index 683526f..0000000 --- a/typescript-express-starter/lib/mongoose/src/app.ts +++ /dev/null @@ -1,71 +0,0 @@ -import * as cookieParser from 'cookie-parser'; -import * as cors from 'cors'; -import * as express from 'express'; -import * as helmet from 'helmet'; -import * as hpp from 'hpp'; -import * as mongoose from 'mongoose'; -import * as logger from 'morgan'; -import Routes from './interfaces/routes.interface'; -import errorMiddleware from './middlewares/error.middleware'; - -class App { - public app: express.Application; - public port: (string | number); - public env: boolean; - - constructor(routes: Routes[]) { - this.app = express(); - this.port = process.env.PORT || 3000; - this.env = process.env.NODE_ENV === 'production' ? true : false; - - this.connectToDatabase(); - this.initializeMiddlewares(); - this.initializeRoutes(routes); - this.initializeErrorHandling(); - } - - public listen() { - this.app.listen(this.port, () => { - console.log(`🚀 App listening on the port ${this.port}`); - }); - } - - public getServer() { - return this.app; - } - - private initializeMiddlewares() { - if (this.env) { - this.app.use(hpp()); - this.app.use(helmet()); - this.app.use(logger('combined')); - this.app.use(cors({ origin: 'your.domain.com', credentials: true })); - } else { - this.app.use(logger('dev')); - this.app.use(cors({ origin: true, credentials: true })); - } - - this.app.use(express.json()); - this.app.use(express.urlencoded({ extended: true })); - this.app.use(cookieParser()); - } - - private initializeRoutes(routes: Routes[]) { - routes.forEach((route) => { - this.app.use('/', route.router); - }); - } - - private initializeErrorHandling() { - this.app.use(errorMiddleware); - } - - private connectToDatabase() { - const { MONGO_USER, MONGO_PASSWORD, MONGO_PATH, MONGO_DATABASE } = process.env; - const options = { useCreateIndex: true, useNewUrlParser: true, useUnifiedTopology: true, useFindAndModify: false }; - - mongoose.connect(`mongodb://${MONGO_USER}:${MONGO_PASSWORD}${MONGO_PATH}/${MONGO_DATABASE}?authSource=admin`, { ...options }); - } -} - -export default App; diff --git a/typescript-express-starter/lib/mongoose/src/controllers/auth.controller.ts b/typescript-express-starter/lib/mongoose/src/controllers/auth.controller.ts deleted file mode 100644 index 47ec441..0000000 --- a/typescript-express-starter/lib/mongoose/src/controllers/auth.controller.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; -import { CreateUserDto } from '../dtos/users.dto'; -import AuthService from '../services/auth.service'; -import { User } from '../interfaces/users.interface'; -import { RequestWithUser } from '../interfaces/auth.interface'; - -class AuthController { - public authService = new AuthService(); - - public signUp = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const signUpUserData: User = await this.authService.signup(userData); - res.status(201).json({ data: signUpUserData, message: 'signup' }); - } catch (error) { - next(error); - } - } - - public logIn = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const { cookie, findUser } = await this.authService.login(userData); - res.setHeader('Set-Cookie', [cookie]); - res.status(200).json({ data: findUser, message: 'login' }); - } catch (error) { - next(error); - } - } - - public logOut = async (req: RequestWithUser, res: Response, next: NextFunction) => { - const userData: User = req.user; - - try { - const logOutUserData: User = await this.authService.logout(userData); - res.setHeader('Set-Cookie', ['Authorization=; Max-age=0']); - res.status(200).json({ data: logOutUserData, message: 'logout' }); - } catch (error) { - next(error); - } - } -} - -export default AuthController; diff --git a/typescript-express-starter/lib/mongoose/src/controllers/index.controller.ts b/typescript-express-starter/lib/mongoose/src/controllers/index.controller.ts deleted file mode 100644 index 8b1915b..0000000 --- a/typescript-express-starter/lib/mongoose/src/controllers/index.controller.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; - -class IndexController { - - public index = (req: Request, res: Response, next: NextFunction) => { - try { - res.sendStatus(200); - } catch (error) { - next(error); - } - } -} - -export default IndexController; diff --git a/typescript-express-starter/lib/mongoose/src/controllers/users.controller.ts b/typescript-express-starter/lib/mongoose/src/controllers/users.controller.ts deleted file mode 100644 index 20447fa..0000000 --- a/typescript-express-starter/lib/mongoose/src/controllers/users.controller.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; -import { CreateUserDto } from '../dtos/users.dto'; -import { User } from '../interfaces/users.interface'; -import userService from '../services/users.service'; - -class UsersController { - public userService = new userService(); - - public getUsers = async (req: Request, res: Response, next: NextFunction) => { - try { - const findAllUsersData: User[] = await this.userService.findAllUser(); - res.status(200).json({ data: findAllUsersData, message: 'findAll' }); - } catch (error) { - next(error); - } - } - - public getUserById = async (req: Request, res: Response, next: NextFunction) => { - const userId: string = req.params.id; - - try { - const findOneUserData: User = await this.userService.findUserById(userId); - res.status(200).json({ data: findOneUserData, message: 'findOne' }); - } catch (error) { - next(error); - } - } - - public createUser = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const createUserData: User = await this.userService.createUser(userData); - res.status(201).json({ data: createUserData, message: 'created' }); - } catch (error) { - next(error); - } - } - - public updateUser = async (req: Request, res: Response, next: NextFunction) => { - const userId: string = req.params.id; - const userData: User = req.body; - - try { - const updateUserData: User = await this.userService.updateUser(userId, userData); - res.status(200).json({ data: updateUserData, message: 'updated' }); - } catch (error) { - next(error); - } - } - - public deleteUser = async (req: Request, res: Response, next: NextFunction) => { - const userId: string = req.params.id; - - try { - const deleteUserData: User = await this.userService.deleteUserData(userId); - res.status(200).json({ data: deleteUserData, message: 'deleted' }); - } catch (error) { - next(error); - } - } -} - -export default UsersController; diff --git a/typescript-express-starter/lib/mongoose/src/dtos/users.dto.ts b/typescript-express-starter/lib/mongoose/src/dtos/users.dto.ts deleted file mode 100644 index e869833..0000000 --- a/typescript-express-starter/lib/mongoose/src/dtos/users.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IsEmail, IsString } from 'class-validator'; - -export class CreateUserDto { - @IsEmail() - public email: string; - - @IsString() - public password: string -} diff --git a/typescript-express-starter/lib/mongoose/src/exceptions/HttpException.ts b/typescript-express-starter/lib/mongoose/src/exceptions/HttpException.ts deleted file mode 100644 index 435ab80..0000000 --- a/typescript-express-starter/lib/mongoose/src/exceptions/HttpException.ts +++ /dev/null @@ -1,12 +0,0 @@ -class HttpException extends Error { - public status: number; - public message: string; - - constructor(status: number, message: string) { - super(message); - this.status = status; - this.message = message; - } -} - -export default HttpException; diff --git a/typescript-express-starter/lib/mongoose/src/interfaces/auth.interface.ts b/typescript-express-starter/lib/mongoose/src/interfaces/auth.interface.ts deleted file mode 100644 index 10d37b3..0000000 --- a/typescript-express-starter/lib/mongoose/src/interfaces/auth.interface.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Request } from 'express'; -import { User } from './users.interface'; - -export interface DataStoredInToken { - _id: string; -} - -export interface TokenData { - token: string; - expiresIn: number; -} - -export interface RequestWithUser extends Request { - user: User; -} diff --git a/typescript-express-starter/lib/mongoose/src/interfaces/routes.interface.ts b/typescript-express-starter/lib/mongoose/src/interfaces/routes.interface.ts deleted file mode 100644 index 3b4eb1f..0000000 --- a/typescript-express-starter/lib/mongoose/src/interfaces/routes.interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Router } from 'express'; - -interface Route { - path: string; - router: Router; -} - -export default Route; diff --git a/typescript-express-starter/lib/mongoose/src/interfaces/users.interface.ts b/typescript-express-starter/lib/mongoose/src/interfaces/users.interface.ts deleted file mode 100644 index 0adbb44..0000000 --- a/typescript-express-starter/lib/mongoose/src/interfaces/users.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface User { - _id: string; - email: string; - password: string; -} diff --git a/typescript-express-starter/lib/mongoose/src/middlewares/auth.middleware.ts b/typescript-express-starter/lib/mongoose/src/middlewares/auth.middleware.ts deleted file mode 100644 index b47c37e..0000000 --- a/typescript-express-starter/lib/mongoose/src/middlewares/auth.middleware.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { NextFunction, Response } from 'express'; -import * as jwt from 'jsonwebtoken'; -import HttpException from '../exceptions/HttpException'; -import { DataStoredInToken, RequestWithUser } from '../interfaces/auth.interface'; -import userModel from '../models/users.model'; - -async function authMiddleware(req: RequestWithUser, res: Response, next: NextFunction) { - const cookies = req.cookies; - - if (cookies && cookies.Authorization) { - const secret = process.env.JWT_SECRET; - - try { - const verificationResponse = jwt.verify(cookies.Authorization, secret) as DataStoredInToken; - const userId = verificationResponse._id; - const findUser = await userModel.findById(userId); - - if (findUser) { - req.user = findUser; - next(); - } else { - next(new HttpException(401, 'Wrong authentication token')); - } - } catch (error) { - next(new HttpException(401, 'Wrong authentication token')); - } - } else { - next(new HttpException(404, 'Authentication token missing')); - } -} - -export default authMiddleware; diff --git a/typescript-express-starter/lib/mongoose/src/middlewares/error.middleware.ts b/typescript-express-starter/lib/mongoose/src/middlewares/error.middleware.ts deleted file mode 100644 index dab7eb8..0000000 --- a/typescript-express-starter/lib/mongoose/src/middlewares/error.middleware.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; -import HttpException from '../exceptions/HttpException'; - -function errorMiddleware(error: HttpException, req: Request, res: Response, next: NextFunction) { - const status: number = error.status || 500; - const message: string = error.message || 'Something went wrong'; - - console.error('[ERROR] ', status, message); - - res.status(status).json({ message }); -} - -export default errorMiddleware; diff --git a/typescript-express-starter/lib/mongoose/src/middlewares/validation.middleware.ts b/typescript-express-starter/lib/mongoose/src/middlewares/validation.middleware.ts deleted file mode 100644 index fbf86c7..0000000 --- a/typescript-express-starter/lib/mongoose/src/middlewares/validation.middleware.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { plainToClass } from 'class-transformer'; -import { validate, ValidationError } from 'class-validator'; -import { RequestHandler } from 'express'; -import HttpException from '../exceptions/HttpException'; - -function validationMiddleware(type: any, skipMissingProperties = false): RequestHandler { - return (req, res, next) => { - validate(plainToClass(type, req.body), { skipMissingProperties }) - .then((errors: ValidationError[]) => { - if (errors.length > 0) { - const message = errors.map((error: ValidationError) => Object.values(error.constraints)).join(', '); - next(new HttpException(400, message)); - } else { - next(); - } - }); - }; -} - -export default validationMiddleware; diff --git a/typescript-express-starter/lib/mongoose/src/models/users.model.ts b/typescript-express-starter/lib/mongoose/src/models/users.model.ts deleted file mode 100644 index 39a51ce..0000000 --- a/typescript-express-starter/lib/mongoose/src/models/users.model.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as mongoose from 'mongoose'; -import { User } from '../interfaces/users.interface'; - -const userSchema = new mongoose.Schema({ - email: String, - password: String -}); - -const userModel = mongoose.model('User', userSchema); - -export default userModel; diff --git a/typescript-express-starter/lib/mongoose/src/routes/auth.route.ts b/typescript-express-starter/lib/mongoose/src/routes/auth.route.ts deleted file mode 100644 index 99d5908..0000000 --- a/typescript-express-starter/lib/mongoose/src/routes/auth.route.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Router } from 'express'; -import AuthController from '../controllers/auth.controller'; -import { CreateUserDto } from '../dtos/users.dto'; -import Route from '../interfaces/routes.interface'; -import authMiddleware from '../middlewares/auth.middleware'; -import validationMiddleware from '../middlewares/validation.middleware'; - -class AuthRoute implements Route { - public path = '/auth'; - public router = Router(); - public authController = new AuthController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.post(`${this.path}/signup`, validationMiddleware(CreateUserDto), this.authController.signUp); - this.router.post(`${this.path}/login`, validationMiddleware(CreateUserDto), this.authController.logIn); - this.router.post(`${this.path}/logout`, authMiddleware, this.authController.logOut); - } -} - -export default AuthRoute; diff --git a/typescript-express-starter/lib/mongoose/src/routes/index.route.ts b/typescript-express-starter/lib/mongoose/src/routes/index.route.ts deleted file mode 100644 index c84e380..0000000 --- a/typescript-express-starter/lib/mongoose/src/routes/index.route.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Router } from 'express'; -import IndexController from '../controllers/index.controller'; -import Route from '../interfaces/routes.interface'; - -class IndexRoute implements Route { - public path = '/'; - public router = Router(); - public indexController = new IndexController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.get(`${this.path}`, this.indexController.index); - } -} - -export default IndexRoute; diff --git a/typescript-express-starter/lib/mongoose/src/routes/users.route.ts b/typescript-express-starter/lib/mongoose/src/routes/users.route.ts deleted file mode 100644 index 7ac9314..0000000 --- a/typescript-express-starter/lib/mongoose/src/routes/users.route.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Router } from 'express'; -import UsersController from '../controllers/users.controller'; -import { CreateUserDto } from '../dtos/users.dto'; -import Route from '../interfaces/routes.interface'; -import validationMiddleware from '../middlewares/validation.middleware'; - -class UsersRoute implements Route { - public path = '/users'; - public router = Router(); - public usersController = new UsersController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.get(`${this.path}`, this.usersController.getUsers); - this.router.get(`${this.path}/:id`, this.usersController.getUserById); - this.router.post(`${this.path}`, validationMiddleware(CreateUserDto), this.usersController.createUser); - this.router.put(`${this.path}/:id`, validationMiddleware(CreateUserDto, true), this.usersController.updateUser); - this.router.delete(`${this.path}/:id`, this.usersController.deleteUser); - } -} - -export default UsersRoute; diff --git a/typescript-express-starter/lib/mongoose/src/server.ts b/typescript-express-starter/lib/mongoose/src/server.ts deleted file mode 100644 index 1692197..0000000 --- a/typescript-express-starter/lib/mongoose/src/server.ts +++ /dev/null @@ -1,16 +0,0 @@ -import 'dotenv/config'; -import App from './app'; -import IndexRoute from './routes/index.route'; -import UsersRoute from './routes/users.route'; -import AuthRoute from './routes/auth.route'; -import validateEnv from './utils/validateEnv'; - -validateEnv(); - -const app = new App([ - new IndexRoute(), - new UsersRoute(), - new AuthRoute(), -]); - -app.listen(); diff --git a/typescript-express-starter/lib/mongoose/src/services/auth.service.ts b/typescript-express-starter/lib/mongoose/src/services/auth.service.ts deleted file mode 100644 index 79b1cfd..0000000 --- a/typescript-express-starter/lib/mongoose/src/services/auth.service.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import * as jwt from 'jsonwebtoken'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { DataStoredInToken, TokenData } from '../interfaces/auth.interface'; -import { User } from '../interfaces/users.interface'; -import userModel from '../models/users.model'; -import { isEmptyObject } from '../utils/util'; - -class AuthService { - public users = userModel; - - public async signup(userData: CreateUserDto): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = await this.users.findOne({ email: userData.email }); - if (findUser) throw new HttpException(409, `You're email ${userData.email} already exists`); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const createUserData: User = await this.users.create({ ...userData, password: hashedPassword }); - - return createUserData; - } - - public async login(userData: CreateUserDto): Promise<{ cookie: string, findUser: User }> { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = await this.users.findOne({ email: userData.email }); - if (!findUser) throw new HttpException(409, `You're email ${userData.email} not found`); - - const isPasswordMatching: boolean = await bcrypt.compare(userData.password, findUser.password); - if (!isPasswordMatching) throw new HttpException(409, "You're password not matching"); - - const tokenData = this.createToken(findUser); - const cookie = this.createCookie(tokenData); - - return { cookie, findUser }; - } - - public async logout(userData: User): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = await this.users.findOne({ password: userData.password }); - if (!findUser) throw new HttpException(409, "You're not user"); - - return findUser; - } - - public createToken(user: User): TokenData { - const dataStoredInToken: DataStoredInToken = { _id: user._id }; - const secret: string = process.env.JWT_SECRET; - const expiresIn: number = 60 * 60; - - return { expiresIn, token: jwt.sign(dataStoredInToken, secret, { expiresIn }) }; - } - - public createCookie(tokenData: TokenData): string { - return `Authorization=${tokenData.token}; HttpOnly; Max-Age=${tokenData.expiresIn};`; - } -} - -export default AuthService; diff --git a/typescript-express-starter/lib/mongoose/src/services/users.service.ts b/typescript-express-starter/lib/mongoose/src/services/users.service.ts deleted file mode 100644 index 3f30275..0000000 --- a/typescript-express-starter/lib/mongoose/src/services/users.service.ts +++ /dev/null @@ -1,52 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { User } from '../interfaces/users.interface'; -import userModel from '../models/users.model'; -import { isEmptyObject } from '../utils/util'; - -class UserService { - public users = userModel; - - public async findAllUser(): Promise { - const users: User[] = await this.users.find(); - return users; - } - - public async findUserById(userId: string): Promise { - const findUser: User = await this.users.findById(userId); - if (!findUser) throw new HttpException(409, "You're not user"); - - return findUser; - } - - public async createUser(userData: CreateUserDto): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = await this.users.findOne({ email: userData.email }); - if (findUser) throw new HttpException(409, `You're email ${userData.email} already exists`); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const createUserData: User = await this.users.create({ ...userData, password: hashedPassword }); - return createUserData; - } - - public async updateUser(userId: string, userData: User): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const updateUserById: User = await this.users.findByIdAndUpdate(userId, { ...userData, password: hashedPassword }); - if (!updateUserById) throw new HttpException(409, "You're not user"); - - return updateUserById; - } - - public async deleteUserData(userId: string): Promise { - const deleteUserById: User = await this.users.findByIdAndDelete(userId); - if (!deleteUserById) throw new HttpException(409, "You're not user"); - - return deleteUserById; - } -} - -export default UserService; diff --git a/typescript-express-starter/lib/mongoose/src/tests/auth.test.ts b/typescript-express-starter/lib/mongoose/src/tests/auth.test.ts deleted file mode 100644 index 487d11e..0000000 --- a/typescript-express-starter/lib/mongoose/src/tests/auth.test.ts +++ /dev/null @@ -1,138 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import * as mongoose from 'mongoose'; -import * as request from 'supertest'; -import App from '../app'; -import AuthRoute from '../routes/auth.route'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { TokenData } from '../interfaces/auth.interface'; -import AuthService from '../services/auth.service'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing AuthController', () => { - describe('POST /signup', () => { - it('response should have the Create userData', () => { - const userData: CreateUserDto = { - email: 'lkm@gmail.com', - password: 'q1w2e3r4' - }; - - const authRoute = new AuthRoute(); - - authRoute.authController.authService.users.findOne = jest - .fn() - .mockReturnValue(Promise.resolve(undefined)); - - authRoute.authController.authService.users.create = jest - .fn() - .mockReturnValue({ _id: 0, ...userData }); - - (mongoose as any).connect = jest.fn(); - const app = new App([authRoute]); - - return request(app.getServer()) - .post(`${authRoute.path}/signup`) - .send(userData); - }); - }); - - describe('POST /login', () => { - it('response should have the Set-Cookie header with the Authorization token', async () => { - const userData: CreateUserDto = { - email: 'lkm@gmail.com', - password: 'q1w2e3r4', - }; - process.env.JWT_SECRET = 'jwt_secret'; - - const authRoute = new AuthRoute(); - - authRoute.authController.authService.users.findOne = jest - .fn() - .mockReturnValue(Promise.resolve({ - _id: 0, - email: 'lim@gmail.com', - password: await bcrypt.hash(userData.password, 10) - })); - - (mongoose as any).connect = jest.fn(); - const app = new App([authRoute]); - return request(app.getServer()) - .post(`${authRoute.path}/login`) - .send(userData) - .expect('Set-Cookie', /^Authorization=.+/); - }); - }); - - describe('POST /logout', () => { - it('logout Set-Cookie Authorization=; Max-age=0', () => { - const authRoute = new AuthRoute(); - - const app = new App([authRoute]); - return request(app.getServer()) - .post(`${authRoute.path}/logout`) - .expect('Set-Cookie', /^Authorization=\;/); - }); - }); -}); - -describe('Testing AuthService', () => { - describe('when creating a cookie', () => { - it('should return a string', () => { - const tokenData: TokenData = { - token: '', - expiresIn: 1 - }; - - const authService = new AuthService(); - - expect(typeof authService.createCookie(tokenData)) - .toEqual('string',); - }); - }); - - describe('when registering a user', () => { - describe('if the email is already token', () => { - it('should throw an error', async () => { - const userData: CreateUserDto = { - email: 'lkm@gmail.com', - password: 'q1w2e3r4' - }; - - const authService = new AuthService(); - - authService.users.findOne = jest - .fn() - .mockReturnValue(Promise.resolve(userData)); - - await expect(authService.signup(userData)) - .rejects.toMatchObject(new HttpException( 400, `User with email ${userData.email} already exists`)); - }); - }); - - describe('if the email is not token', () => { - it('should not throw an error', async () => { - const userData: CreateUserDto = { - email: 'lkm@gmail.com', - password: 'q1w2e3r4' - }; - process.env.JWT_SECRET = 'jwt_secret'; - - const authService = new AuthService(); - - authService.users.findOne = jest - .fn() - .mockReturnValue(Promise.resolve(undefined)); - - authService.users.create = jest - .fn() - .mockReturnValue({ _id: 0, ...userData }); - - await expect(authService.signup(userData)) - .resolves.toBeDefined(); - }); - }); - }); -}); diff --git a/typescript-express-starter/lib/mongoose/src/tests/index.test.ts b/typescript-express-starter/lib/mongoose/src/tests/index.test.ts deleted file mode 100644 index ea4089a..0000000 --- a/typescript-express-starter/lib/mongoose/src/tests/index.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as request from 'supertest'; -import App from '../app'; -import IndexRoute from '../routes/index.route'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing Index', () => { - describe('[GET] /', () => { - it('response statusCode 200', () => { - const indexRoute = new IndexRoute(); - const app = new App([indexRoute]); - - return request(app.getServer()) - .get(`${indexRoute.path}`) - .expect(200); - }); - }); -}); diff --git a/typescript-express-starter/lib/mongoose/src/tests/users.test.ts b/typescript-express-starter/lib/mongoose/src/tests/users.test.ts deleted file mode 100644 index 03ae8d2..0000000 --- a/typescript-express-starter/lib/mongoose/src/tests/users.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as mongoose from 'mongoose'; -import * as request from 'supertest'; -import App from '../app'; -import UsersRoute from '../routes/users.route'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing Users', () => { - describe('GET /users', () => { - it('response All Users', () => { - const usersRoute = new UsersRoute(); - usersRoute.usersController.userService.users.find = jest - .fn() - .mockReturnValue(Promise.resolve([{ - email: 'example@gmail.com', - password: 'q1w2e3r4!', - }, - ])); - - (mongoose as any).connect = jest.fn(); - const app = new App([usersRoute]); - return request(app.getServer()) - .get(`${usersRoute.path}`) - .expect(200); - }); - }); -}); diff --git a/typescript-express-starter/lib/mongoose/src/utils/util.ts b/typescript-express-starter/lib/mongoose/src/utils/util.ts deleted file mode 100644 index f3c4e8d..0000000 --- a/typescript-express-starter/lib/mongoose/src/utils/util.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const isEmptyObject = (obj: object): boolean => { - return !Object.keys(obj).length; -}; diff --git a/typescript-express-starter/lib/mongoose/src/utils/validateEnv.ts b/typescript-express-starter/lib/mongoose/src/utils/validateEnv.ts deleted file mode 100644 index 7c0835e..0000000 --- a/typescript-express-starter/lib/mongoose/src/utils/validateEnv.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { cleanEnv, port, str } from 'envalid'; - -function validateEnv() { - cleanEnv(process.env, { - NODE_ENV: str(), - MONGO_USER: str(), - MONGO_PASSWORD: str(), - MONGO_PATH: str(), - MONGO_DATABASE: str(), - JWT_SECRET: str(), - PORT: port(), - }); -} - -export default validateEnv; diff --git a/typescript-express-starter/lib/mongoose/tsconfig.json b/typescript-express-starter/lib/mongoose/tsconfig.json deleted file mode 100644 index b6bfafb..0000000 --- a/typescript-express-starter/lib/mongoose/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "sourceMap": true, - "target": "es2017", - "outDir": "./dist", - "baseUrl": "./src", - "alwaysStrict": true, - "noImplicitAny": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "allowSyntheticDefaultImports": true, - "moduleResolution": "node", - "typeRoots": ["./node_modules/@types"] - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/typescript-express-starter/lib/mongoose/tslint.json b/typescript-express-starter/lib/mongoose/tslint.json deleted file mode 100644 index 185a918..0000000 --- a/typescript-express-starter/lib/mongoose/tslint.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "defaultSeverity": "error", - "extends": ["tslint:recommended", "tslint-config-airbnb"], - "jsRules": { - "no-unused-expression": true - }, - "rules": { - "max-line-length": [true, 150], - "prefer-template": false, - "interface-name": [true, "never-prefix"], - "import-name": false, - "no-console": false, - "object-literal-sort-keys": false, - "disable-next-line": ["align", "no-trailing-whitespace"], - "max-classes-per-file": true, - "no-parameter-reassignment": false - }, - "rulesDirectory": [] -} diff --git a/typescript-express-starter/lib/sequelize/.env b/typescript-express-starter/lib/sequelize/.env deleted file mode 100644 index a15aa57..0000000 --- a/typescript-express-starter/lib/sequelize/.env +++ /dev/null @@ -1,6 +0,0 @@ -MYSQL_USER=root -MYSQL_PASSWORD=password -MYSQL_PATH=localhost -MYSQL_DATABASE=sequelize -JWT_SECRET=jwt_secret -PORT=3000 diff --git a/typescript-express-starter/lib/sequelize/.gitignore b/typescript-express-starter/lib/sequelize/.gitignore deleted file mode 100644 index 09ea094..0000000 --- a/typescript-express-starter/lib/sequelize/.gitignore +++ /dev/null @@ -1,34 +0,0 @@ -# compiled output -/dist -/node_modules - -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -lerna-debug.log* - -# OS -.DS_Store - -# Tests -/coverage -/.nyc_output - -# IDEs and editors -/.idea -.project -.classpath -.c9/ -*.launch -.settings/ -*.sublime-workspace - -# IDE - VSCode -.vscode/* -!.vscode/settings.json -!.vscode/tasks.json -!.vscode/launch.json -!.vscode/extensions.json diff --git a/typescript-express-starter/lib/sequelize/docker-compose.yml b/typescript-express-starter/lib/sequelize/docker-compose.yml deleted file mode 100644 index 5e17468..0000000 --- a/typescript-express-starter/lib/sequelize/docker-compose.yml +++ /dev/null @@ -1,12 +0,0 @@ -version: "3.3" - -services: - mysql: - image: mysql:5.7 - container_name: mysql - environment: - MYSQL_ROOT_USER: root - MYSQL_ROOT_PASSWORD: password - MYSQL_DATABASE: sequelize - ports: - - 3306:3306 diff --git a/typescript-express-starter/lib/sequelize/jest.config.js b/typescript-express-starter/lib/sequelize/jest.config.js deleted file mode 100644 index 3f878c4..0000000 --- a/typescript-express-starter/lib/sequelize/jest.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testEnvironment: "node" -}; diff --git a/typescript-express-starter/lib/sequelize/package.json b/typescript-express-starter/lib/sequelize/package.json deleted file mode 100644 index c356818..0000000 --- a/typescript-express-starter/lib/sequelize/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "typescript-express-starter", - "version": "0.0.0", - "scripts": { - "start": "cross-env NODE_ENV=production ts-node --transpile-only src/server.ts", - "dev": "cross-env NODE_ENV=development nodemon --watch src --delay 1 --exec 'ts-node' src/server.ts", - "test": "jest --forceExit --detectOpenHandles", - "lint": "tslint -p tsconfig.json -c tslint.json" - } -} diff --git a/typescript-express-starter/lib/sequelize/src/app.ts b/typescript-express-starter/lib/sequelize/src/app.ts deleted file mode 100644 index ac642a6..0000000 --- a/typescript-express-starter/lib/sequelize/src/app.ts +++ /dev/null @@ -1,64 +0,0 @@ -import * as cookieParser from 'cookie-parser'; -import * as cors from 'cors'; -import * as express from 'express'; -import * as helmet from 'helmet'; -import * as hpp from 'hpp'; -import * as logger from 'morgan'; -import Routes from './interfaces/routes.interface'; -import errorMiddleware from './middlewares/error.middleware'; -import { sequelize } from './models/index.model'; - -class App { - public app: express.Application; - public port: (string | number); - public env: boolean; - - constructor(routes: Routes[]) { - this.app = express(); - this.port = process.env.PORT || 3000; - this.env = process.env.NODE_ENV === 'production' ? true : false; - - this.initializeMiddlewares(); - this.initializeRoutes(routes); - this.initializeErrorHandling(); - } - - public listen() { - this.app.listen(this.port, () => { - console.log(`🚀 App listening on the port ${this.port}`); - }); - } - - public getServer() { - return this.app; - } - - private initializeMiddlewares() { - if (this.env) { - this.app.use(hpp()); - this.app.use(helmet()); - this.app.use(logger('combined')); - this.app.use(cors({ origin: 'your.domain.com', credentials: true })); - } else { - this.app.use(logger('dev')); - this.app.use(cors({ origin: true, credentials: true })); - } - sequelize.sync({ force: false }); - this.app.use(express.json()); - this.app.use(express.urlencoded({ extended: true })); - this.app.use(cookieParser()); - } - - private initializeRoutes(routes: Routes[]) { - routes.forEach((route) => { - this.app.use('/', route.router); - }); - } - - private initializeErrorHandling() { - this.app.use(errorMiddleware); - } - -} - -export default App; diff --git a/typescript-express-starter/lib/sequelize/src/controllers/auth.controller.ts b/typescript-express-starter/lib/sequelize/src/controllers/auth.controller.ts deleted file mode 100644 index 47ec441..0000000 --- a/typescript-express-starter/lib/sequelize/src/controllers/auth.controller.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; -import { CreateUserDto } from '../dtos/users.dto'; -import AuthService from '../services/auth.service'; -import { User } from '../interfaces/users.interface'; -import { RequestWithUser } from '../interfaces/auth.interface'; - -class AuthController { - public authService = new AuthService(); - - public signUp = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const signUpUserData: User = await this.authService.signup(userData); - res.status(201).json({ data: signUpUserData, message: 'signup' }); - } catch (error) { - next(error); - } - } - - public logIn = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const { cookie, findUser } = await this.authService.login(userData); - res.setHeader('Set-Cookie', [cookie]); - res.status(200).json({ data: findUser, message: 'login' }); - } catch (error) { - next(error); - } - } - - public logOut = async (req: RequestWithUser, res: Response, next: NextFunction) => { - const userData: User = req.user; - - try { - const logOutUserData: User = await this.authService.logout(userData); - res.setHeader('Set-Cookie', ['Authorization=; Max-age=0']); - res.status(200).json({ data: logOutUserData, message: 'logout' }); - } catch (error) { - next(error); - } - } -} - -export default AuthController; diff --git a/typescript-express-starter/lib/sequelize/src/controllers/index.controller.ts b/typescript-express-starter/lib/sequelize/src/controllers/index.controller.ts deleted file mode 100644 index 8b1915b..0000000 --- a/typescript-express-starter/lib/sequelize/src/controllers/index.controller.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; - -class IndexController { - - public index = (req: Request, res: Response, next: NextFunction) => { - try { - res.sendStatus(200); - } catch (error) { - next(error); - } - } -} - -export default IndexController; diff --git a/typescript-express-starter/lib/sequelize/src/controllers/users.controller.ts b/typescript-express-starter/lib/sequelize/src/controllers/users.controller.ts deleted file mode 100644 index fb1e78b..0000000 --- a/typescript-express-starter/lib/sequelize/src/controllers/users.controller.ts +++ /dev/null @@ -1,64 +0,0 @@ -import { NextFunction, Request, Response } from 'express'; -import { CreateUserDto } from '../dtos/users.dto'; -import { User } from '../interfaces/users.interface'; -import userService from '../services/users.service'; - -class UsersController { - public userService = new userService(); - - public getUsers = async (req: Request, res: Response, next: NextFunction) => { - try { - const findAllUsersData: User[] = await this.userService.findAllUser(); - res.status(200).json({ data: findAllUsersData, message: 'findAll' }); - } catch (error) { - next(error); - } - } - - public getUserById = async (req: Request, res: Response, next: NextFunction) => { - const userId: number = Number(req.params.id); - - try { - const findOneUserData: User = await this.userService.findUserById(userId); - res.status(200).json({ data: findOneUserData, message: 'findOne' }); - } catch (error) { - next(error); - } - } - - public createUser = async (req: Request, res: Response, next: NextFunction) => { - const userData: CreateUserDto = req.body; - - try { - const createUserData: User = await this.userService.createUser(userData); - res.status(201).json({ data: createUserData, message: 'created' }); - } catch (error) { - next(error); - } - } - - public updateUser = async (req: Request, res: Response, next: NextFunction) => { - const userId: number = Number(req.params.id); - const userData: User = req.body; - - try { - const updateUserData: User = await this.userService.updateUser(userId, userData); - res.status(200).json({ data: updateUserData, message: 'updated' }); - } catch (error) { - next(error); - } - } - - public deleteUser = async (req: Request, res: Response, next: NextFunction) => { - const userId: number = Number(req.params.id); - - try { - const deleteUserData: User = await this.userService.deleteUserData(userId); - res.status(200).json({ data: deleteUserData, message: 'deleted' }); - } catch (error) { - next(error); - } - } -} - -export default UsersController; diff --git a/typescript-express-starter/lib/sequelize/src/dtos/users.dto.ts b/typescript-express-starter/lib/sequelize/src/dtos/users.dto.ts deleted file mode 100644 index 411f051..0000000 --- a/typescript-express-starter/lib/sequelize/src/dtos/users.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { IsString, IsEmail } from 'class-validator'; - -export class CreateUserDto { - @IsEmail() - public email: string; - - @IsString() - public password: string; -} diff --git a/typescript-express-starter/lib/sequelize/src/exceptions/HttpException.ts b/typescript-express-starter/lib/sequelize/src/exceptions/HttpException.ts deleted file mode 100644 index 435ab80..0000000 --- a/typescript-express-starter/lib/sequelize/src/exceptions/HttpException.ts +++ /dev/null @@ -1,12 +0,0 @@ -class HttpException extends Error { - public status: number; - public message: string; - - constructor(status: number, message: string) { - super(message); - this.status = status; - this.message = message; - } -} - -export default HttpException; diff --git a/typescript-express-starter/lib/sequelize/src/interfaces/auth.interface.ts b/typescript-express-starter/lib/sequelize/src/interfaces/auth.interface.ts deleted file mode 100644 index 15ff6db..0000000 --- a/typescript-express-starter/lib/sequelize/src/interfaces/auth.interface.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { Request } from 'express'; -import { User } from './users.interface'; - -export interface DataStoredInToken { - id: number; -} - -export interface TokenData { - token: string; - expiresIn: number; -} - -export interface RequestWithUser extends Request { - user: User; -} diff --git a/typescript-express-starter/lib/sequelize/src/interfaces/routes.interface.ts b/typescript-express-starter/lib/sequelize/src/interfaces/routes.interface.ts deleted file mode 100644 index 3b4eb1f..0000000 --- a/typescript-express-starter/lib/sequelize/src/interfaces/routes.interface.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Router } from 'express'; - -interface Route { - path: string; - router: Router; -} - -export default Route; diff --git a/typescript-express-starter/lib/sequelize/src/interfaces/users.interface.ts b/typescript-express-starter/lib/sequelize/src/interfaces/users.interface.ts deleted file mode 100644 index 7b9654c..0000000 --- a/typescript-express-starter/lib/sequelize/src/interfaces/users.interface.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface User { - id: number; - email: string; - password: string; -} diff --git a/typescript-express-starter/lib/sequelize/src/middlewares/auth.middleware.ts b/typescript-express-starter/lib/sequelize/src/middlewares/auth.middleware.ts deleted file mode 100644 index e626961..0000000 --- a/typescript-express-starter/lib/sequelize/src/middlewares/auth.middleware.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { NextFunction, Response } from 'express'; -import * as jwt from 'jsonwebtoken'; -import HttpException from '../exceptions/HttpException'; -import { DataStoredInToken, RequestWithUser } from '../interfaces/auth.interface'; -import userModel from '../models/users.model'; - -async function authMiddleware(req: RequestWithUser, res: Response, next: NextFunction) { - const cookies = req.cookies; - - if (cookies && cookies.Authorization) { - const secret = process.env.JWT_SECRET; - - try { - const verificationResponse = jwt.verify(cookies.Authorization, secret) as DataStoredInToken; - const userId = verificationResponse.id; - const findUser = await userModel.findByPk(userId); - - if (findUser) { - req.user = findUser; - next(); - } else { - next(new HttpException(401, 'Wrong authentication token')); - } - } catch (error) { - next(new HttpException(401, 'Wrong authentication token')); - } - } else { - next(new HttpException(404, 'Authentication token missing')); - } -} - -export default authMiddleware; diff --git a/typescript-express-starter/lib/sequelize/src/middlewares/error.middleware.ts b/typescript-express-starter/lib/sequelize/src/middlewares/error.middleware.ts deleted file mode 100644 index 73cadc1..0000000 --- a/typescript-express-starter/lib/sequelize/src/middlewares/error.middleware.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Request, Response, NextFunction } from 'express'; -import HttpException from '../exceptions/HttpException'; - -function errorMiddleware(error: HttpException, req: Request, res: Response, next: NextFunction) { - const status: number = error.status || 500; - const message: string = error.message || 'Something went wrong'; - - console.error('[ERROR] ', status, message); - - res.status(status).json({ message }); -} - -export default errorMiddleware; diff --git a/typescript-express-starter/lib/sequelize/src/middlewares/validation.middleware.ts b/typescript-express-starter/lib/sequelize/src/middlewares/validation.middleware.ts deleted file mode 100644 index fbf86c7..0000000 --- a/typescript-express-starter/lib/sequelize/src/middlewares/validation.middleware.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { plainToClass } from 'class-transformer'; -import { validate, ValidationError } from 'class-validator'; -import { RequestHandler } from 'express'; -import HttpException from '../exceptions/HttpException'; - -function validationMiddleware(type: any, skipMissingProperties = false): RequestHandler { - return (req, res, next) => { - validate(plainToClass(type, req.body), { skipMissingProperties }) - .then((errors: ValidationError[]) => { - if (errors.length > 0) { - const message = errors.map((error: ValidationError) => Object.values(error.constraints)).join(', '); - next(new HttpException(400, message)); - } else { - next(); - } - }); - }; -} - -export default validationMiddleware; diff --git a/typescript-express-starter/lib/sequelize/src/models/index.model.ts b/typescript-express-starter/lib/sequelize/src/models/index.model.ts deleted file mode 100644 index bf334d0..0000000 --- a/typescript-express-starter/lib/sequelize/src/models/index.model.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { Sequelize } from 'sequelize-typescript'; -import User from './users.model'; - -export const sequelize = new Sequelize( - process.env.MYSQL_DATABASE, - process.env.MYSQL_USER, - process.env.MYSQL_PASSWORD, - { - host: process.env.MYSQL_PATH, - dialect: 'mysql', - timezone: '+09:00', - define: { - charset: 'utf8mb4', - collate: 'utf8mb4_general_ci', - }, - pool: { - min: 0, - max: 30, - idle: 10000, - acquire: 30000, - }, - }, -); - -sequelize.addModels([User]); - -sequelize.authenticate().catch((err: Error) => { - console.error('Unable to connect to the database:', err); -}); diff --git a/typescript-express-starter/lib/sequelize/src/models/users.model.ts b/typescript-express-starter/lib/sequelize/src/models/users.model.ts deleted file mode 100644 index 63aae79..0000000 --- a/typescript-express-starter/lib/sequelize/src/models/users.model.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { AllowNull, AutoIncrement, Column, DataType, Model, PrimaryKey, Table } from 'sequelize-typescript'; - -@Table({ modelName: 'user', timestamps: true, paranoid: true }) -export default class User extends Model { - @PrimaryKey - @AutoIncrement - @Column - id: number; - - @AllowNull(false) - @Column(DataType.STRING(45)) - email: string; - - @AllowNull(false) - @Column(DataType.STRING(255)) - password: string; -} diff --git a/typescript-express-starter/lib/sequelize/src/routes/auth.route.ts b/typescript-express-starter/lib/sequelize/src/routes/auth.route.ts deleted file mode 100644 index 99d5908..0000000 --- a/typescript-express-starter/lib/sequelize/src/routes/auth.route.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Router } from 'express'; -import AuthController from '../controllers/auth.controller'; -import { CreateUserDto } from '../dtos/users.dto'; -import Route from '../interfaces/routes.interface'; -import authMiddleware from '../middlewares/auth.middleware'; -import validationMiddleware from '../middlewares/validation.middleware'; - -class AuthRoute implements Route { - public path = '/auth'; - public router = Router(); - public authController = new AuthController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.post(`${this.path}/signup`, validationMiddleware(CreateUserDto), this.authController.signUp); - this.router.post(`${this.path}/login`, validationMiddleware(CreateUserDto), this.authController.logIn); - this.router.post(`${this.path}/logout`, authMiddleware, this.authController.logOut); - } -} - -export default AuthRoute; diff --git a/typescript-express-starter/lib/sequelize/src/routes/index.route.ts b/typescript-express-starter/lib/sequelize/src/routes/index.route.ts deleted file mode 100644 index c84e380..0000000 --- a/typescript-express-starter/lib/sequelize/src/routes/index.route.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Router } from 'express'; -import IndexController from '../controllers/index.controller'; -import Route from '../interfaces/routes.interface'; - -class IndexRoute implements Route { - public path = '/'; - public router = Router(); - public indexController = new IndexController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.get(`${this.path}`, this.indexController.index); - } -} - -export default IndexRoute; diff --git a/typescript-express-starter/lib/sequelize/src/routes/users.route.ts b/typescript-express-starter/lib/sequelize/src/routes/users.route.ts deleted file mode 100644 index 5473833..0000000 --- a/typescript-express-starter/lib/sequelize/src/routes/users.route.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Router } from 'express'; -import UsersController from '../controllers/users.controller'; -import { CreateUserDto } from '../dtos/users.dto'; -import Route from '../interfaces/routes.interface'; -import validationMiddleware from '../middlewares/validation.middleware'; - -class UsersRoute implements Route { - public path = '/users'; - public router = Router(); - public usersController = new UsersController(); - - constructor() { - this.initializeRoutes(); - } - - private initializeRoutes() { - this.router.get(`${this.path}`, this.usersController.getUsers); - this.router.get(`${this.path}/:id(\\d+)`, this.usersController.getUserById); - this.router.post(`${this.path}`, validationMiddleware(CreateUserDto), this.usersController.createUser); - this.router.put(`${this.path}/:id(\\d+)`, validationMiddleware(CreateUserDto, true), this.usersController.updateUser); - this.router.delete(`${this.path}/:id(\\d+)`, this.usersController.deleteUser); - } -} - -export default UsersRoute; diff --git a/typescript-express-starter/lib/sequelize/src/server.ts b/typescript-express-starter/lib/sequelize/src/server.ts deleted file mode 100644 index 1692197..0000000 --- a/typescript-express-starter/lib/sequelize/src/server.ts +++ /dev/null @@ -1,16 +0,0 @@ -import 'dotenv/config'; -import App from './app'; -import IndexRoute from './routes/index.route'; -import UsersRoute from './routes/users.route'; -import AuthRoute from './routes/auth.route'; -import validateEnv from './utils/validateEnv'; - -validateEnv(); - -const app = new App([ - new IndexRoute(), - new UsersRoute(), - new AuthRoute(), -]); - -app.listen(); diff --git a/typescript-express-starter/lib/sequelize/src/services/auth.service.ts b/typescript-express-starter/lib/sequelize/src/services/auth.service.ts deleted file mode 100644 index 87c9eac..0000000 --- a/typescript-express-starter/lib/sequelize/src/services/auth.service.ts +++ /dev/null @@ -1,62 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import * as jwt from 'jsonwebtoken'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { DataStoredInToken, TokenData } from '../interfaces/auth.interface'; -import { User } from '../interfaces/users.interface'; -import userModel from '../models/users.model'; -import { isEmptyObject } from '../utils/util'; - -class AuthService { - public users = userModel; - - public async signup(userData: CreateUserDto): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = await this.users.findOne({ where: { email: userData.email } }); - if (findUser) throw new HttpException(409, `You're email ${userData.email} already exists`); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const createUserData: User = await this.users.create({ ...userData, password: hashedPassword }); - - return createUserData; - } - - public async login(userData: CreateUserDto): Promise<{ cookie: string, findUser: User }> { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = await this.users.findOne({ where: { email: userData.email } }); - if (!findUser) throw new HttpException(409, `You're email ${userData.email} not found`); - - const isPasswordMatching: boolean = await bcrypt.compare(userData.password, findUser.password); - if (!isPasswordMatching) throw new HttpException(409, "You're password not matching"); - - const tokenData = this.createToken(findUser); - const cookie = this.createCookie(tokenData); - - return { cookie, findUser }; - } - - public async logout(userData: User): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = await this.users.findOne({ where: { password: userData.password } }); - if (!findUser) throw new HttpException(409, "You're not user"); - - return findUser; - } - - public createToken(user: User): TokenData { - const dataStoredInToken: DataStoredInToken = { id: user.id }; - const secret: string = process.env.JWT_SECRET; - const expiresIn: number = 60 * 60; - - return { expiresIn, token: jwt.sign(dataStoredInToken, secret, { expiresIn }) }; - } - - public createCookie(tokenData: TokenData): string { - return `Authorization=${tokenData.token}; HttpOnly; Max-Age=${tokenData.expiresIn};`; - } -} - -export default AuthService; diff --git a/typescript-express-starter/lib/sequelize/src/services/users.service.ts b/typescript-express-starter/lib/sequelize/src/services/users.service.ts deleted file mode 100644 index d713f7b..0000000 --- a/typescript-express-starter/lib/sequelize/src/services/users.service.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { User } from '../interfaces/users.interface'; -import userModel from '../models/users.model'; -import { isEmptyObject } from '../utils/util'; - -class UserService { - public users = userModel; - - public async findAllUser(): Promise { - const users: User[] = await this.users.findAll(); - return users; - } - - public async findUserById(userId: number): Promise { - const findUser: User = await this.users.findByPk(userId); - if (!findUser) throw new HttpException(409, "You're not user"); - - return findUser; - } - - public async createUser(userData: CreateUserDto): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const findUser: User = await this.users.findOne({ where: { email: userData.email } }); - if (findUser) throw new HttpException(409, `You're email ${userData.email} already exists`); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const createUserData: User = await this.users.create({ ...userData, password: hashedPassword }); - - return createUserData; - } - - public async updateUser(userId: number, userData: User): Promise { - if (isEmptyObject(userData)) throw new HttpException(400, "You're not userData"); - - const hashedPassword = await bcrypt.hash(userData.password, 10); - const updateUser: User = await this.users.update({ ...userData, password: hashedPassword }, { where: { id: userId } }); - if (!updateUser) throw new HttpException(409, "You're not user"); - - return updateUser; - } - - public async deleteUserData(userId: number): Promise { - const deleteUser: User = await this.users.destroy({ where: { id: userId } }); - if (!deleteUser) throw new HttpException(409, "You're not user"); - - return deleteUser; - } -} - -export default UserService; diff --git a/typescript-express-starter/lib/sequelize/src/tests/auth.test.ts b/typescript-express-starter/lib/sequelize/src/tests/auth.test.ts deleted file mode 100644 index 0f33d73..0000000 --- a/typescript-express-starter/lib/sequelize/src/tests/auth.test.ts +++ /dev/null @@ -1,118 +0,0 @@ -import * as bcrypt from 'bcrypt'; -import * as request from 'supertest'; -import App from '../app'; -import AuthRoute from '../routes/auth.route'; -import { CreateUserDto } from '../dtos/users.dto'; -import HttpException from '../exceptions/HttpException'; -import { TokenData } from '../interfaces/auth.interface'; -import AuthService from '../services/auth.service'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing Auth', () => { - describe('[POST] /signup', () => { - it('response should have the Create userData', () => { - const userData: CreateUserDto = { - email: 'lkm@gmail.com', - password: 'q1w2e3r4', - }; - const authRoute = new AuthRoute(); - const app = new App([authRoute]); - - return request(app.getServer()) - .post(`${authRoute.path}/signup`) - .send(userData); - }); - }); - - describe('[POST] /login', () => { - it('response should have the Set-Cookie header with the Authorization token', async () => { - const userData: CreateUserDto = { - email: 'lim@gmail.com', - password: 'q1w2e3r4', - }; - process.env.JWT_SECRET = 'jwt_secret'; - const authRoute = new AuthRoute(); - const app = new App([authRoute]); - - return request(app.getServer()) - .post(`${authRoute.path}/login`) - .send(userData) - .expect('Set-Cookie', /^Authorization=.+/); - }); - }); - - describe('[POST] /logout', () => { - it('logout Set-Cookie Authorization=; Max-age=0', () => { - const authRoute = new AuthRoute(); - const app = new App([authRoute]); - - return request(app.getServer()) - .post(`${authRoute.path}/logout`) - .expect('Set-Cookie', /^Authorization=\;/); - }); - }); -}); - -// describe('Testing AuthService', () => { -// describe('when creating a cookie', () => { -// it('should return a string', () => { -// const tokenData: TokenData = { -// token: '', -// expiresIn: 1, -// }; - -// const authService = new AuthService(); - -// expect(typeof authService.createCookie(tokenData)) -// .toEqual('string'); -// }); -// }); - -// describe('when registering a user', () => { -// describe('if the email is already token', () => { -// it('should throw an error', async () => { -// const userData: CreateUserDto = { -// email: 'lkm@gmail.com', -// password: 'q1w2e3r4', -// }; - -// const authService = new AuthService(); - -// authService.users.find = jest -// .fn() -// .mockReturnValue(Promise.resolve(userData)); - -// await expect(authService.signup(userData)) -// .rejects -// .toMatchObject(new HttpException(400, `User with email ${userData.email} already exists`)); -// }); -// }); - -// describe('if the email is not token', () => { -// it('should not throw an error', async () => { -// const userData: CreateUserDto = { -// email: 'lkm@gmail.com', -// password: 'q1w2e3r4', -// }; -// process.env.JWT_SECRET = 'jwt_secret'; - -// const authService = new AuthService(); - -// authService.users.find = jest -// .fn() -// .mockReturnValue(Promise.resolve(undefined)); - -// authService.users = jest -// .fn() -// .mockReturnValue({ _id: 0, ...userData }); - -// await expect(authService.signup(userData)) -// .resolves -// .toBeDefined(); -// }); -// }); -// }); -// }); diff --git a/typescript-express-starter/lib/sequelize/src/tests/index.test.ts b/typescript-express-starter/lib/sequelize/src/tests/index.test.ts deleted file mode 100644 index ea4089a..0000000 --- a/typescript-express-starter/lib/sequelize/src/tests/index.test.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as request from 'supertest'; -import App from '../app'; -import IndexRoute from '../routes/index.route'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing Index', () => { - describe('[GET] /', () => { - it('response statusCode 200', () => { - const indexRoute = new IndexRoute(); - const app = new App([indexRoute]); - - return request(app.getServer()) - .get(`${indexRoute.path}`) - .expect(200); - }); - }); -}); diff --git a/typescript-express-starter/lib/sequelize/src/tests/users.test.ts b/typescript-express-starter/lib/sequelize/src/tests/users.test.ts deleted file mode 100644 index 9eb1e4a..0000000 --- a/typescript-express-starter/lib/sequelize/src/tests/users.test.ts +++ /dev/null @@ -1,83 +0,0 @@ -import * as request from 'supertest'; -import App from '../app'; -import { User } from '../interfaces/users.interface'; -import userModel from '../models/users.model'; -import UserRoute from '../routes/users.route'; -import { CreateUserDto } from 'dtos/users.dto'; - -afterAll(async () => { - await new Promise(resolve => setTimeout(() => resolve(), 500)); -}); - -describe('Testing Users', () => { - describe('[GET] /users', () => { - it('response statusCode 200 / findAll', () => { - const findUser: User[] = userModel; - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .get(`${usersRoute.path}`) - .expect(200, { data: findUser, message: 'findAll' }); - }); - }); - - describe('[GET] /users/:id', () => { - it('response statusCode 200 / findOne', () => { - const userId: number = 1; - const findUser: User = userModel.find(user => user.id === userId); - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .get(`${usersRoute.path}/${userId}`) - .expect(200, { data: findUser, message: 'findOne' }); - }); - }); - - describe('[POST] /users', () => { - it('response statusCode 201 / created', async () => { - const userData: CreateUserDto = { - email: 'lkm@gmail.com', - password: 'q1w2e3r4', - }; - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .post(`${usersRoute.path}`) - .send(userData) - .expect(201); - }); - }); - - describe('[PUT] /users/:id', () => { - it('response statusCode 200 / updated', async () => { - const userId: number = 1; - const userData: CreateUserDto = { - email: 'lim@gmail.com', - password: '1q2w3e4r', - }; - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .put(`${usersRoute.path}/${userId}`) - .send(userData) - .expect(200); - }); - }); - - describe('[DELETE] /users/:id', () => { - it('response statusCode 200 / deleted', () => { - const userId = 1; - const deleteUser: User[] = userModel.filter(user => user.id !== userId); - const usersRoute = new UserRoute(); - const app = new App([usersRoute]); - - return request(app.getServer()) - .delete(`${usersRoute.path}/${userId}`) - .expect(200, { data: deleteUser, message: 'deleted' }); - }); - }); -}); diff --git a/typescript-express-starter/lib/sequelize/src/utils/util.ts b/typescript-express-starter/lib/sequelize/src/utils/util.ts deleted file mode 100644 index f3c4e8d..0000000 --- a/typescript-express-starter/lib/sequelize/src/utils/util.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const isEmptyObject = (obj: object): boolean => { - return !Object.keys(obj).length; -}; diff --git a/typescript-express-starter/lib/sequelize/src/utils/validateEnv.ts b/typescript-express-starter/lib/sequelize/src/utils/validateEnv.ts deleted file mode 100644 index f755221..0000000 --- a/typescript-express-starter/lib/sequelize/src/utils/validateEnv.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { cleanEnv, port, str } from 'envalid'; - -function validateEnv() { - cleanEnv(process.env, { - NODE_ENV: str(), - MYSQL_USER: str(), - MYSQL_PASSWORD: str(), - MYSQL_PATH: str(), - MYSQL_DATABASE: str(), - JWT_SECRET: str(), - PORT: port(), - }); -} - -export default validateEnv; diff --git a/typescript-express-starter/lib/sequelize/tsconfig.json b/typescript-express-starter/lib/sequelize/tsconfig.json deleted file mode 100644 index b6bfafb..0000000 --- a/typescript-express-starter/lib/sequelize/tsconfig.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "compilerOptions": { - "sourceMap": true, - "target": "es2017", - "outDir": "./dist", - "baseUrl": "./src", - "alwaysStrict": true, - "noImplicitAny": true, - "experimentalDecorators": true, - "emitDecoratorMetadata": true, - "allowSyntheticDefaultImports": true, - "moduleResolution": "node", - "typeRoots": ["./node_modules/@types"] - }, - "include": ["src/**/*.ts"], - "exclude": ["node_modules"] -} diff --git a/typescript-express-starter/lib/sequelize/tslint.json b/typescript-express-starter/lib/sequelize/tslint.json deleted file mode 100644 index 185a918..0000000 --- a/typescript-express-starter/lib/sequelize/tslint.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "defaultSeverity": "error", - "extends": ["tslint:recommended", "tslint-config-airbnb"], - "jsRules": { - "no-unused-expression": true - }, - "rules": { - "max-line-length": [true, 150], - "prefer-template": false, - "interface-name": [true, "never-prefix"], - "import-name": false, - "no-console": false, - "object-literal-sort-keys": false, - "disable-next-line": ["align", "no-trailing-whitespace"], - "max-classes-per-file": true, - "no-parameter-reassignment": false - }, - "rulesDirectory": [] -} diff --git a/typescript-express-starter/lib/typescript-express-starter.js b/typescript-express-starter/lib/typescript-express-starter.js deleted file mode 100644 index bed8c74..0000000 --- a/typescript-express-starter/lib/typescript-express-starter.js +++ /dev/null @@ -1,116 +0,0 @@ -/***************************************************************** - * Create new typescript-express-starter project. - * created by Lim Kyungmin, 12/18/2019 - *****************************************************************/ - -const path = require('path'); -const { readdir } = require('fs').promises; -const editJsonFile = require('edit-json-file'); -const { exec } = require('child_process'); -const ncp = require('ncp').ncp; -const inquirer = require('inquirer'); -const ora = require('ora'); -const chalk = require('chalk'); -const { promisify } = require('util'); -const asyncExec = promisify(exec); - -async function tsExpressStarter(projectName) { - let spinner; - - try { - const template = await selectedTemplates(); - - console.log('[ 1 / 3 ] 🔍 copying project...'); - console.log('[ 2 / 3 ] 🚚 fetching dependencies...'); - - await copyProjectFiles(projectName, template); - await updatePackageJson(projectName); - const dependencies = await getDependencies(template); - - console.log('[ 3 / 3 ] 🔗 linking dependencies...'); - - console.log('\u001b[2m──────────────\u001b[22m'); - - spinner = ora('Install modules...\n'); - spinner.start(); - - await installDependencies(projectName, dependencies, spinner); - - spinner.succeed(chalk`{green Complete setup project}`); - } catch (error) { - spinner.fail(chalk`{red Please leave this error as an issue}`); - console.error(error); - } -} - -async function selectedTemplates() { - const directories = await getDirectories(); - const directoryChoices = [...directories, new inquirer.Separator()]; - const { selectedTemplates } = await inquirer.prompt([ - { - type: 'list', - name: 'selectedTemplates', - message: 'Select a templates', - choices: directoryChoices, - }, - ]); - - return selectedTemplates; -} - -async function getDirectories() { - const contents = await readdir(__dirname, { withFileTypes: true }); - const directories = contents.filter(p => p.isDirectory()).map(p => p.name); - - return directories; -} - -function copyProjectFiles(destination, directory) { - const prjFolder = `./${directory}`; - const source = path.join(__dirname, prjFolder); - - return new Promise((resolve, reject) => { - ncp.limit = 16; - ncp(source, destination, function(err) { - if (err) reject(err); - resolve(); - }); - }); -} - -async function updatePackageJson(destination) { - let file = editJsonFile(destination + '/package.json', { autosave: true }); - file.set('name', path.basename(destination)); -} - -async function getDependencies(directory) { - let dependencies = - 'bcrypt class-transformer class-validator cookie-parser cors cross-env dotenv envalid express helmet hpp jest jsonwebtoken morgan ts-jest ts-node typescript'; - let devDependencies = - '@types/bcrypt @types/cookie-parser @types/cors @types/express @types/helmet @types/hpp @types/jest @types/jsonwebtoken @types/morgan @types/node @types/supertest' + - ' supertest tslint tslint-config-airbnb'; - - switch (directory) { - case 'mongoose': { - dependencies += ' mongoose'; - devDependencies += ' @types/mongoose'; - } break; - case 'sequelize': { - dependencies += ' mysql2 sequelize sequelize-typescript'; - } - } - - return { dependencies, devDependencies }; -} - -async function installDependencies(destination, { dependencies, devDependencies }, spinner) { - const options = { cwd: destination }; - - spinner.text = 'Install dependencies...'; - await asyncExec('npm i -s ' + dependencies, options); - - spinner.text = 'Install devDependencies...'; - await asyncExec('npm i -D ' + devDependencies, options); -} - -module.exports = tsExpressStarter; diff --git a/typescript-express-starter/package.json b/typescript-express-starter/package.json deleted file mode 100644 index f4c608d..0000000 --- a/typescript-express-starter/package.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "typescript-express-starter", - "version": "2.3.0", - "description": "Quick and Easy TypeScript Express Starter", - "author": "AGUMON ", - "license": "MIT", - "main": "bin/cli.js", - "keywords": [ - "bcrypt", - "express", - "mongoose", - "sequlize", - "jest", - "jsonwebtoken", - "typescript" - ], - "bin": { - "typescript-express-starter": "bin/cli.js" - }, - "scripts": { - "start": "node bin/cli.js", - "typescript-express-starter": "node bin/cli.js" - }, - "dependencies": { - "chalk": "^3.0.0", - "edit-json-file": "^1.3.2", - "inquirer": "^6.5.2", - "ncp": "^2.0.0", - "ora": "^4.0.3" - }, - "devDependencies": {}, - "repository": { - "type": "git", - "url": "git+https://github.com/ljlm0402/typescript-express-starter.git" - }, - "bugs": { - "url": "https://github.com/ljlm0402/typescript-express-starter/issues" - }, - "homepage": "https://github.com/ljlm0402/typescript-express-starter#readme" -}