rapidrestify
Version:
Create a robust Node.js backend REST API boilerplate integrated seamlessly with MongoDB. This package offers a comprehensive foundation for swiftly developing RESTful APIs. It includes a collection of pre-configured components, aiding in rapid setup and d
350 lines • 318 kB
JSON
{
"name": "mysql1",
"type": "folder",
"children": [
{
"type": "file",
"name": ".gitignore",
"content": "# Logs\r\n*.log\r\n\r\n# Enviornment variables\r\n.env\r\n\r\n# Dependency directories\r\n/node_modules\r\n\r\n# Optional npm cache directory\r\n.npm\r\ntemp\r\n\r\n# Optional REPL history\r\n.node_repl_history\r\n*.sql\r\n.idea\r\n.vscode\r\nlogs/*\r\ncache\r\n*.txt\r\n*.aof\r\ndata",
"children": []
},
{
"type": "file",
"name": ".eslintrc.json",
"content": "{\r\n \"env\": {\r\n \"commonjs\": true,\r\n \"es2021\": true,\r\n \"node\": true,\r\n \"jest\": true\r\n },\r\n \"extends\": [\"eslint:recommended\", \"prettier\"],\r\n \"parserOptions\": {\r\n \"ecmaVersion\": \"latest\"\r\n },\r\n \"rules\": {\r\n \"linebreak-style\": [\"error\", \"unix\"],\r\n \"semi\": [\"error\", \"always\"],\r\n \"no-console\": \"error\",\r\n \"no-unused-vars\": \"error\"\r\n }\r\n}\r\n",
"children": []
},
{
"type": "file",
"name": "app.js",
"content": "require('dotenv').config();\r\nconst express = require('express');\r\nconst cors = require('cors');\r\nconst compression = require('compression');\r\nconst cookieParser = require('cookie-parser');\r\nconst morgan = require('morgan');\r\nconst path = require('path');\r\nconst helmet = require('helmet');\r\nconst passport = require('passport');\r\nconst cookieSession = require('cookie-session');\r\n\r\n// imports\r\nconst { logger } = require('./src/utils');\r\nconst indexRoutes = require('./src/routes');\r\nconst { HELPER } = require('./src/helpers');\r\n\r\n// express servers\r\nconst app = express();\r\n\r\napp.use(\r\n cookieSession({\r\n name: 'test-auth',\r\n keys: ['key1', 'key2'],\r\n })\r\n);\r\n\r\napp.use(passport.initialize());\r\napp.use(passport.session());\r\n\r\n// mongoose connection\r\n\r\napp.use(express.json());\r\napp.use(express.urlencoded({ extended: true, parameterLimit: 1000000 }));\r\napp.use(compression());\r\napp.use(cookieParser());\r\n\r\napp.use(\r\n cors({\r\n origin: '*',\r\n methods: 'GET,HEAD,PUT,PATCH,POST,DELETE',\r\n credentials: true,\r\n optionsSuccessStatus: 204,\r\n })\r\n);\r\n\r\napp.use(helmet());\r\napp.use(morgan('[:date[web]] :method :url :status :response-time ms - :res[content-length]'));\r\n\r\n// Enabled CORS\r\napp.use((req, res, next) => {\r\n res.setHeader('Access-Control-Allow-Origin', '*');\r\n res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,PATCH,DELETE');\r\n res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization');\r\n\r\n // intercept OPTIONS method\r\n if (req.method === 'OPTIONS') {\r\n res.send(200);\r\n } else {\r\n next();\r\n }\r\n});\r\n\r\n// Public Path\r\nconst publicPath = path.join(__dirname, 'src/public');\r\napp.use(express.static(publicPath));\r\n\r\n// api Routes\r\napp.use('/api/v1', indexRoutes);\r\n\r\n// errorHandler\r\napp.use(HELPER.errorHandler);\r\n\r\n// routesHandler\r\napp.use(HELPER.routeHandler);\r\n\r\n// handle exceptions\r\nprocess.on('uncaughtException', function (err) {\r\n logger.error(err);\r\n});\r\n\r\n// dev server\r\n\r\n// handle rejection\r\nprocess.on('unhandledRejection', function (err) {\r\n logger.error(err);\r\n});\r\n\r\nmodule.exports = app;\r\n",
"children": []
},
{
"type": "file",
"name": "env.sample",
"content": "#APP\r\nNODE_ENV=\r\nPORT=\r\n\r\n#DB\r\nDB_USERNAME=\r\nDB_PASSWORD=\r\nDB_NAME=\r\nDB_HOST=\r\nDB_PORT=\r\nDB_DIALECT=\r\n\r\n\r\n# aws creds\r\nAWS_ACCESS_KEY_ID=\r\nAWS_SECRET_ACCESS_KEY=\r\nS3_ENDPOINT=\r\nBUCKET_NAME=\r\nFOLDER_NAME=\r\n",
"children": []
},
{
"type": "file",
"name": ".prettierrc",
"content": "{\r\n \"trailingComma\": \"es5\",\r\n \"tabWidth\": 4,\r\n \"semi\": true,\r\n \"singleQuote\": true,\r\n \"printWidth\": 140\r\n}\r\n",
"children": []
},
{
"type": "file",
"name": "package.json",
"content": "{\r\n \"name\": \"nodejs-express-sequelize-boilerplate\",\r\n \"version\": \"1.0.0\",\r\n \"description\": \"Boilerplate for NodeJS Application with Express, PostgresSQL & Sequelize ORM\",\r\n \"main\": \"app.js\",\r\n \"scripts\": {\r\n \"format:check\": \"prettier --check .\",\r\n \"format\": \"prettier --write .\",\r\n \"lint:check\": \"eslint .\",\r\n \"lint\": \"eslint --fix .\",\r\n \"test\": \"npm run test\",\r\n \"prestart\": \"npx sequelize-cli db:migrate && npx sequelize-cli db:seed:all\",\r\n \"start\": \"node ./bin/www\",\r\n \"dev\": \"nodemon ./bin/www\"\r\n },\r\n \"keywords\": [\r\n \"nodejs\",\r\n \"express\",\r\n \"sequelize\",\r\n \"PostgresSQL\"\r\n ],\r\n \"author\": \"Accubits\",\r\n \"license\": \"ISC\",\r\n \"dependencies\": {\r\n \"aws-sdk\": \"^2.1579.0\",\r\n \"bcrypt\": \"^5.1.1\",\r\n \"compression\": \"^1.7.4\",\r\n \"cookie-parser\": \"^1.4.6\",\r\n \"cookie-session\": \"^2.1.0\",\r\n \"cors\": \"^2.8.5\",\r\n \"dotenv\": \"^16.4.5\",\r\n \"express\": \"^4.18.3\",\r\n \"helmet\": \"^7.1.0\",\r\n \"joi\": \"^17.12.2\",\r\n \"jsonwebtoken\": \"^9.0.2\",\r\n \"morgan\": \"^1.10.0\",\r\n \"multer\": \"^1.4.5-lts.1\",\r\n \"mysql2\": \"^3.9.2\",\r\n \"passport\": \"^0.7.0\",\r\n \"pg\": \"^8.11.3\",\r\n \"pgsn\": \"^1.1.3\",\r\n \"pino\": \"^8.19.0\",\r\n \"pino-pretty\": \"^10.3.1\",\r\n \"sequelize\": \"^6.37.1\",\r\n \"swagger-jsdoc\": \"^6.2.8\",\r\n \"swagger-ui-express\": \"^5.0.0\"\r\n },\r\n \"devDependencies\": {\r\n \"cross-env\": \"^7.0.3\",\r\n \"eslint\": \"^8.57.0\",\r\n \"eslint-config-prettier\": \"^9.1.0\",\r\n \"nodemon\": \"^3.1.0\",\r\n \"prettier\": \"^3.2.5\",\r\n \"sequelize-cli\": \"^6.6.2\"\r\n }\r\n}\r\n",
"children": []
},
{
"type": "file",
"name": ".sequelizerc",
"content": "const path = require('path');\r\n\r\nmodule.exports = {\r\n 'models-path': path.resolve('./src/database/models'),\r\n 'seeders-path': path.resolve('./src/database/seeders'),\r\n 'migrations-path': path.resolve('./src/database/migrations'),\r\n config: path.resolve('./src/config/database.js'),\r\n};\r\n",
"children": []
},
{
"name": "src",
"type": "folder",
"children": [
{
"name": "config",
"type": "folder",
"children": [
{
"type": "file",
"name": "constants.js",
"content": "module.exports = {\r\n APP: {\r\n port: process.env.PORT,\r\n env: process.env.NODE_ENV,\r\n },\r\n USER: {\r\n ROLES: {\r\n ADMIN: 'ADMIN',\r\n USER: 'USER',\r\n },\r\n STATUS: {\r\n VERIFIED: 'verified',\r\n UNVERIFIED: 'unverified',\r\n },\r\n PASSWORD: {\r\n DEFAULT: 'test@default',\r\n },\r\n },\r\n JWT: {},\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "database.js",
"content": "require('dotenv').config();\r\nmodule.exports = {\r\n production: {\r\n username: process.env.DB_USERNAME,\r\n password: process.env.DB_PASSWORD,\r\n database: process.env.DB_NAME,\r\n host: process.env.DB_HOST,\r\n port: process.env.DB_PORT || 5432,\r\n dialect: process.env.DB_DIALECT || 'postgres',\r\n seederStorage: 'sequelize',\r\n dialectOptions: { decimalNumbers: true },\r\n logging: false,\r\n pool: {\r\n max: 5,\r\n min: 0,\r\n acquire: 30000,\r\n idle: 10000,\r\n },\r\n },\r\n development: {\r\n username: process.env.DB_USERNAME,\r\n password: process.env.DB_PASSWORD,\r\n database: process.env.DB_NAME,\r\n host: process.env.DB_HOST,\r\n port: process.env.DB_PORT || 5432,\r\n dialect: process.env.DB_DIALECT || 'postgres',\r\n seederStorage: 'sequelize',\r\n dialectOptions: { decimalNumbers: true },\r\n logging: false,\r\n pool: {\r\n max: 5,\r\n min: 0,\r\n acquire: 30000,\r\n idle: 10000,\r\n },\r\n },\r\n test: {\r\n username: process.env.DB_USERNAME,\r\n password: process.env.DB_PASSWORD,\r\n database: process.env.DB_NAME,\r\n host: process.env.DB_HOST,\r\n port: process.env.DB_PORT || 5432,\r\n dialect: process.env.DB_DIALECT || 'postgres',\r\n seederStorage: 'sequelize',\r\n dialectOptions: { decimalNumbers: true },\r\n logging: false,\r\n pool: {\r\n max: 5,\r\n min: 0,\r\n acquire: 30000,\r\n idle: 10000,\r\n },\r\n },\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "httpCodes.js",
"content": "module.exports = {\r\n OK: 200,\r\n CREATED: 201,\r\n ACCEPTED: 202,\r\n NO_CONTENT: 204,\r\n BAD_REQUEST: 400,\r\n UNAUTHORIZED: 401,\r\n FORBIDDEN: 403,\r\n NOT_FOUND: 404,\r\n PRECONDITION_FAILED: 412,\r\n UNPROCESSABLE_ENTITY: 422,\r\n FAILED_DEPENDENCY: 424,\r\n TOO_MANY_REQUESTS: 429,\r\n INTERNAL_SERVER_ERROR: 500,\r\n BAD_GATEWAY: 502,\r\n SERVICE_UNAVAILABLE: 503,\r\n UNSUPPORTED_MEDIA: 415,\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "index.js",
"content": "const constants = require('./constants');\r\nconst messages = require('./messages');\r\nconst httpCodes = require('./httpCodes');\r\n\r\nmodule.exports = {\r\n CONSTANTS: constants,\r\n MESSAGES: messages,\r\n HTTP_CODES: httpCodes,\r\n JWT: {\r\n ACCESS_TOKEN_SECRET: process.env.ACCESS_TOKEN_SECRET || 'secret_key',\r\n REFRESH_TOKEN_SECRET: process.env.REFRESH_TOKEN_SECRET || 'secret_key',\r\n ACCESS_TOKEN_TIME: process.env.ACCESS_TOKEN_TIME || '1d',\r\n REFRESH_TOKEN_TIME: process.env.REFRESH_TOKEN_TIME || '7d',\r\n },\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "messages.js",
"content": "module.exports = {\r\n LOGIN_SUCCESS: 'Login successful',\r\n LOGIN_FAILED: 'Login failed',\r\n WRONG_PASSWORD: 'Incorrect password',\r\n CREATED: 'Successfully created',\r\n TOGGLE_TRACKER: 'Toggle Successfully Tracked',\r\n FILE_UPLOAD: 'Successfully File Upload.',\r\n REGISTER_USER: 'You are successfully registered.',\r\n SEND_OTP: 'Otp has been sent your register number.',\r\n SEND_OTP_EMAIL: 'Otp has been sent your register email.',\r\n SUCCESS_OTP: 'Otp Verified',\r\n FAILED_OTP: 'Invalid Otp.',\r\n INVALID_USERNAME: 'Invalid username.',\r\n CREATE_FAILED: 'Failed to create record',\r\n GET_RECORD_SUCCESS: 'Retrieved records successfully',\r\n GET_SINGLE_RECORD: 'Retrieved single record successfully',\r\n UPDATE_SUCCESS: 'Record updated successfully',\r\n PASSWORD_CHANGES: 'Password has been changed.',\r\n DELETE_SUCCESS: 'Record deleted successfully',\r\n NOT_FOUND: 'Record Not Found.',\r\n NOT_FOUND_FUN: (message) => `${message} does not exist.`,\r\n ROUTE_NOT_FOUND: 'Route Not Found!',\r\n EMAIL_NOT_VERIFIED: 'Email must be verified',\r\n EMAIL_ALREADY_TAKEN: 'Email Already taken',\r\n BAD_REQUEST: 'Bad request',\r\n BAD_ROUTINE_ID: 'Invalid routine id',\r\n BAD_PILLAR_ID: 'Invalid pillar id',\r\n UNAUTHORIZED: 'Unauthorized access',\r\n FORBIDDEN: 'Access forbidden',\r\n PRECONDITION_FAILED: 'Precondition failed',\r\n TOO_MANY_REQUESTS: 'Too many requests',\r\n SERVICE_UNAVAILABLE: 'Service unavailable',\r\n INTERNAL_SERVER_ERROR: 'Internal server error',\r\n EMAIL_ALREADY_EXISTS: 'The email address is already in use by another account.',\r\n AUTH_ERRORS: {\r\n TOKEN_HEADER: 'Token header not found',\r\n TOKEN: 'Token not found',\r\n UNAUTHORIZED: 'Oops! Unauthorised access',\r\n BLOCKED: 'Oops! You are block. Contact to admin.',\r\n },\r\n\r\n ERROR: {\r\n LOGIN: {\r\n USERNAME: 'Incorrect username or password. Please try again',\r\n WRONG_PASS: 'Password is incorrect. Please try again',\r\n },\r\n },\r\n};\r\n",
"children": []
}
]
},
{
"name": "middlewares",
"type": "folder",
"children": [
{
"type": "file",
"name": "authorisation.js",
"content": "const { MESSAGES } = require('../config');\r\nconst db = require('../database/models');\r\nconst { UserModel } = require('../database/models/users.model');\r\nconst { UnauthorizedException } = require('../helpers/errorResponse');\r\nconst { jwt } = require('../utils');\r\n\r\nmodule.exports = {\r\n validateAccessToken:\r\n (allowedRoles = []) =>\r\n async (req, res, next) => {\r\n try {\r\n if (!req.headers.authorization) throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.TOKEN_HEADER);\r\n\r\n const token = req.headers.authorization.split(' ')[1]; // Extracting Bearer token from header.\r\n\r\n if (!token) throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.TOKEN);\r\n\r\n const decoded = await jwt.verifyAccessToken(token);\r\n\r\n const user = await db.UserModel.findOne({\r\n id: decoded.id,\r\n deletedAt: null,\r\n });\r\n\r\n if (!user) {\r\n throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.UNAUTHORIZED);\r\n }\r\n\r\n if (user.isBlock) {\r\n throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.BLOCKED);\r\n }\r\n\r\n if (allowedRoles.includes(decoded.role)) {\r\n req.user = decoded;\r\n next();\r\n } else {\r\n throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.UNAUTHORIZED);\r\n }\r\n } catch (error) {\r\n next(error);\r\n }\r\n },\r\n validateRefreshToken:\r\n (allowedRoles = []) =>\r\n async (req, res, next) => {\r\n try {\r\n if (!req.headers.authorization) throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.TOKEN_HEADER);\r\n\r\n const token = req.headers.authorization.split(' ')[1]; // Extracting Bearer token from header.s\r\n if (!token) throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.TOKEN);\r\n const decoded = await jwt.verifyRefreshToken(token);\r\n\r\n if (allowedRoles.includes(decoded.role)) {\r\n req.user = decoded;\r\n next();\r\n } else {\r\n throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.UNAUTHORIZED);\r\n }\r\n } catch (error) {\r\n next(error);\r\n }\r\n },\r\n\r\n isAuthenticated: (req, res, next) => {\r\n if (req.user) {\r\n next();\r\n } else {\r\n throw new UnauthorizedException(MESSAGES.AUTH_ERRORS.UNAUTHORIZED);\r\n }\r\n\r\n // if (!req.isAuthenticated()) {\r\n // throw new UnauthorizedException(\"Oops! Unauthorised access\");\r\n // }\r\n // next();\r\n },\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "index.js",
"content": "const validation = require('./validation');\r\nexports.MDWR = {\r\n ...require('./authorisation'),\r\n ...require('./upload.files'),\r\n validationMiddleware: validation,\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "routes.js",
"content": "const express = require('express');\r\nconst CONTROLLER = require('./controller');\r\nconst { MDWR } = require('../../middlewares');\r\nconst { SCHEMA } = require('./validation');\r\nconst { CONSTANTS } = require('../../config');\r\n\r\nconst router = express.Router();\r\n\r\nrouter.post('/register', MDWR.validationMiddleware(SCHEMA.SIGNUP), CONTROLLER.REGISTER);\r\n\r\nrouter.post('/login', MDWR.validationMiddleware(SCHEMA.LOGIN), CONTROLLER.LOGIN);\r\n\r\nrouter.get('/profile', MDWR.validateAccessToken(CONSTANTS.USER.ROLES.USER), CONTROLLER.VIEW);\r\n\r\nrouter.patch('/update', MDWR.validateAccessToken(CONSTANTS.USER.ROLES.USER), MDWR.validationMiddleware(SCHEMA.UPDATE), CONTROLLER.UPDATE);\r\n\r\nrouter.delete('/delete', MDWR.validateAccessToken(CONSTANTS.USER.ROLES.USER), CONTROLLER.DELETE);\r\n\r\nmodule.exports = router;\r\n",
"children": []
},
{
"type": "file",
"name": "upload.files.js",
"content": "const multer = require('multer');\r\nconst fileFilter = (req, file, cb) => {\r\n cb(null, true);\r\n};\r\nmodule.exports = {\r\n uploadFile: multer({ storage: multer.memoryStorage(), fileFilter }).single('file'),\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "validation.js",
"content": "const { PreconditionException } = require('../helpers/errorResponse');\r\n\r\nconst options = {\r\n basic: {\r\n abortEarly: false,\r\n convert: true,\r\n },\r\n array: {\r\n abortEarly: false,\r\n convert: true,\r\n },\r\n};\r\n\r\nmodule.exports = (schema) => (req, res, next) => {\r\n Object.keys(schema).forEach((key) => {\r\n const { error } = schema[key].validate(req[key], options);\r\n console.log(error);\r\n if (error) {\r\n console.log(error);\r\n const message = error.details[0].message || 'Invalid Inputs';\r\n throw new PreconditionException(message);\r\n }\r\n });\r\n next();\r\n};\r\n",
"children": []
}
]
},
{
"name": "utils",
"type": "folder",
"children": [
{
"type": "file",
"name": "bcrypt.js",
"content": "const bcrypt = require('bcrypt');\r\nconst { HELPER } = require('../helpers');\r\n\r\nexports.verifyPassword = (plainPassword, hashPassword) => {\r\n return new Promise((resolve, reject) => {\r\n bcrypt.compare(plainPassword, hashPassword, function (err, result) {\r\n resolve(result);\r\n reject(err);\r\n });\r\n });\r\n};\r\n\r\nexports.generatePassword = async (password) => {\r\n try {\r\n const saltRounds = 10;\r\n const salt = await bcrypt.genSalt(saltRounds);\r\n const hash = await bcrypt.hash(password, salt);\r\n return hash;\r\n } catch (error) {\r\n throw error;\r\n }\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "aws.utils.js",
"content": "require('dotenv').config();\r\nconst AWS = require('aws-sdk');\r\nconst path = require('path');\r\nconst logger = require('./logger');\r\n\r\nAWS.config.apiVersions = { s3: '2012-10-17' };\r\n\r\nAWS.config.update({\r\n accessKeyId: process.env.AWS_ACCESS_KEY_ID,\r\n secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,\r\n region: process.env.S3_REGION,\r\n});\r\n\r\nconst s3 = new AWS.S3();\r\n\r\nexports.putObject = async (file) => {\r\n try {\r\n const params = {\r\n Bucket: process.env.BUCKET_NAME,\r\n Key: `${process.env.FOLDER_NAME}/__${Date.now()}${path.extname(file.originalname)}`,\r\n Body: file.buffer,\r\n ContentType: file.mimetype,\r\n };\r\n return await s3.upload(params).promise();\r\n } catch (error) {\r\n logger.error(error);\r\n return null;\r\n }\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "index.js",
"content": "const logger = require('./logger');\r\nconst bcrypt = require('./bcrypt');\r\nconst jwt = require('./jwt');\r\nconst PGSN = require('./panigation');\r\n\r\nmodule.exports = { logger, bcrypt, jwt, PGSN };\r\n",
"children": []
},
{
"type": "file",
"name": "jwt.js",
"content": "const { JWT } = require('../config');\r\nconst { HELPER } = require('../helpers');\r\nconst jwt = require('jsonwebtoken');\r\n\r\nexports.verifyAccessToken = (token) => {\r\n // eslint-disable-next-line no-unused-vars\r\n return new Promise((resolve, reject) => {\r\n jwt.verify(token, JWT.ACCESS_TOKEN_SECRET, (err, decoded) => {\r\n if (err) throw new HELPER.BadRequestException('Invalid Token');\r\n resolve(decoded);\r\n });\r\n });\r\n};\r\n\r\nexports.verifyRefreshToken = (token) => {\r\n // eslint-disable-next-line no-unused-vars\r\n return new Promise((resolve, reject) => {\r\n jwt.verify(token, JWT.REFRESH_TOKEN_SECRET, (err, decoded) => {\r\n if (err) throw new HELPER.BadRequestException('Invalid Token');\r\n resolve(decoded);\r\n });\r\n });\r\n};\r\n\r\nexports.generateAccessToken = (payload) => {\r\n return jwt.sign({ ...payload }, JWT.ACCESS_TOKEN_SECRET, {\r\n expiresIn: JWT.ACCESS_TOKEN_TIME,\r\n });\r\n};\r\n\r\nexports.generateRefreshToken = (payload) => {\r\n return jwt.sign({ ...payload }, JWT.REFRESH_TOKEN_SECRET, {\r\n expiresIn: JWT.REFRESH_TOKEN_TIME,\r\n });\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "logger.js",
"content": "const pino = require('pino');\r\n\r\nconst logger = pino({\r\n transport: {\r\n target: 'pino-pretty',\r\n options: {\r\n colorize: true,\r\n translateTime: 'yyyy-dd-mm, h:MM:ss TT',\r\n },\r\n },\r\n});\r\n\r\nmodule.exports = logger;\r\n",
"children": []
},
{
"type": "file",
"name": "panigation.js",
"content": "const { PGSN } = require('pgsn');\r\n\r\nexports.getPagingData = (data, page, limit) => {\r\n const { count: totalItems, rows } = data;\r\n return PGSN.getPagingData({ rows: rows, totalItems, page, limit });\r\n};\r\n",
"children": []
}
]
},
{
"name": "routes",
"type": "folder",
"children": [
{
"type": "file",
"name": "index.js",
"content": "const express = require('express');\r\nconst { usersRoutes } = require('../modules/users');\r\nconst router = express.Router();\r\n\r\nrouter.use('/users', usersRoutes);\r\n\r\nmodule.exports = router;\r\n",
"children": []
}
]
},
{
"name": "database",
"type": "folder",
"children": [
{
"name": "migrations",
"type": "folder",
"children": [
{
"type": "file",
"name": "20240305042615-create-users.js",
"content": "module.exports = {\r\n async up(queryInterface, Sequelize) {\r\n return Promise.all([\r\n await queryInterface.createTable('Users', {\r\n id: {\r\n allowNull: false,\r\n autoIncrement: true,\r\n primaryKey: true,\r\n type: Sequelize.BIGINT,\r\n },\r\n role: {\r\n type: Sequelize.ENUM('USER', 'ADMIN'),\r\n defaultValue: 'USER',\r\n },\r\n name: {\r\n type: Sequelize.STRING,\r\n allowNull: true,\r\n },\r\n email: {\r\n type: Sequelize.STRING,\r\n unique: true,\r\n allowNull: false,\r\n },\r\n password: {\r\n type: Sequelize.STRING,\r\n allowNull: false,\r\n },\r\n status: {\r\n type: Sequelize.ENUM('active', 'inactive'),\r\n defaultValue: 'active',\r\n },\r\n createdAt: {\r\n type: Sequelize.DATE,\r\n allowNull: false,\r\n },\r\n updatedAt: {\r\n type: Sequelize.DATE,\r\n allowNull: false,\r\n },\r\n deletedAt: {\r\n type: Sequelize.DATE,\r\n allowNull: true,\r\n },\r\n }),\r\n ]);\r\n },\r\n\r\n // eslint-disable-next-line no-unused-vars\r\n async down(queryInterface, Sequelize) {\r\n return queryInterface.dropTable('Users');\r\n },\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "20240305042642-create-products.js",
"content": "module.exports = {\r\n async up(queryInterface, Sequelize) {\r\n return Promise.all([\r\n await queryInterface.createTable('Products', {\r\n id: {\r\n allowNull: false,\r\n autoIncrement: true,\r\n primaryKey: true,\r\n type: Sequelize.BIGINT,\r\n },\r\n userId: { type: Sequelize.INTEGER, allowNull: false },\r\n catId: { type: Sequelize.INTEGER, allowNull: false },\r\n name: { type: Sequelize.STRING, allowNull: false },\r\n description: { type: Sequelize.STRING, allowNull: false },\r\n qty: { type: Sequelize.INTEGER, defaultValue: 0 },\r\n price: { type: Sequelize.INTEGER, defaultValue: 0 },\r\n status: { type: Sequelize.ENUM('active', 'inactive'), defaultValue: 'active' },\r\n createdAt: { type: Sequelize.DATE, allowNull: false },\r\n updatedAt: { type: Sequelize.DATE, allowNull: false },\r\n deletedAt: { type: Sequelize.DATE, allowNull: true },\r\n }),\r\n ]);\r\n },\r\n\r\n // eslint-disable-next-line no-unused-vars\r\n async down(queryInterface, Sequelize) {\r\n return queryInterface.dropTable('Products');\r\n },\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "20240305044410-create-files.js",
"content": "module.exports = {\r\n async up(queryInterface, Sequelize) {\r\n return Promise.all([\r\n await queryInterface.createTable('Products', {\r\n id: {\r\n allowNull: false,\r\n autoIncrement: true,\r\n primaryKey: true,\r\n type: Sequelize.BIGINT,\r\n },\r\n userId: { type: Sequelize.INTEGER, allowNull: true },\r\n fileName: { type: Sequelize.STRING, allowNull: true },\r\n dirName: { type: Sequelize.STRING, allowNull: true },\r\n mimetype: { type: Sequelize.STRING, allowNull: true },\r\n fileSize: { type: Sequelize.INTEGER, defaultValue: 0 },\r\n bucket: { type: Sequelize.INTEGER, defaultValue: null },\r\n url: { type: Sequelize.STRING, defaultValue: null },\r\n status: { type: Sequelize.ENUM('active', 'inactive'), defaultValue: 'active' },\r\n createdAt: { type: Sequelize.DATE, allowNull: false },\r\n updatedAt: { type: Sequelize.DATE, allowNull: false },\r\n deletedAt: { type: Sequelize.DATE, allowNull: true },\r\n }),\r\n ]);\r\n },\r\n\r\n // eslint-disable-next-line no-unused-vars\r\n async down(queryInterface, Sequelize) {\r\n return queryInterface.dropTable('Products');\r\n },\r\n};\r\n",
"children": []
}
]
},
{
"name": "models",
"type": "folder",
"children": [
{
"type": "file",
"name": "files.model.js",
"content": "const { Model } = require('sequelize');\r\n\r\nmodule.exports = (sequelize, DataTypes) => {\r\n class FileModel extends Model {\r\n static associate(model) {\r\n FileModel.belongsTo(model.UserModel, { foreignKey: 'userId', as: 'user' });\r\n }\r\n }\r\n FileModel.init(\r\n {\r\n userId: {\r\n type: DataTypes.INTEGER,\r\n allowNull: false,\r\n references: {\r\n model: {\r\n tableName: 'Users',\r\n key: 'id',\r\n },\r\n },\r\n },\r\n fileName: { type: DataTypes.INTEGER, allowNull: true },\r\n dirName: { type: DataTypes.STRING, allowNull: true },\r\n mimetype: { type: DataTypes.STRING, allowNull: true },\r\n fileSize: { type: DataTypes.INTEGER, defaultValue: 0 },\r\n bucket: { type: DataTypes.INTEGER, defaultValue: null },\r\n url: { type: DataTypes.STRING, defaultValue: null },\r\n status: { type: DataTypes.ENUM('active', 'inactive'), defaultValue: 'active' },\r\n },\r\n {\r\n sequelize,\r\n modelName: FileModel.name,\r\n tableName: 'Files',\r\n paranoid: true,\r\n timestamps: true,\r\n }\r\n );\r\n\r\n return FileModel;\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "index.js",
"content": "'use strict';\r\n\r\nconst fs = require('fs');\r\nconst path = require('path');\r\nconst Sequelize = require('sequelize');\r\nconst basename = path.basename(__filename);\r\nconst env = process.env.NODE_ENV || 'development';\r\nconst config = require(__dirname + '/../../config/database.js')[env];\r\nconst db = {};\r\n\r\nlet sequelize;\r\nif (config.use_env_variable) {\r\n sequelize = new Sequelize(process.env[config.use_env_variable], config);\r\n} else {\r\n sequelize = new Sequelize(config.database, config.username, config.password, config);\r\n}\r\n\r\nfs.readdirSync(__dirname)\r\n .filter((file) => {\r\n return file.indexOf('.') !== 0 && file !== basename && file.slice(-3) === '.js';\r\n })\r\n .forEach((file) => {\r\n const model = require(path.join(__dirname, file))(sequelize, Sequelize.DataTypes);\r\n db[model.name] = model;\r\n });\r\n\r\nObject.keys(db).forEach((modelName) => {\r\n if (db[modelName].associate) {\r\n db[modelName].associate(db);\r\n }\r\n});\r\n\r\ndb.sequelize = sequelize;\r\ndb.Sequelize = Sequelize;\r\n\r\nmodule.exports = db;\r\n",
"children": []
},
{
"type": "file",
"name": "users.model.js",
"content": "const { Model } = require('sequelize');\r\n\r\nmodule.exports = (sequelize, DataTypes) => {\r\n class UserModel extends Model {\r\n static associate(model) {\r\n UserModel.hasMany(model.ProductModel, { foreignKey: 'userId', as: 'products' });\r\n UserModel.hasMany(model.FileModel, { foreignKey: 'userId', as: 'files' });\r\n }\r\n }\r\n UserModel.init(\r\n {\r\n role: {\r\n type: DataTypes.ENUM('USER', 'ADMIN'),\r\n defaultValue: 'USER',\r\n },\r\n name: {\r\n type: DataTypes.STRING,\r\n allowNull: true,\r\n },\r\n email: {\r\n type: DataTypes.STRING,\r\n unique: true,\r\n allowNull: false,\r\n },\r\n password: {\r\n type: DataTypes.STRING,\r\n allowNull: false,\r\n },\r\n status: {\r\n type: DataTypes.ENUM('active', 'inactive'),\r\n defaultValue: 'active',\r\n },\r\n },\r\n {\r\n sequelize,\r\n modelName: UserModel.name,\r\n tableName: 'Users',\r\n paranoid: true,\r\n timestamps: true,\r\n }\r\n );\r\n\r\n return UserModel;\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "products.model.js",
"content": "const { Model } = require('sequelize');\r\n\r\nmodule.exports = (sequelize, DataTypes) => {\r\n class ProductModel extends Model {\r\n static associate(model) {\r\n ProductModel.belongsTo(model.UserModel, { foreignKey: 'userId', as: 'user' });\r\n }\r\n }\r\n ProductModel.init(\r\n {\r\n id: {\r\n allowNull: false,\r\n autoIncrement: true,\r\n primaryKey: true,\r\n type: DataTypes.BIGINT,\r\n },\r\n userId: {\r\n type: DataTypes.INTEGER,\r\n allowNull: false,\r\n references: {\r\n model: {\r\n tableName: 'Users',\r\n key: 'id',\r\n },\r\n },\r\n },\r\n catId: { type: DataTypes.INTEGER, allowNull: true },\r\n name: { type: DataTypes.STRING, allowNull: false },\r\n description: { type: DataTypes.STRING, allowNull: false },\r\n qty: { type: DataTypes.INTEGER, defaultValue: 0 },\r\n price: { type: DataTypes.INTEGER, defaultValue: 0 },\r\n status: { type: DataTypes.ENUM('active', 'inactive'), defaultValue: 'active' },\r\n },\r\n {\r\n sequelize,\r\n modelName: ProductModel.name,\r\n tableName: 'Products',\r\n paranoid: true,\r\n timestamps: true,\r\n }\r\n );\r\n\r\n return ProductModel;\r\n};\r\n",
"children": []
}
]
}
]
},
{
"name": "helpers",
"type": "folder",
"children": [
{
"type": "file",
"name": "errorHandler.js",
"content": "const { HTTP_CODES, MESSAGES } = require('../config');\r\nconst { ErrorResponse } = require('./errorResponse');\r\nconst { logger } = require('../utils');\r\nconst { errorResponse } = require('./response');\r\n\r\n// eslint-disable-next-line no-unused-vars\r\nexports.errorHandler = (err, req, res, next) => {\r\n let error = { ...err };\r\n\r\n error.message = err.message;\r\n\r\n if (error.name === 'SequelizeUniqueConstraintError') {\r\n error = new ErrorResponse(MESSAGES.EMAIL_ALREADY_EXISTS, HTTP_CODES.BAD_REQUEST);\r\n }\r\n\r\n if (err.type === 'TypeError') {\r\n const message = 'TypeError' + err.value;\r\n error = new ErrorResponse(message, HTTP_CODES.BAD_REQUEST);\r\n }\r\n\r\n if (err.name === 'CastError') {\r\n const message = 'Resource not found with ID of ' + err.value;\r\n error = new ErrorResponse(message, HTTP_CODES.NOT_FOUND);\r\n }\r\n\r\n if (err.code === 11000) {\r\n const message = 'Duplicate field value entered';\r\n error = new ErrorResponse(message, HTTP_CODES.BAD_REQUEST);\r\n }\r\n\r\n if (err.statusCode === 412) {\r\n const message = error.message.split('/');\r\n error = new ErrorResponse(message[0].split('\"').join(''), HTTP_CODES.BAD_REQUEST);\r\n }\r\n\r\n errorResponse(res, error.statusCode || 500, error.message || 'Something went wrong. Please try again later.', error.err || {});\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "index.js",
"content": "exports.HELPER = {\r\n ...require('./errorHandler'),\r\n ...require('./response'),\r\n ...require('./routeHandler'),\r\n ...require('./errorResponse'),\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "response.js",
"content": "const { HTTP_CODES } = require('../config');\r\n\r\nconst formatResponse = (res, success, statusCode, message = 'Success', data) =>\r\n res.status(statusCode).json({\r\n success,\r\n code: statusCode || 500,\r\n message,\r\n data,\r\n });\r\n\r\nexports.success = (res, message, data) => formatResponse(res, true, HTTP_CODES.OK, message, data);\r\nexports.created = (res, message, data) => formatResponse(res, true, HTTP_CODES.CREATED, message, data);\r\nexports.noContent = (res) => res.status(HTTP_CODES.NO_CONTENT).send();\r\n\r\nexports.serviceResponse = (success, code, message, data = {}) => {\r\n return { success, code, message, data };\r\n};\r\n\r\n// Success Response\r\nexports.successResponse = (res, code, message, data) => formatResponse(res, true, code, message, data);\r\n\r\n// Error Response\r\nexports.errorResponse = (res, code, message, data) => formatResponse(res, false, code, message, data);\r\n",
"children": []
},
{
"type": "file",
"name": "routeHandler.js",
"content": "const { HTTP_CODES, CONSTANTS, MESSAGES } = require('../config');\r\n\r\nexports.routeHandler = async (req, res) => {\r\n res.status(HTTP_CODES.NOT_FOUND || 500).json({\r\n success: false,\r\n code: HTTP_CODES.NOT_FOUND || 500,\r\n message: MESSAGES.ROUTE_NOT_FOUND,\r\n data: {},\r\n });\r\n};\r\n",
"children": []
},
{
"name": "errorResponse",
"type": "folder",
"children": [
{
"type": "file",
"name": "badRequest.js",
"content": "const { HTTP_CODES } = require('../../config');\r\n\r\nclass BadRequestException extends Error {\r\n constructor(message, err = null) {\r\n super(message);\r\n this.type = 'Bad Request';\r\n this.statusCode = HTTP_CODES.BAD_REQUEST;\r\n this.err = err;\r\n }\r\n}\r\n\r\nmodule.exports = BadRequestException;\r\n",
"children": []
},
{
"type": "file",
"name": "errorResponse.js",
"content": "class ErrorResponse extends Error {\r\n constructor(message, statusCode) {\r\n super(message);\r\n this.type = 'Error';\r\n this.statusCode = statusCode;\r\n }\r\n}\r\n\r\nmodule.exports = ErrorResponse;\r\n",
"children": []
},
{
"type": "file",
"name": "notFound.js",
"content": "const { HTTP_CODES } = require('../../config');\r\n\r\nclass NotFoundException extends Error {\r\n constructor(message) {\r\n super(message);\r\n this.type = 'Not Found';\r\n this.statusCode = HTTP_CODES.NOT_FOUND;\r\n }\r\n}\r\n\r\nmodule.exports = NotFoundException;\r\n",
"children": []
},
{
"type": "file",
"name": "precondition.js",
"content": "const { HTTP_CODES } = require('../../config');\r\n\r\nclass PreconditionException extends Error {\r\n constructor(message, err = null) {\r\n super(message);\r\n this.type = 'Precondition Failed';\r\n this.statusCode = HTTP_CODES.PRECONDITION_FAILED;\r\n this.err = err;\r\n }\r\n}\r\n\r\nmodule.exports = PreconditionException;\r\n",
"children": []
},
{
"type": "file",
"name": "index.js",
"content": "const BadRequestException = require('./badRequest');\r\nconst NotFoundException = require('./notFound');\r\nconst PreconditionException = require('./precondition');\r\nconst UnauthorizedException = require('./unauthorized');\r\nconst UnHandledException = require('./unhandled');\r\nconst ErrorResponse = require('./errorResponse');\r\n\r\nmodule.exports = {\r\n BadRequestException,\r\n NotFoundException,\r\n PreconditionException,\r\n UnauthorizedException,\r\n UnHandledException,\r\n ErrorResponse,\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "unhandled.js",
"content": "const { HTTP_CODES } = require('../../config');\r\n\r\nclass UnHandledException extends Error {\r\n constructor(err = null) {\r\n const message = 'Internal Server Error';\r\n super(message);\r\n this.type = 'Internal Server Error';\r\n this.err = err;\r\n this.statusCode = HTTP_CODES.INTERNAL_SERVER_ERROR;\r\n }\r\n}\r\n\r\nmodule.exports = UnHandledException;\r\n",
"children": []
},
{
"type": "file",
"name": "unauthorized.js",
"content": "const { HTTP_CODES } = require('../../config');\r\n\r\nclass UnauthorizedException extends Error {\r\n constructor(message) {\r\n super(message);\r\n this.type = 'Unauthorized';\r\n this.statusCode = HTTP_CODES.UNAUTHORIZED;\r\n }\r\n}\r\n\r\nmodule.exports = UnauthorizedException;\r\n",
"children": []
}
]
}
]
},
{
"name": "modules",
"type": "folder",
"children": [
{
"name": "files",
"type": "folder",
"children": [
{
"type": "file",
"name": "controller.js",
"content": "const SERVICES = require('./service');\r\nconst { HELPER } = require('../../helpers');\r\n\r\nexports.ADD = async (req, res, next) => {\r\n try {\r\n const { file, user } = req;\r\n const response = await SERVICES.ADD(user, file);\r\n if (!response.success) {\r\n return HELPER.errorResponse(res, response.code, response.message, response.data);\r\n }\r\n return HELPER.successResponse(res, response.code, response.message, response.data);\r\n } catch (error) {\r\n next(error);\r\n }\r\n};\r\n",
"children": []
},
{
"type": "file",
"name": "index.js",
"content": "const filesRoutes = require('./routes');\r\nconst filesService = require('./service');\r\nmodule.exports = { filesRoutes, filesService };\r\n",
"children": []
},
{
"type": "file",
"name": "service.js",
"content": "const { HTTP_CODES, MESSAGES, CONSTANTS } = require('../../config');\r\nconst { HELPER } = require('../../helpers');\r\nconst { jwt, bcrypt } = require('../../utils');\r\nconst db = require('../../database/models');\r\nconst { putObject } = require('../../utils/aws.utils');\r\n\r\nexports.ADD = async (user, file) => {\r\n const obj = await putObject(file);\r\n if (!obj) throw new BadRequestException(MESSAGES.BAD_REQUEST);\r\n const options = {};\r\n options.userId = user.id;\r\n options.fileName = obj.Key.split('/')[1];\r\n options.dirName = obj.Key.split('/')[0];\r\n options.fileSize = file.size;\r\n options.mimetype = file.mimetype;\r\n options.bucket = obj.Bucket;\r\n options.url = obj.Location;\r\n const response = await db.FileModel.create(options);\r\n if (!response) throw new BadRequestException(MESSAGES.BAD_REQUEST);\r\n return serviceResponse(true, HTTP_CODES.CREATED, MESSAGES.FILE_UPLOAD, {\r\n id: response.id,\r\n url: obj.Location,\r\n });\r\n};\r\n\r\nexports.LOGIN = async (payload) => {\r\n payload.email = payload.email.toLowerCase();\r\n const user = await db.UserModel.findOne({ where: { email: payload.email, deletedAt: null } });\r\n\r\n if (!user) throw new HELPER.BadRequestException(MESSAGES.BAD_REQUEST);\r\n\r\n const isMatch = await bcrypt.verifyPassword(payload.password, user.password);\r\n if (!isMatch) throw new HELPER.BadRequestException(MESSAGES.BAD_REQUEST);\r\n\r\n const accessToken = jwt.generateAccessToken({\r\n id: user.id,\r\n email: user.email,\r\n role: CONSTANTS.USER.ROLES.USER,\r\n });\r\n\r\n const refreshToken = jwt.generateRefreshToken({\r\n id: user.id,\r\n email: user.email,\r\n role: CONSTANTS.USER.ROLES.USER,\r\n });\r\n\r\n return HELPER.serviceResponse(true, HTTP_CODES.OK, MESSAGES.LOGIN_SUCCESS, {\r\n id: user.id,\r\n role: user.role,\r\n email: user.email,\r\n accessToken,\r\n refreshToken,\r\n });\r\n};\r\n\r\nexports.VIEW = async (id) => {\r\n const findQuery = {};\r\n findQuery['$and'] = [];\r\n findQuery['$and'].push({ id, deletedAt: null });\r\n const response = await db.UserModel.findOne({ whire: findQuery });\r\n if (!response) throw new HELPER.NotFoundException(MESSAGES.NOT_FOUND);\r\n return HELPER.serviceResponse(true, HTTP_CODES.OK, MESSAGES.GET_RECORD_SUCCESS, response);\r\n};\r\n\r\nexports.UPDATE = async (id, payload) => {\r\n const findQuery = {};\r\n findQuery['$and'] = [];\r\n findQuery['$and'].push({ id, deletedAt: null });\r\n const response = await db.UserModel.findOne({ whire: findQuery });\r\n if (!response) throw new HELPER.NotFoundException(MESSAGES.NOT_FOUND);\r\n await db.UserModel.update(payload, {\r\n where: findQuery,\r\n });\r\n return HELPER.serviceResponse(true, HTTP_CODES.OK, MESSAGES.UPDATE_SUCCESS);\r\n};\r\n\r\nexports.DELETE = async (id) => {\r\n const findQuery = {};\r\n findQuery['$and'] = [];\r\n findQuery['$and'].push({ id, deletedAt: null });\r\n const response = await db.UserModel.findOne({ whire: findQuery });\r\n if (!response) throw new HELPER.NotFoundException(MESSAGES.NOT_FOUND);\r\n\r\n await db.UserModel.update(\r\n { deletedAt: new Date() },\r\n {\r\n where: findQuery,\r\n }\r\n );\r\n\r\n return HELPER.serviceResponse(true, HTTP_CODES.OK, MESSAGES.DELETE_SUCCESS);\r\n};\r\n\r\n// const { MESSAGES, CONSTANTS } = require('../../config');\r\n// const db = require('../../database/models');\r\n// const { BadRequestException } = require('../../helpers/errorResponse');\r\n// const { bcrypt, jwt } = require('../../utils');\r\n\r\n// exports.register = async (user) => {\r\n// user.password = await bcrypt.generatePassword(user.password);\r\n// const response = await db.User.create(user);\r\n// return {\r\n// id: response.id,\r\n// name: response.name,\r\n// email: response.email,\r\n// createdAt: response.createdAt,\r\n// };\r\n// };\r\n\r\n// exports.login = async (params) => {\r\n// const { email, password } = params;\r\n\r\n// const user = await db.User.findOne({ where: { email } });\r\n// if (!user) throw new BadRequestException(MESSAGES.USER.LOGIN.INVALID_CREDS);\r\n\r\n// const passwordMatch = await bcrypt.verifyPassword(password, user.password);\r\n// if (!passwordMatch) throw new BadRequestException(MESSAGES.USER.LOGIN.INVALID_CREDS);\r\n\r\n// const accessToken = jwt.generateAccessToken({ id: user.id, email: user.email, role: CONSTANTS.USER.ROLES.USER });\r\n\r\n// return {\r\n// success: true,\r\n// id: user.id,\r\n// name: user.name,\r\n// email: user.email,\r\n// role: 'USER',\r\n// accessToken,\r\n// };\r\n// };\r\n",
"children": []
},
{
"type": "file",
"name": "routes.js",
"content": "const express = require('express');\r\nconst CONTROLLER = require('./controller');\r\nconst { MDWR } = require('../../middlewares');\r\n\r\nconst router = express.Router();\r\n\r\nrouter.put('/bucket', MDWR.uploadFile, CONTROLLER.ADD);\r\n\r\nmodule.exports = router;\r\n",
"children": []
},
{
"type": "file",
"name": "validation.js",
"content": "const Joi = require('joi');\r\n\r\nconst SCHEMA = {\r\n SIGNUP: {\r\n body: Joi.object().keys({\r\n