├── .env.default ├── .gitignore ├── LICENSE.md ├── README.md ├── app.js ├── bin └── www ├── controllers └── .gitkeep ├── db.js ├── models └── .gitkeep ├── package.json ├── postcss.config.js ├── public ├── css │ └── style.css └── js │ └── home.bundle.js ├── routes ├── index.js └── users.js ├── src ├── home.js └── scss │ └── style.scss ├── tests └── default-test.js ├── views ├── error.hbs ├── index.hbs └── partials │ ├── footer-end.hbs │ ├── footer.hbs │ └── header.hbs ├── webpack.config.js └── yarn.lock /.env.default: -------------------------------------------------------------------------------- 1 | NODE_ENV= 2 | 3 | DB_HOST= 4 | DB_USER= 5 | DB_PASSWORD= 6 | DB_NAME= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Dependency directory 26 | # https://docs.npmjs.com/cli/shrinkwrap#caveats 27 | node_modules 28 | 29 | # Debug log from npm 30 | npm-debug.log 31 | 32 | # Webpack source maps 33 | *.map 34 | 35 | # Local env file with credentials 36 | .env 37 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | -- 4 | 5 | Copyright © 2017-2018 Chris Courses 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## NOTICE 2 | 3 | This repo will be deprecated once the new Chris Courses Node Auth series is released on YouTube. 4 | 5 | The new series uses the custom Chris Courses web app framework, [Voyager](https://github.com/chriscourses/voyager), which is a much more robust and scalable solution than express-cc. Please check it out in the meantime during the wait for the new series. 6 | 7 | ## License 8 | 9 | express-cc is an open-source framework running under the [MIT License](https://opensource.org/licenses/MIT). 10 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var path = require('path'); 3 | var favicon = require('serve-favicon'); 4 | var logger = require('morgan'); 5 | var cookieParser = require('cookie-parser'); 6 | var bodyParser = require('body-parser'); 7 | 8 | var index = require('./routes/index'); 9 | var users = require('./routes/users'); 10 | 11 | var app = express(); 12 | 13 | require('dotenv').config(); 14 | 15 | // view engine setup 16 | app.set('views', path.join(__dirname, 'views')); 17 | app.set('view engine', 'hbs'); 18 | 19 | // uncomment after placing your favicon in /public 20 | //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); 21 | app.use(logger('dev')); 22 | app.use(bodyParser.json()); 23 | app.use(bodyParser.urlencoded({ extended: false })); 24 | app.use(cookieParser()); 25 | app.use(express.static(path.join(__dirname, 'public'))); 26 | 27 | app.use('/', index); 28 | app.use('/users', users); 29 | 30 | // catch 404 and forward to error handler 31 | app.use(function(req, res, next) { 32 | var err = new Error('Not Found'); 33 | err.status = 404; 34 | next(err); 35 | }); 36 | 37 | // error handler 38 | app.use(function(err, req, res, next) { 39 | // set locals, only providing error in development 40 | res.locals.message = err.message; 41 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 42 | 43 | // render the error page 44 | res.status(err.status || 500); 45 | res.render('error'); 46 | }); 47 | 48 | 49 | // Handlebars default config 50 | const hbs = require('hbs'); 51 | const fs = require('fs'); 52 | 53 | const partialsDir = __dirname + '/views/partials'; 54 | 55 | const filenames = fs.readdirSync(partialsDir); 56 | 57 | filenames.forEach(function (filename) { 58 | const matches = /^([^.]+).hbs$/.exec(filename); 59 | if (!matches) { 60 | return; 61 | } 62 | const name = matches[1]; 63 | const template = fs.readFileSync(partialsDir + '/' + filename, 'utf8'); 64 | hbs.registerPartial(name, template); 65 | }); 66 | 67 | hbs.registerHelper('json', function(context) { 68 | return JSON.stringify(context, null, 2); 69 | }); 70 | 71 | 72 | module.exports = app; 73 | -------------------------------------------------------------------------------- /bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('cc-express:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /controllers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christopher4lis/express-cc/c0cb97ba228cffe65efaf69a3b79a75c55629c3f/controllers/.gitkeep -------------------------------------------------------------------------------- /db.js: -------------------------------------------------------------------------------- 1 | var mysql = require('mysql') 2 | var connection = mysql.createConnection({ 3 | host: process.env.DB_HOST, 4 | user: process.env.DB_USER, 5 | password: process.env.DB_PASSWORD, 6 | database : process.env.DB_NAME 7 | }) 8 | 9 | connection.connect() 10 | 11 | module.exports = connection; -------------------------------------------------------------------------------- /models/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/christopher4lis/express-cc/c0cb97ba228cffe65efaf69a3b79a75c55629c3f/models/.gitkeep -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cc-express", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "body-parser": "~1.15.2", 10 | "cookie-parser": "~1.4.3", 11 | "debug": "~2.2.0", 12 | "express": "~4.14.0", 13 | "hbs": "~4.0.1", 14 | "morgan": "~1.7.0", 15 | "mysql": "^2.13.0", 16 | "serve-favicon": "~2.3.0" 17 | }, 18 | "devDependencies": { 19 | "babel-core": "^6.24.1", 20 | "babel-loader": "^7.0.0", 21 | "babel-preset-env": "^1.4.0", 22 | "browser-sync": "^2.18.8", 23 | "browser-sync-webpack-plugin": "^1.1.4", 24 | "chai": "^3.5.0", 25 | "css-loader": "^0.25.0", 26 | "extract-text-webpack-plugin": "^2.1.0", 27 | "mocha": "^3.4.1", 28 | "node-sass": "^3.13.0", 29 | "postcss-loader": "^1.1.1", 30 | "sass-loader": "^4.0.2", 31 | "style-loader": "^0.13.1", 32 | "webpack": "^2.2.0", 33 | "webpack-dotenv-plugin": "^2.0.0" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer')({ /* ...options */ }) 4 | ] 5 | }; -------------------------------------------------------------------------------- /public/css/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; } 3 | 4 | /*# sourceMappingURL=style.css.map*/ -------------------------------------------------------------------------------- /public/js/home.bundle.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) { 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ } 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ i: moduleId, 15 | /******/ l: false, 16 | /******/ exports: {} 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.l = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // identity function for calling harmony imports with the correct context 37 | /******/ __webpack_require__.i = function(value) { return value; }; 38 | /******/ 39 | /******/ // define getter function for harmony exports 40 | /******/ __webpack_require__.d = function(exports, name, getter) { 41 | /******/ if(!__webpack_require__.o(exports, name)) { 42 | /******/ Object.defineProperty(exports, name, { 43 | /******/ configurable: false, 44 | /******/ enumerable: true, 45 | /******/ get: getter 46 | /******/ }); 47 | /******/ } 48 | /******/ }; 49 | /******/ 50 | /******/ // getDefaultExport function for compatibility with non-harmony modules 51 | /******/ __webpack_require__.n = function(module) { 52 | /******/ var getter = module && module.__esModule ? 53 | /******/ function getDefault() { return module['default']; } : 54 | /******/ function getModuleExports() { return module; }; 55 | /******/ __webpack_require__.d(getter, 'a', getter); 56 | /******/ return getter; 57 | /******/ }; 58 | /******/ 59 | /******/ // Object.prototype.hasOwnProperty.call 60 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 61 | /******/ 62 | /******/ // __webpack_public_path__ 63 | /******/ __webpack_require__.p = ""; 64 | /******/ 65 | /******/ // Load entry module and return exports 66 | /******/ return __webpack_require__(__webpack_require__.s = 1); 67 | /******/ }) 68 | /************************************************************************/ 69 | /******/ ([ 70 | /* 0 */ 71 | /***/ (function(module, exports) { 72 | 73 | // removed by extract-text-webpack-plugin 74 | 75 | /***/ }), 76 | /* 1 */ 77 | /***/ (function(module, exports, __webpack_require__) { 78 | 79 | "use strict"; 80 | 81 | 82 | __webpack_require__(0); 83 | 84 | /***/ }) 85 | /******/ ]); 86 | //# sourceMappingURL=home.bundle.js.map -------------------------------------------------------------------------------- /routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | res.render('index', { title: 'Express' }); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /routes/users.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET users listing. */ 5 | router.get('/', function(req, res, next) { 6 | res.send('respond with a resource'); 7 | }); 8 | 9 | module.exports = router; 10 | -------------------------------------------------------------------------------- /src/home.js: -------------------------------------------------------------------------------- 1 | require('./scss/style.scss'); -------------------------------------------------------------------------------- /src/scss/style.scss: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | } -------------------------------------------------------------------------------- /tests/default-test.js: -------------------------------------------------------------------------------- 1 | const assert = require('chai').assert; 2 | 3 | describe('1 + 1', function() { 4 | it('should equal 2', function() { 5 | assert.strictEqual((1 + 1), 2); 6 | }); 7 | }); -------------------------------------------------------------------------------- /views/error.hbs: -------------------------------------------------------------------------------- 1 |
{{error.stack}}4 | -------------------------------------------------------------------------------- /views/index.hbs: -------------------------------------------------------------------------------- 1 | {{> header }} 2 | 3 |
Welcome to {{title}}
5 | 6 | {{> footer-end }} -------------------------------------------------------------------------------- /views/partials/footer-end.hbs: -------------------------------------------------------------------------------- 1 | 2 | 10 |