From cd82995922cca4dc9c8dd4e3cc9d678908018ad1 Mon Sep 17 00:00:00 2001 From: fred1code Date: Sat, 22 May 2021 14:15:40 -0500 Subject: [PATCH] platzi master --- .env-example | 8 +- package-lock.json | 88 +++++- package.json | 7 +- platzi.mwb | Bin 0 -> 7454 bytes platzi.postman_collection.json | 204 +++++++++++++ src/app.js | 11 +- src/config/config.js | 20 ++ src/controllers/categories/controller.js | 51 ++++ src/controllers/categories/index.js | 4 + src/controllers/products/controller.js | 50 ++++ src/controllers/products/index.js | 4 + src/db.sql | 28 ++ src/models/categories.js | 66 +++++ src/models/connection.js | 36 +++ src/models/products.js | 68 +++++ src/routes/categories.js | 70 +++++ src/routes/index.js | 9 + src/routes/products.js | 59 ++++ src/swagger.json | 357 +++++++++++++++++++++++ src/utils/error.js | 9 + src/utils/network/errors.js | 13 + src/utils/network/response.js | 22 ++ 22 files changed, 1176 insertions(+), 8 deletions(-) create mode 100644 platzi.mwb create mode 100644 platzi.postman_collection.json create mode 100644 src/config/config.js create mode 100644 src/controllers/categories/controller.js create mode 100644 src/controllers/categories/index.js create mode 100644 src/controllers/products/controller.js create mode 100644 src/controllers/products/index.js create mode 100644 src/db.sql create mode 100644 src/models/categories.js create mode 100644 src/models/connection.js create mode 100644 src/models/products.js create mode 100644 src/routes/categories.js create mode 100644 src/routes/index.js create mode 100644 src/routes/products.js create mode 100644 src/swagger.json create mode 100644 src/utils/error.js create mode 100644 src/utils/network/errors.js create mode 100644 src/utils/network/response.js diff --git a/.env-example b/.env-example index dfce8c4d..74ca79de 100644 --- a/.env-example +++ b/.env-example @@ -1,7 +1,7 @@ PORT=3000 -MONGO_USER= +MONGO_USER=root MONGO_PASSWORD= -MONGO_HOST= -MONGO_DB_NAME= -MONGO_PORT= +MONGO_HOST=localhot +MONGO_DB_NAME=platzi +MONGO_PORT=3306 MONGO_CONNECTION= \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 76a7fcef..aefc3f07 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,13 @@ "version": "1.0.0", "license": "ISC", "dependencies": { + "body-parser": "^1.19.0", "cors": "^2.8.5", "dotenv": "^8.2.0", "express": "^4.17.1", - "mongodb": "^3.6.6" + "mongodb": "^3.6.6", + "mysql": "^2.18.1", + "swagger-ui-express": "^4.1.6" }, "devDependencies": { "jest": "^26.6.3", @@ -1894,6 +1897,14 @@ "tweetnacl": "^0.14.3" } }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -6716,6 +6727,20 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "node_modules/mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "dependencies": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/nan": { "version": "2.14.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", @@ -8465,6 +8490,14 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "node_modules/sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -8881,6 +8914,25 @@ "node": ">=8" } }, + "node_modules/swagger-ui-dist": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.49.0.tgz", + "integrity": "sha512-R1+eT16XNP1bBLfacISifZAkFJlpwvWsS2vVurF5pbIFZnmCasD/hj+9r/q7urYdQyb0B6v11mDnuYU7rUpfQg==" + }, + "node_modules/swagger-ui-express": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", + "integrity": "sha512-Xs2BGGudvDBtL7RXcYtNvHsFtP1DBFPMJFRxHe5ez/VG/rzVOEjazJOOSc/kSCyxreCTKfJrII6MJlL9a6t8vw==", + "dependencies": { + "swagger-ui-dist": "^3.18.1" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -11273,6 +11325,11 @@ "tweetnacl": "^0.14.3" } }, + "bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" + }, "binary-extensions": { "version": "1.13.1", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", @@ -14975,6 +15032,17 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" }, + "mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "requires": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + } + }, "nan": { "version": "2.14.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", @@ -16372,6 +16440,11 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A=" + }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -16685,6 +16758,19 @@ } } }, + "swagger-ui-dist": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-3.49.0.tgz", + "integrity": "sha512-R1+eT16XNP1bBLfacISifZAkFJlpwvWsS2vVurF5pbIFZnmCasD/hj+9r/q7urYdQyb0B6v11mDnuYU7rUpfQg==" + }, + "swagger-ui-express": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", + "integrity": "sha512-Xs2BGGudvDBtL7RXcYtNvHsFtP1DBFPMJFRxHe5ez/VG/rzVOEjazJOOSc/kSCyxreCTKfJrII6MJlL9a6t8vw==", + "requires": { + "swagger-ui-dist": "^3.18.1" + } + }, "symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", diff --git a/package.json b/package.json index 279a5416..b2f225f1 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,13 @@ "description": "Reto 9 Octubre 26: Curso de Backend con Node", "main": "index.js", "dependencies": { + "body-parser": "^1.19.0", "cors": "^2.8.5", "dotenv": "^8.2.0", "express": "^4.17.1", - "mongodb": "^3.6.6" + "mongodb": "^3.6.6", + "mysql": "^2.18.1", + "swagger-ui-express": "^4.1.6" }, "devDependencies": { "jest": "^26.6.3", @@ -25,7 +28,7 @@ }, "keywords": [], "author": "", - "license": "ISC", + "license": "MIT", "bugs": { "url": "https://github.com/platzi/escuelajs-reto-09/issues" }, diff --git a/platzi.mwb b/platzi.mwb new file mode 100644 index 0000000000000000000000000000000000000000..e99dfc07b95ce1c8c3f13cb8a28bf55837bc4556 GIT binary patch literal 7454 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 { + conn.query(`SELECT * FROM categoris`, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); +} +function getCategoriesId(json) { + return new Promise((resolve, reject) => { + conn.query(`SELECT * FROM categoris WHERE id = ${json.id}`, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); +} +function postCategories(json) { + return new Promise((resolve, reject) => { + conn.query(`INSERT INTO platzi.categoris + (name, img) + VALUES('${json.name}', '${json.img}'); + `, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); +} +function putCategories(json) { + return new Promise((resolve, reject) => { + conn.query(`UPDATE platzi.categoris + SET name='${json.name}', img='${json.img}' + WHERE id=${json.id}; + `, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); +} +function deleteCategories(json) { + return new Promise((resolve, reject) => { + conn.query(`DELETE FROM platzi.categoris + WHERE id=${json.id};`, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); +} +function getCategoriesIdProducts(json) { + return new Promise((resolve, reject) => { + conn.query(`SELECT * FROM products WHERE categorys_id = ${json.id}`, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); +} + +module.exports = { + getCategories, + getCategoriesId, + postCategories, + putCategories, + deleteCategories, + getCategoriesIdProducts, +}; diff --git a/src/models/connection.js b/src/models/connection.js new file mode 100644 index 00000000..9a67a934 --- /dev/null +++ b/src/models/connection.js @@ -0,0 +1,36 @@ +const mysql = require('mysql'); +const config = require('../config/config'); + +const dbconf = { + host: config.mysql.host, + port: config.mysql.port, + user: config.mysql.user, + password: config.mysql.password, + database: config.mysql.database, +}; + +let connection; +function handleCon() { + connection = mysql.createConnection(dbconf); + + connection.connect((err) => { + if (err) { + console.error('[db err]', err); + setTimeout(handleCon, 2000); + } else { + console.log('DB Connected'); + } + }); + + connection.on('error', (err) => { + console.error('[db err]', err); + if (err.code === 'PROTOCOL_CONNECTION_LOST') { + handleCon(); + } else { + throw err; + } + }); +} + +handleCon(); +module.exports= connection; \ No newline at end of file diff --git a/src/models/products.js b/src/models/products.js new file mode 100644 index 00000000..d05ea087 --- /dev/null +++ b/src/models/products.js @@ -0,0 +1,68 @@ +const conn = require('./connection.js'); + +function getProducts(json) { + console.log(json); + return new Promise((resolve, reject) => { + conn.query(`SELECT * FROM products`, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); +} + +function getProductsId(json) { + return new Promise((resolve, reject) => { + conn.query(`SELECT * FROM products WHERE id = ${json.id}`, (err, data) => { + if (err) return reject(err); + resolve(data); + }); + }); +} +function postProducts(json) { + return new Promise((resolve, reject) => { + conn.query( + `INSERT INTO platzi.products + (name, price, description, img, categorys_id) + VALUES('${json.name}', '${json.price}', '${json.description}', '${json.img}', ${json.category_id}); + `, + (err, data) => { + if (err) return reject(err); + resolve(data); + } + ); + }); +} +function putProducts(json) { + return new Promise((resolve, reject) => { + conn.query( + `UPDATE platzi.products + SET name='${json.name}', price='${json.price}', description='${json.description}', img='${json.img}', categorys_id=${json.category_id} + WHERE id=${json.id}; + `, + (err, data) => { + if (err) return reject(err); + resolve(data); + } + ); + }); +} +function deleteProducts(json) { + return new Promise((resolve, reject) => { + conn.query( + `DELETE FROM platzi.products + WHERE id=${json.id};`, + (err, data) => { + if (err) return reject(err); + resolve(data); + } + ); + }); +} + +module.exports = { + getProducts, + getProductsId, + postProducts, + putProducts, + deleteProducts, +}; diff --git a/src/routes/categories.js b/src/routes/categories.js new file mode 100644 index 00000000..7850e1b1 --- /dev/null +++ b/src/routes/categories.js @@ -0,0 +1,70 @@ +const express = require('express'); +const response = require('../utils/network/response'); +const Controller = require('../controllers/categories/index'); + +const app = express(); + +app.get('/categories', getCategories); +app.get('/categories/:id', getCategoriesId); +app.post('/categories', postCategories); +app.put('/categories/:id', putCategories); +app.delete('/categories/:id', deleteCategories); +app.get('/categories/:id/products', getCategoriesIdProducts); + +function getCategories(req, res) { + Controller.getCategories() + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 400); + }); +} +function getCategoriesId(req, res) { + Controller.getCategoriesId(req.params) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 400); + }); +} +function postCategories(req, res) { + Controller.postCategories(req.body) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 400); + }); +} +function putCategories(req, res) { + console.log('entro'); + Controller.putCategories(req.body, req.params) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 400); + }); +} +function deleteCategories(req, res) { + Controller.deleteCategories(req.params) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 400); + }); +} +function getCategoriesIdProducts(req, res) { + Controller.getCategoriesIdProducts(req.params) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 400); + }); +} + +module.exports = app; diff --git a/src/routes/index.js b/src/routes/index.js new file mode 100644 index 00000000..8c99b02b --- /dev/null +++ b/src/routes/index.js @@ -0,0 +1,9 @@ +const express = require('express'); + +const app = express(); + +app.use(require('./products')); +app.use(require('./categories')); + + +module.exports = app; diff --git a/src/routes/products.js b/src/routes/products.js new file mode 100644 index 00000000..0de0bd84 --- /dev/null +++ b/src/routes/products.js @@ -0,0 +1,59 @@ +const express = require('express'); +const response = require('../utils/network/response'); +const Controller = require('../controllers/products/index'); + +const app = express(); + +app.get('/products', getProducts); +app.get('/products/:id', getProductsId); +app.post('/products', postProducts); +app.put('/products/:id', putProducts); +app.delete('/products/:id', deleteProducts); + +function getProducts(req, res) { + Controller.getProducts() + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 500); + }); +} +function getProductsId(req, res) { + Controller.getProductsId(req.params) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 500); + }); +} +function postProducts(req, res) { + Controller.postProducts(req.body) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 500); + }); +} +function putProducts(req, res) { + Controller.putProducts(req.body, req.params) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 500); + }); +} +function deleteProducts(req, res) { + Controller.deleteProducts(req.params) + .then((user) => { + response.success(req, res, user, 200); + }) + .catch((err) => { + response.error(req, res, err.message, 500); + }); +} + +module.exports = app; diff --git a/src/swagger.json b/src/swagger.json new file mode 100644 index 00000000..2fec5ebc --- /dev/null +++ b/src/swagger.json @@ -0,0 +1,357 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.0", + "title": "platzi", + "contact": {} + }, + "host": "localhost:3000", + "basePath": "/api", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/products": { + "get": { + "summary": "get products", + "tags": [ + "Misc" + ], + "operationId": "getproducts", + "deprecated": false, + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + }, + "post": { + "summary": "post products", + "tags": [ + "Misc" + ], + "operationId": "postproducts", + "deprecated": false, + "produces": [ + "application/json" + ], + "consumes": [ + "application/x-www-form-urlencoded" + ], + "parameters": [ + { + "name": "name", + "in": "formData", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "price", + "in": "formData", + "required": true, + "type": "integer", + "format": "int32", + "description": "" + }, + { + "name": "description", + "in": "formData", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "img", + "in": "formData", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "category_id", + "in": "formData", + "required": true, + "type": "integer", + "format": "int32", + "description": "" + } + ], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + } + }, + "/products/2": { + "get": { + "summary": "get products id", + "tags": [ + "Misc" + ], + "operationId": "getproductsid", + "deprecated": false, + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + }, + "delete": { + "summary": "delete products id", + "tags": [ + "Misc" + ], + "operationId": "deleteproductsid", + "deprecated": false, + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + } + }, + "/products/1": { + "put": { + "summary": "put products id", + "tags": [ + "Misc" + ], + "operationId": "putproductsid", + "deprecated": false, + "produces": [ + "application/json" + ], + "consumes": [ + "application/x-www-form-urlencoded" + ], + "parameters": [ + { + "name": "name", + "in": "formData", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "price", + "in": "formData", + "required": true, + "type": "integer", + "format": "int32", + "description": "" + }, + { + "name": "description", + "in": "formData", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "img", + "in": "formData", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "category_id", + "in": "formData", + "required": true, + "type": "integer", + "format": "int32", + "description": "" + } + ], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + } + }, + "/categories": { + "get": { + "summary": "get categories", + "tags": [ + "Misc" + ], + "operationId": "getcategories", + "deprecated": false, + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + }, + "post": { + "summary": "post categories", + "tags": [ + "Misc" + ], + "operationId": "postcategories", + "deprecated": false, + "produces": [ + "application/json" + ], + "consumes": [ + "application/x-www-form-urlencoded" + ], + "parameters": [ + { + "name": "name", + "in": "formData", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "img", + "in": "formData", + "required": true, + "type": "string", + "description": "" + } + ], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + } + }, + "/categories/1": { + "get": { + "summary": "get categories id", + "tags": [ + "Misc" + ], + "operationId": "getcategoriesid", + "deprecated": false, + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + } + }, + "/categories/2": { + "put": { + "summary": "put categories id", + "tags": [ + "Misc" + ], + "operationId": "putcategoriesid", + "deprecated": false, + "produces": [ + "application/json" + ], + "consumes": [ + "application/x-www-form-urlencoded" + ], + "parameters": [ + { + "name": "name", + "in": "formData", + "required": true, + "type": "string", + "description": "" + }, + { + "name": "img", + "in": "formData", + "required": true, + "type": "string", + "description": "" + } + ], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + }, + "delete": { + "summary": "delete categories id", + "tags": [ + "Misc" + ], + "operationId": "deletecategoriesid", + "deprecated": false, + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + } + }, + "/categories/1/products": { + "get": { + "summary": "get categories id products", + "tags": [ + "Misc" + ], + "operationId": "getcategoriesidproducts", + "deprecated": false, + "produces": [ + "application/json" + ], + "parameters": [], + "responses": { + "200": { + "description": "", + "headers": {} + } + } + } + } + }, + "tags": [ + { + "name": "Misc", + "description": "" + } + ] +} \ No newline at end of file diff --git a/src/utils/error.js b/src/utils/error.js new file mode 100644 index 00000000..3ff82644 --- /dev/null +++ b/src/utils/error.js @@ -0,0 +1,9 @@ +function err(message, code) { + let e = new Error(message); + + if (code) { + e.statusCode = code; + } + return e; + +} \ No newline at end of file diff --git a/src/utils/network/errors.js b/src/utils/network/errors.js new file mode 100644 index 00000000..6a072803 --- /dev/null +++ b/src/utils/network/errors.js @@ -0,0 +1,13 @@ +const response = require('./response'); + +function errors(err, req, res, next) { + console.error('[error]', err); + + const message = err.message || 'Internal Error'; + const status = err.statusCode || 500; + + response.error(req, res, message, status) + +} + +module.exports = errors; \ No newline at end of file diff --git a/src/utils/network/response.js b/src/utils/network/response.js new file mode 100644 index 00000000..1d40e687 --- /dev/null +++ b/src/utils/network/response.js @@ -0,0 +1,22 @@ +exports.success = function (req, res, message, status) { + let statusCode = status || 200; + let statusMessage = message || ''; + + res.status(statusCode).send({ + error: false, + status: status, + body: statusMessage, + }); + }; + + exports.error = function (req, res, message, status) { + let statusCode = status || 500; + let statusMessage = message || 'Internal server error'; + + res.status(statusCode).send({ + error: false, + status: status, + body: statusMessage, + }); + }; + \ No newline at end of file