├── .gitignore
├── LICENSE
├── README.md
├── config.js
├── controllers
└── helloWorld.js
├── db
└── db.js
├── flightplan.js
├── models
└── helloWorld.js
├── package-lock.json
├── package.json
├── routes
└── helloWorld.js
└── server.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 maciej jordanek
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # express-simple
2 | > A project for fast development of REST APIs, where routes can return JSON documents
3 |
4 | Simple starter, barebone structure based on ExpressJS. Helps to easily create controllers for routes. Provides Flightplan file for simple deployment strategy.
5 |
6 | This project uses the following libraries:
7 | - [Express](https://www.npmjs.com/package/express)
8 | - [Helmet](https://www.npmjs.com/package/helmet)
9 | - [Morgan](https://www.npmjs.com/package/morgan)
10 | - [Body-parser](https://www.npmjs.com/package/body-parser)
11 | - [Flightplan](https://www.npmjs.com/package/flightplan)
12 | - [Fly](https://www.npmjs.com/package/fly)
13 |
14 | ## Installation
15 | Open your terminal and run the following commands:
16 | ```
17 | git clone https://github.com/mjrdnk/express-simple
18 | cd express-simple/ && npm install
19 | ```
20 | ## Usage
21 | To run express-simple in development, run this command from your project directory:
22 |
23 | ```
24 | npm run dev
25 | ```
26 |
27 | To run express-simple in production, run this command from your project directory:
28 |
29 | ```
30 | npm start
31 | ```
32 |
33 | Then, go to http://localhost:5000/api/v1.0/hello
34 |
35 | You will see this screen in your browser
36 |
37 |
38 |
39 | ## Examples
40 |
41 | #### Example : nexmo sms service
42 | To write your custom controllers write your functions in a file and export the module, like this:
43 | ```javascript
44 | const Nexmo = require('nexmo');
45 |
46 | function nexmo () {
47 | this.nexmo = {}
48 | this.apiKey = yourapiKey; // get your api key and secret from nexmo.com
49 | this.apiSecret = yourapiSecret;
50 | this.sendSms = sendSms;
51 | }
52 |
53 | this.nex = new Nexmo ({
54 | apiKey : this.apiKey,
55 | apiSecret : this.apiSecret
56 | });
57 |
58 | let sendSms = (from,to,message) => {
59 | this.nex.message.sendSms(from, to, message, (err,responseData) => {
60 | if (err) {
61 | console.log('err', err.message);
62 | return;
63 | }
64 | });
65 | }
66 | module.exports = nexmo;
67 | ```
68 |
69 | The controller can be reused in a router nexmo.route.js file, like this:
70 | ```javascript
71 | const router = require(express).Router();
72 |
73 | const NexmoController = require('../controllers/nexmo.js');
74 |
75 | router.get('/sms', NexmoController.sendSms);
76 |
77 | module.export = router
78 | ```
79 |
80 | Then you can use it in your server.js file, like this:
81 | ```javascript
82 | const nexmo = require('./routes/nexmo.route.js');
83 |
84 | app.use(API_BASE, nexmo);
85 | ```
86 |
87 | ## Enviroment Variables
88 |
89 | #### `$SSH_AUTH_SOCK`
90 | Contains the path of the unix file socket that the agent uses for communication with other processes. This is essential for `ssh-add`. [See more details](http://blog.joncairns.com/2013/12/understanding-ssh-agent-and-ssh-add/).
91 |
92 |
93 | ## Credit
94 | Flightplan based on [this gist](https://gist.github.com/learncodeacademy/35045e64d2bbe6eb14f9)
95 |
96 | ## License
97 |
98 | [MIT](LICENSE)
99 |
--------------------------------------------------------------------------------
/config.js:
--------------------------------------------------------------------------------
1 | // place for your constants
2 | // !!! note for production: sensitive data should be included in environmental variables
3 |
4 | module.exports = {
5 | API_BASE: '/api/v1.0'
6 | };
--------------------------------------------------------------------------------
/controllers/helloWorld.js:
--------------------------------------------------------------------------------
1 | // place for your controller's functions
2 |
3 | // HelloWorldController defines methods
4 | // you can import them in your the corresponding route file in routes/ folder
5 | let HelloWorldController = {
6 | get: get
7 | };
8 |
9 | function get (req, res, next) {
10 | res.json({
11 | 'hello world': 'hello world'
12 | });
13 | }
14 |
15 | module.exports = HelloWorldController;
--------------------------------------------------------------------------------
/db/db.js:
--------------------------------------------------------------------------------
1 | // place for your database configuration
--------------------------------------------------------------------------------
/flightplan.js:
--------------------------------------------------------------------------------
1 | // run on your deployment machine by typing executing:
2 | // fly development or fly production
3 |
4 | var plan = require('flightplan');
5 |
6 | var appName = 'API_NAME';
7 | var username = 'USERNAME'; // username on server machine
8 | var startFile = 'server.js';
9 |
10 | var tmpDir = appName+'-' + new Date().getTime();
11 |
12 | // configuration
13 | plan.target('development', [
14 | {
15 | host: 'HOST_IP',
16 | username: username,
17 | agent: process.env.SSH_AUTH_SOCK
18 | }
19 | ]);
20 |
21 | plan.target('production', [
22 | {
23 | host: 'HOST_IP',
24 | username: username,
25 | agent: process.env.SSH_AUTH_SOCK
26 | },
27 | //add in another server if you have more than one
28 | // {
29 | // host: '104.131.93.216',
30 | // username: username,
31 | // agent: process.env.SSH_AUTH_SOCK
32 | // }
33 | ]);
34 |
35 | // run commands on localhost
36 | plan.local(function(local) {
37 | // uncomment these if you need to run a build on your machine first
38 | // local.log('Run build');
39 | // local.exec('gulp build');
40 |
41 | local.log('Copy files to remote hosts');
42 | var filesToCopy = local.exec('git ls-files', {silent: true});
43 | // rsync files to all the destination's hosts
44 | local.transfer(filesToCopy, '/tmp/' + tmpDir);
45 | });
46 |
47 | // run commands on remote hosts (destinations)
48 | plan.remote(function(remote) {
49 | remote.log('Move folder to root');
50 | remote.sudo('cp -R /tmp/' + tmpDir + ' ~', {user: username});
51 | remote.rm('-rf /tmp/' + tmpDir);
52 |
53 | remote.log('Install dependencies');
54 | remote.sudo('npm --production --prefix ~/' + tmpDir + ' install ~/' + tmpDir, {user: username});
55 |
56 | remote.log('Reload application');
57 | remote.sudo('ln -snf ~/' + tmpDir + ' ~/'+appName, {user: username});
58 |
59 | remote.exec('cd ~/'+ appName + '&&' + 'forever start ./' + startFile, {failsafe: true});
60 | remote.exec('cd ~/'+ appName + '&&' + 'forever start ./' + startFile);
61 | });
62 |
--------------------------------------------------------------------------------
/models/helloWorld.js:
--------------------------------------------------------------------------------
1 | // place for your ODM models
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "weendify-api",
3 | "version": "0.0.5",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "base64url": {
8 | "version": "2.0.0",
9 | "resolved": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz",
10 | "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs="
11 | },
12 | "buffer-equal-constant-time": {
13 | "version": "1.0.1",
14 | "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
15 | "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk="
16 | },
17 | "ecdsa-sig-formatter": {
18 | "version": "1.0.9",
19 | "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz",
20 | "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=",
21 | "requires": {
22 | "base64url": "2.0.0",
23 | "safe-buffer": "5.1.1"
24 | }
25 | },
26 | "hoek": {
27 | "version": "2.16.3",
28 | "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz",
29 | "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0="
30 | },
31 | "isemail": {
32 | "version": "1.2.0",
33 | "resolved": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz",
34 | "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo="
35 | },
36 | "joi": {
37 | "version": "6.10.1",
38 | "resolved": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz",
39 | "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=",
40 | "requires": {
41 | "hoek": "2.16.3",
42 | "isemail": "1.2.0",
43 | "moment": "2.19.1",
44 | "topo": "1.1.0"
45 | }
46 | },
47 | "jsonwebtoken": {
48 | "version": "7.4.3",
49 | "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.3.tgz",
50 | "integrity": "sha1-d/UCHeBYtgWheD+hKD6ZgS5kVjg=",
51 | "requires": {
52 | "joi": "6.10.1",
53 | "jws": "3.1.4",
54 | "lodash.once": "4.1.1",
55 | "ms": "2.0.0",
56 | "xtend": "4.0.1"
57 | }
58 | },
59 | "jwa": {
60 | "version": "1.1.5",
61 | "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz",
62 | "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=",
63 | "requires": {
64 | "base64url": "2.0.0",
65 | "buffer-equal-constant-time": "1.0.1",
66 | "ecdsa-sig-formatter": "1.0.9",
67 | "safe-buffer": "5.1.1"
68 | }
69 | },
70 | "jws": {
71 | "version": "3.1.4",
72 | "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz",
73 | "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=",
74 | "requires": {
75 | "base64url": "2.0.0",
76 | "jwa": "1.1.5",
77 | "safe-buffer": "5.1.1"
78 | }
79 | },
80 | "lodash.once": {
81 | "version": "4.1.1",
82 | "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
83 | "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
84 | },
85 | "moment": {
86 | "version": "2.19.1",
87 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.19.1.tgz",
88 | "integrity": "sha1-VtoaLRy/AdOLfhr8McELz6GSkWc="
89 | },
90 | "ms": {
91 | "version": "2.0.0",
92 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
93 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
94 | },
95 | "nexmo": {
96 | "version": "2.0.2",
97 | "resolved": "https://registry.npmjs.org/nexmo/-/nexmo-2.0.2.tgz",
98 | "integrity": "sha1-Flsgr3sKVmiQcUt+v1O+ZF8Flv0=",
99 | "requires": {
100 | "jsonwebtoken": "7.4.3",
101 | "uuid": "2.0.3"
102 | }
103 | },
104 | "safe-buffer": {
105 | "version": "5.1.1",
106 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
107 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg=="
108 | },
109 | "topo": {
110 | "version": "1.1.0",
111 | "resolved": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz",
112 | "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=",
113 | "requires": {
114 | "hoek": "2.16.3"
115 | }
116 | },
117 | "uuid": {
118 | "version": "2.0.3",
119 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
120 | "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho="
121 | },
122 | "xtend": {
123 | "version": "4.0.1",
124 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
125 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
126 | }
127 | }
128 | }
129 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-simple-api",
3 | "version": "0.0.5",
4 | "description": "",
5 | "main": "server.js",
6 | "scripts": {
7 | "dev": "nodemon server.js",
8 | "start": "node server.js",
9 | "test": "echo \"Error: no test specified\" && exit 1"
10 | },
11 | "author": "",
12 | "license": "ISC",
13 | "dependencies": {
14 | "body-parser": "^1.15.2",
15 | "express": "^4.14.0",
16 | "helmet": "^3.1.0",
17 | "morgan": "^1.7.0"
18 | },
19 | "devDependencies": {
20 | "flightplan": "^0.6.15",
21 | "fly": "^2.0.4",
22 | "nodemon": "^1.12.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/routes/helloWorld.js:
--------------------------------------------------------------------------------
1 | let express = require('express');
2 | let router = express.Router();
3 |
4 | let HelloWorldController = require('../controllers/helloWorld.js');
5 |
6 | // .get is a method which 'sits' on HelloWorldController
7 | // for more check controllers/helloWorld.js
8 | router.get('/hello', HelloWorldController.get);
9 |
10 | module.exports = router;
11 |
--------------------------------------------------------------------------------
/server.js:
--------------------------------------------------------------------------------
1 | let express = require('express');
2 | let path = require('path');
3 | let bodyParser = require('body-parser');
4 | let morgan = require('morgan');
5 | let helmet = require('helmet');
6 | let config = require('./config.js');
7 | let app = express()
8 |
9 | let port = config.PORT || '5000';
10 | let API_BASE = config.API_BASE;
11 | let helloWorld = require('./routes/helloWorld.js');
12 |
13 | app.use(function(req, res, next) {
14 | res.setHeader("Access-Control-Allow-Origin", "*");
15 | res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
16 | res.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
17 | next();
18 | });
19 | app.use(helmet());
20 | app.use(morgan('dev'));
21 | app.use(bodyParser.json());
22 | app.use(bodyParser.urlencoded({
23 | extended: false
24 | }));
25 |
26 | app.use(API_BASE, helloWorld);
27 |
28 | app.listen(port, function() {
29 | console.log('express-simple is running on port ', port);
30 | });
31 |
--------------------------------------------------------------------------------