From d8b859850ec280711a49593aec0ec617031dd1c7 Mon Sep 17 00:00:00 2001 From: Filip Rojek Date: Sat, 30 Jul 2022 22:28:06 +0200 Subject: [PATCH] changes: - norkconfig se generuje lepe a actually ho pouzivam - pri vytvareni projektu je mozne vybrat si orm (mongoose & sequlize) - default modely pro db se kopiruji na zaklade parametru db z norkconfigu - updatnutej ts skeleton - dropnul jsem support pro js --- package.json | 2 +- progress-blog.md | 14 +- src/create.ts | 46 ++++-- src/global.ts | 13 ++ src/interfaces/CreateInterface.ts | 8 + src/skeletons/express-ts/.gitignore | 2 +- src/skeletons/express-ts/.prettierrc | 33 ++-- src/skeletons/express-ts/jest.config.js | 5 - src/skeletons/express-ts/norkconfig.json | 3 +- src/skeletons/express-ts/package.json | 42 ++--- src/skeletons/express-ts/src/.env.example | 13 +- src/skeletons/express-ts/src/app.ts | 14 +- .../express-ts/src/config/database.ts | 20 +-- .../src/{utils => config}/environment.ts | 27 +++- .../express-ts/src/config/postgres.config.ts | 10 -- .../express-ts/src/config/sequelize.config.ts | 10 ++ .../src/controllers/rootController.ts | 2 +- src/skeletons/express-ts/src/logs/.gitignore | 1 + .../src/middlewares/authMiddleware.ts | 51 ++++-- .../src/middlewares/handleValidation.ts | 5 +- .../express-ts/src/middlewares/index.ts | 4 +- .../express-ts/src/routes/rootRoutes.ts | 6 +- src/skeletons/express-ts/src/server.ts | 18 +-- .../express-ts/src/services/globalService.ts | 145 +++++++++++++++++- src/skeletons/express-ts/tsconfig.json | 134 +++++++--------- src/skeletons/mongoose-models/User.ts | 40 +++++ src/skeletons/sequelize-models/User.ts | 35 +++++ 27 files changed, 507 insertions(+), 196 deletions(-) delete mode 100644 src/skeletons/express-ts/jest.config.js rename src/skeletons/express-ts/src/{utils => config}/environment.ts (55%) delete mode 100644 src/skeletons/express-ts/src/config/postgres.config.ts create mode 100644 src/skeletons/express-ts/src/config/sequelize.config.ts create mode 100644 src/skeletons/express-ts/src/logs/.gitignore create mode 100644 src/skeletons/mongoose-models/User.ts create mode 100644 src/skeletons/sequelize-models/User.ts diff --git a/package.json b/package.json index e6f2471..0adf78c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nork", - "version": "3.0.4", + "version": "3.0.5", "description": "The best node.js 'framework' :)", "main": "dist/app.js", "bin": "dist/app.js", diff --git a/progress-blog.md b/progress-blog.md index 7f52da0..7771b49 100644 --- a/progress-blog.md +++ b/progress-blog.md @@ -5,6 +5,9 @@ - https://auth0.com/blog/refresh-tokens-what-are-they-and-when-to-use-them/ - [ ] version of nork control - [ ] upgrade to newer version system +- [ ] updatnout make files (obzvlast modely a rozlisovat modely podle norkconfigu) +- [ ] vyzadovat aktualni verzi 3.#.# pro make commandy (pouzivaly se jiny predtim soubory) +- [ ] moznost vytvorit projekt bez db ### 11-24-2021 @@ -19,6 +22,15 @@ - je treba dopsat par types a fixnout zbytek erroru - zatim netestovana funkcnost -### 1-10.2022 +### 1-10-2022 - dodelal jsem create a otestoval ho - [x] create + +### 7-30-2022 + - norkconfig se generuje lepe a actually ho pouzivam + - pri vytvareni projektu je mozne vybrat si orm (mongoose & sequlize) + - default modely pro db se kopiruji na zaklade parametru db z norkconfigu + - updatnutej ts skeleton + - dropnul jsem support pro js + + - version update: 3.0.5 diff --git a/src/create.ts b/src/create.ts index f56e2fa..cdc609d 100644 --- a/src/create.ts +++ b/src/create.ts @@ -22,7 +22,17 @@ export default class Create { name: 'lang', choices: [ { name: 'Typescript', value: 'ts' }, - { name: 'Javascript', value: 'js' }, + { name: 'Javascript - DEPRECATED', value: 'js' }, + ], + }, + { + type: 'list', + message: `Pick the database & ORM you're using:`, + name: 'db', + choices: [ + { name: 'MongoDB - Mongoose', value: { db: 'mongodb', orm: 'mongoose' } }, + { name: 'MySQL - Sequelize', value: { db: 'mysql', orm: 'sequelize' } }, + { name: 'PostgreSQL - Sequelize', value: { db: 'postgresql', orm: 'sequelize' } }, ], }, { @@ -30,39 +40,57 @@ export default class Create { name: 'author', message: 'Enter your name:', }, + { + type: 'input', + name: 'email', + message: 'Enter your email:', + }, + { + type: 'input', + name: 'website', + message: 'Enter your website:', + }, ] // remove first question if project name is already known - if (projectName) { - questions.shift() - } + if (projectName) questions.shift() const answers = await inquirer.prompt(questions) const data: CreateInterface = { project_name: answers.project_name ? answers.project_name : process.argv[3], lang: answers.lang, author: answers.author, + database: answers.db, + website: answers.website, + email: answers.email, } // copy skeleton to new project process.argv.includes('-i') ? (projectPath = process.cwd()) : (projectPath = path.join(process.cwd(), data.project_name)) fs.copySync(path.join(__dirname, './skeletons/express-' + data.lang), projectPath) + // copy default db models to new project + if (data.database.orm == 'mongoose') fs.copySync(path.join(__dirname, './skeletons/mongoose-models/'), projectPath + '/src/models') + if (data.database.orm == 'sequelize') fs.copySync(path.join(__dirname, './skeletons/sequelize-models/'), projectPath + '/src/models') + // edit package.json file const pkgJson = fs.readJsonSync(path.join(projectPath, 'package.json')) - // const pkgJson = require(path.join(projectPath, 'package.json')) - pkgJson.name = data.project_name - pkgJson.author = data.author - + pkgJson.author = `${data.author} <${data.email}> (${data.website})` fs.writeFile(path.join(projectPath, 'package.json'), JSON.stringify(pkgJson, null, 2), err => { if (err) return global.logError(err.message) }) + // create norkconfig.json + const norkconfig: any = { ...data } + norkconfig['version'] = require('../package.json').version + fs.writeFileSync(path.join(projectPath, 'norkconfig.json'), JSON.stringify(norkconfig, null, 2)) + console.log(colors.yellow('Project settings')) console.log(colors.yellow('------------------')) console.log(pad(colors.gray('Project name: '), 30), data.project_name) - console.log(pad(colors.gray('Author: '), 30), data.author) + console.log(pad(colors.gray('Author: '), 30), pkgJson.author) console.log(pad(colors.gray('Language: '), 30), global.langToLanguage(String(data.lang))) + console.log(pad(colors.gray('Database: '), 30), global.dbToDatabase(String(data.database.db))) return global.logSuccess(`Project ${data.project_name} created successfully!`) } diff --git a/src/global.ts b/src/global.ts index 1c32e4f..3cd606f 100644 --- a/src/global.ts +++ b/src/global.ts @@ -24,4 +24,17 @@ export default class Global { return 'Unknown language' } } + + static dbToDatabase(lang: string): string { + switch (lang) { + case 'mongodb': + return 'MongoDB' + case 'postgresql': + return 'PostgreSQL' + case 'mysql': + return 'MySQL' + default: + return 'Unknown database' + } + } } diff --git a/src/interfaces/CreateInterface.ts b/src/interfaces/CreateInterface.ts index b4a5d25..0ccc8dd 100644 --- a/src/interfaces/CreateInterface.ts +++ b/src/interfaces/CreateInterface.ts @@ -1,5 +1,13 @@ +interface database { + db: string + orm: string +} + export interface Create { project_name: string author: string lang: string + database: database + email: string + website: string } diff --git a/src/skeletons/express-ts/.gitignore b/src/skeletons/express-ts/.gitignore index 66e0c76..e25adac 100644 --- a/src/skeletons/express-ts/.gitignore +++ b/src/skeletons/express-ts/.gitignore @@ -1,5 +1,5 @@ # Logs -logs +#logs *.log npm-debug.log* yarn-debug.log* diff --git a/src/skeletons/express-ts/.prettierrc b/src/skeletons/express-ts/.prettierrc index fceb42a..d0dd41b 100644 --- a/src/skeletons/express-ts/.prettierrc +++ b/src/skeletons/express-ts/.prettierrc @@ -1,20 +1,15 @@ { - "arrowParens": "avoid", - "bracketSpacing": true, - "endOfLine": "lf", - "htmlWhitespaceSensitivity": "css", - "insertPragma": false, - "jsxBracketSameLine": true, - "jsxSingleQuote": true, - "printWidth": 200, - "proseWrap": "preserve", - "quoteProps": "as-needed", - "requirePragma": false, - "semi": false, - "singleQuote": true, - "tabWidth": 4, - "trailingComma": "all", - "useTabs": true, - "vueIndentScriptAndStyle": true, - "parser": "typescript" -} \ No newline at end of file + "tabWidth": 4, + "useTabs": true, + "singleQuote": true, + "semi": false, + "trailingComma": "none", + "jsxSingleQuote": true, + "jsxBracketSameLine": true, + "printWidth": 200, + "bracketSpacing": true, + "vueIndentScriptAndStyle": true, + "arrowParens": "always", + "bracketSameLine": false, + "endOfLine": "lf" +} diff --git a/src/skeletons/express-ts/jest.config.js b/src/skeletons/express-ts/jest.config.js deleted file mode 100644 index 5839600..0000000 --- a/src/skeletons/express-ts/jest.config.js +++ /dev/null @@ -1,5 +0,0 @@ -/** @type {import('@ts-jest/dist/types').InitialOptionsTsJest} */ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', -}; \ No newline at end of file diff --git a/src/skeletons/express-ts/norkconfig.json b/src/skeletons/express-ts/norkconfig.json index 22d2a0c..cb5b32d 100644 --- a/src/skeletons/express-ts/norkconfig.json +++ b/src/skeletons/express-ts/norkconfig.json @@ -1,4 +1,5 @@ { "lang": "ts", - "db": "" + "db": "", + "orm": "" } \ No newline at end of file diff --git a/src/skeletons/express-ts/package.json b/src/skeletons/express-ts/package.json index 3f00f89..e23f598 100644 --- a/src/skeletons/express-ts/package.json +++ b/src/skeletons/express-ts/package.json @@ -2,20 +2,22 @@ "name": "project-name", "version": "1.0.0", "description": "", - "main": "app.js", - "scripts": { - "start": "node -r tsconfig-paths/register -r ts-node/register dist/server.js", - "start:dev": "npx nodemon src/server.ts", - "dev": "nodemon src/server.ts", - "test": "jest", - "clean": "rimraf dist/*", - "copy-assets": "ts-node src/utils/copyAssets", - "tsc": "tsc -p .", - "build": "npm-run-all clean tsc copy-assets" - }, + "main": "dist/server.js", + "private": "true", "keywords": [], "author": "", + "repository": "github:username/repo", "license": "ISC", + "scripts": { + "start": "node dist/server.js", + "start:dev": "nodemon src/server.ts", + "test": "jest", + "clean": "rimraf dist/*", + "copy-assets": "npx ts-node src/utils/copyAssets", + "tsc": "tsc -p .", + "build": "npm-run-all clean tsc copy-assets", + "format": "npx prettier --write ." + }, "dependencies": { "colors": "1.4.0", "cookie-parser": "^1.4.5", @@ -23,11 +25,10 @@ "dotenv": "^8.2.0", "ejs": "^3.1.6", "express": "^4.17.1", - "express-validator": "^6.14.0", + "express-validator": "^6.14.2", "fs-extra": "^10.0.0", "jsonwebtoken": "^8.5.1", "mongoose": "^5.12.3", - "morgan": "^1.10.0", "pg": "^8.7.1", "pg-hstore": "^2.3.4", "sequelize": "^6.15.0" @@ -38,7 +39,7 @@ "@types/ejs": "^3.0.6", "@types/express": "^4.17.11", "@types/fs-extra": "^9.0.12", - "@types/jest": "^27.0.1", + "@types/jest": "^27.5.2", "@types/jsonwebtoken": "^8.5.8", "@types/mongoose": "^5.10.5", "@types/morgan": "^1.9.2", @@ -48,11 +49,15 @@ "npm-run-all": "^4.1.5", "rimraf": "^3.0.2", "shelljs": "^0.8.4", - "ts-jest": "^27.0.5", - "ts-node": "^9.1.1", - "tsconfig-paths": "^3.11.0", - "typescript": "^4.2.4" + "ts-jest": "^27.1.5", + "ts-node": "^10.8.1", + "typescript": "^4.2.4", + "morgan": "^1.10.0" }, + "jest": { + "preset": "ts-jest", + "testEnvironment": "node" + }, "nodemonConfig": { "ignore": [ "**/*.test.ts", @@ -63,7 +68,6 @@ "watch": [ "src" ], - "exec": "node -r tsconfig-paths/register -r ts-node/register ./src/server.ts", "ext": "ts, js" } } diff --git a/src/skeletons/express-ts/src/.env.example b/src/skeletons/express-ts/src/.env.example index a6d54b2..602b583 100644 --- a/src/skeletons/express-ts/src/.env.example +++ b/src/skeletons/express-ts/src/.env.example @@ -2,8 +2,11 @@ APP_PORT = 6060 APP_HOSTNAME = 'localhost' APP_HOST = 'http://localhost:8080' # frontend url -CORS_WHITELIST = http://172.15.46.21:8080;http://192.168.0.1:8080 +# Timezone +TZ = 'Europe/Prague' + +CORS_WHITELIST = http://172.15.46.21:8080;http://192.168.0.1:8080 JWT_SECRET = '' # MongoDB @@ -14,4 +17,10 @@ DB_PORT = 5432 DB_HOST = '127.0.0.1' DB_USERNAME = '' DB_PASSWORD = '' -DB_DATABASE = '' \ No newline at end of file +DB_DATABASE = '' + +# SMTP +SMTP_HOST = '' +SMTP_USER = '' +SMTP_PASS = '' +SMTP_FROM = '' diff --git a/src/skeletons/express-ts/src/app.ts b/src/skeletons/express-ts/src/app.ts index f190a11..bb3bc6a 100644 --- a/src/skeletons/express-ts/src/app.ts +++ b/src/skeletons/express-ts/src/app.ts @@ -3,10 +3,16 @@ import morgan from 'morgan' import path from 'path' import cors from 'cors' import cookieParser from 'cookie-parser' -import { router as routes } from '@/routes' -import { router as middlewares } from '@/middlewares' +import { router as routes } from './routes' +import { router as middlewares } from './middlewares' +import env from './config/environment' -const corsWhitelist = ['http://localhost:8080', 'http://localhost:6060'] +export let corsWhitelist: Array +if (env.CORS_WHITELIST != 'undefined') { + corsWhitelist = [...['http://localhost:8080', 'http://localhost:6040'], ...env.CORS_WHITELIST.split(';')] +} else { + corsWhitelist = ['http://localhost:8080', 'http://localhost:6040'] +} const corsOptions = { origin: function (origin: any, callback: any) { if (!origin || corsWhitelist.indexOf(origin) !== -1) { @@ -16,7 +22,7 @@ const corsOptions = { } }, optionsSuccessStatus: 200, - credentials: true, + credentials: true } export const app = express() diff --git a/src/skeletons/express-ts/src/config/database.ts b/src/skeletons/express-ts/src/config/database.ts index 80694ef..da0e1cf 100644 --- a/src/skeletons/express-ts/src/config/database.ts +++ b/src/skeletons/express-ts/src/config/database.ts @@ -1,22 +1,22 @@ import mongoose from 'mongoose' -import config from '@/utils/environment' -import { Err, Succ } from '@/services/globalService' -import db from '@/config/postgres.config' +import env from './environment' +import { Err, Succ } from '../services/globalService' +import db from './sequelize.config' // MongoDB -const dbURI: string = config.DB_URI +const dbURI: string = env.DB_URI function connect() { - if (!config.NORK.db) { + if (!env.NORK.database) { new Err(500, 'no database is in norkcfg.json') return false } - if (config.NORK.db == 'mongodb') { + if (env.NORK.database.orm == 'mongoose') { mongoose .connect(dbURI, { useNewUrlParser: true, useUnifiedTopology: true, - useCreateIndex: true, + useCreateIndex: true }) .then(() => { new Succ(200, 'connected to db') @@ -28,7 +28,7 @@ function connect() { }) } - if (config.NORK.db == 'postgresql') { + if (env.NORK.database.orm == 'sequelize') { db.sync() .then(() => { new Succ(200, 'connected to db') @@ -40,8 +40,8 @@ function connect() { }) } - if (config.NORK.db.length > 0) { - new Err(500, `unsupported database ${config.NORK.db}`) + if (env.NORK.database.db.length > 0) { + new Err(500, `unsupported database ${env.NORK.database.db}`) return false } } diff --git a/src/skeletons/express-ts/src/utils/environment.ts b/src/skeletons/express-ts/src/config/environment.ts similarity index 55% rename from src/skeletons/express-ts/src/utils/environment.ts rename to src/skeletons/express-ts/src/config/environment.ts index b955f49..11d65c4 100644 --- a/src/skeletons/express-ts/src/utils/environment.ts +++ b/src/skeletons/express-ts/src/config/environment.ts @@ -1,13 +1,14 @@ import path from 'path' import fs from 'fs-extra' -import { Err } from '@/services/globalService' +import { Err } from '../services/globalService' import dotenv from 'dotenv' +const env_path = process.env.NODE_ENV ? `../.env.${process.env.NODE_ENV}` : '../.env' -dotenv.config({ path: path.join(__dirname, '../.env') }) +dotenv.config({ path: path.join(__dirname, env_path) }) const norkcfg = fs.readJSONSync(path.join(__dirname, '../../norkconfig.json')) -if (norkcfg.db) { - if (norkcfg.db == 'postgresql') { +if (norkcfg.database) { + if (norkcfg.database.db == 'postgresql') { if (!process.env.DB_PORT) { process.env.DB_PORT = '5432' } @@ -21,6 +22,18 @@ if (norkcfg.db) { } } +if (!fs.existsSync(path.join(__dirname, env_path))) { + console.log('$env_path = ', env_path) + console.log('$__dirname = ', __dirname) + new Err(500, `.env file for ${process.env.NODE_ENV ? process.env.NODE_ENV : ''} environment does not exists`) + process.exit() +} + +if (process.env.JWT_SECRET === undefined || process.env.JWT_SECRET == '') { + new Err(500, 'JWT_SECRET is not set!') + process.exit() +} + export default { // General APP_PORT: Number(process.env.APP_PORT), @@ -36,5 +49,11 @@ export default { DB_USERNAME: String(process.env.DB_USERNAME), DB_PASSWORD: String(process.env.DB_PASSWORD), DB_DATABASE: String(process.env.DB_DATABASE), + // Nork NORK: norkcfg, + // SMTP + SMTP_HOST: String(process.env.SMTP_HOST), + SMTP_USER: String(process.env.SMTP_USER), + SMTP_PASS: String(process.env.SMTP_PASS), + SMTP_FROM: String(process.env.SMTP_FROM) } diff --git a/src/skeletons/express-ts/src/config/postgres.config.ts b/src/skeletons/express-ts/src/config/postgres.config.ts deleted file mode 100644 index 0f469f0..0000000 --- a/src/skeletons/express-ts/src/config/postgres.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Sequelize } from 'sequelize' -import config from '@/utils/environment' - -const db = new Sequelize(config.DB_DATABASE, config.DB_USERNAME, config.DB_PASSWORD, { - host: config.DB_HOST, - dialect: 'postgres', - logging: false, -}) - -export default db diff --git a/src/skeletons/express-ts/src/config/sequelize.config.ts b/src/skeletons/express-ts/src/config/sequelize.config.ts new file mode 100644 index 0000000..b2c05d9 --- /dev/null +++ b/src/skeletons/express-ts/src/config/sequelize.config.ts @@ -0,0 +1,10 @@ +import { Sequelize } from 'sequelize' +import env from './environment' + +const db = new Sequelize(env.DB_DATABASE, env.DB_USERNAME, env.DB_PASSWORD, { + host: env.DB_HOST, + dialect: 'postgres', + logging: false +}) + +export default db diff --git a/src/skeletons/express-ts/src/controllers/rootController.ts b/src/skeletons/express-ts/src/controllers/rootController.ts index 4a94a0d..1cad825 100644 --- a/src/skeletons/express-ts/src/controllers/rootController.ts +++ b/src/skeletons/express-ts/src/controllers/rootController.ts @@ -1,6 +1,6 @@ import { Request, Response } from 'express' -export const root_get = (req: Request, res: Response) => { +export function root_get(req: Request, res: Response) { res.render('home') return true } diff --git a/src/skeletons/express-ts/src/logs/.gitignore b/src/skeletons/express-ts/src/logs/.gitignore new file mode 100644 index 0000000..bf0824e --- /dev/null +++ b/src/skeletons/express-ts/src/logs/.gitignore @@ -0,0 +1 @@ +*.log \ No newline at end of file diff --git a/src/skeletons/express-ts/src/middlewares/authMiddleware.ts b/src/skeletons/express-ts/src/middlewares/authMiddleware.ts index 292bea0..f4d0275 100644 --- a/src/skeletons/express-ts/src/middlewares/authMiddleware.ts +++ b/src/skeletons/express-ts/src/middlewares/authMiddleware.ts @@ -1,24 +1,37 @@ import { Request, Response, NextFunction } from 'express' import jwt from 'jsonwebtoken' -import env from '@/utils/environment' -import { Err, Succ } from '@/services/globalService' -// import User from '@/models/User' // uncomment this +import env from '../config/environment' +import { Err, Succ } from '../services/globalService' +import User from '../models/User' // uncomment this -export const requireAuth = (req: Request, res: Response, next: NextFunction) => { +export function requireAuth(req: Request, res: Response, next: NextFunction) { const token = req.cookies.jwt new Err(500, 'uncomment code in authMiddleware before using!') - /* if (token) { + if (token) { jwt.verify(token, env.JWT_SECRET, async (err: any, decodedToken: any) => { if (err) { // console.error(err.message) - res.status(401).send(new Err(401, 'user is not authenticated')) + res.status(401).json(new Err(401, 'user is not authenticated')) } if (!err) { - const user = await User.findByPk(decodedToken.id) + const user = (async () => { + if (env.NORK.db.orm) { + if (env.NORK.db.orm == 'sequelize') { + return await User.findByPk(decodedToken.id) + } + if (env.NORK.db.orm == 'mongoose') { + return await User.findById(decodedToken.id) + } + } else { + return null + } + })() + if (user === null) { - res.status(401).send(new Err(401, 'user is not authenticated')) + res.status(401).json(new Err(401, 'user is not authenticated')) return } + res.locals.user = user new Succ(100, 'user is authenticated') next() @@ -27,6 +40,24 @@ export const requireAuth = (req: Request, res: Response, next: NextFunction) => } if (!token) { - res.status(401).send(new Err(401, 'user is not authenticated')) - } */ + res.status(401).json(new Err(401, 'user is not authenticated')) + } +} + +export function requireVerified(req: Request, res: Response, next: NextFunction) { + if (res.locals.user._id) { + if (res.locals.user.verified) { + new Succ(100, 'user is verified') + next() + return + } + + res.status(403).json(new Err(403, 'user is not verified')) + return + } + + if (!res.locals.user._id) { + res.status(401).json(new Err(401, 'user is not authenticated')) + return + } } diff --git a/src/skeletons/express-ts/src/middlewares/handleValidation.ts b/src/skeletons/express-ts/src/middlewares/handleValidation.ts index 3f72c18..43c5ef8 100644 --- a/src/skeletons/express-ts/src/middlewares/handleValidation.ts +++ b/src/skeletons/express-ts/src/middlewares/handleValidation.ts @@ -1,13 +1,16 @@ import { Request, Response, NextFunction } from 'express' import { validationResult } from 'express-validator' +import { Err } from '../services/globalService' class Middleware { handleValidationError(req: Request, res: Response, next: NextFunction) { const error = validationResult(req) if (!error.isEmpty()) { - return res.status(400).json(error.array()[0]) + new Err(400, error) + return res.status(400).json(new Err(400, 'validation error', error.array()[0])) } next() } } + export default new Middleware() diff --git a/src/skeletons/express-ts/src/middlewares/index.ts b/src/skeletons/express-ts/src/middlewares/index.ts index 3ac1fdb..ded99aa 100644 --- a/src/skeletons/express-ts/src/middlewares/index.ts +++ b/src/skeletons/express-ts/src/middlewares/index.ts @@ -1,6 +1,6 @@ import { Router } from 'express' -import { router as sayHiMiddleware } from '@/middlewares/sayHiMiddleware' +import { router as sayHiMiddleware } from '../middlewares/sayHiMiddleware' export const router = Router() -router.use(sayHiMiddleware) +// router.use(sayHiMiddleware) diff --git a/src/skeletons/express-ts/src/routes/rootRoutes.ts b/src/skeletons/express-ts/src/routes/rootRoutes.ts index d7f5384..e13cea1 100644 --- a/src/skeletons/express-ts/src/routes/rootRoutes.ts +++ b/src/skeletons/express-ts/src/routes/rootRoutes.ts @@ -1,7 +1,7 @@ import { Router } from 'express' -import * as rootController from '@/controllers/rootController' -import rootValidator from '@/validators/rootValidator' -import handleValidation from '@/middlewares/handleValidation' +import * as rootController from '../controllers/rootController' +import rootValidator from '../validators/rootValidator' +import handleValidation from '../middlewares/handleValidation' export const router = Router() const mws = [handleValidation.handleValidationError] diff --git a/src/skeletons/express-ts/src/server.ts b/src/skeletons/express-ts/src/server.ts index 619976d..0128b12 100644 --- a/src/skeletons/express-ts/src/server.ts +++ b/src/skeletons/express-ts/src/server.ts @@ -1,20 +1,20 @@ import http from 'http' -import { app } from '@/app' -import config from '@/utils/environment' -import { Succ } from '@/services/globalService' -import database from '@/config/database' -const port: number = config.APP_PORT || 8080 -const hostname: string = config.APP_HOSTNAME || 'localhost' -const server = http.createServer(app) +import { app } from './app' +import env from './config/environment' +import { Succ } from './services/globalService' +import database from './config/database' +const port: number = env.APP_PORT || 8080 +const hostname: string = env.APP_HOSTNAME || 'localhost' +export const server = http.createServer(app) // Server export function runServer(): void { server.listen(port, hostname, () => { - new Succ(200, `Server is listening on http://localhost:${port}`) + new Succ(200, `Server is listening on http://${hostname}:${port}`) }) } -if (!config.NORK.db) { +if (!env.NORK.database) { runServer() } else { const db_connection = database() diff --git a/src/skeletons/express-ts/src/services/globalService.ts b/src/skeletons/express-ts/src/services/globalService.ts index 9464eed..78e579e 100644 --- a/src/skeletons/express-ts/src/services/globalService.ts +++ b/src/skeletons/express-ts/src/services/globalService.ts @@ -1,21 +1,43 @@ import colors from 'colors' -import { ErrType } from '@/interfaces/globalInterface' +import fs from 'fs' +import path from 'path' + +export interface ErrType { + code: number + message: string + data?: any +} export class Err implements ErrType { code: number message: string + data: any - constructor(code: number, message: string) { + constructor(code: number, message: string | object, data: any = null) { this.code = code - this.message = message + typeof message === 'object' ? (this.message = JSON.stringify(message)) : (this.message = message) + data ? (this.data = data) : false + // typeof data === 'object' ? (this.data = JSON.stringify(data)) : (this.data = data) + this.drop() } drop() { + if (this.data) { + console.log(colors.bgRed(`${this.code}`) + colors.bgBlack.red(` ${this.message}`) + this.data) + Log.make('Err', this.code, this.message, this.data) + return { + code: this.code, + message: this.message, + data: this.data + } + } + console.log(colors.bgRed(`${this.code}`) + colors.bgBlack.red(` ${this.message}`)) + Log.make('Err', this.code, this.message) return { code: this.code, - message: this.message, + message: this.message } } } @@ -23,18 +45,129 @@ export class Err implements ErrType { export class Succ { code: number message: string + data?: any - constructor(code: number, message: string) { + constructor(code: number, message: string, data: any = null) { this.code = code this.message = message + data ? (this.data = data) : false this.drop() } drop() { + if (this.data) { + console.log(colors.bgGreen.black(`${this.code}`) + colors.green.bgBlack(` ${this.message}`) + this.data) + return { + code: this.code, + message: this.message, + data: this.data + } + } + console.log(colors.bgGreen.black(`${this.code}`) + colors.green.bgBlack(` ${this.message}`)) return { code: this.code, - message: this.message, + message: this.message + } + } +} + +export interface LogType { + type: 'Err' | 'Succ' | 'Info' + code?: number + message?: string + data?: any + logFile?: string +} +export class Log implements LogType { + type: 'Err' | 'Succ' | 'Info' + code?: number + message?: string + data?: any + logFile?: string + + /** + * @param type + * - Type of log + * - Err | Succ | Info + * @param code + * - not required + * - HTTP status code + * @param message + * - could be anything + * @param data + * - could be anything + * @param logFile + * - name of logFile + * - default is log type file + */ + constructor(type: 'Err' | 'Succ' | 'Info', code?: number, message?: string, data?: any, logFile?: string) { + this.type = type + this.code = code + this.message = message + this.data = data + this.logFile = logFile + + if (!this.logFile) { + this.logFile = `${type}.global.log` + } else { + this.logFile = this.logFile + '.log' + } + + this.logFile = path.join(__dirname, this.logFile) + } + + static pathMake(type: string, name?: string) { + let logName + if (!name) { + logName = `${type}.global.log` + } else { + logName = name + '.log' + } + + return path.join(__dirname, '../logs/' + logName) + } + + /** + * returns current date in my custom format + */ + static dateNow(): string { + /** + * @param num: number + * + * receives number and returns two digits number + * example: + * input num = 9 => returns string 09 + */ + function add0(num: number): string { + if (num.toString().length <= 1) { + return '0' + String(num) + } + return String(num) + } + + const d = new Date() + return `${d.getFullYear()}-${add0(d.getMonth() + 1)}-${add0(d.getDate())} ${add0(d.getHours())}:${add0(d.getMinutes())}:${add0(d.getSeconds())}` + } + + static make(type: 'Err' | 'Succ' | 'Info', code?: number, message?: string, data?: any, logFile?: string) { + let realPath = Log.pathMake(type, logFile) + let formattedData = `Date: "${Log.dateNow()}" Type: "${type}"` + + code ? (formattedData += ` Code: "${code}"`) : false + message ? (formattedData += ` Message: "${message}"`) : false + if (data) { + if (typeof data === 'object') { + data = JSON.stringify(data) + } + formattedData += ` Data: "${data}"` + } + formattedData += '\n' + + if (fs.existsSync(realPath)) { + fs.appendFileSync(realPath, formattedData) + } else { + fs.writeFileSync(realPath, formattedData) } } } diff --git a/src/skeletons/express-ts/tsconfig.json b/src/skeletons/express-ts/tsconfig.json index 8f4eb08..a6f9e39 100644 --- a/src/skeletons/express-ts/tsconfig.json +++ b/src/skeletons/express-ts/tsconfig.json @@ -1,85 +1,63 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ - /* Basic Options */ - // "incremental": true, /* Enable incremental compilation */ - "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ - // "lib": [], /* Specify library files to be included in the compilation. */ - // "allowJs": true, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ - // "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./dist", /* Redirect output structure to the directory. */ - "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "es6", + + /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ + "module": "commonjs", - /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "./dist", - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ + /* Redirect output structure to the directory. */ + "rootDir": "./src", + /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - "paths": { - "@/*": ["src/","src/*"], - "@dist/*": ["dist/*"], - "@controllers/*": ["src/controllers/"], - "@interfaces/*": ["src/interfaces/*"], - "@middlewares/*": ["src/middlewares/*"], - "@models/*": ["src/models/*"], - "@public/*": ["src/public/*"], - "@routes/*": ["src/routes/*"], - "@services/*": ["src/services/*"], - "@test/*": ["src/test/*"], - "@utils/*": ["src/utils/*"], - "@validators/*": ["src/validators/*"], - "@views/*": ["src/views/*"], - }, - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Strict Type-Checking Options */ + "strict": true, + /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - - /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ - } + "baseUrl": "./", + "esModuleInterop": true, + /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "resolveJsonModule": true, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Experimental Options */ + "experimentalDecorators": true, + /* Enables experimental support for ES7 decorators. */ + "emitDecoratorMetadata": true, + /* Enables experimental support for emitting type metadata for decorators. */ + /* Advanced Options */ + "skipLibCheck": true, + /* Skip type checking of declaration files. */ + "forceConsistentCasingInFileNames": true + /* Disallow inconsistently-cased references to the same file. */ + }, + "exclude": ["src/tests"] } diff --git a/src/skeletons/mongoose-models/User.ts b/src/skeletons/mongoose-models/User.ts new file mode 100644 index 0000000..68fb524 --- /dev/null +++ b/src/skeletons/mongoose-models/User.ts @@ -0,0 +1,40 @@ +import path from 'path' +import { Schema, model } from 'mongoose' + +export const schemaName = path.basename(__filename).split('.')[0] +const schema = new Schema( + { + username: { + type: String, + required: true + }, + email: { + type: String, + required: true, + unique: true + }, + password: { + type: String, + required: true + }, + domains: [ + { + role: Number, + domain_id: String + } + ], + verification_code: { + type: Number, + length: 6 + }, + verified: { + type: Boolean, + default: false + } + }, + { + timestamps: true + } +) + +export default model(path.basename(__filename).split('.')[0], schema) diff --git a/src/skeletons/sequelize-models/User.ts b/src/skeletons/sequelize-models/User.ts new file mode 100644 index 0000000..49b8051 --- /dev/null +++ b/src/skeletons/sequelize-models/User.ts @@ -0,0 +1,35 @@ +import { DataTypes, Model } from 'sequelize' +import path from 'path' +import db from '../config/sequelize.config.ts' + +class Instance extends Model {} + +Instance.init( + { + _id: { + type: DataTypes.UUID, + primaryKey: true, + allowNull: false, + unique: true, + }, + username: { + type: DataTypes.STRING, + allowNull: false, + }, + password: { + type: DataTypes.STRING, + allowNull: false, + }, + email: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + }, + }, + { + sequelize: db, + tableName: path.basename(__filename).split('.')[0].toLowerCase(), + }, +) + +export default Instance