├── README.md ├── app ├── config │ ├── db.config.js │ └── env.js ├── controllers │ └── controller.js ├── models │ └── customer.model.js └── routers │ └── router.js ├── package-lock.json ├── package.json └── server.js /README.md: -------------------------------------------------------------------------------- 1 | # Reactjs Nodejs PostgreSQL Example 2 | 3 | ![reactjs nodejs postgresql](https://loizenai.com/wp-content/uploads/2020/11/Reactjs-Nodejs-PostgreSQL-CRUD-Example.png) 4 | 5 | Link tutorial: https://loizenai.com/reactjs-nodejs-postgresql-example/ 6 | 7 | In the tutorial, I introduce how to build an “React.js Nodejs CRUD PostgreSQL Example” project with the help of Ajax to POST/GET/PUT/DELETE requests with step by step coding examples: 8 | 9 | – Nodejs project produces CRUD RestAPIs with PostgreSQL database using the supporting of Sequelize ORM. 10 | – React.js project will consume the Nodejs CRUD RestAPIs by Ajax then show up on Reactjs component’s views. 11 | 12 | List to do: 13 | 14 | – I draw a fullstack overview Diagram Architecture from React.js Frontend to PostgreSQL database through Nodejs RestAPI backend. 15 | – Develop Nodejs CRUD RestAPIs with the supporting of Sequelize ORM. 16 | – Implement Reactjs CRUD application with Ajax fetching APIs to do CRUD request (Post/Get/Put/Delete) to Nodejs Backend APIs. 17 | – I create a testsuite with a number of integrative testcases with CRUD RestAPI requests from Reactjs to do CRUD requests to Nodejs RestAPIs Server and save/retrieve data to PostgreSQL database. 18 | 19 | ## Overall Architecture System: Reactjs + Nodejs + PostgreSQL 20 | 21 | ![Overall Architecture System: Reactjs + Nodejs + PostgreSQL]https://loizenai.com/wp-content/uploads/2020/11/React.js-Nodejs-PostgreSQL-Diagram-Architecture.png 22 | 23 | - We build a backend: Nodejs CRUD Application with PostgreSQL that provides RestAPIs for POST/GET/PUT/DELETE data entities and store them in PostgreSQL database. 24 | - We implement React.js CRUD Application that use Ajax to interact (call/receive requests) with Nodejs CRUD application and display corresponding data in Reactjs Component. 25 | 26 | ## Nodejs PostgreSQL CRUD Design Application 27 | 28 | ![Nodejs PostgreSQL CRUD Design](https://loizenai.com/wp-content/uploads/2020/11/Nodejs-Build-CRUD-MySQL-Architecture-Overview-1.png) 29 | 30 | We have 4 main blocks for the application: 31 | 32 | - For building RestAPIs in Nodejs application, we use Express framework. 33 | - For interacting with database PostgreSQL, we use Sequelize ORM. 34 | - We define APIs URL in router.js file 35 | - We implement how to process each API URL in controller.js file 36 | - We use Bootstrap and JQuery Ajax to implement frontend client. 37 | 38 | ## Reactjs CRUD Application Design 39 | 40 | [Reactjs CRUD Application design](https://loizenai.com/wp-content/uploads/2020/11/Reactjs-CRUD-RestAPI-Application-Frontend-Architecture-Diagram-2.png) 41 | 42 | – Reactjs CRUD Application is designed with 2 main layers: 43 | 44 | React.js components let you split the UI into independent, reusable pieces, and think about each piece in isolation. 45 | Ajax is used by Reactjs component to fetch (post/put/get/delete) data from remote restapi by http request 46 | 47 | Reactjs CRUD Application defines 5 components: 48 | 49 | - Home.js is used serve as the landing page for your app. 50 | - AppNavbar.js is used to establish a common UI feature between components. 51 | - CustomerList.js is used to show all customers in the web-page 52 | - CustomerEdit.js is used to modify the existed customer 53 | - App.js uses React Router to navigate between components. 54 | 55 | ## Integrative Project Goal 56 | 57 | ![Integrative Project Goal](https://loizenai.com/wp-content/uploads/2020/11/Reactjs-application-show-list-data-after-update-a-customer.png) 58 | 59 | Tutorial Link: [Reactjs Nodejs PostgreSQL Example](https://loizenai.com/reactjs-nodejs-postgresql-example/) 60 | 61 | Nodejs Reactjs Tutorial: 62 | - [How to Integrate Reactjs with Nodejs Tutorial](https://loizenai.com/integrate-reactjs-nodejs-tutorial/) 63 | - [Reactjs Node.js MySQL CRUD Example](https://loizenai.com/reactjs-nodejs-crud-mysql/) 64 | - [Reactjs Nodejs PostgreSQL Example](https://loizenai.com/reactjs-nodejs-postgresql-example/) 65 | - [Reactjs Nodejs MongoDB CRUD Example – MERN Stack Application](https://loizenai.com/reactjs-nodejs-mongodb-crud/) 66 | -------------------------------------------------------------------------------- /app/config/db.config.js: -------------------------------------------------------------------------------- 1 | const env = require('./env.js'); 2 | 3 | const Sequelize = require('sequelize'); 4 | const sequelize = new Sequelize(env.database, env.username, env.password, { 5 | host: env.host, 6 | dialect: env.dialect, 7 | operatorsAliases: false, 8 | 9 | pool: { 10 | max: env.max, 11 | min: env.pool.min, 12 | acquire: env.pool.acquire, 13 | idle: env.pool.idle 14 | } 15 | }); 16 | const db = {}; 17 | 18 | db.Sequelize = Sequelize; 19 | db.sequelize = sequelize; 20 | 21 | db.Customer = require('../models/customer.model.js')(sequelize, Sequelize); 22 | 23 | module.exports = db; -------------------------------------------------------------------------------- /app/config/env.js: -------------------------------------------------------------------------------- 1 | const env = { 2 | database: 'loizenaidb', 3 | username: 'postgres', 4 | password: '123', 5 | host: 'localhost', 6 | dialect: 'postgres', 7 | pool: { 8 | max: 5, 9 | min: 0, 10 | acquire: 30000, 11 | idle: 10000 12 | } 13 | }; 14 | 15 | module.exports = env; -------------------------------------------------------------------------------- /app/controllers/controller.js: -------------------------------------------------------------------------------- 1 | const db = require('../config/db.config.js'); 2 | const Customer = db.Customer; 3 | 4 | /** 5 | * Save a Customer object to database MySQL/PostgreSQL 6 | * @param {*} req 7 | * @param {*} res 8 | */ 9 | exports.createCustomer = (req, res) => { 10 | let customer = {}; 11 | 12 | try{ 13 | // Building Customer object from upoading request's body 14 | customer.firstname = req.body.firstname; 15 | customer.lastname = req.body.lastname; 16 | customer.address = req.body.address; 17 | customer.age = req.body.age; 18 | 19 | // Save to MySQL database 20 | Customer.create(customer, 21 | {attributes: ['id', 'firstname', 'lastname', 'age', 'address', "copyright"]}) 22 | .then(result => { 23 | res.status(200).json(result); 24 | }); 25 | }catch(error){ 26 | res.status(500).json({ 27 | message: "Fail!", 28 | error: error.message 29 | }); 30 | } 31 | } 32 | 33 | /** 34 | * Retrieve Customer information from database 35 | * @param {*} req 36 | * @param {*} res 37 | */ 38 | exports.customers = (req, res) => { 39 | // find all Customer information from 40 | try{ 41 | Customer.findAll({attributes: ['id', 'firstname', 'lastname', 'age', 'address', 'copyright']}) 42 | .then(customers => { 43 | res.status(200).json(customers); 44 | }) 45 | }catch(error) { 46 | // log on console 47 | console.log(error); 48 | 49 | res.status(500).json({ 50 | message: "Error!", 51 | error: error 52 | }); 53 | } 54 | } 55 | 56 | exports.getCustomer = (req, res) => { 57 | Customer.findByPk(req.params.id, 58 | {attributes: ['id', 'firstname', 'lastname', 'age', 'address', 'copyright']}) 59 | .then(customer => { 60 | res.status(200).json(customer); 61 | }).catch(error => { 62 | // log on console 63 | console.log(error); 64 | 65 | res.status(500).json({ 66 | message: "Error!", 67 | error: error 68 | }); 69 | }) 70 | } 71 | 72 | /** 73 | * Updating a Customer 74 | * @param {*} req 75 | * @param {*} res 76 | */ 77 | exports.updateCustomer = async (req, res) => { 78 | try{ 79 | let customer = await Customer.findByPk(req.body.id); 80 | 81 | if(!customer){ 82 | // return a response to client 83 | res.status(404).json({ 84 | message: "Not Found for updating a customer with id = " + customerId, 85 | error: "404" 86 | }); 87 | } else { 88 | // update new change to database 89 | let updatedObject = { 90 | firstname: req.body.firstname, 91 | lastname: req.body.lastname, 92 | address: req.body.address, 93 | age: req.body.age 94 | } 95 | let result = await Customer.update(updatedObject, 96 | { 97 | returning: true, 98 | where: {id: req.body.id}, 99 | attributes: ['id', 'firstname', 'lastname', 'age', 'address', 'copyright'] 100 | } 101 | ); 102 | 103 | // return the response to client 104 | if(!result) { 105 | res.status(500).json({ 106 | message: "Error -> Can not update a customer with id = " + req.params.id, 107 | error: "Can NOT Updated", 108 | }); 109 | } 110 | 111 | res.status(200).json(result); 112 | } 113 | } catch(error){ 114 | res.status(500).json({ 115 | message: "Error -> Can not update a customer with id = " + req.params.id, 116 | error: error.message 117 | }); 118 | } 119 | } 120 | 121 | /** 122 | * Delete a Customer by ID 123 | * @param {*} req 124 | * @param {*} res 125 | */ 126 | exports.deleteCustomer = async (req, res) => { 127 | try{ 128 | let customerId = req.params.id; 129 | let customer = await Customer.findByPk(customerId); 130 | 131 | if(!customer){ 132 | res.status(404).json({ 133 | message: "Does Not exist a Customer with id = " + customerId, 134 | error: "404", 135 | }); 136 | } else { 137 | await customer.destroy(); 138 | res.status(200); 139 | } 140 | } catch(error) { 141 | res.status(500).json({ 142 | message: "Error -> Can NOT delete a customer with id = " + req.params.id, 143 | error: error.message 144 | }); 145 | } 146 | } -------------------------------------------------------------------------------- /app/models/customer.model.js: -------------------------------------------------------------------------------- 1 | module.exports = (sequelize, Sequelize) => { 2 | const Customer = sequelize.define('customer', { 3 | id: { 4 | type: Sequelize.INTEGER, 5 | autoIncrement: true, 6 | primaryKey: true 7 | }, 8 | firstname: { 9 | type: Sequelize.STRING 10 | }, 11 | lastname: { 12 | type: Sequelize.STRING 13 | }, 14 | address: { 15 | type: Sequelize.STRING 16 | }, 17 | age: { 18 | type: Sequelize.INTEGER 19 | }, 20 | copyright: { 21 | type: Sequelize.STRING, 22 | defaultValue: "https://loizenai.com" 23 | } 24 | }); 25 | 26 | return Customer; 27 | } 28 | -------------------------------------------------------------------------------- /app/routers/router.js: -------------------------------------------------------------------------------- 1 | let express = require('express'); 2 | let router = express.Router(); 3 | 4 | const customers = require('../controllers/controller.js'); 5 | 6 | router.post('/api/customer', customers.createCustomer); 7 | router.get('/api/customer/:id', customers.getCustomer); 8 | router.get('/api/customers', customers.customers); 9 | router.put('/api/customer', customers.updateCustomer); 10 | router.delete('/api/customer/:id', customers.deleteCustomer); 11 | 12 | module.exports = router; -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-reactjs-restapi-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/node": { 8 | "version": "14.14.5", 9 | "resolved": "https://registry.npmjs.org/@types/node/-/node-14.14.5.tgz", 10 | "integrity": "sha512-H5Wn24s/ZOukBmDn03nnGTp18A60ny9AmCwnEcgJiTgSGsCO7k+NWP7zjCCbhlcnVCoI+co52dUAt9GMhOSULw==" 11 | }, 12 | "accepts": { 13 | "version": "1.3.7", 14 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", 15 | "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", 16 | "requires": { 17 | "mime-types": "~2.1.24", 18 | "negotiator": "0.6.2" 19 | } 20 | }, 21 | "any-promise": { 22 | "version": "1.3.0", 23 | "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", 24 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" 25 | }, 26 | "array-flatten": { 27 | "version": "1.1.1", 28 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 29 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 30 | }, 31 | "body-parse": { 32 | "version": "0.1.0", 33 | "resolved": "https://registry.npmjs.org/body-parse/-/body-parse-0.1.0.tgz", 34 | "integrity": "sha512-k0PDF7vZZpspXlwoM8ywh9PIHZokooS0Rek4M8Vekoro7XuuaWVhjgTpdzIRrfKj5oLQahwjn621/4kG4d91xw==" 35 | }, 36 | "body-parser": { 37 | "version": "1.19.0", 38 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", 39 | "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", 40 | "requires": { 41 | "bytes": "3.1.0", 42 | "content-type": "~1.0.4", 43 | "debug": "2.6.9", 44 | "depd": "~1.1.2", 45 | "http-errors": "1.7.2", 46 | "iconv-lite": "0.4.24", 47 | "on-finished": "~2.3.0", 48 | "qs": "6.7.0", 49 | "raw-body": "2.4.0", 50 | "type-is": "~1.6.17" 51 | } 52 | }, 53 | "buffer-writer": { 54 | "version": "2.0.0", 55 | "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", 56 | "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" 57 | }, 58 | "bytes": { 59 | "version": "3.1.0", 60 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", 61 | "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" 62 | }, 63 | "content-disposition": { 64 | "version": "0.5.3", 65 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", 66 | "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", 67 | "requires": { 68 | "safe-buffer": "5.1.2" 69 | } 70 | }, 71 | "content-type": { 72 | "version": "1.0.4", 73 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 74 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 75 | }, 76 | "cookie": { 77 | "version": "0.4.0", 78 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", 79 | "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" 80 | }, 81 | "cookie-signature": { 82 | "version": "1.0.6", 83 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 84 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 85 | }, 86 | "cors": { 87 | "version": "2.8.5", 88 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 89 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 90 | "requires": { 91 | "object-assign": "^4", 92 | "vary": "^1" 93 | } 94 | }, 95 | "debug": { 96 | "version": "2.6.9", 97 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 98 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 99 | "requires": { 100 | "ms": "2.0.0" 101 | } 102 | }, 103 | "denque": { 104 | "version": "1.4.1", 105 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", 106 | "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" 107 | }, 108 | "depd": { 109 | "version": "1.1.2", 110 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 111 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 112 | }, 113 | "destroy": { 114 | "version": "1.0.4", 115 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 116 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 117 | }, 118 | "dottie": { 119 | "version": "2.0.2", 120 | "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", 121 | "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" 122 | }, 123 | "ee-first": { 124 | "version": "1.1.1", 125 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 126 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 127 | }, 128 | "encodeurl": { 129 | "version": "1.0.2", 130 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 131 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 132 | }, 133 | "escape-html": { 134 | "version": "1.0.3", 135 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 136 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 137 | }, 138 | "etag": { 139 | "version": "1.8.1", 140 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 141 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 142 | }, 143 | "express": { 144 | "version": "4.17.1", 145 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", 146 | "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", 147 | "requires": { 148 | "accepts": "~1.3.7", 149 | "array-flatten": "1.1.1", 150 | "body-parser": "1.19.0", 151 | "content-disposition": "0.5.3", 152 | "content-type": "~1.0.4", 153 | "cookie": "0.4.0", 154 | "cookie-signature": "1.0.6", 155 | "debug": "2.6.9", 156 | "depd": "~1.1.2", 157 | "encodeurl": "~1.0.2", 158 | "escape-html": "~1.0.3", 159 | "etag": "~1.8.1", 160 | "finalhandler": "~1.1.2", 161 | "fresh": "0.5.2", 162 | "merge-descriptors": "1.0.1", 163 | "methods": "~1.1.2", 164 | "on-finished": "~2.3.0", 165 | "parseurl": "~1.3.3", 166 | "path-to-regexp": "0.1.7", 167 | "proxy-addr": "~2.0.5", 168 | "qs": "6.7.0", 169 | "range-parser": "~1.2.1", 170 | "safe-buffer": "5.1.2", 171 | "send": "0.17.1", 172 | "serve-static": "1.14.1", 173 | "setprototypeof": "1.1.1", 174 | "statuses": "~1.5.0", 175 | "type-is": "~1.6.18", 176 | "utils-merge": "1.0.1", 177 | "vary": "~1.1.2" 178 | } 179 | }, 180 | "finalhandler": { 181 | "version": "1.1.2", 182 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 183 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 184 | "requires": { 185 | "debug": "2.6.9", 186 | "encodeurl": "~1.0.2", 187 | "escape-html": "~1.0.3", 188 | "on-finished": "~2.3.0", 189 | "parseurl": "~1.3.3", 190 | "statuses": "~1.5.0", 191 | "unpipe": "~1.0.0" 192 | } 193 | }, 194 | "forwarded": { 195 | "version": "0.1.2", 196 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", 197 | "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" 198 | }, 199 | "fresh": { 200 | "version": "0.5.2", 201 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 202 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 203 | }, 204 | "generate-function": { 205 | "version": "2.3.1", 206 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", 207 | "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", 208 | "requires": { 209 | "is-property": "^1.0.2" 210 | } 211 | }, 212 | "http-errors": { 213 | "version": "1.7.2", 214 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", 215 | "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", 216 | "requires": { 217 | "depd": "~1.1.2", 218 | "inherits": "2.0.3", 219 | "setprototypeof": "1.1.1", 220 | "statuses": ">= 1.5.0 < 2", 221 | "toidentifier": "1.0.0" 222 | } 223 | }, 224 | "iconv-lite": { 225 | "version": "0.4.24", 226 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 227 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 228 | "requires": { 229 | "safer-buffer": ">= 2.1.2 < 3" 230 | } 231 | }, 232 | "inflection": { 233 | "version": "1.12.0", 234 | "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", 235 | "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" 236 | }, 237 | "inherits": { 238 | "version": "2.0.3", 239 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 240 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 241 | }, 242 | "ipaddr.js": { 243 | "version": "1.9.1", 244 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 245 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 246 | }, 247 | "is-property": { 248 | "version": "1.0.2", 249 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 250 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=" 251 | }, 252 | "lodash": { 253 | "version": "4.17.20", 254 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", 255 | "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" 256 | }, 257 | "long": { 258 | "version": "4.0.0", 259 | "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", 260 | "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" 261 | }, 262 | "lru-cache": { 263 | "version": "6.0.0", 264 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 265 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 266 | "requires": { 267 | "yallist": "^4.0.0" 268 | } 269 | }, 270 | "media-typer": { 271 | "version": "0.3.0", 272 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 273 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 274 | }, 275 | "merge-descriptors": { 276 | "version": "1.0.1", 277 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 278 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 279 | }, 280 | "methods": { 281 | "version": "1.1.2", 282 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 283 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 284 | }, 285 | "mime": { 286 | "version": "1.6.0", 287 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 288 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 289 | }, 290 | "mime-db": { 291 | "version": "1.44.0", 292 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", 293 | "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" 294 | }, 295 | "mime-types": { 296 | "version": "2.1.27", 297 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", 298 | "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", 299 | "requires": { 300 | "mime-db": "1.44.0" 301 | } 302 | }, 303 | "moment": { 304 | "version": "2.29.1", 305 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz", 306 | "integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==" 307 | }, 308 | "moment-timezone": { 309 | "version": "0.5.31", 310 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", 311 | "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", 312 | "requires": { 313 | "moment": ">= 2.9.0" 314 | } 315 | }, 316 | "ms": { 317 | "version": "2.0.0", 318 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 319 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 320 | }, 321 | "mysql2": { 322 | "version": "2.2.5", 323 | "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.2.5.tgz", 324 | "integrity": "sha512-XRqPNxcZTpmFdXbJqb+/CtYVLCx14x1RTeNMD4954L331APu75IC74GDqnZMEt1kwaXy6TySo55rF2F3YJS78g==", 325 | "requires": { 326 | "denque": "^1.4.1", 327 | "generate-function": "^2.3.1", 328 | "iconv-lite": "^0.6.2", 329 | "long": "^4.0.0", 330 | "lru-cache": "^6.0.0", 331 | "named-placeholders": "^1.1.2", 332 | "seq-queue": "^0.0.5", 333 | "sqlstring": "^2.3.2" 334 | }, 335 | "dependencies": { 336 | "iconv-lite": { 337 | "version": "0.6.2", 338 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.2.tgz", 339 | "integrity": "sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ==", 340 | "requires": { 341 | "safer-buffer": ">= 2.1.2 < 3.0.0" 342 | } 343 | } 344 | } 345 | }, 346 | "named-placeholders": { 347 | "version": "1.1.2", 348 | "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.2.tgz", 349 | "integrity": "sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA==", 350 | "requires": { 351 | "lru-cache": "^4.1.3" 352 | }, 353 | "dependencies": { 354 | "lru-cache": { 355 | "version": "4.1.5", 356 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", 357 | "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", 358 | "requires": { 359 | "pseudomap": "^1.0.2", 360 | "yallist": "^2.1.2" 361 | } 362 | }, 363 | "yallist": { 364 | "version": "2.1.2", 365 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", 366 | "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" 367 | } 368 | } 369 | }, 370 | "negotiator": { 371 | "version": "0.6.2", 372 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", 373 | "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" 374 | }, 375 | "object-assign": { 376 | "version": "4.1.1", 377 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 378 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 379 | }, 380 | "on-finished": { 381 | "version": "2.3.0", 382 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 383 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 384 | "requires": { 385 | "ee-first": "1.1.1" 386 | } 387 | }, 388 | "packet-reader": { 389 | "version": "1.0.0", 390 | "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", 391 | "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" 392 | }, 393 | "parseurl": { 394 | "version": "1.3.3", 395 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 396 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 397 | }, 398 | "path-to-regexp": { 399 | "version": "0.1.7", 400 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 401 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 402 | }, 403 | "pg": { 404 | "version": "8.4.2", 405 | "resolved": "https://registry.npmjs.org/pg/-/pg-8.4.2.tgz", 406 | "integrity": "sha512-E9FlUrrc7w3+sbRmL1CSw99vifACzB2TjhMM9J5w9D1LIg+6un0jKkpHS1EQf2CWhKhec2bhrBLVMmUBDbjPRQ==", 407 | "requires": { 408 | "buffer-writer": "2.0.0", 409 | "packet-reader": "1.0.0", 410 | "pg-connection-string": "^2.4.0", 411 | "pg-pool": "^3.2.2", 412 | "pg-protocol": "^1.3.0", 413 | "pg-types": "^2.1.0", 414 | "pgpass": "1.x" 415 | } 416 | }, 417 | "pg-connection-string": { 418 | "version": "2.4.0", 419 | "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.4.0.tgz", 420 | "integrity": "sha512-3iBXuv7XKvxeMrIgym7njT+HlZkwZqqGX4Bu9cci8xHZNT+Um1gWKqCsAzcC0d95rcKMU5WBg6YRUcHyV0HZKQ==" 421 | }, 422 | "pg-hstore": { 423 | "version": "2.3.3", 424 | "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.3.tgz", 425 | "integrity": "sha512-qpeTpdkguFgfdoidtfeTho1Q1zPVPbtMHgs8eQ+Aan05iLmIs3Z3oo5DOZRclPGoQ4i68I1kCtQSJSa7i0ZVYg==", 426 | "requires": { 427 | "underscore": "^1.7.0" 428 | } 429 | }, 430 | "pg-int8": { 431 | "version": "1.0.1", 432 | "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", 433 | "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" 434 | }, 435 | "pg-pool": { 436 | "version": "3.2.2", 437 | "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.2.tgz", 438 | "integrity": "sha512-ORJoFxAlmmros8igi608iVEbQNNZlp89diFVx6yV5v+ehmpMY9sK6QgpmgoXbmkNaBAx8cOOZh9g80kJv1ooyA==" 439 | }, 440 | "pg-protocol": { 441 | "version": "1.3.0", 442 | "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.3.0.tgz", 443 | "integrity": "sha512-64/bYByMrhWULUaCd+6/72c9PMWhiVFs3EVxl9Ct6a3v/U8+rKgqP2w+kKg/BIGgMJyB+Bk/eNivT32Al+Jghw==" 444 | }, 445 | "pg-types": { 446 | "version": "2.2.0", 447 | "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", 448 | "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", 449 | "requires": { 450 | "pg-int8": "1.0.1", 451 | "postgres-array": "~2.0.0", 452 | "postgres-bytea": "~1.0.0", 453 | "postgres-date": "~1.0.4", 454 | "postgres-interval": "^1.1.0" 455 | } 456 | }, 457 | "pgpass": { 458 | "version": "1.0.4", 459 | "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz", 460 | "integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==", 461 | "requires": { 462 | "split2": "^3.1.1" 463 | } 464 | }, 465 | "postgres-array": { 466 | "version": "2.0.0", 467 | "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", 468 | "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" 469 | }, 470 | "postgres-bytea": { 471 | "version": "1.0.0", 472 | "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", 473 | "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" 474 | }, 475 | "postgres-date": { 476 | "version": "1.0.7", 477 | "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", 478 | "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==" 479 | }, 480 | "postgres-interval": { 481 | "version": "1.2.0", 482 | "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", 483 | "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", 484 | "requires": { 485 | "xtend": "^4.0.0" 486 | } 487 | }, 488 | "proxy-addr": { 489 | "version": "2.0.6", 490 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", 491 | "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", 492 | "requires": { 493 | "forwarded": "~0.1.2", 494 | "ipaddr.js": "1.9.1" 495 | } 496 | }, 497 | "pseudomap": { 498 | "version": "1.0.2", 499 | "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", 500 | "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" 501 | }, 502 | "qs": { 503 | "version": "6.7.0", 504 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", 505 | "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" 506 | }, 507 | "range-parser": { 508 | "version": "1.2.1", 509 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 510 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 511 | }, 512 | "raw-body": { 513 | "version": "2.4.0", 514 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", 515 | "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", 516 | "requires": { 517 | "bytes": "3.1.0", 518 | "http-errors": "1.7.2", 519 | "iconv-lite": "0.4.24", 520 | "unpipe": "1.0.0" 521 | } 522 | }, 523 | "readable-stream": { 524 | "version": "3.6.0", 525 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 526 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 527 | "requires": { 528 | "inherits": "^2.0.3", 529 | "string_decoder": "^1.1.1", 530 | "util-deprecate": "^1.0.1" 531 | } 532 | }, 533 | "retry-as-promised": { 534 | "version": "3.2.0", 535 | "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", 536 | "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", 537 | "requires": { 538 | "any-promise": "^1.3.0" 539 | } 540 | }, 541 | "safe-buffer": { 542 | "version": "5.1.2", 543 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 544 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 545 | }, 546 | "safer-buffer": { 547 | "version": "2.1.2", 548 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 549 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 550 | }, 551 | "semver": { 552 | "version": "7.3.2", 553 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", 554 | "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" 555 | }, 556 | "send": { 557 | "version": "0.17.1", 558 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", 559 | "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", 560 | "requires": { 561 | "debug": "2.6.9", 562 | "depd": "~1.1.2", 563 | "destroy": "~1.0.4", 564 | "encodeurl": "~1.0.2", 565 | "escape-html": "~1.0.3", 566 | "etag": "~1.8.1", 567 | "fresh": "0.5.2", 568 | "http-errors": "~1.7.2", 569 | "mime": "1.6.0", 570 | "ms": "2.1.1", 571 | "on-finished": "~2.3.0", 572 | "range-parser": "~1.2.1", 573 | "statuses": "~1.5.0" 574 | }, 575 | "dependencies": { 576 | "ms": { 577 | "version": "2.1.1", 578 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", 579 | "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" 580 | } 581 | } 582 | }, 583 | "seq-queue": { 584 | "version": "0.0.5", 585 | "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", 586 | "integrity": "sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4=" 587 | }, 588 | "sequelize": { 589 | "version": "6.3.5", 590 | "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.5.tgz", 591 | "integrity": "sha512-MiwiPkYSA8NWttRKAXdU9h0TxP6HAc1fl7qZmMO/VQqQOND83G4nZLXd0kWILtAoT9cxtZgFqeb/MPYgEeXwsw==", 592 | "requires": { 593 | "debug": "^4.1.1", 594 | "dottie": "^2.0.0", 595 | "inflection": "1.12.0", 596 | "lodash": "^4.17.15", 597 | "moment": "^2.26.0", 598 | "moment-timezone": "^0.5.31", 599 | "retry-as-promised": "^3.2.0", 600 | "semver": "^7.3.2", 601 | "sequelize-pool": "^6.0.0", 602 | "toposort-class": "^1.0.1", 603 | "uuid": "^8.1.0", 604 | "validator": "^10.11.0", 605 | "wkx": "^0.5.0" 606 | }, 607 | "dependencies": { 608 | "debug": { 609 | "version": "4.2.0", 610 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", 611 | "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", 612 | "requires": { 613 | "ms": "2.1.2" 614 | } 615 | }, 616 | "ms": { 617 | "version": "2.1.2", 618 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 619 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 620 | } 621 | } 622 | }, 623 | "sequelize-pool": { 624 | "version": "6.1.0", 625 | "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", 626 | "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==" 627 | }, 628 | "serve-static": { 629 | "version": "1.14.1", 630 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", 631 | "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", 632 | "requires": { 633 | "encodeurl": "~1.0.2", 634 | "escape-html": "~1.0.3", 635 | "parseurl": "~1.3.3", 636 | "send": "0.17.1" 637 | } 638 | }, 639 | "setprototypeof": { 640 | "version": "1.1.1", 641 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", 642 | "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" 643 | }, 644 | "split2": { 645 | "version": "3.2.2", 646 | "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", 647 | "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", 648 | "requires": { 649 | "readable-stream": "^3.0.0" 650 | } 651 | }, 652 | "sqlstring": { 653 | "version": "2.3.2", 654 | "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.2.tgz", 655 | "integrity": "sha512-vF4ZbYdKS8OnoJAWBmMxCQDkiEBkGQYU7UZPtL8flbDRSNkhaXvRJ279ZtI6M+zDaQovVU4tuRgzK5fVhvFAhg==" 656 | }, 657 | "statuses": { 658 | "version": "1.5.0", 659 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 660 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 661 | }, 662 | "string_decoder": { 663 | "version": "1.3.0", 664 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 665 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 666 | "requires": { 667 | "safe-buffer": "~5.2.0" 668 | }, 669 | "dependencies": { 670 | "safe-buffer": { 671 | "version": "5.2.1", 672 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 673 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 674 | } 675 | } 676 | }, 677 | "toidentifier": { 678 | "version": "1.0.0", 679 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", 680 | "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" 681 | }, 682 | "toposort-class": { 683 | "version": "1.0.1", 684 | "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", 685 | "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" 686 | }, 687 | "type-is": { 688 | "version": "1.6.18", 689 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 690 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 691 | "requires": { 692 | "media-typer": "0.3.0", 693 | "mime-types": "~2.1.24" 694 | } 695 | }, 696 | "underscore": { 697 | "version": "1.11.0", 698 | "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.11.0.tgz", 699 | "integrity": "sha512-xY96SsN3NA461qIRKZ/+qox37YXPtSBswMGfiNptr+wrt6ds4HaMw23TP612fEyGekRE6LNRiLYr/aqbHXNedw==" 700 | }, 701 | "unpipe": { 702 | "version": "1.0.0", 703 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 704 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 705 | }, 706 | "util-deprecate": { 707 | "version": "1.0.2", 708 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 709 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 710 | }, 711 | "utils-merge": { 712 | "version": "1.0.1", 713 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 714 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 715 | }, 716 | "uuid": { 717 | "version": "8.3.1", 718 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", 719 | "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==" 720 | }, 721 | "validator": { 722 | "version": "10.11.0", 723 | "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", 724 | "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" 725 | }, 726 | "vary": { 727 | "version": "1.1.2", 728 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 729 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 730 | }, 731 | "wkx": { 732 | "version": "0.5.0", 733 | "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", 734 | "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", 735 | "requires": { 736 | "@types/node": "*" 737 | } 738 | }, 739 | "xtend": { 740 | "version": "4.0.2", 741 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 742 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" 743 | }, 744 | "yallist": { 745 | "version": "4.0.0", 746 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 747 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" 748 | } 749 | } 750 | } 751 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nodejs-reactjs-restapi-example", 3 | "version": "1.0.0", 4 | "description": "Nodejs Reactjs RestAPI CRUD MySQL database", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/loizenai" 12 | }, 13 | "keywords": [ 14 | "nodejs", 15 | "reactjs", 16 | "crud", 17 | "mysql" 18 | ], 19 | "author": "https://loizenai.com", 20 | "license": "ISC", 21 | "dependencies": { 22 | "body-parse": "^0.1.0", 23 | "cors": "^2.8.5", 24 | "express": "^4.17.1", 25 | "mysql2": "^2.2.5", 26 | "pg": "^8.4.2", 27 | "pg-hstore": "^2.3.3", 28 | "sequelize": "^6.3.5" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const app = express(); 3 | 4 | var bodyParser = require('body-parser'); 5 | 6 | global.__basedir = __dirname; 7 | 8 | const db = require('./app/config/db.config.js'); 9 | 10 | const Customer = db.Customer; 11 | 12 | let router = require('./app/routers/router.js'); 13 | 14 | const cors = require('cors') 15 | const corsOptions = { 16 | origin: 'http://localhost:4200', 17 | optionsSuccessStatus: 200 18 | } 19 | app.use(cors(corsOptions)); 20 | 21 | app.use(bodyParser.json()); 22 | app.use(express.static('resources')); 23 | app.use('/', router); 24 | 25 | // Create a Server 26 | const server = app.listen(8080, function () { 27 | 28 | let host = server.address().address 29 | let port = server.address().port 30 | 31 | console.log("App listening at http://%s:%s", host, port); 32 | }) 33 | 34 | db.sequelize.sync({force: true}).then(() => { 35 | console.log('Drop and Resync with { force: true }'); 36 | Customer.sync().then(() => { 37 | const customers = [ 38 | { firstname: 'Jack', lastname: 'Smith', 39 | age: 23, address: '374 William S Canning Blvd'}, 40 | { firstname: 'Adam', lastname: 'Johnson', 41 | age: 31, address: 'Fall River MA 2721. 121 Worcester Rd'}, 42 | { firstname: 'Dana', lastname: 'Bay', 43 | age: 46, address: 'Framingham MA 1701. 677 Timpany Blvd'}, 44 | ] 45 | 46 | for(let i=0; i