From 23539b9eaf1efe10efd722b45a3880364d3d7260 Mon Sep 17 00:00:00 2001 From: Joshua Shoemaker Date: Wed, 12 Aug 2020 22:00:07 -0500 Subject: [PATCH] feat: added node server --- package-lock.json | 73 +++++++++++++++++++++++++++++++++++++++++------ package.json | 6 ++++ server/Server.js | 61 +++++++++++++++++++++++++++++++++++++++ server/index.js | 29 +++++++++++++++++++ 4 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 server/Server.js create mode 100644 server/index.js diff --git a/package-lock.json b/package-lock.json index 3ade89e..1055f25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3269,6 +3269,23 @@ "ms": "2.0.0" } }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -4080,6 +4097,15 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" }, + "cookie-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6" + } + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -6775,21 +6801,21 @@ "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=" }, "http-errors": { - "version": "1.7.2", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", - "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz", + "integrity": "sha512-4I8r0C5JDhT5VkvI47QktDW75rNlGVsUf/8hzjCC/wkWI/jdTRmBb9aI7erSG82r1bjKY3F6k28WnsVxB1C73A==", "requires": { "depd": "~1.1.2", - "inherits": "2.0.3", - "setprototypeof": "1.1.1", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", "statuses": ">= 1.5.0 < 2", "toidentifier": "1.0.0" }, "dependencies": { - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" } } }, @@ -10786,6 +10812,23 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" } } }, @@ -11776,6 +11819,18 @@ } } }, + "http-errors": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.3.tgz", + "integrity": "sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.4", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, "mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", diff --git a/package.json b/package.json index 285bd11..4d63a4f 100644 --- a/package.json +++ b/package.json @@ -2,12 +2,17 @@ "name": "lovelace.technology", "version": "0.1.0", "private": true, + "type": "module", "dependencies": { "@testing-library/jest-dom": "^4.2.4", "@testing-library/react": "^9.5.0", "@testing-library/user-event": "^7.2.1", + "body-parser": "^1.19.0", "chart.js": "^2.9.3", + "cookie-parser": "^1.4.5", "downloadjs": "^1.4.7", + "express": "^4.17.1", + "http-errors": "^1.8.0", "js2excel": "^1.0.1", "lovelacejs": "^0.2.1", "react": "^16.13.1", @@ -21,6 +26,7 @@ "scripts": { "start": "react-scripts start", "build": "react-scripts build", + "server": "node ./server/index", "test": "react-scripts test", "eject": "react-scripts eject" }, diff --git a/server/Server.js b/server/Server.js new file mode 100644 index 0000000..564b8bc --- /dev/null +++ b/server/Server.js @@ -0,0 +1,61 @@ +import express from 'express' +import createError from 'http-errors' +import path from 'path' +import bodyParser from 'body-parser' +import cookieParser from 'cookie-parser' + +let instance = null + +class Server { + constructor () { + if (!instance) { instance = this } + + this.createApp() + this.setupAppOptions() + this.setupAppRoutes() + this.setupAppErrors() + return instance + } + + createApp = () => { + this.app = express() + this.app.use(express.json()) + this.app.use(express.urlencoded({ extended: false })) + this.app.use(cookieParser()) + this.app.use(express.static('./build')) + this.app.use(bodyParser.json()) + + } + + setupAppErrors = () => { + this.app.use((request, response, next) => { + next(createError(404)) + }) + + this.app.use((error, request, response, next) => { + response.locals.message = error.message + response.locals.error = request.app.get('env') === 'development' ? error : {} + + response.status(error.status || 500) + response.send('error') + }) + } + + setupAppRoutes = () => { + const __dirname = path.resolve() + this.app.get('*', (request, response, next) => { + response.sendFile(path.join(__dirname, '/build/index.html')) + }) + } + + setupAppOptions = () => { + this.app.use((request, response, next) => { + response.header('Access-Control-Allow-Origin', request.headers.origin || '*') + response.header('Access-Control-Allow-Methods', 'GET,POST,PUT,PATCH,HEAD,DELETE,OPTIONS') + response.header('Access-Control-Allow-Headers', 'Content-Type,x-requested-with') + next() + }) + } +} + +export default Server \ No newline at end of file diff --git a/server/index.js b/server/index.js new file mode 100644 index 0000000..322d3e0 --- /dev/null +++ b/server/index.js @@ -0,0 +1,29 @@ +import http from 'http' +import Server from './Server.js' + +const main = () => { + + const port = normalizePort(process.env.PORT || '5003') + const webService = createServer() + + webService.listen(port, () => { + console.log(`Server is listening on ${port}`) + }) +} + +const createServer = () => { + const server = new Server() + return http.createServer(server.app) +} + +const normalizePort = portString => { + const port = parseInt(portString, 10) + + if (isNaN(port)) return portString + else if (port >= 0 ) return port + else return 0 +} + +main() + +export { main, createServer, normalizePort } \ No newline at end of file