├── .eslintignore ├── server ├── routes │ ├── hello.js │ └── index.js ├── core │ ├── logger.js │ ├── sequelize.js │ └── express.js ├── config │ ├── config.json │ └── index.js ├── models │ └── index.js └── index.js ├── client ├── App.vue ├── index.js ├── routes.js ├── index.html └── views │ └── HelloWorld.vue ├── .eslintrc.js ├── .babelrc ├── config ├── prod.json └── staging.json ├── utils └── clean.js ├── webpack.config.dev.js ├── .gitignore ├── webpack.config.prod.js ├── README.md ├── webpack.config.js └── package.json /.eslintignore: -------------------------------------------------------------------------------- 1 | dist/*.js 2 | dist/**/*.js -------------------------------------------------------------------------------- /server/routes/hello.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = function (router) { 3 | router.route('/hello') 4 | .get((req, res) => { 5 | res.json('Hello World!') 6 | }) 7 | } 8 | -------------------------------------------------------------------------------- /client/App.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parserOptions: { 3 | parser: 'babel-eslint' 4 | }, 5 | extends: [ 6 | 'plugin:vue/recommended', 7 | 'standard' 8 | ], 9 | plugins: [ 10 | 'vue' 11 | ] 12 | } -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "targets": { 7 | "browsers": [ 8 | "last 2 Chrome versions", "IE 11" 9 | ] 10 | } 11 | } 12 | ] 13 | ] 14 | } -------------------------------------------------------------------------------- /config/prod.json: -------------------------------------------------------------------------------- 1 | { 2 | "apps": [ 3 | { 4 | "name": "hello-world-prod", 5 | "script": "server/index.js", 6 | "env": { 7 | "NODE_ENV": "production", 8 | "PORT": "8080" 9 | } 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /config/staging.json: -------------------------------------------------------------------------------- 1 | { 2 | "apps": [ 3 | { 4 | "name": "hello-world-staging", 5 | "script": "server/index.js", 6 | "env": { 7 | "NODE_ENV": "staging", 8 | "PORT": "8080" 9 | } 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /client/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | import router from './routes' 4 | 5 | import App from './App.vue' 6 | 7 | import 'isomorphic-fetch' 8 | 9 | new Vue({ 10 | router, 11 | render: createEle => createEle(App) 12 | }).$mount('#app') 13 | -------------------------------------------------------------------------------- /server/core/logger.js: -------------------------------------------------------------------------------- 1 | const winston = require('winston') 2 | 3 | winston.level = 'debug' 4 | const logger = new (winston.Logger)({ 5 | transports: [ 6 | // colorize the output to the console 7 | new (winston.transports.Console)({ 8 | colorize: true, 9 | prettyPrint: true 10 | }) 11 | ] 12 | }) 13 | 14 | module.exports = logger 15 | -------------------------------------------------------------------------------- /client/routes.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import VueRouter from 'vue-router' 3 | 4 | import HelloWorld from './views/HelloWorld.vue' 5 | 6 | Vue.use(VueRouter) 7 | 8 | const siteRoutes = [{ 9 | path: '/', 10 | component: HelloWorld 11 | }] 12 | 13 | const vueRouter = new VueRouter({ 14 | mode: 'history', 15 | routes: siteRoutes 16 | }) 17 | 18 | export default vueRouter 19 | -------------------------------------------------------------------------------- /client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Hello World 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /server/config/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "test": { 3 | "PORT": 3000, 4 | "DATABASE_URI": "postgres://user:password@localhost:5432/testing" 5 | }, 6 | "development": { 7 | "PORT": 3000, 8 | "DATABASE_URI": "postgres://user:password@localhost:5432/development" 9 | }, 10 | "production": { 11 | "PORT": 8080, 12 | "DATABASE_URI": "postgres://user:password@localhost:5432/portfolio" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /server/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const path = require('path') 3 | const fs = require('fs') 4 | 5 | const basename = path.basename(module.filename) 6 | const router = express.Router() 7 | 8 | fs.readdirSync(__dirname) 9 | .filter(file => (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')) 10 | .forEach((file) => { 11 | require(`./${file}`)(router) 12 | }) 13 | 14 | module.exports = router 15 | -------------------------------------------------------------------------------- /server/core/sequelize.js: -------------------------------------------------------------------------------- 1 | const logger = require('./logger') 2 | 3 | const config = require('../config') 4 | 5 | const Sequelize = require('sequelize') 6 | 7 | const sequelize = new Sequelize(config.DATABASE_URI) 8 | 9 | sequelize 10 | .authenticate() 11 | .then(() => { 12 | logger.info('Successfully established connection to database') 13 | }) 14 | .catch((err) => { 15 | logger.error('Unable to connect to database', err) 16 | }) 17 | 18 | module.exports = sequelize 19 | -------------------------------------------------------------------------------- /client/views/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 21 | 22 | 28 | -------------------------------------------------------------------------------- /utils/clean.js: -------------------------------------------------------------------------------- 1 | const logger = require('../server/core/logger') 2 | const dayjs = require('dayjs') 3 | const chalk = require('chalk') 4 | 5 | logger.info() 6 | logger.info(chalk.bold('---------------------[ Cleaning DB at %s ]---------------------------'), dayjs() 7 | .format('YYYY-MM-DD HH:mm:ss.SSS')) 8 | 9 | const models = require('../server/models') 10 | 11 | // sync models 12 | models.sequelize.sync({ force: false }) 13 | .then(() => { 14 | logger.info(chalk.bold('---------------------[ Cleaned DB at %s ]---------------------------'), dayjs() 15 | .format('YYYY-MM-DD HH:mm:ss.SSS')) 16 | process.exit() 17 | }) 18 | -------------------------------------------------------------------------------- /server/models/index.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const sequelize = require('../core/sequelize') 4 | 5 | const db = {} 6 | 7 | const basename = path.basename(module.filename) 8 | 9 | // Filter non "." starting files and index.js locally 10 | fs.readdirSync(__dirname) 11 | .filter(file => (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js')) 12 | .forEach((file) => { 13 | const model = sequelize.import(path.join(__dirname, file)) 14 | db[model.name] = model 15 | }) 16 | 17 | Object.keys(db) 18 | .forEach((modelName) => { 19 | if ('associate' in db[modelName]) { 20 | db[modelName].associate(db) 21 | } 22 | }) 23 | 24 | db.sequelize = sequelize 25 | 26 | module.exports = db 27 | -------------------------------------------------------------------------------- /webpack.config.dev.js: -------------------------------------------------------------------------------- 1 | const config = {} 2 | 3 | const webpack = require('webpack') 4 | 5 | config.mode = "development" 6 | 7 | config.devServer = { 8 | hot: true 9 | } 10 | 11 | config.entry = ['eventsource-polyfill', 'babel-polyfill', 'webpack-hot-middleware/client?name=frontPage', './client/index.js'] 12 | 13 | config.plugins = [ 14 | new webpack.HotModuleReplacementPlugin() 15 | ] 16 | 17 | config.module = { 18 | rules: [ 19 | { 20 | test: /\.css$/, 21 | use: [ 22 | 'vue-style-loader', 23 | 'css-loader' 24 | ] 25 | }, 26 | { 27 | test: /\.scss$/, 28 | use: [{ 29 | loader: "style-loader" 30 | }, { 31 | loader: "css-loader" 32 | }, { 33 | loader: "sass-loader" 34 | }] 35 | } 36 | ] 37 | } 38 | 39 | module.exports = config 40 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | const config = require('./config') 2 | const logger = require('./core/logger') 3 | const dayjs = require('dayjs') 4 | const chalk = require('chalk') 5 | 6 | logger.info() 7 | logger.info(chalk.bold('---------------------[ Server starting at %s ]---------------------------'), dayjs() 8 | .format('YYYY-MM-DD HH:mm:ss.SSS')) 9 | 10 | const models = require('./models') 11 | const app = require('./core/express') 12 | 13 | const startServer = () => { 14 | // Start init 15 | app.listen(config.PORT, () => { 16 | logger.info(`Server running at port: ${chalk.green(config.PORT)}`) 17 | }) 18 | } 19 | 20 | // sync models 21 | if (!config.isTestMode() && config.resyncEnabled() === true) { 22 | models.sequelize.sync({ force: true }) 23 | .then(startServer) 24 | } else { 25 | startServer() 26 | } 27 | 28 | module.exports = app 29 | -------------------------------------------------------------------------------- /server/config/index.js: -------------------------------------------------------------------------------- 1 | const _ = require('lodash') 2 | 3 | const config = require('./config.json') 4 | 5 | const webpackConfig = require('../../webpack.config') 6 | 7 | const curConfig = { 8 | isDevMode () { 9 | return !process.env.NODE_ENV || process.env.NODE_ENV === 'development' 10 | }, 11 | isStagingMode () { 12 | return process.env.NODE_ENV === 'staging' 13 | }, 14 | isProdMode () { 15 | return process.env.NODE_ENV === 'production' 16 | }, 17 | isTestMode () { 18 | return process.env.NODE_ENV === 'test' 19 | }, 20 | resyncEnabled () { 21 | return false 22 | }, 23 | webpackConfig 24 | } 25 | 26 | let resConfig = {} 27 | 28 | if (process.env.NODE_ENV) { 29 | resConfig = config[process.env.NODE_ENV] 30 | } else { 31 | resConfig = config.development 32 | } 33 | 34 | const configs = _.merge(resConfig, curConfig) 35 | 36 | // Additional Configs 37 | configs.imageDir = `${configs.PUBLIC_DIR}/images` 38 | 39 | module.exports = configs 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### NodeJS Gitignore 2 | 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 (http://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 | # output of builds 63 | /dist 64 | -------------------------------------------------------------------------------- /server/core/express.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const helmet = require('helmet') 3 | const helmetCsp = require('helmet-csp') 4 | const webpack = require('webpack') 5 | const bodyParser = require('body-parser') 6 | 7 | const config = require('../config') 8 | 9 | const app = express() 10 | 11 | // Projection 12 | app.use(helmet.xssFilter()) 13 | app.use(helmet.frameguard()) 14 | app.use(helmet.hidePoweredBy()) 15 | 16 | // Defaults 17 | app.use(bodyParser.urlencoded({ 18 | extended: false 19 | })) 20 | app.use(bodyParser.json()) 21 | 22 | // public folder 23 | app.use('/public', express.static('static')) 24 | 25 | // API 26 | const router = require('../routes') 27 | 28 | app.use('/api', router) 29 | 30 | app.use(require('connect-history-api-fallback')({ 31 | index: '/index.html', 32 | rewrites: [ 33 | ], 34 | verbose: false 35 | })) 36 | 37 | // Hot middleware 38 | if (config.isDevMode()) { 39 | const compiler = webpack(config.webpackConfig) 40 | 41 | app.use(require('webpack-dev-middleware')(compiler, { 42 | stats: { 43 | colors: true 44 | } 45 | })) 46 | app.use(require('webpack-hot-middleware')(compiler)) 47 | } else { 48 | app.use(helmetCsp({ 49 | directives: { 50 | defaultSrc: ["'self'"], 51 | scriptSrc: ["'self'"], 52 | styleSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"] 53 | } 54 | })) 55 | app.use(express.static('dist')) 56 | } 57 | 58 | module.exports = app 59 | -------------------------------------------------------------------------------- /webpack.config.prod.js: -------------------------------------------------------------------------------- 1 | const config = {} 2 | 3 | const CssNano = require('cssnano') 4 | const webpack = require('webpack') 5 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 6 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin') 7 | 8 | config.mode = "production" 9 | 10 | config.entry = ['babel-polyfill', './client/index.js'] 11 | 12 | config.optimization = { 13 | minimizer: [ 14 | new UglifyJsPlugin({ 15 | cache: true, 16 | parallel: true, 17 | uglifyOptions: { 18 | compress: false, 19 | ecma: 6, 20 | mangle: true 21 | }, 22 | sourceMap: false 23 | }) 24 | ] 25 | } 26 | config.plugins = [ 27 | new webpack.optimize.AggressiveMergingPlugin(), 28 | new webpack.optimize.OccurrenceOrderPlugin(), 29 | new webpack.optimize.ModuleConcatenationPlugin(), 30 | new webpack.DefinePlugin({ 31 | 'process.env': { 32 | NODE_ENV: '"production"' 33 | } 34 | }), 35 | new MiniCssExtractPlugin({ 36 | filename: 'main.css' 37 | }) 38 | ] 39 | 40 | config.module = { 41 | rules: [ 42 | { 43 | test: /\.(css|sass|scss)$/, 44 | use: [ 45 | MiniCssExtractPlugin.loader, 46 | { 47 | loader: 'css-loader', 48 | options: { 49 | importLoaders: 2, 50 | sourceMap: false 51 | } 52 | }, 53 | { 54 | loader: 'postcss-loader', 55 | options: { 56 | plugins: () => [ 57 | require('autoprefixer') 58 | ], 59 | sourceMap: false 60 | } 61 | }, 62 | { 63 | loader: 'sass-loader', 64 | options: { 65 | sourceMap: false 66 | } 67 | } 68 | ] 69 | } 70 | ] 71 | } 72 | 73 | 74 | module.exports = config 75 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nodejs - Vue - Postgresql Sample Project 2 | This is an example project featuring the use of nodejs, vuejs and postgresql in the same project 3 | 4 | ## Requirements 5 | 1. Nodejs/npm/pm2 6 | 2. Postgresql 7 | 8 | If you are running on any ubuntu variants, you can run this to get things started quickly 9 | ```bash 10 | echo "Installing Nodejs" 11 | sudo apt-get install nodejs -y 12 | sudo ln -s "$(which nodejs)" /usr/bin/node 13 | sudo apt-get install npm -y 14 | 15 | echo "Upgrade nodejs" 16 | sudo npm install n -g 17 | sudo n stable 18 | 19 | echo "Installing Postgres" 20 | sudo apt-get install postgresql postgresql-contrib 21 | ``` 22 | 23 | For windows, install following executables 24 | 25 | [Installing nodejs on windows](blog.teamtreehouse.com/install-node-js-npm-windows) 26 | 27 | [Installing postgresql on windows](https://www.labkey.org/Documentation/wiki-page.view?name=installPostgreSQLWindows) 28 | 29 | For macos, get brew and execute following commands 30 | ```shell 31 | brew install node 32 | brew install postgresql 33 | ``` 34 | 35 | Then upgrade nodejs and install the dependencies 36 | ```powershell 37 | npm install n -g 38 | n stable 39 | npm install -g pm2 40 | ``` 41 | 42 | ## Setting up 43 | Before running the code, we need to setup postgresql and append the postgresql details in server/config/config.json 44 | 45 | Open up the psql console and run the following command 46 | ```psql 47 | CREATE USER user WITH PASSWORD 'secret'; 48 | CREATE DATABASE development; 49 | GRANT ALL PRIVILEGES ON DATABASE development TO user; 50 | ``` 51 | 52 | then modify the config.json DATABASE_URI params with the following (assuming using development environment) 53 | ```json 54 | "development": { 55 | "PORT": 3000, 56 | "DATABASE_URI": "postgres://user:secret@localhost:5432/development" 57 | }, 58 | ``` 59 | 60 | ## Usage 61 | Simply run following commands on the root folder to start 62 | 63 | ```bash 64 | npm install 65 | npm start 66 | ``` 67 | 68 | # Changelog 69 | 70 | ## Breaking Change 71 | - Added support for Webpack4, ESLint and Babel 7 72 | - Cleaned code and structure 73 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const HtmlWebpackPlugin = require('html-webpack-plugin') 3 | const { VueLoaderPlugin } = require('vue-loader') 4 | 5 | const merge = require('webpack-merge') 6 | 7 | /** 8 | * Environment type 9 | */ 10 | const DEV = process.env.NODE_ENV === 'development' 11 | const PROD = process.env.NODE_ENV === 'production' 12 | const STAGING = process.env.NODE_ENV === 'staging' 13 | 14 | let config = { 15 | name: 'frontPage' 16 | } 17 | 18 | config.output = { 19 | path: path.resolve(__dirname, './dist'), 20 | filename: 'build.js', 21 | publicPath: '/' 22 | } 23 | 24 | config.resolve = { 25 | alias: { 26 | vue: 'vue/dist/vue.common.js', 27 | styles: path.resolve(__dirname, './client/assets/stylesheet'), 28 | components: path.resolve(__dirname, './client/components') 29 | } 30 | } 31 | 32 | config.module = { 33 | rules: [ 34 | /** 35 | * Linting 36 | */ 37 | { 38 | test: /\.(js|vue)$/, 39 | use: 'eslint-loader', 40 | enforce: 'pre' 41 | }, 42 | /** 43 | * Compile 44 | */ 45 | { 46 | test: /\.js$/, 47 | exclude: /node_modules/, 48 | use: { 49 | loader: 'babel-loader', 50 | } 51 | }, 52 | { 53 | test: /\.vue$/, 54 | use: 'vue-loader' 55 | }, 56 | { 57 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 58 | use: [{ 59 | loader: 'url-loader', 60 | options: { 61 | limit: 10000 62 | } 63 | }] 64 | }, 65 | { 66 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 67 | use: [{ 68 | loader: 'url-loader', 69 | options: { 70 | limit: 10000 71 | } 72 | }] 73 | } 74 | ] 75 | } 76 | 77 | config.plugins = [ 78 | new HtmlWebpackPlugin({ 79 | filename: path.join(__dirname, 'dist/index.html'), 80 | template: path.join(__dirname, 'client/index.html'), 81 | inject: true 82 | }), 83 | new VueLoaderPlugin() 84 | ] 85 | 86 | if (DEV) { 87 | config = merge(config, require('./webpack.config.dev.js')) 88 | } else if (PROD || STAGING) { 89 | config = merge(config, require('./webpack.config.prod.js')) 90 | } 91 | module.exports = [config] 92 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "helloworld", 3 | "description": "hello world page", 4 | "version": "0.1.0", 5 | "author": "helloworld@example.com", 6 | "scripts": { 7 | "test": "nyc mocha --timeout=3000", 8 | "lint": "eslint --ext .js,.vue . client/** server/**", 9 | "lint:fix": "eslint --ext .js,.vue --fix . client/** server/**", 10 | "start": "npm run start:dev", 11 | "start:dev": "cross-env NODE_ENV=development nodemon server/index.js --ignore client/ --ignore admin/", 12 | "start:staging": "npm run build:prod && npm run node:staging", 13 | "start:prod": "npm run build:prod && npm run node:prod", 14 | "clean:dev": "cross-env NODE_ENV=development node utils/clean.js", 15 | "clean:staging": "cross-env NODE_ENV=staging node utils/clean.js", 16 | "clean:prod": "cross-env NODE_ENV=production node utils/clean.js", 17 | "migrate:dev": "cd server && cross-env NODE_ENV=development ../node_modules/.bin/sequelize db:migrate", 18 | "migrate:staging": "cd server && cross-env NODE_ENV=staging ../node_modules/.bin/sequelize db:migrate", 19 | "migrate:prod": "cd server && cross-env NODE_ENV=production ../node_modules/.bin/sequelize db:migrate", 20 | "node:staging": "pm2 start config/staging.json", 21 | "node:prod": "pm2 start config/prod.json", 22 | "build:prod": "npm run webpack:prod", 23 | "webpack:prod": "cross-env NODE_ENV=production webpack --progress --hide-modules --mode production", 24 | "webpack:dev": "cross-env NODE_ENV=development webpack --progress --hide-modules --mode development" 25 | }, 26 | "devDependencies": { 27 | "babel-core": "^6.26.3", 28 | "babel-eslint": "^8.2.6", 29 | "babel-loader": "^7.1.5", 30 | "babel-polyfill": "^6.26.0", 31 | "babel-preset-env": "^1.7.0", 32 | "cross-env": "^5.2.1", 33 | "css-loader": "^0.28.11", 34 | "eslint": "^4.19.1", 35 | "eslint-config-standard": "^12.0.0", 36 | "eslint-loader": "^2.2.1", 37 | "eslint-plugin-import": "^2.20.1", 38 | "eslint-plugin-node": "^6.0.1", 39 | "eslint-plugin-promise": "^3.8.0", 40 | "eslint-plugin-standard": "^3.1.0", 41 | "eslint-plugin-vue": "^4.7.1", 42 | "eventsource-polyfill": "^0.9.6", 43 | "extract-text-webpack-plugin": "^3.0.2", 44 | "hoek": "^5.0.4", 45 | "html-webpack-plugin": "^3.2.0", 46 | "isomorphic-fetch": "^2.2.1", 47 | "mini-css-extract-plugin": "^0.4.5", 48 | "nodemon": "^1.19.4", 49 | "path": "^0.12.7", 50 | "pm2": "^2.10.4", 51 | "postcss-loader": "^2.1.6", 52 | "sass-loader": "^7.3.1", 53 | "style-loader": "^0.21.0", 54 | "vue-loader": "^15.9.0", 55 | "vue-template-compiler": "^2.6.11", 56 | "webpack": "^4.42.0", 57 | "webpack-cli": "^2.1.5", 58 | "webpack-merge": "^4.2.2" 59 | }, 60 | "dependencies": { 61 | "body-parser": "^1.19.0", 62 | "connect-history-api-fallback": "^1.6.0", 63 | "dayjs": "^1.8.22", 64 | "es6-promise": "^4.2.8", 65 | "express": "^4.17.1", 66 | "fs": "0.0.1-security", 67 | "helmet": "^3.21.3", 68 | "helmet-csp": "^2.9.5", 69 | "lodash": "^4.17.15", 70 | "node-sass": "^7.0.0", 71 | "pg": "^7.18.2", 72 | "sequelize": "^4.44.4", 73 | "vue": "^2.6.11", 74 | "vue-localstorage": "^0.6.2", 75 | "vue-router": "^3.1.6", 76 | "webpack-dev-middleware": "^3.7.2", 77 | "webpack-hot-middleware": "^2.25.0", 78 | "winston": "^2.4.4" 79 | } 80 | } 81 | --------------------------------------------------------------------------------