├── .dockerignore ├── .env ├── .env.example ├── .gitignore ├── Dockerfile ├── app.js ├── controllers ├── client.controller.js ├── order.controller.js └── transport.controller.js ├── models ├── log.js └── order.js ├── npm ├── package-lock.json ├── package.json ├── rabbit ├── receivers.js └── sender.js ├── readme.md ├── repository ├── logClient.repository.js ├── logOrder.repository.js ├── logTransport.repository.js └── order.repository.js ├── routes ├── api │ ├── client.js │ ├── index.js │ ├── order.js │ └── transport.js └── index.js ├── services ├── clientCRS.service.js ├── clientQRS.service.js ├── order.service.js └── transport.service.js ├── views ├── error.pug ├── index.pug └── layout.pug └── wait-for-it.sh /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | Dockerfile 4 | .dockerignore 5 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | MESSAGE_QUEUE= 2 | MONGO_CONN_CLIENT_LOG_QRS= 3 | MONGO_CONN_CLIENT_LOG_CRS= 4 | MONGO_CONN_ORDER_LOG= 5 | MONGO_CONN_ORDERS= 6 | MONGO_CONN_TRANSPORT_LOG= 7 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | MESSAGE_QUEUE= 2 | MONGO_CONN_CLIENT_LOG_QRS= 3 | MONGO_CONN_CLIENT_LOG_CRS= 4 | MONGO_CONN_ORDER_LOG= 5 | MONGO_CONN_ORDERS= 6 | MONGO_CONN_TRANSPORT_LOG= 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # next.js build output 63 | .next 64 | 65 | Receivers/ 66 | /.idea/ 67 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:8 2 | 3 | # Create app directory 4 | WORKDIR /usr/src 5 | 6 | # Install app dependencies 7 | # A wildcard is used to ensure both package.json AND package-lock.json are copied 8 | # where available (npm@5+) 9 | COPY package*.json ./ 10 | 11 | RUN npm install 12 | # If you are building your code for production 13 | # RUN npm ci --only=production 14 | 15 | # Bundle app source 16 | COPY . . 17 | 18 | EXPOSE 8765 19 | CMD [ "npm", "start" ] 20 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | require('dotenv').config(); 2 | const express = require('express'); 3 | const cors = require('cors'); 4 | const path = require('path'); 5 | const receivers = require('./rabbit/receivers'); 6 | 7 | let app = express(); 8 | const bodyParser = require('body-parser'); 9 | 10 | 11 | // configure app to use bodyParser() 12 | // this will let us get the data from a POST 13 | app.use(bodyParser.urlencoded({ extended: true })); 14 | app.use(bodyParser.json()); 15 | app.use(cors()); 16 | app.use(express.json()); 17 | app.use(express.urlencoded({ extended: false })); 18 | app.set('view engine', 'pug') 19 | app.set("views", path.join(__dirname, "views")); 20 | 21 | receivers.clientReceiver(); 22 | receivers.orderReceiver(); 23 | receivers.transportReceiver(); 24 | 25 | app.use(require('./routes')); 26 | 27 | // error handler 28 | app.use(function(err, req, res, next) { 29 | // set locals, only providing error in development 30 | res.locals.message = err.message; 31 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 32 | 33 | // render the error page 34 | res.status(err.status || 500); 35 | res.render('error'); 36 | }); 37 | 38 | var server = app.listen( process.env.PORT || 8765, function(){ 39 | console.log('Listening on port ' + server.address().port); 40 | }); 41 | 42 | module.exports = app; 43 | -------------------------------------------------------------------------------- /controllers/client.controller.js: -------------------------------------------------------------------------------- 1 | const clientQRSService = require('../services/clientQRS.service') 2 | const clientCRSService = require('../services/clientCRS.service') 3 | 4 | exports.new = async(req, res, next) => { 5 | try { 6 | await clientCRSService.new(req.body, res); 7 | } catch (e) { 8 | res.status(500).send({ 9 | message: 'Failed to create new order.'+ e 10 | }); 11 | } 12 | } 13 | 14 | exports.update = async(req, res, next) => { 15 | try { 16 | await clientCRSService.update(req.params.id, req.body, res); 17 | } catch (e) { 18 | res.status(500).send({ 19 | message: 'Failed to update order.'+ e 20 | }); 21 | } 22 | } 23 | 24 | exports.cancel = async(req, res, next) => { 25 | try { 26 | await clientCRSService.cancel(req.params.id, res); 27 | } catch (e) { 28 | res.status(500).send({ 29 | message: 'Failed to delete order.'+ e 30 | }); 31 | } 32 | } 33 | 34 | exports.getAll = async(req, res, next) => { 35 | try { 36 | await clientQRSService.getAll(res); 37 | } catch (e) { 38 | res.status(500).send({ 39 | message: 'Failed to get orders.'+ e 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /controllers/order.controller.js: -------------------------------------------------------------------------------- 1 | const orderService = require('../services/order.service'); 2 | 3 | exports.confirm = async(req, res) => { 4 | try { 5 | req.body.status='confirmed'; 6 | await orderService.confirm(req.params.id, req.body, res); 7 | } catch (e) { 8 | res.status(500).send({ 9 | message: 'Failed to confirm new order.'+ e 10 | }); 11 | } 12 | }; 13 | 14 | -------------------------------------------------------------------------------- /controllers/transport.controller.js: -------------------------------------------------------------------------------- 1 | const transportService = require('../services/transport.service'); 2 | 3 | exports.delivering = async(req, res) => { 4 | try { 5 | const data = await transportService.deliver(req.params.id, req.body, res); 6 | res.status(200).send(data); 7 | } catch (e) { 8 | res.status(500).send({ 9 | message: 'Failed to begin delivering new order.'+ e 10 | }); 11 | } 12 | }; 13 | 14 | exports.delivered = async(req, res) => { 15 | try { 16 | await transportService.delivered(req.params.id, req.body, res); 17 | } catch (e) { 18 | res.status(500).send({ 19 | message: 'Failed to deliver new order.'+ e 20 | }); 21 | } 22 | }; 23 | -------------------------------------------------------------------------------- /models/log.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | 4 | const client_log_conn_qrs = process.env.MONGO_CONN_CLIENT_LOG_QRS; 5 | const client_log_conn_crs = process.env.MONGO_CONN_CLIENT_LOG_CRS; 6 | const order_log_conn = process.env.MONGO_CONN_ORDER_LOG; 7 | const transport_log_conn = process.env.MONGO_CONN_TRANSPORT_LOG; 8 | 9 | const LogSchema = new Schema({ 10 | log: {type: String, max: 100}, 11 | created: { type: Date, default: Date.now } 12 | }); 13 | 14 | const client_qrs_log = mongoose.client_qrs_log = mongoose.createConnection(client_log_conn_qrs, { useNewUrlParser: true }); 15 | const client_crs_log = mongoose.client_crs_log = mongoose.createConnection(client_log_conn_crs, { useNewUrlParser: true }); 16 | const orders_log = mongoose.orders_log = mongoose.createConnection(order_log_conn, { useNewUrlParser: true }); 17 | const transport_log = mongoose.transport_log = mongoose.createConnection(transport_log_conn, { useNewUrlParser: true }); 18 | 19 | client_qrs_log.on('error', function (err) { 20 | console.log( "client_qrs_log" + err); 21 | }); 22 | 23 | client_crs_log.on('error', function (err) { 24 | console.log( "client_crs_log" + err); 25 | }); 26 | 27 | orders_log.on('error', function (err) { 28 | console.log( "orders_log" + err); 29 | }); 30 | 31 | transport_log.on('error', function (err) { 32 | console.log( "transport_log" + err); 33 | }); 34 | 35 | 36 | const clientCrsLog = client_qrs_log.model('Log', LogSchema); 37 | const clientQrsLog = client_crs_log.model('Log', LogSchema); 38 | const orderLog = orders_log.model('Log', LogSchema); 39 | const transportLog = transport_log.model('Log', LogSchema); 40 | 41 | module.exports = { 42 | clientCrsLog, 43 | clientQrsLog, 44 | transportLog, 45 | orderLog 46 | }; 47 | -------------------------------------------------------------------------------- /models/order.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | const Schema = mongoose.Schema; 3 | 4 | const OrderSchema = new Schema({ 5 | created: { type: Date, default: Date.now }, 6 | updated: { type: Date, default: Date.now }, 7 | status: { type: String, default: 'created' }, 8 | recipe: {type: String, max: 100}, 9 | date: {type: Date, default: Date.now}, 10 | delivery_place: {type: String, max: 200, default: "Famalicão"}, 11 | service: {type: Boolean, default: true}, 12 | payment: {type: String, default: "MBWay", max: 100} 13 | }); 14 | 15 | const orders_conn = process.env.MONGO_CONN_ORDERS; 16 | 17 | const orders = mongoose.createConnection(orders_conn, { useNewUrlParser: true }); 18 | 19 | const Order = orders.model('Order', OrderSchema); 20 | 21 | module.exports = Order; 22 | -------------------------------------------------------------------------------- /npm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/csampaio26/nodejs-microservices/2455bc01177d251e77b074a816b1edd253a3de24/npm -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "insis-microservices", 3 | "version": "1.0.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@types/babel-types": { 8 | "version": "7.0.7", 9 | "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.7.tgz", 10 | "integrity": "sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ==" 11 | }, 12 | "@types/babylon": { 13 | "version": "6.16.5", 14 | "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz", 15 | "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==", 16 | "requires": { 17 | "@types/babel-types": "*" 18 | } 19 | }, 20 | "@types/bson": { 21 | "version": "4.0.5", 22 | "resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.0.5.tgz", 23 | "integrity": "sha512-vVLwMUqhYJSQ/WKcE60eFqcyuWse5fGH+NMAXHuKrUAPoryq3ATxk5o4bgYNtg5aOM4APVg7Hnb3ASqUYG0PKg==", 24 | "requires": { 25 | "@types/node": "*" 26 | } 27 | }, 28 | "@types/mongodb": { 29 | "version": "3.6.20", 30 | "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz", 31 | "integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==", 32 | "requires": { 33 | "@types/bson": "*", 34 | "@types/node": "*" 35 | } 36 | }, 37 | "@types/node": { 38 | "version": "18.14.2", 39 | "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.2.tgz", 40 | "integrity": "sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==" 41 | }, 42 | "accepts": { 43 | "version": "1.3.8", 44 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 45 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 46 | "requires": { 47 | "mime-types": "~2.1.34", 48 | "negotiator": "0.6.3" 49 | }, 50 | "dependencies": { 51 | "mime-db": { 52 | "version": "1.52.0", 53 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 54 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 55 | }, 56 | "mime-types": { 57 | "version": "2.1.35", 58 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 59 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 60 | "requires": { 61 | "mime-db": "1.52.0" 62 | } 63 | } 64 | } 65 | }, 66 | "acorn": { 67 | "version": "3.3.0", 68 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 69 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=" 70 | }, 71 | "acorn-globals": { 72 | "version": "3.1.0", 73 | "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz", 74 | "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=", 75 | "requires": { 76 | "acorn": "^4.0.4" 77 | }, 78 | "dependencies": { 79 | "acorn": { 80 | "version": "4.0.13", 81 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 82 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" 83 | } 84 | } 85 | }, 86 | "align-text": { 87 | "version": "0.1.4", 88 | "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", 89 | "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", 90 | "requires": { 91 | "kind-of": "^3.0.2", 92 | "longest": "^1.0.1", 93 | "repeat-string": "^1.5.2" 94 | } 95 | }, 96 | "amqplib": { 97 | "version": "0.5.3", 98 | "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.5.3.tgz", 99 | "integrity": "sha512-ZOdUhMxcF+u62rPI+hMtU1NBXSDFQ3eCJJrenamtdQ7YYwh7RZJHOIM1gonVbZ5PyVdYH4xqBPje9OYqk7fnqw==", 100 | "requires": { 101 | "bitsyntax": "~0.1.0", 102 | "bluebird": "^3.5.2", 103 | "buffer-more-ints": "~1.0.0", 104 | "readable-stream": "1.x >=1.1.9", 105 | "safe-buffer": "~5.1.2", 106 | "url-parse": "~1.4.3" 107 | } 108 | }, 109 | "array-flatten": { 110 | "version": "1.1.1", 111 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 112 | "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" 113 | }, 114 | "asap": { 115 | "version": "2.0.6", 116 | "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", 117 | "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=" 118 | }, 119 | "babel-runtime": { 120 | "version": "6.26.0", 121 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 122 | "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", 123 | "requires": { 124 | "core-js": "^2.4.0", 125 | "regenerator-runtime": "^0.11.0" 126 | } 127 | }, 128 | "babel-types": { 129 | "version": "6.26.0", 130 | "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", 131 | "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", 132 | "requires": { 133 | "babel-runtime": "^6.26.0", 134 | "esutils": "^2.0.2", 135 | "lodash": "^4.17.4", 136 | "to-fast-properties": "^1.0.3" 137 | } 138 | }, 139 | "babylon": { 140 | "version": "6.18.0", 141 | "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", 142 | "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==" 143 | }, 144 | "bitsyntax": { 145 | "version": "0.1.0", 146 | "resolved": "https://registry.npmjs.org/bitsyntax/-/bitsyntax-0.1.0.tgz", 147 | "integrity": "sha512-ikAdCnrloKmFOugAfxWws89/fPc+nw0OOG1IzIE72uSOg/A3cYptKCjSUhDTuj7fhsJtzkzlv7l3b8PzRHLN0Q==", 148 | "requires": { 149 | "buffer-more-ints": "~1.0.0", 150 | "debug": "~2.6.9", 151 | "safe-buffer": "~5.1.2" 152 | } 153 | }, 154 | "bl": { 155 | "version": "2.2.1", 156 | "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", 157 | "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", 158 | "requires": { 159 | "readable-stream": "^2.3.5", 160 | "safe-buffer": "^5.1.1" 161 | }, 162 | "dependencies": { 163 | "isarray": { 164 | "version": "1.0.0", 165 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 166 | "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" 167 | }, 168 | "readable-stream": { 169 | "version": "2.3.8", 170 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", 171 | "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", 172 | "requires": { 173 | "core-util-is": "~1.0.0", 174 | "inherits": "~2.0.3", 175 | "isarray": "~1.0.0", 176 | "process-nextick-args": "~2.0.0", 177 | "safe-buffer": "~5.1.1", 178 | "string_decoder": "~1.1.1", 179 | "util-deprecate": "~1.0.1" 180 | } 181 | }, 182 | "string_decoder": { 183 | "version": "1.1.1", 184 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", 185 | "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", 186 | "requires": { 187 | "safe-buffer": "~5.1.0" 188 | } 189 | } 190 | } 191 | }, 192 | "bluebird": { 193 | "version": "3.5.4", 194 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.4.tgz", 195 | "integrity": "sha512-FG+nFEZChJrbQ9tIccIfZJBz3J7mLrAhxakAbnrJWn8d7aKOC+LWifa0G+p4ZqKp4y13T7juYvdhq9NzKdsrjw==" 196 | }, 197 | "body-parser": { 198 | "version": "1.20.2", 199 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", 200 | "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", 201 | "requires": { 202 | "bytes": "3.1.2", 203 | "content-type": "~1.0.5", 204 | "debug": "2.6.9", 205 | "depd": "2.0.0", 206 | "destroy": "1.2.0", 207 | "http-errors": "2.0.0", 208 | "iconv-lite": "0.4.24", 209 | "on-finished": "2.4.1", 210 | "qs": "6.11.0", 211 | "raw-body": "2.5.2", 212 | "type-is": "~1.6.18", 213 | "unpipe": "1.0.0" 214 | }, 215 | "dependencies": { 216 | "content-type": { 217 | "version": "1.0.5", 218 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", 219 | "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==" 220 | }, 221 | "depd": { 222 | "version": "2.0.0", 223 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 224 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 225 | }, 226 | "destroy": { 227 | "version": "1.2.0", 228 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", 229 | "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" 230 | }, 231 | "on-finished": { 232 | "version": "2.4.1", 233 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", 234 | "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", 235 | "requires": { 236 | "ee-first": "1.1.1" 237 | } 238 | } 239 | } 240 | }, 241 | "bson": { 242 | "version": "1.1.6", 243 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", 244 | "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" 245 | }, 246 | "buffer-more-ints": { 247 | "version": "1.0.0", 248 | "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz", 249 | "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==" 250 | }, 251 | "bytes": { 252 | "version": "3.1.2", 253 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 254 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 255 | }, 256 | "call-bind": { 257 | "version": "1.0.2", 258 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 259 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 260 | "requires": { 261 | "function-bind": "^1.1.1", 262 | "get-intrinsic": "^1.0.2" 263 | } 264 | }, 265 | "camelcase": { 266 | "version": "1.2.1", 267 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", 268 | "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" 269 | }, 270 | "center-align": { 271 | "version": "0.1.3", 272 | "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", 273 | "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", 274 | "requires": { 275 | "align-text": "^0.1.3", 276 | "lazy-cache": "^1.0.3" 277 | } 278 | }, 279 | "character-parser": { 280 | "version": "2.2.0", 281 | "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz", 282 | "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=", 283 | "requires": { 284 | "is-regex": "^1.0.3" 285 | } 286 | }, 287 | "clean-css": { 288 | "version": "4.2.1", 289 | "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", 290 | "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", 291 | "requires": { 292 | "source-map": "~0.6.0" 293 | } 294 | }, 295 | "cliui": { 296 | "version": "2.1.0", 297 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", 298 | "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", 299 | "requires": { 300 | "center-align": "^0.1.1", 301 | "right-align": "^0.1.1", 302 | "wordwrap": "0.0.2" 303 | } 304 | }, 305 | "constantinople": { 306 | "version": "3.1.2", 307 | "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz", 308 | "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==", 309 | "requires": { 310 | "@types/babel-types": "^7.0.0", 311 | "@types/babylon": "^6.16.2", 312 | "babel-types": "^6.26.0", 313 | "babylon": "^6.18.0" 314 | } 315 | }, 316 | "content-disposition": { 317 | "version": "0.5.4", 318 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 319 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 320 | "requires": { 321 | "safe-buffer": "5.2.1" 322 | }, 323 | "dependencies": { 324 | "safe-buffer": { 325 | "version": "5.2.1", 326 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 327 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 328 | } 329 | } 330 | }, 331 | "content-type": { 332 | "version": "1.0.4", 333 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 334 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 335 | }, 336 | "cookie": { 337 | "version": "0.4.2", 338 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", 339 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" 340 | }, 341 | "cookie-signature": { 342 | "version": "1.0.6", 343 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 344 | "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" 345 | }, 346 | "core-js": { 347 | "version": "2.6.8", 348 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.8.tgz", 349 | "integrity": "sha512-RWlREFU74TEkdXzyl1bka66O3kYp8jeTXrvJZDzVVMH8AiHUSOFpL1yfhQJ+wHocAm1m+4971W1PPzfLuCv1vg==" 350 | }, 351 | "core-util-is": { 352 | "version": "1.0.2", 353 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 354 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 355 | }, 356 | "cors": { 357 | "version": "2.8.5", 358 | "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", 359 | "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", 360 | "requires": { 361 | "object-assign": "^4", 362 | "vary": "^1" 363 | } 364 | }, 365 | "debug": { 366 | "version": "2.6.9", 367 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 368 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 369 | "requires": { 370 | "ms": "2.0.0" 371 | } 372 | }, 373 | "decamelize": { 374 | "version": "1.2.0", 375 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 376 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" 377 | }, 378 | "denque": { 379 | "version": "1.5.1", 380 | "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", 381 | "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" 382 | }, 383 | "depd": { 384 | "version": "1.1.2", 385 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 386 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 387 | }, 388 | "destroy": { 389 | "version": "1.0.4", 390 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 391 | "integrity": "sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==" 392 | }, 393 | "doctypes": { 394 | "version": "1.1.0", 395 | "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz", 396 | "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk=" 397 | }, 398 | "dotenv": { 399 | "version": "8.0.0", 400 | "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.0.0.tgz", 401 | "integrity": "sha512-30xVGqjLjiUOArT4+M5q9sYdvuR4riM6yK9wMcas9Vbp6zZa+ocC9dp6QoftuhTPhFAiLK/0C5Ni2nou/Bk8lg==" 402 | }, 403 | "ee-first": { 404 | "version": "1.1.1", 405 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 406 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 407 | }, 408 | "encodeurl": { 409 | "version": "1.0.2", 410 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 411 | "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==" 412 | }, 413 | "escape-html": { 414 | "version": "1.0.3", 415 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 416 | "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" 417 | }, 418 | "esutils": { 419 | "version": "2.0.2", 420 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 421 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=" 422 | }, 423 | "etag": { 424 | "version": "1.8.1", 425 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 426 | "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" 427 | }, 428 | "express": { 429 | "version": "4.17.3", 430 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", 431 | "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", 432 | "requires": { 433 | "accepts": "~1.3.8", 434 | "array-flatten": "1.1.1", 435 | "body-parser": "1.19.2", 436 | "content-disposition": "0.5.4", 437 | "content-type": "~1.0.4", 438 | "cookie": "0.4.2", 439 | "cookie-signature": "1.0.6", 440 | "debug": "2.6.9", 441 | "depd": "~1.1.2", 442 | "encodeurl": "~1.0.2", 443 | "escape-html": "~1.0.3", 444 | "etag": "~1.8.1", 445 | "finalhandler": "~1.1.2", 446 | "fresh": "0.5.2", 447 | "merge-descriptors": "1.0.1", 448 | "methods": "~1.1.2", 449 | "on-finished": "~2.3.0", 450 | "parseurl": "~1.3.3", 451 | "path-to-regexp": "0.1.7", 452 | "proxy-addr": "~2.0.7", 453 | "qs": "6.9.7", 454 | "range-parser": "~1.2.1", 455 | "safe-buffer": "5.2.1", 456 | "send": "0.17.2", 457 | "serve-static": "1.14.2", 458 | "setprototypeof": "1.2.0", 459 | "statuses": "~1.5.0", 460 | "type-is": "~1.6.18", 461 | "utils-merge": "1.0.1", 462 | "vary": "~1.1.2" 463 | }, 464 | "dependencies": { 465 | "body-parser": { 466 | "version": "1.19.2", 467 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", 468 | "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", 469 | "requires": { 470 | "bytes": "3.1.2", 471 | "content-type": "~1.0.4", 472 | "debug": "2.6.9", 473 | "depd": "~1.1.2", 474 | "http-errors": "1.8.1", 475 | "iconv-lite": "0.4.24", 476 | "on-finished": "~2.3.0", 477 | "qs": "6.9.7", 478 | "raw-body": "2.4.3", 479 | "type-is": "~1.6.18" 480 | } 481 | }, 482 | "bytes": { 483 | "version": "3.1.2", 484 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 485 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 486 | }, 487 | "http-errors": { 488 | "version": "1.8.1", 489 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", 490 | "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", 491 | "requires": { 492 | "depd": "~1.1.2", 493 | "inherits": "2.0.4", 494 | "setprototypeof": "1.2.0", 495 | "statuses": ">= 1.5.0 < 2", 496 | "toidentifier": "1.0.1" 497 | } 498 | }, 499 | "inherits": { 500 | "version": "2.0.4", 501 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 502 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 503 | }, 504 | "qs": { 505 | "version": "6.9.7", 506 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", 507 | "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" 508 | }, 509 | "raw-body": { 510 | "version": "2.4.3", 511 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", 512 | "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", 513 | "requires": { 514 | "bytes": "3.1.2", 515 | "http-errors": "1.8.1", 516 | "iconv-lite": "0.4.24", 517 | "unpipe": "1.0.0" 518 | } 519 | }, 520 | "safe-buffer": { 521 | "version": "5.2.1", 522 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 523 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 524 | }, 525 | "setprototypeof": { 526 | "version": "1.2.0", 527 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 528 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 529 | }, 530 | "toidentifier": { 531 | "version": "1.0.1", 532 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 533 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 534 | } 535 | } 536 | }, 537 | "finalhandler": { 538 | "version": "1.1.2", 539 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 540 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 541 | "requires": { 542 | "debug": "2.6.9", 543 | "encodeurl": "~1.0.2", 544 | "escape-html": "~1.0.3", 545 | "on-finished": "~2.3.0", 546 | "parseurl": "~1.3.3", 547 | "statuses": "~1.5.0", 548 | "unpipe": "~1.0.0" 549 | } 550 | }, 551 | "forwarded": { 552 | "version": "0.2.0", 553 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 554 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 555 | }, 556 | "fresh": { 557 | "version": "0.5.2", 558 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 559 | "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==" 560 | }, 561 | "function-bind": { 562 | "version": "1.1.1", 563 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 564 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 565 | }, 566 | "get-intrinsic": { 567 | "version": "1.2.0", 568 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 569 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 570 | "requires": { 571 | "function-bind": "^1.1.1", 572 | "has": "^1.0.3", 573 | "has-symbols": "^1.0.3" 574 | } 575 | }, 576 | "has": { 577 | "version": "1.0.3", 578 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 579 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 580 | "requires": { 581 | "function-bind": "^1.1.1" 582 | } 583 | }, 584 | "has-symbols": { 585 | "version": "1.0.3", 586 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 587 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" 588 | }, 589 | "http-errors": { 590 | "version": "2.0.0", 591 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", 592 | "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", 593 | "requires": { 594 | "depd": "2.0.0", 595 | "inherits": "2.0.4", 596 | "setprototypeof": "1.2.0", 597 | "statuses": "2.0.1", 598 | "toidentifier": "1.0.1" 599 | }, 600 | "dependencies": { 601 | "depd": { 602 | "version": "2.0.0", 603 | "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", 604 | "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" 605 | }, 606 | "inherits": { 607 | "version": "2.0.4", 608 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 609 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 610 | }, 611 | "statuses": { 612 | "version": "2.0.1", 613 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", 614 | "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" 615 | } 616 | } 617 | }, 618 | "iconv-lite": { 619 | "version": "0.4.24", 620 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 621 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 622 | "requires": { 623 | "safer-buffer": ">= 2.1.2 < 3" 624 | } 625 | }, 626 | "inherits": { 627 | "version": "2.0.3", 628 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 629 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" 630 | }, 631 | "ipaddr.js": { 632 | "version": "1.9.1", 633 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 634 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 635 | }, 636 | "is-buffer": { 637 | "version": "1.1.6", 638 | "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", 639 | "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" 640 | }, 641 | "is-expression": { 642 | "version": "3.0.0", 643 | "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz", 644 | "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=", 645 | "requires": { 646 | "acorn": "~4.0.2", 647 | "object-assign": "^4.0.1" 648 | }, 649 | "dependencies": { 650 | "acorn": { 651 | "version": "4.0.13", 652 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 653 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=" 654 | } 655 | } 656 | }, 657 | "is-promise": { 658 | "version": "2.1.0", 659 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 660 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" 661 | }, 662 | "is-regex": { 663 | "version": "1.0.4", 664 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", 665 | "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", 666 | "requires": { 667 | "has": "^1.0.1" 668 | } 669 | }, 670 | "isarray": { 671 | "version": "0.0.1", 672 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", 673 | "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" 674 | }, 675 | "js-stringify": { 676 | "version": "1.0.2", 677 | "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", 678 | "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds=" 679 | }, 680 | "jstransformer": { 681 | "version": "1.0.0", 682 | "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", 683 | "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=", 684 | "requires": { 685 | "is-promise": "^2.0.0", 686 | "promise": "^7.0.1" 687 | } 688 | }, 689 | "kareem": { 690 | "version": "2.3.2", 691 | "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.2.tgz", 692 | "integrity": "sha512-STHz9P7X2L4Kwn72fA4rGyqyXdmrMSdxqHx9IXon/FXluXieaFA6KJ2upcHAHxQPQ0LeM/OjLrhFxifHewOALQ==" 693 | }, 694 | "kind-of": { 695 | "version": "3.2.2", 696 | "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", 697 | "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", 698 | "requires": { 699 | "is-buffer": "^1.1.5" 700 | } 701 | }, 702 | "lazy-cache": { 703 | "version": "1.0.4", 704 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", 705 | "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" 706 | }, 707 | "lodash": { 708 | "version": "4.17.21", 709 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", 710 | "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" 711 | }, 712 | "longest": { 713 | "version": "1.0.1", 714 | "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", 715 | "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" 716 | }, 717 | "media-typer": { 718 | "version": "0.3.0", 719 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 720 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 721 | }, 722 | "memory-pager": { 723 | "version": "1.5.0", 724 | "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", 725 | "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", 726 | "optional": true 727 | }, 728 | "merge-descriptors": { 729 | "version": "1.0.1", 730 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 731 | "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" 732 | }, 733 | "methods": { 734 | "version": "1.1.2", 735 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 736 | "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==" 737 | }, 738 | "mime": { 739 | "version": "1.6.0", 740 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 741 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 742 | }, 743 | "mime-db": { 744 | "version": "1.40.0", 745 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz", 746 | "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA==" 747 | }, 748 | "mime-types": { 749 | "version": "2.1.24", 750 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz", 751 | "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==", 752 | "requires": { 753 | "mime-db": "1.40.0" 754 | } 755 | }, 756 | "mongodb": { 757 | "version": "3.7.3", 758 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", 759 | "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", 760 | "requires": { 761 | "bl": "^2.2.1", 762 | "bson": "^1.1.4", 763 | "denque": "^1.4.1", 764 | "optional-require": "^1.1.8", 765 | "safe-buffer": "^5.1.2", 766 | "saslprep": "^1.0.0" 767 | }, 768 | "dependencies": { 769 | "optional-require": { 770 | "version": "1.1.8", 771 | "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", 772 | "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", 773 | "requires": { 774 | "require-at": "^1.0.6" 775 | } 776 | } 777 | } 778 | }, 779 | "mongoose": { 780 | "version": "5.13.15", 781 | "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.13.15.tgz", 782 | "integrity": "sha512-cxp1Gbb8yUWkaEbajdhspSaKzAvsIvOtRlYD87GN/P2QEUhpd6bIvebi36T6M0tIVAMauNaK9SPA055N3PwF8Q==", 783 | "requires": { 784 | "@types/bson": "1.x || 4.0.x", 785 | "@types/mongodb": "^3.5.27", 786 | "bson": "^1.1.4", 787 | "kareem": "2.3.2", 788 | "mongodb": "3.7.3", 789 | "mongoose-legacy-pluralize": "1.0.2", 790 | "mpath": "0.8.4", 791 | "mquery": "3.2.5", 792 | "ms": "2.1.2", 793 | "optional-require": "1.0.x", 794 | "regexp-clone": "1.0.0", 795 | "safe-buffer": "5.2.1", 796 | "sift": "13.5.2", 797 | "sliced": "1.0.1" 798 | }, 799 | "dependencies": { 800 | "ms": { 801 | "version": "2.1.2", 802 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 803 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 804 | }, 805 | "safe-buffer": { 806 | "version": "5.2.1", 807 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 808 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 809 | } 810 | } 811 | }, 812 | "mongoose-legacy-pluralize": { 813 | "version": "1.0.2", 814 | "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", 815 | "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" 816 | }, 817 | "mpath": { 818 | "version": "0.8.4", 819 | "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.8.4.tgz", 820 | "integrity": "sha512-DTxNZomBcTWlrMW76jy1wvV37X/cNNxPW1y2Jzd4DZkAaC5ZGsm8bfGfNOthcDuRJujXLqiuS6o3Tpy0JEoh7g==" 821 | }, 822 | "mquery": { 823 | "version": "3.2.5", 824 | "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.5.tgz", 825 | "integrity": "sha512-VjOKHHgU84wij7IUoZzFRU07IAxd5kWJaDmyUzQlbjHjyoeK5TNeeo8ZsFDtTYnSgpW6n/nMNIHvE3u8Lbrf4A==", 826 | "requires": { 827 | "bluebird": "3.5.1", 828 | "debug": "3.1.0", 829 | "regexp-clone": "^1.0.0", 830 | "safe-buffer": "5.1.2", 831 | "sliced": "1.0.1" 832 | }, 833 | "dependencies": { 834 | "bluebird": { 835 | "version": "3.5.1", 836 | "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", 837 | "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" 838 | }, 839 | "debug": { 840 | "version": "3.1.0", 841 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 842 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 843 | "requires": { 844 | "ms": "2.0.0" 845 | } 846 | } 847 | } 848 | }, 849 | "ms": { 850 | "version": "2.0.0", 851 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 852 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 853 | }, 854 | "negotiator": { 855 | "version": "0.6.3", 856 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 857 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 858 | }, 859 | "object-assign": { 860 | "version": "4.1.1", 861 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 862 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 863 | }, 864 | "object-inspect": { 865 | "version": "1.12.3", 866 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 867 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==" 868 | }, 869 | "on-finished": { 870 | "version": "2.3.0", 871 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 872 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 873 | "requires": { 874 | "ee-first": "1.1.1" 875 | } 876 | }, 877 | "optional-require": { 878 | "version": "1.0.3", 879 | "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.0.3.tgz", 880 | "integrity": "sha512-RV2Zp2MY2aeYK5G+B/Sps8lW5NHAzE5QClbFP15j+PWmP+T9PxlJXBOOLoSAdgwFvS4t0aMR4vpedMkbHfh0nA==" 881 | }, 882 | "parseurl": { 883 | "version": "1.3.3", 884 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 885 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 886 | }, 887 | "path-parse": { 888 | "version": "1.0.7", 889 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 890 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 891 | }, 892 | "path-to-regexp": { 893 | "version": "0.1.7", 894 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 895 | "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" 896 | }, 897 | "process-nextick-args": { 898 | "version": "2.0.1", 899 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", 900 | "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" 901 | }, 902 | "promise": { 903 | "version": "7.3.1", 904 | "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", 905 | "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", 906 | "requires": { 907 | "asap": "~2.0.3" 908 | } 909 | }, 910 | "proxy-addr": { 911 | "version": "2.0.7", 912 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 913 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 914 | "requires": { 915 | "forwarded": "0.2.0", 916 | "ipaddr.js": "1.9.1" 917 | } 918 | }, 919 | "pug": { 920 | "version": "2.0.3", 921 | "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.3.tgz", 922 | "integrity": "sha1-ccuoJTfJWl6rftBGluQiH1Oqh44=", 923 | "requires": { 924 | "pug-code-gen": "^2.0.1", 925 | "pug-filters": "^3.1.0", 926 | "pug-lexer": "^4.0.0", 927 | "pug-linker": "^3.0.5", 928 | "pug-load": "^2.0.11", 929 | "pug-parser": "^5.0.0", 930 | "pug-runtime": "^2.0.4", 931 | "pug-strip-comments": "^1.0.3" 932 | } 933 | }, 934 | "pug-code-gen": { 935 | "version": "2.0.3", 936 | "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.3.tgz", 937 | "integrity": "sha512-r9sezXdDuZJfW9J91TN/2LFbiqDhmltTFmGpHTsGdrNGp3p4SxAjjXEfnuK2e4ywYsRIVP0NeLbSAMHUcaX1EA==", 938 | "requires": { 939 | "constantinople": "^3.1.2", 940 | "doctypes": "^1.1.0", 941 | "js-stringify": "^1.0.1", 942 | "pug-attrs": "^2.0.4", 943 | "pug-error": "^1.3.3", 944 | "pug-runtime": "^2.0.5", 945 | "void-elements": "^2.0.1", 946 | "with": "^5.0.0" 947 | }, 948 | "dependencies": { 949 | "pug-attrs": { 950 | "version": "2.0.4", 951 | "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz", 952 | "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==", 953 | "requires": { 954 | "constantinople": "^3.0.1", 955 | "js-stringify": "^1.0.1", 956 | "pug-runtime": "^2.0.5" 957 | } 958 | }, 959 | "pug-error": { 960 | "version": "1.3.3", 961 | "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz", 962 | "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ==" 963 | }, 964 | "pug-runtime": { 965 | "version": "2.0.5", 966 | "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz", 967 | "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw==" 968 | } 969 | } 970 | }, 971 | "pug-error": { 972 | "version": "1.3.2", 973 | "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.2.tgz", 974 | "integrity": "sha1-U659nSm7A89WRJOgJhCfVMR/XyY=" 975 | }, 976 | "pug-filters": { 977 | "version": "3.1.0", 978 | "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.0.tgz", 979 | "integrity": "sha1-JxZVVbwEwjbkqisDZiRt+gIbYm4=", 980 | "requires": { 981 | "clean-css": "^4.1.11", 982 | "constantinople": "^3.0.1", 983 | "jstransformer": "1.0.0", 984 | "pug-error": "^1.3.2", 985 | "pug-walk": "^1.1.7", 986 | "resolve": "^1.1.6", 987 | "uglify-js": "^2.6.1" 988 | } 989 | }, 990 | "pug-lexer": { 991 | "version": "4.0.0", 992 | "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.0.0.tgz", 993 | "integrity": "sha1-IQwYRX7y4XYCQnQMXmR715TOwng=", 994 | "requires": { 995 | "character-parser": "^2.1.1", 996 | "is-expression": "^3.0.0", 997 | "pug-error": "^1.3.2" 998 | } 999 | }, 1000 | "pug-linker": { 1001 | "version": "3.0.5", 1002 | "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.5.tgz", 1003 | "integrity": "sha1-npp65ABWgtAn3uuWsAD4juuDoC8=", 1004 | "requires": { 1005 | "pug-error": "^1.3.2", 1006 | "pug-walk": "^1.1.7" 1007 | } 1008 | }, 1009 | "pug-load": { 1010 | "version": "2.0.11", 1011 | "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.11.tgz", 1012 | "integrity": "sha1-5kjlftET/iwfRdV4WOorrWvAFSc=", 1013 | "requires": { 1014 | "object-assign": "^4.1.0", 1015 | "pug-walk": "^1.1.7" 1016 | } 1017 | }, 1018 | "pug-parser": { 1019 | "version": "5.0.0", 1020 | "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.0.tgz", 1021 | "integrity": "sha1-45Stmz/KkxI5QK/4hcBuRKt+aOQ=", 1022 | "requires": { 1023 | "pug-error": "^1.3.2", 1024 | "token-stream": "0.0.1" 1025 | } 1026 | }, 1027 | "pug-runtime": { 1028 | "version": "2.0.4", 1029 | "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.4.tgz", 1030 | "integrity": "sha1-4XjhvaaKsujArPybztLFT9iM61g=" 1031 | }, 1032 | "pug-strip-comments": { 1033 | "version": "1.0.3", 1034 | "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.3.tgz", 1035 | "integrity": "sha1-8VWVkiBu3G+FMQ2s9K+0igJa9Z8=", 1036 | "requires": { 1037 | "pug-error": "^1.3.2" 1038 | } 1039 | }, 1040 | "pug-walk": { 1041 | "version": "1.1.7", 1042 | "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.7.tgz", 1043 | "integrity": "sha1-wA1cUSi6xYBr7BXSt+fNq+QlMfM=" 1044 | }, 1045 | "qs": { 1046 | "version": "6.11.0", 1047 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", 1048 | "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", 1049 | "requires": { 1050 | "side-channel": "^1.0.4" 1051 | } 1052 | }, 1053 | "querystringify": { 1054 | "version": "2.1.1", 1055 | "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.1.1.tgz", 1056 | "integrity": "sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==" 1057 | }, 1058 | "range-parser": { 1059 | "version": "1.2.1", 1060 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1061 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1062 | }, 1063 | "raw-body": { 1064 | "version": "2.5.2", 1065 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", 1066 | "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", 1067 | "requires": { 1068 | "bytes": "3.1.2", 1069 | "http-errors": "2.0.0", 1070 | "iconv-lite": "0.4.24", 1071 | "unpipe": "1.0.0" 1072 | } 1073 | }, 1074 | "readable-stream": { 1075 | "version": "1.1.14", 1076 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", 1077 | "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", 1078 | "requires": { 1079 | "core-util-is": "~1.0.0", 1080 | "inherits": "~2.0.1", 1081 | "isarray": "0.0.1", 1082 | "string_decoder": "~0.10.x" 1083 | } 1084 | }, 1085 | "regenerator-runtime": { 1086 | "version": "0.11.1", 1087 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", 1088 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" 1089 | }, 1090 | "regexp-clone": { 1091 | "version": "1.0.0", 1092 | "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", 1093 | "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" 1094 | }, 1095 | "repeat-string": { 1096 | "version": "1.6.1", 1097 | "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", 1098 | "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" 1099 | }, 1100 | "require-at": { 1101 | "version": "1.0.6", 1102 | "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", 1103 | "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" 1104 | }, 1105 | "requires-port": { 1106 | "version": "1.0.0", 1107 | "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", 1108 | "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" 1109 | }, 1110 | "resolve": { 1111 | "version": "1.11.0", 1112 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.11.0.tgz", 1113 | "integrity": "sha512-WL2pBDjqT6pGUNSUzMw00o4T7If+z4H2x3Gz893WoUQ5KW8Vr9txp00ykiP16VBaZF5+j/OcXJHZ9+PCvdiDKw==", 1114 | "requires": { 1115 | "path-parse": "^1.0.6" 1116 | } 1117 | }, 1118 | "right-align": { 1119 | "version": "0.1.3", 1120 | "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", 1121 | "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", 1122 | "requires": { 1123 | "align-text": "^0.1.1" 1124 | } 1125 | }, 1126 | "safe-buffer": { 1127 | "version": "5.1.2", 1128 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1129 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1130 | }, 1131 | "safer-buffer": { 1132 | "version": "2.1.2", 1133 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1134 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1135 | }, 1136 | "saslprep": { 1137 | "version": "1.0.3", 1138 | "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", 1139 | "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", 1140 | "optional": true, 1141 | "requires": { 1142 | "sparse-bitfield": "^3.0.3" 1143 | } 1144 | }, 1145 | "send": { 1146 | "version": "0.17.2", 1147 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", 1148 | "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", 1149 | "requires": { 1150 | "debug": "2.6.9", 1151 | "depd": "~1.1.2", 1152 | "destroy": "~1.0.4", 1153 | "encodeurl": "~1.0.2", 1154 | "escape-html": "~1.0.3", 1155 | "etag": "~1.8.1", 1156 | "fresh": "0.5.2", 1157 | "http-errors": "1.8.1", 1158 | "mime": "1.6.0", 1159 | "ms": "2.1.3", 1160 | "on-finished": "~2.3.0", 1161 | "range-parser": "~1.2.1", 1162 | "statuses": "~1.5.0" 1163 | }, 1164 | "dependencies": { 1165 | "http-errors": { 1166 | "version": "1.8.1", 1167 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", 1168 | "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", 1169 | "requires": { 1170 | "depd": "~1.1.2", 1171 | "inherits": "2.0.4", 1172 | "setprototypeof": "1.2.0", 1173 | "statuses": ">= 1.5.0 < 2", 1174 | "toidentifier": "1.0.1" 1175 | } 1176 | }, 1177 | "inherits": { 1178 | "version": "2.0.4", 1179 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1180 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1181 | }, 1182 | "ms": { 1183 | "version": "2.1.3", 1184 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1185 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1186 | }, 1187 | "setprototypeof": { 1188 | "version": "1.2.0", 1189 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1190 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1191 | }, 1192 | "toidentifier": { 1193 | "version": "1.0.1", 1194 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1195 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1196 | } 1197 | } 1198 | }, 1199 | "serve-static": { 1200 | "version": "1.14.2", 1201 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", 1202 | "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", 1203 | "requires": { 1204 | "encodeurl": "~1.0.2", 1205 | "escape-html": "~1.0.3", 1206 | "parseurl": "~1.3.3", 1207 | "send": "0.17.2" 1208 | } 1209 | }, 1210 | "setprototypeof": { 1211 | "version": "1.2.0", 1212 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1213 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1214 | }, 1215 | "side-channel": { 1216 | "version": "1.0.4", 1217 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1218 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1219 | "requires": { 1220 | "call-bind": "^1.0.0", 1221 | "get-intrinsic": "^1.0.2", 1222 | "object-inspect": "^1.9.0" 1223 | } 1224 | }, 1225 | "sift": { 1226 | "version": "13.5.2", 1227 | "resolved": "https://registry.npmjs.org/sift/-/sift-13.5.2.tgz", 1228 | "integrity": "sha512-+gxdEOMA2J+AI+fVsCqeNn7Tgx3M9ZN9jdi95939l1IJ8cZsqS8sqpJyOkic2SJk+1+98Uwryt/gL6XDaV+UZA==" 1229 | }, 1230 | "sliced": { 1231 | "version": "1.0.1", 1232 | "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", 1233 | "integrity": "sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA==" 1234 | }, 1235 | "source-map": { 1236 | "version": "0.6.1", 1237 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1238 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" 1239 | }, 1240 | "sparse-bitfield": { 1241 | "version": "3.0.3", 1242 | "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", 1243 | "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", 1244 | "optional": true, 1245 | "requires": { 1246 | "memory-pager": "^1.0.2" 1247 | } 1248 | }, 1249 | "statuses": { 1250 | "version": "1.5.0", 1251 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1252 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1253 | }, 1254 | "string_decoder": { 1255 | "version": "0.10.31", 1256 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", 1257 | "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" 1258 | }, 1259 | "to-fast-properties": { 1260 | "version": "1.0.3", 1261 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", 1262 | "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=" 1263 | }, 1264 | "toidentifier": { 1265 | "version": "1.0.1", 1266 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1267 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1268 | }, 1269 | "token-stream": { 1270 | "version": "0.0.1", 1271 | "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz", 1272 | "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo=" 1273 | }, 1274 | "type-is": { 1275 | "version": "1.6.18", 1276 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1277 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1278 | "requires": { 1279 | "media-typer": "0.3.0", 1280 | "mime-types": "~2.1.24" 1281 | } 1282 | }, 1283 | "uglify-js": { 1284 | "version": "2.8.29", 1285 | "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", 1286 | "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", 1287 | "requires": { 1288 | "source-map": "~0.5.1", 1289 | "uglify-to-browserify": "~1.0.0", 1290 | "yargs": "~3.10.0" 1291 | }, 1292 | "dependencies": { 1293 | "source-map": { 1294 | "version": "0.5.7", 1295 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", 1296 | "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" 1297 | } 1298 | } 1299 | }, 1300 | "uglify-to-browserify": { 1301 | "version": "1.0.2", 1302 | "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", 1303 | "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", 1304 | "optional": true 1305 | }, 1306 | "unpipe": { 1307 | "version": "1.0.0", 1308 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1309 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1310 | }, 1311 | "url-parse": { 1312 | "version": "1.4.7", 1313 | "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz", 1314 | "integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==", 1315 | "requires": { 1316 | "querystringify": "^2.1.1", 1317 | "requires-port": "^1.0.0" 1318 | } 1319 | }, 1320 | "util-deprecate": { 1321 | "version": "1.0.2", 1322 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1323 | "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" 1324 | }, 1325 | "utils-merge": { 1326 | "version": "1.0.1", 1327 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1328 | "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==" 1329 | }, 1330 | "vary": { 1331 | "version": "1.1.2", 1332 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1333 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1334 | }, 1335 | "void-elements": { 1336 | "version": "2.0.1", 1337 | "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", 1338 | "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" 1339 | }, 1340 | "window-size": { 1341 | "version": "0.1.0", 1342 | "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", 1343 | "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" 1344 | }, 1345 | "with": { 1346 | "version": "5.1.1", 1347 | "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz", 1348 | "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=", 1349 | "requires": { 1350 | "acorn": "^3.1.0", 1351 | "acorn-globals": "^3.0.0" 1352 | } 1353 | }, 1354 | "wordwrap": { 1355 | "version": "0.0.2", 1356 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", 1357 | "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" 1358 | }, 1359 | "yargs": { 1360 | "version": "3.10.0", 1361 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", 1362 | "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", 1363 | "requires": { 1364 | "camelcase": "^1.0.2", 1365 | "cliui": "^2.1.0", 1366 | "decamelize": "^1.0.0", 1367 | "window-size": "0.1.0" 1368 | } 1369 | } 1370 | } 1371 | } 1372 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "insis-microservices", 3 | "version": "1.0.0", 4 | "description": "nodejs insis", 5 | "author": "Carla Sampaio carlamsampaio01@gmail.com", 6 | "license": "MIT", 7 | "main": "app.js", 8 | "scripts": { 9 | "start": "node app.js" 10 | }, 11 | "dependencies": { 12 | "amqplib": "^0.5.3", 13 | "body-parser": "^1.20.2", 14 | "cors": "^2.8.5", 15 | "dotenv": "^8.0.0", 16 | "express": "^4.17.3", 17 | "mongoose": "^5.13.15", 18 | "pug": "^2.0.3" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /rabbit/receivers.js: -------------------------------------------------------------------------------- 1 | const amqp = require('amqplib/callback_api'); 2 | const logOrder = require('../repository/logOrder.repository'); 3 | const logClient = require('../repository/logClient.repository'); 4 | const logTransport = require('../repository/logTransport.repository'); 5 | 6 | 7 | exports.clientReceiver = () => { 8 | amqp.connect(process.env.MESSAGE_QUEUE, function(error0, connection) { 9 | if (error0) { 10 | throw error0; 11 | } 12 | connection.createChannel(function(error1, channel) { 13 | if (error1) { 14 | throw error1; 15 | } 16 | 17 | const subscribedExchanges = ['Order', 'Transport']; 18 | 19 | for(let i = 0; i < subscribedExchanges.length; i++){ 20 | channel.assertExchange(subscribedExchanges[i], 'fanout', { 21 | durable: false 22 | }); 23 | 24 | channel.assertQueue('', { 25 | exclusive: true 26 | }, function(error2, q) { 27 | if (error2) { 28 | throw error2; 29 | } 30 | console.log(` [*] Client waiting for messages in %s. To exit press CTRL+C`, q.queue); 31 | 32 | channel.bindQueue(q.queue, subscribedExchanges[i], ''); 33 | 34 | channel.consume(q.queue, async function(msg) { 35 | if(msg.content) { 36 | console.log(` [x] Client received: ${ msg.content.toString() } `); 37 | await logClient.newQRS(msg.content.toString()) 38 | await logClient.newCRS(msg.content.toString()) 39 | } 40 | }, { 41 | noAck: true 42 | }); 43 | }); 44 | } 45 | }); 46 | }); 47 | } 48 | 49 | exports.orderReceiver = () => { 50 | amqp.connect(process.env.MESSAGE_QUEUE, function(error0, connection) { 51 | if (error0) { 52 | throw error0; 53 | } 54 | connection.createChannel(function(error1, channel) { 55 | if (error1) { 56 | throw error1; 57 | } 58 | 59 | const subscribedExchanges = ['Client', 'Stock', 'Kitchen', 'Transport']; 60 | 61 | for(let i = 0; i < subscribedExchanges.length; i++){ 62 | channel.assertExchange(subscribedExchanges[i], 'fanout', { 63 | durable: false 64 | }); 65 | 66 | channel.assertQueue('', { 67 | exclusive: true 68 | }, function(error2, q) { 69 | if (error2) { 70 | throw error2; 71 | } 72 | console.log(` [*] Order waiting for messages in %s. To exit press CTRL+C`, q.queue); 73 | 74 | channel.bindQueue(q.queue, subscribedExchanges[i], ''); 75 | 76 | channel.consume(q.queue, async function(msg) { 77 | if(msg.content) { 78 | console.log(` [x] Order received: ${ msg.content.toString() } `); 79 | await logOrder.new(msg.content.toString()) 80 | } 81 | }, { 82 | noAck: true 83 | }); 84 | }); 85 | } 86 | }); 87 | }); 88 | } 89 | 90 | exports.transportReceiver = () => { 91 | amqp.connect(process.env.MESSAGE_QUEUE, function(error0, connection) { 92 | if (error0) { 93 | throw error0; 94 | } 95 | connection.createChannel(function(error1, channel) { 96 | if (error1) { 97 | throw error1; 98 | } 99 | 100 | const subscribedExchanges = ['Kitchen']; 101 | 102 | for(let i = 0; i < subscribedExchanges.length; i++){ 103 | channel.assertExchange(subscribedExchanges[i], 'fanout', { 104 | durable: false 105 | }); 106 | 107 | channel.assertQueue('', { 108 | exclusive: true 109 | }, function(error2, q) { 110 | if (error2) { 111 | throw error2; 112 | } 113 | console.log(` [*] Transport waiting for messages in %s. To exit press CTRL+C`, q.queue); 114 | 115 | channel.bindQueue(q.queue, subscribedExchanges[i], ''); 116 | 117 | channel.consume(q.queue, async function(msg) { 118 | if(msg.content) { 119 | console.log(` [x] Transport received: ${ msg.content.toString() } `); 120 | await logTransport.new(msg.content.toString()) 121 | } 122 | }, { 123 | noAck: true 124 | }); 125 | }); 126 | } 127 | }); 128 | }); 129 | } 130 | -------------------------------------------------------------------------------- /rabbit/sender.js: -------------------------------------------------------------------------------- 1 | const amqp = require('amqplib/callback_api'); 2 | 3 | exports.send = (EXCHANGE_NAME, message) => { 4 | 5 | amqp.connect(process.env.MESSAGE_QUEUE, function(error0, connection) { 6 | if (error0) { 7 | throw error0; 8 | } 9 | connection.createChannel(function(error1, channel) { 10 | if (error1) { 11 | throw error1; 12 | } 13 | 14 | channel.assertExchange(EXCHANGE_NAME, 'fanout', { 15 | durable: false 16 | }); 17 | 18 | channel.publish(EXCHANGE_NAME, '', Buffer.from(message)); 19 | 20 | console.log(` [x] ${EXCHANGE_NAME} Sent: ${message} `); 21 | 22 | setTimeout(function() { 23 | connection.close(); 24 | }, 500); 25 | }); 26 | }); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | > ### Example Node (Express + Mongoose) codebase containing microservices with their respective databases. 2 | 3 | # Getting started 4 | 5 | To get the Node server running locally: 6 | 7 | - Clone this repo 8 | - `npm install` to install all required dependencies 9 | - Copy the .env.example to .env file, to make the environment file 10 | 11 | # Code Overview 12 | 13 | ## Dependencies 14 | 15 | - [expressjs](https://github.com/expressjs/express) - The server for handling and routing HTTP requests 16 | - [mongoose](https://github.com/Automattic/mongoose) - For modeling and mapping MongoDB data to javascript 17 | - [amqp](https://www.rabbitmq.com/getstarted.html) - Advanced Message Queuing Protocol 18 | 19 | ## Application Structure 20 | 21 | - `app.js` - The entry point to the application. This file defines our express server and connects it to MongoDB using mongoose. It also requires the routes and models we'll be using in the application. 22 | - `routes/` - This folder contains the route definitions for our API. 23 | - `models/` - This folder contains the schema definitions for our Mongoose models. 24 | - `controllers/` - This folder handles the requests made by the user. 25 | - `services/` - This folder contains all the business logic. 26 | - `repository/` - This folder contains the repository pattern. 27 | - `rabbit/` - This folder contains the generic messaging sender. 28 | 29 | -------------------------------------------------------------------------------- /repository/logClient.repository.js: -------------------------------------------------------------------------------- 1 | // Set up mongoose connection 2 | const Log = require('../models/log'); 3 | 4 | exports.newQRS = async(body) => { 5 | let log = new Log.clientQrsLog( 6 | { 7 | log: body 8 | } 9 | ); 10 | 11 | log.save(function(err) { 12 | if (err) { 13 | console.log("error"); 14 | throw err; 15 | } 16 | }); 17 | return log; 18 | }; 19 | 20 | 21 | exports.newCRS = async(body) => { 22 | let log = new Log.clientCrsLog( 23 | { 24 | log: body 25 | } 26 | ); 27 | 28 | log.save(function(err) { 29 | if (err) { 30 | console.log("error"); 31 | throw err; 32 | } 33 | }); 34 | return log; 35 | }; 36 | -------------------------------------------------------------------------------- /repository/logOrder.repository.js: -------------------------------------------------------------------------------- 1 | // Set up mongoose connection 2 | const Log = require('../models/log'); 3 | 4 | exports.new = async(body) => { 5 | let log = new Log.orderLog( 6 | { 7 | log: body 8 | } 9 | ); 10 | 11 | log.save(function(err) { 12 | if (err) { 13 | console.log("error"); 14 | throw err; 15 | } 16 | }); 17 | return log; 18 | }; 19 | 20 | 21 | -------------------------------------------------------------------------------- /repository/logTransport.repository.js: -------------------------------------------------------------------------------- 1 | // Set up mongoose connection 2 | const Log = require('../models/log'); 3 | 4 | exports.new = async(body) => { 5 | let log = new Log.transportLog( 6 | { 7 | log: body 8 | } 9 | ); 10 | 11 | log.save(function(err) { 12 | if (err) { 13 | console.log("error"); 14 | throw err; 15 | } 16 | }); 17 | return log; 18 | }; 19 | 20 | 21 | -------------------------------------------------------------------------------- /repository/order.repository.js: -------------------------------------------------------------------------------- 1 | // Set up mongoose connection 2 | const Order = require('../models/order'); 3 | 4 | exports.new = async(body) => { 5 | let order = new Order( 6 | { 7 | body 8 | } 9 | ); 10 | 11 | order.save(function(err, newOrder) { 12 | order._id = newOrder._id; 13 | if (err) { 14 | console.log("error"); 15 | throw err; 16 | } 17 | }); 18 | return order; 19 | }; 20 | 21 | exports.getAll = async() => { 22 | return Order.find({}); 23 | }; 24 | 25 | exports.delete = async(id) => { 26 | 27 | const order = await Order.findById(id).exec(); 28 | order.status = "deleted"; 29 | 30 | await Order.findByIdAndUpdate(id, {$set: order}, { useFindAndModify: false }).exec(); 31 | 32 | let updatedOrder = await Order.findById(id).exec(); 33 | return updatedOrder; 34 | }; 35 | 36 | exports.update = async(id, body) => { 37 | 38 | body.status = "updated"; 39 | 40 | await Order.findByIdAndUpdate(id, {$set: body}, { useFindAndModify: false }).exec(); 41 | 42 | let updatedOrder = await Order.findById(id).exec(); 43 | return updatedOrder; 44 | }; 45 | 46 | exports.confirm = async(id, body) => { 47 | 48 | body.status = "confirmed"; 49 | 50 | await Order.findByIdAndUpdate(id, {$set: body}, { useFindAndModify: false }).exec(); 51 | 52 | let updatedOrder = await Order.findById(id).exec(); 53 | return updatedOrder; 54 | }; 55 | 56 | 57 | exports.delivering = async(id, body) => { 58 | 59 | body.status = "delivering"; 60 | 61 | await Order.findByIdAndUpdate(id, {$set: body}, { useFindAndModify: false }).exec(); 62 | 63 | let updatedOrder = await Order.findById(id).exec(); 64 | return updatedOrder; 65 | }; 66 | 67 | exports.delivered = async(id, body) => { 68 | 69 | body.status = "delivered"; 70 | 71 | await Order.findByIdAndUpdate(id, {$set: body}, { useFindAndModify: false }).exec(); 72 | 73 | let updatedOrder = await Order.findById(id).exec(); 74 | return updatedOrder; 75 | }; 76 | 77 | 78 | exports.get = async(id,) => { 79 | const order = await Order.findById(id).exec(); 80 | return order; 81 | }; 82 | -------------------------------------------------------------------------------- /routes/api/client.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const clientController = require('../../controllers/client.controller') 4 | 5 | router.post('/new', clientController.new); 6 | router.delete('/:id', clientController.cancel); 7 | router.put('/:id', clientController.update); 8 | router.get('/', clientController.getAll); 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /routes/api/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | router.use('/client', require('./client')); 5 | router.use('/order', require('./order')); 6 | router.use('/transport', require('./transport')); 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /routes/api/order.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const orderController = require('../../controllers/order.controller'); 4 | 5 | router.post('/:id/confirm', orderController.confirm); 6 | 7 | module.exports = router; 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /routes/api/transport.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const transportController = require('../../controllers/transport.controller'); 4 | 5 | router.post('/:id/delivering', transportController.delivering); 6 | router.post('/:id/delivered', transportController.delivered); 7 | 8 | module.exports = router; 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | router.use('/api', require('./api')); 5 | 6 | router.get('/', function(req, res, next) { 7 | res.render('index', { title: 'NodeJS Microservices' }); 8 | }); 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /services/clientCRS.service.js: -------------------------------------------------------------------------------- 1 | const rabbitSender = require('../rabbit/sender'); 2 | const EXCHANGE_NAME = "Client"; 3 | const orderRepository = require('../repository/order.repository'); 4 | const logRepository = require('../repository/logClient.repository'); 5 | 6 | exports.new = async (body, res) => { 7 | const order = await orderRepository.new(body); 8 | 9 | const newLog = await logRepository.newCRS(`Order created :${order._id}.`); 10 | 11 | rabbitSender.send(EXCHANGE_NAME, newLog.log); 12 | 13 | res.status(201).send(newLog.log); 14 | }; 15 | 16 | exports.cancel = async (id, res) => { 17 | const order = await orderRepository.get(id); 18 | if(order.status == "updated" || order.status == "created") { 19 | const newLog = await logRepository.newCRS(`Order deleted :${id}.`); 20 | 21 | await orderRepository.delete(id); 22 | 23 | rabbitSender.send(EXCHANGE_NAME, newLog.log ); 24 | res.status(202).send(newLog.log); 25 | } else { 26 | res.status(400).send(`Cant cancel an order when its ${order.status}`); 27 | } 28 | }; 29 | 30 | exports.update = async (id, body, res) => { 31 | const order = await orderRepository.get(id); 32 | if(order.status == "updated" || order.status == "created") { 33 | const newLog = await logRepository.newCRS(`Order updated :${id}.`); 34 | 35 | await orderRepository.update(id, body); 36 | 37 | rabbitSender.send(EXCHANGE_NAME, newLog.log ); 38 | res.status(202).send(newLog.log); 39 | } else { 40 | res.status(400).send(`Cant update an order when its ${order.status}`); 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /services/clientQRS.service.js: -------------------------------------------------------------------------------- 1 | const orderRepository = require('../repository/order.repository'); 2 | const logRepository = require('../repository/logClient.repository'); 3 | 4 | exports.getAll = async (res) => { 5 | await logRepository.newQRS("Orders returned."); 6 | const all = await orderRepository.getAll(); 7 | res.status(202).send(all); 8 | }; 9 | 10 | -------------------------------------------------------------------------------- /services/order.service.js: -------------------------------------------------------------------------------- 1 | const rabbitSender = require('../rabbit/sender'); 2 | const EXCHANGE_NAME = "Order"; 3 | const orderRepository = require('../repository/order.repository'); 4 | const logRepository = require('../repository/logOrder.repository'); 5 | 6 | exports.confirm = async (id, body, res) => { 7 | const order = await orderRepository.get(id); 8 | if(order.status == "updated" || order.status == "created") { 9 | const newLog = await logRepository.new(`Order confirmed :${id}.`); 10 | 11 | await orderRepository.confirm(id, body) 12 | 13 | rabbitSender.send(EXCHANGE_NAME, newLog.log ); 14 | res.status(202).send(newLog.log); 15 | } else { 16 | res.status(400).send(`Cant confirm an order when its ${order.status}`); 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /services/transport.service.js: -------------------------------------------------------------------------------- 1 | const rabbitSender = require('../rabbit/sender'); 2 | const EXCHANGE_NAME = "Transport"; 3 | const orderRepository = require('../repository/order.repository'); 4 | const logRepository = require('../repository/logTransport.repository'); 5 | 6 | exports.deliver = async (id, body, res) => { 7 | const order = await orderRepository.get(id); 8 | if(order.status == "cooked" ) { 9 | const newLog = await logRepository.new(`Order delivering :${id}.`); 10 | 11 | await orderRepository.delivering(id, body) 12 | 13 | rabbitSender.send(EXCHANGE_NAME, newLog.log); 14 | res.status(202).send(newLog.log); 15 | } else { 16 | res.status(400).send(`Cant begin delivery an order when its ${order.status}`); 17 | } 18 | }; 19 | 20 | exports.delivered = async (id, body, res) => { 21 | const order = await orderRepository.get(id); 22 | if(order.status == "delivering" ) { 23 | const newLog = await logRepository.new(`Order delivered :${id}.`); 24 | 25 | await orderRepository.delivered(id, body) 26 | 27 | rabbitSender.send(EXCHANGE_NAME, newLog.log); 28 | res.status(202).send(newLog.log); 29 | } else { 30 | res.status(400).send(`Cant deliver an order when its ${order.status}`); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /views/error.pug: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= message 5 | h2= error.status 6 | pre #{error.stack} 7 | -------------------------------------------------------------------------------- /views/index.pug: -------------------------------------------------------------------------------- 1 | extends layout 2 | 3 | block content 4 | h1= title 5 | p Welcome to #{title} 6 | p These microservices communicate thought RabbiqMQ . 7 | p Source code: 8 | a(href='https://github.com/carlasampaio01/nodejs-microservices') GitHub 9 | -------------------------------------------------------------------------------- /views/layout.pug: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title= title 5 | link(rel='stylesheet', href='/stylesheets/style.css') 6 | body 7 | block content 8 | -------------------------------------------------------------------------------- /wait-for-it.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Use this script to test if a given TCP host/port are available 3 | 4 | WAITFORIT_cmdname=${0##*/} 5 | 6 | echoerr() { if [[ $WAITFORIT_QUIET -ne 1 ]]; then echo "$@" 1>&2; fi } 7 | 8 | usage() 9 | { 10 | cat << USAGE >&2 11 | Usage: 12 | $WAITFORIT_cmdname host:port [-s] [-t timeout] [-- command args] 13 | -h HOST | --host=HOST Host or IP under test 14 | -p PORT | --port=PORT TCP port under test 15 | Alternatively, you specify the host and port as host:port 16 | -s | --strict Only execute subcommand if the test succeeds 17 | -q | --quiet Don't output any status messages 18 | -t TIMEOUT | --timeout=TIMEOUT 19 | Timeout in seconds, zero for no timeout 20 | -- COMMAND ARGS Execute command with args after the test finishes 21 | USAGE 22 | exit 1 23 | } 24 | 25 | wait_for() 26 | { 27 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 28 | echoerr "$WAITFORIT_cmdname: waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 29 | else 30 | echoerr "$WAITFORIT_cmdname: waiting for $WAITFORIT_HOST:$WAITFORIT_PORT without a timeout" 31 | fi 32 | WAITFORIT_start_ts=$(date +%s) 33 | while : 34 | do 35 | if [[ $WAITFORIT_ISBUSY -eq 1 ]]; then 36 | nc -z $WAITFORIT_HOST $WAITFORIT_PORT 37 | WAITFORIT_result=$? 38 | else 39 | (echo > /dev/tcp/$WAITFORIT_HOST/$WAITFORIT_PORT) >/dev/null 2>&1 40 | WAITFORIT_result=$? 41 | fi 42 | if [[ $WAITFORIT_result -eq 0 ]]; then 43 | WAITFORIT_end_ts=$(date +%s) 44 | echoerr "$WAITFORIT_cmdname: $WAITFORIT_HOST:$WAITFORIT_PORT is available after $((WAITFORIT_end_ts - WAITFORIT_start_ts)) seconds" 45 | break 46 | fi 47 | sleep 1 48 | done 49 | return $WAITFORIT_result 50 | } 51 | 52 | wait_for_wrapper() 53 | { 54 | # In order to support SIGINT during timeout: http://unix.stackexchange.com/a/57692 55 | if [[ $WAITFORIT_QUIET -eq 1 ]]; then 56 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --quiet --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 57 | else 58 | timeout $WAITFORIT_BUSYTIMEFLAG $WAITFORIT_TIMEOUT $0 --child --host=$WAITFORIT_HOST --port=$WAITFORIT_PORT --timeout=$WAITFORIT_TIMEOUT & 59 | fi 60 | WAITFORIT_PID=$! 61 | trap "kill -INT -$WAITFORIT_PID" INT 62 | wait $WAITFORIT_PID 63 | WAITFORIT_RESULT=$? 64 | if [[ $WAITFORIT_RESULT -ne 0 ]]; then 65 | echoerr "$WAITFORIT_cmdname: timeout occurred after waiting $WAITFORIT_TIMEOUT seconds for $WAITFORIT_HOST:$WAITFORIT_PORT" 66 | fi 67 | return $WAITFORIT_RESULT 68 | } 69 | 70 | # process arguments 71 | while [[ $# -gt 0 ]] 72 | do 73 | case "$1" in 74 | *:* ) 75 | WAITFORIT_hostport=(${1//:/ }) 76 | WAITFORIT_HOST=${WAITFORIT_hostport[0]} 77 | WAITFORIT_PORT=${WAITFORIT_hostport[1]} 78 | shift 1 79 | ;; 80 | --child) 81 | WAITFORIT_CHILD=1 82 | shift 1 83 | ;; 84 | -q | --quiet) 85 | WAITFORIT_QUIET=1 86 | shift 1 87 | ;; 88 | -s | --strict) 89 | WAITFORIT_STRICT=1 90 | shift 1 91 | ;; 92 | -h) 93 | WAITFORIT_HOST="$2" 94 | if [[ $WAITFORIT_HOST == "" ]]; then break; fi 95 | shift 2 96 | ;; 97 | --host=*) 98 | WAITFORIT_HOST="${1#*=}" 99 | shift 1 100 | ;; 101 | -p) 102 | WAITFORIT_PORT="$2" 103 | if [[ $WAITFORIT_PORT == "" ]]; then break; fi 104 | shift 2 105 | ;; 106 | --port=*) 107 | WAITFORIT_PORT="${1#*=}" 108 | shift 1 109 | ;; 110 | -t) 111 | WAITFORIT_TIMEOUT="$2" 112 | if [[ $WAITFORIT_TIMEOUT == "" ]]; then break; fi 113 | shift 2 114 | ;; 115 | --timeout=*) 116 | WAITFORIT_TIMEOUT="${1#*=}" 117 | shift 1 118 | ;; 119 | --) 120 | shift 121 | WAITFORIT_CLI=("$@") 122 | break 123 | ;; 124 | --help) 125 | usage 126 | ;; 127 | *) 128 | echoerr "Unknown argument: $1" 129 | usage 130 | ;; 131 | esac 132 | done 133 | 134 | if [[ "$WAITFORIT_HOST" == "" || "$WAITFORIT_PORT" == "" ]]; then 135 | echoerr "Error: you need to provide a host and port to test." 136 | usage 137 | fi 138 | 139 | WAITFORIT_TIMEOUT=${WAITFORIT_TIMEOUT:-15} 140 | WAITFORIT_STRICT=${WAITFORIT_STRICT:-0} 141 | WAITFORIT_CHILD=${WAITFORIT_CHILD:-0} 142 | WAITFORIT_QUIET=${WAITFORIT_QUIET:-0} 143 | 144 | # check to see if timeout is from busybox? 145 | WAITFORIT_TIMEOUT_PATH=$(type -p timeout) 146 | WAITFORIT_TIMEOUT_PATH=$(realpath $WAITFORIT_TIMEOUT_PATH 2>/dev/null || readlink -f $WAITFORIT_TIMEOUT_PATH) 147 | if [[ $WAITFORIT_TIMEOUT_PATH =~ "busybox" ]]; then 148 | WAITFORIT_ISBUSY=1 149 | WAITFORIT_BUSYTIMEFLAG="-t" 150 | 151 | else 152 | WAITFORIT_ISBUSY=0 153 | WAITFORIT_BUSYTIMEFLAG="" 154 | fi 155 | 156 | if [[ $WAITFORIT_CHILD -gt 0 ]]; then 157 | wait_for 158 | WAITFORIT_RESULT=$? 159 | exit $WAITFORIT_RESULT 160 | else 161 | if [[ $WAITFORIT_TIMEOUT -gt 0 ]]; then 162 | wait_for_wrapper 163 | WAITFORIT_RESULT=$? 164 | else 165 | wait_for 166 | WAITFORIT_RESULT=$? 167 | fi 168 | fi 169 | 170 | if [[ $WAITFORIT_CLI != "" ]]; then 171 | if [[ $WAITFORIT_RESULT -ne 0 && $WAITFORIT_STRICT -eq 1 ]]; then 172 | echoerr "$WAITFORIT_cmdname: strict mode, refusing to execute subprocess" 173 | exit $WAITFORIT_RESULT 174 | fi 175 | exec "${WAITFORIT_CLI[@]}" 176 | else 177 | exit $WAITFORIT_RESULT 178 | fi 179 | --------------------------------------------------------------------------------