1 | [![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![MIT License][license-image]][license-url] [![Build Status][travis-image]][travis-url]
|
2 |
|
3 | # Novation-Mobile
|
4 |
|
5 | Novation-Mobile is a framework using a NodeJS/MongoDB + Mongoose/Socket.IO/Redis stack. It was built by [Novation Mobile](http://www.novationmobile.com) to create scaleable Node.js servers with an emphasis on quick, standardized development.
|
6 |
|
7 | Get the source from [GitHub](https://github.com/chapinkapa/novation-mobile) or install via NPM
|
8 |
|
9 | npm install novation-mobile --save
|
10 |
|
11 | **Note:** this will take a while. We include all the dependencies to run this.
|
12 |
|
13 | ## Version
|
14 |
|
15 | 0.5.0
|
16 |
|
17 | ## How to use
|
18 |
|
19 | In a web.js file at your project root, use the following to set up a novation-mobile server:
|
20 |
|
21 | var nm = require('novation-mobile');
|
22 |
|
23 | var config = {
|
24 | appName: 'ExampleApp',
|
25 | server: 'Main',
|
26 | port: process.argv[2] || 4050,
|
27 | useStaticServer: true,
|
28 | favicon: 'favicon.ico',
|
29 | envLocation: '_env.js',
|
30 | preContent: 'routes.js',
|
31 | postContent: 'routes2.js',
|
32 | mongooseSchemaLocation: '_schema.js',
|
33 | viewEngine: 'jade',
|
34 | viewDirectory: 'views',
|
35 | publicDirectory: 'public',
|
36 | servers: ['Main:' + os.hostname()],
|
37 | logger: {
|
38 | userName: '',
|
39 | password: ''
|
40 | },
|
41 | api: {
|
42 | location: 'api'
|
43 | },
|
44 | onlineUsersConfig: {
|
45 | timer:900
|
46 | }
|
47 | };
|
48 |
|
49 | nm.extra(__dirname).server(config);
|
50 |
|
51 | Each option should be customized for your app.
|
52 |
|
53 | #### Config Options:
|
54 |
|
55 | 1. **appName**: Name of your app.
|
56 | 1. **server**: Name of the server that the current code is running on.
|
57 | 1. **port:** What port to run server on. Defaults to process.env.PORT and then to 4050.
|
58 | 1. **useStaticServer:** Wether to allow the server to act as a static server for a specified folder. Used with viewEngine, viewDirectory, and publicDirectory. Defaults to true.
|
59 | 1. **favicon:** Location of your favicon. Defaults to 'public'.
|
60 | 1. **[envLocation](#environmental-variables)**: Location of your environmental variables.
|
61 | 1. **[preContent](#routes)**: Location of your routes that run before api routes.
|
62 | 1. **[postContent](#routes)**: Location of your routes that run after api routes.
|
63 | 1. **[mongooseSchemaLocation](#mongoose-schema)**: Location of your mongoose schema. Defaults to '_schema.js'.
|
64 | 1. **viewEngine:** Which view engine to use. Example: jade, html, handlebars, etc.
|
65 | 1. **viewEngine:** Which directory to be used to serve views, if using dynamic views.
|
66 | 1. **publicDirectory:** Which directory to be used as your 'static folder.'
|
67 | 1. **servers**: An array of servers that is used by redis-logger and socket.io-online-users.
|
68 | 1. **logger.username**: username to access the redis-logger
|
69 | 1. **logger.password**: password to access the redis-logger
|
70 | 1. **[api.location](#standard-apis)**: Location of your api folder.
|
71 | 1. **[api.version](#standard-apis)**: The version number the server should use for internal calls.
|
72 | 1. **[api.addSocketsToRoom](#standard-apis)**: A function that is called every API call that allows you to add a socket/user to a room for socket.io. The function has two arguments: (session, socket);
|
73 | 1. **onlineUsersConfig:** An object with configuration options to use socket.io-online-users.
|
74 | 1. **onlineUsersConfig.timer**: The buffer time until the server updates the server with who is online.
|
75 | 1. **ssl**: An object of options to use ssl on your node server.
|
76 | 1. **ssl.key:** Location of key file to use.
|
77 | 1. **ssl.cert:** Location of the cert file to use.
|
78 | 1. **ssl.port:** Port to have your node.js https server run on.
|
79 | 1. **sslRedirect:** Redirect http to https.
|
80 | 1. **dontUseRedisTTL:** do not use a ttl for redis.
|
81 | 1. **ttl:** Time in seconds until redis expires documents. Defaults to 3600.
|
82 |
|
83 | ## Components
|
84 |
|
85 | ### Environmental Variables
|
86 |
|
87 | ##### Location: _env.js
|
88 |
|
89 | Allows you to set environment variables used throughout the app:
|
90 |
|
91 | exports.configureEnvironment = function(app, process) {
|
92 | // required variables
|
93 | process.env['SESSION_KEY'] = 'my_express.sid';
|
94 | process.env['SESSION_SECRET'] = 'exampleSecret';
|
95 | process.env['COOKIE_KEY'] = 'ExampleCookie';
|
96 | process.env.MONGO_URI = '';
|
97 | process.env.REDIS_URI = 'redis://redis:redis@ip:port/dbindex';
|
98 |
|
99 | // add your own
|
100 | process.env['SOME_API_KEY'] = 'aaa111nnn123';
|
101 | };
|
102 |
|
103 | ### Routes
|
104 |
|
105 | ##### Location: routes.js
|
106 |
|
107 | Allows you to create custom routes for your app.
|
108 |
|
109 | exports.content = function(app, io) {
|
110 | // you can use this page for additional, custom routes
|
111 | app.get('/', function(req, res, next) {
|
112 | res.send('This is an example server');
|
113 | });
|
114 | };
|
115 |
|
116 | ### Standard APIs
|
117 |
|
118 | ##### Location: api/
|
119 |
|
120 | Allows you to create APIs that can be accessed by both socket.io and by RESTful requests.
|
121 |
|
122 | Say I want to call the function 'run' under 'SomeAPI'. I can request the API either using ``http://localhost:4050/api/SomeAPI/run`` or by using sockets on the client:
|
123 |
|
124 | socket.emit('api', 'SomeAPI', 'run', {
|
125 | testData: 'I Am Groot'
|
126 | }, function(err, data) {
|
127 | if (err) {
|
128 | console.log(err);
|
129 | } else {
|
130 | console.log(data);
|
131 | }
|
132 | });
|
133 |
|
134 | The contents of ``api/SomeAPI.js`` then look like:
|
135 |
|
136 | exports.run = function() {
|
137 | console.log(data.testData); // prints "I Am Groot"
|
138 |
|
139 | var number = Math.random();
|
140 | if (number < .5) {
|
141 | return fn('This is a standard error message.');
|
142 | } else {
|
143 | return fn(null, {
|
144 | data: 'This the standard way to send data back to the client.'
|
145 | });
|
146 | }
|
147 | };
|
148 |
|
149 | Extras has the following properties:
|
150 | - ``mongoose`` - access to the mongoose variable.
|
151 | - ``io``
|
152 | - ``socket`` - the particular socket connection, if available
|
153 | - ``connectionType`` - either socket or http.
|
154 | - ``fileName`` - the file that the API is being hit by.
|
155 | - ``req`` - if available
|
156 | - ``res`` - if available
|
157 | - ``method`` - the method that is being called.
|
158 | - ``ipAddress``
|
159 | - ``hostname``
|
160 |
|
161 | ###### API Middleware Example
|
162 |
|
163 | function testSession(data,fn,session,extras,next){
|
164 | if(!session){
|
165 | return fn("You have to have a session for this.");
|
166 | } else {
|
167 | return next();
|
168 | }
|
169 | }
|
170 |
|
171 | exports.testSession=API2(testSession,testSession,function(data,fn,session,extras){
|
172 | fn(null, 'You have a session!');
|
173 | });
|
174 |
|
175 | exports.fn=function(){
|
176 | fn(null, 'yay!!');
|
177 | };
|
178 |
|
179 | exports.staticVariacle=1;
|
180 |
|
181 | ## next()
|
182 |
|
183 | Next allows you to run the next functon in the iteration. If you want to skip all middleware except the last function, run next({
|
184 | finish: true
|
185 | }).
|
186 |
|
187 | Also, if you use the middleware and do not provide a connectionType in extras, API2 will add 'internal' to the connectionType.
|
188 |
|
189 | ## after()
|
190 |
|
191 | If you want to run an API after another API is complete, you may add an after() call to the middleware.
|
192 |
|
193 | var middleware = API('middleware');
|
194 | var afterware = API('afterware');
|
195 |
|
196 | exports.run = API2(middleware.checkCredentials, function(data, fn, session, extras) {
|
197 |
|
198 | if (!data) {
|
199 | return fn('You did not send any data.');
|
200 | }
|
201 |
|
202 | var number = Math.random();
|
203 | console.log('We are sending back this number::', number);
|
204 | return fn(null, number);
|
205 |
|
206 | });
|
207 |
|
208 | exports.run.after(afterware.testLog);
|
209 |
|
210 | In the above example, the ``run()`` API will use middleware to check access credentials. If the credentials middleware finishes successfully, our API does its work. As soon as ``fn(null, number)`` is called, the afterware API called ``eventLog`` is triggered. What happens inside the afterware API has no impact on what the ``run()`` API does. An afterware API gets the parameters ``err, res, data, session, extras``, and might look something like:
|
211 |
|
212 | exports.testLog = function(err, res, data, session, extras) {
|
213 | if (err) {
|
214 | return console.log('The API experienced an error. Log the error to the DB.')
|
215 | } else {
|
216 | return console.log('We can log the number ' + res + ' to the DB.');
|
217 | }
|
218 | };
|
219 |
|
220 | ## API Promises
|
221 |
|
222 | With 0.5.0 we are introducing promises for our APIs. To turn any of our APIs as a promise, run API.Q.
|
223 | Although it should be compatible with several promise libraries, I recommend using the module, [q](https://www.npmjs.org/package/q).
|
224 |
|
225 | var User = API.Q('User');
|
226 |
|
227 | User.getData({},'session','extras').then(function(){
|
228 | console.log('success',arguments);
|
229 | },function(){
|
230 | console.log('fail',arguments);
|
231 | });
|
232 |
|
233 | ### Mongoose Schema
|
234 |
|
235 | ##### Location: schema.js
|
236 |
|
237 | Allows you to create a mongoose schema that can be used throughout your app. Configure your file to look like this:
|
238 |
|
239 | var mongoose = require('mongoose');
|
240 | var Schema = mongoose.Schema;
|
241 |
|
242 | exports.User = mongoose.model('User', new Schema({
|
243 | firstName: String,
|
244 | lastName: String,
|
245 | fullName: String
|
246 | }));
|
247 |
|
248 | **Note:** everything you export in here will be attached to the global scope. It will be accessible throughout your whole server.
|
249 |
|
250 |
|
251 | [license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
|
252 | [license-url]: https://github.com/chapinkapa/novation-mobile/blob/master/LICENSE
|
253 |
|
254 | [npm-version-image]: http://img.shields.io/npm/v/novation-mobile.svg?style=flat-square
|
255 | [npm-downloads-image]: http://img.shields.io/npm/dm/novation-mobile.svg?style=flat-square
|
256 | [npm-url]: https://npmjs.org/package/novation-mobile
|
257 |
|
258 | [travis-image]: http://img.shields.io/travis/chapinkapa/novation-mobile.svg?style=flat-square
|
259 | [travis-url]: http://travis-ci.org/chapinkapa/novation-mobile |
\ | No newline at end of file |