Skip to content

Commit c3996fd

Browse files
committed
Version 0.0.1
- Initial implementation of ExpressInitializer - Basic happy path unit tests - README elaborated - Coverage script setup with 90% coverage
1 parent a16f7a5 commit c3996fd

File tree

14 files changed

+649
-0
lines changed

14 files changed

+649
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Logs
22
logs
33
*.log
4+
README.html
45

56
# Runtime data
67
pids
@@ -12,6 +13,7 @@ lib-cov
1213

1314
# Coverage directory used by tools like istanbul
1415
coverage
16+
coverage.html
1517

1618
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
1719
.grunt

.jshintrc

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"node": true,
3+
"browser": true,
4+
"esnext": true,
5+
"bitwise": true,
6+
"camelcase": true,
7+
"curly": true,
8+
"eqeqeq": true,
9+
"immed": true,
10+
"latedef": true,
11+
"newcap": true,
12+
"noarg": true,
13+
"quotmark": "single",
14+
"regexp": true,
15+
"undef": true,
16+
"unused": true,
17+
"trailing": true,
18+
"smarttabs": true,
19+
"white": true
20+
}

README.md

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,196 @@ express-initializers
22
====================
33

44
An Express App initializer pattern to tame large apps.
5+
6+
### Example
7+
8+
Usually your `server.js` or `app.js` is cluttered with a bunch of `app.use` and `app.set` middlewares:
9+
10+
```js
11+
var path = require('path'),
12+
exphbs = require('express3-handlebars'),
13+
express = require('express'),
14+
favicon = require('serve-favicon'),
15+
port = process.env.PORT || 3000,
16+
app = express();
17+
18+
// Set the port for easy access
19+
app.set('port', port);
20+
21+
// Set up favicon serving
22+
app.use(favicon('favicon.ico'));
23+
24+
// Set up the handlebars view engine
25+
var hbs = exphbs.create({
26+
layoutsDir: path.join(__dirname, 'views', 'layouts'),
27+
partialsDir: path.join(__dirname, 'views', 'partials'),
28+
defaultLayout: path.join(__dirname, 'views', 'layouts', 'layout.stache'),
29+
extname: '.stache',
30+
// Specify helpers here
31+
helpers: {
32+
foo: function () { return 'FOO!'; },
33+
bar: function () { return 'BAR!'; }
34+
}
35+
});
36+
app.engine('.stache', hbs.engine);
37+
rname, 'views'));
38+
app.set('view engine', '.stache');
39+
40+
/* etc. */
41+
42+
app.listen(app.get('port'), function () {
43+
console.log('Now listening on port ' + app.get('port'));
44+
});
45+
```
46+
47+
This module aims to let you break each individual middleware configuration into their own file for tidier code. Given an example directory structure like this:
48+
49+
```shell
50+
├── app.js
51+
├── initializers
52+
│   ├── favicon.js
53+
│   ├── port.js
54+
│   ├── routes.js
55+
│   └── views.js
56+
```
57+
58+
Your app setup file would look something like this:
59+
60+
```js
61+
var express = require('express'),
62+
initialize = require('express-initializers'),
63+
64+
app = express();
65+
66+
// Let the initializers run
67+
initialize(app)
68+
.then(function () {
69+
// Start listening for requests
70+
app.listen(app.get('port'), function () {
71+
console.log('Now listening on port ' + app.get('port'));
72+
});
73+
})
74+
.catch(function (err) {
75+
console.log('Unable to initialize app: ' + err.message);
76+
console.log(err.stack);
77+
});
78+
```
79+
80+
And each middleware configuration is moved into its own file. From simple examples like `port.js`:
81+
82+
```js
83+
// initializers/port.js
84+
module.exports = {
85+
configure: function (app) {
86+
app.set('port', process.env.PORT || 3000);
87+
}
88+
};
89+
```
90+
91+
To more complex things like view engines or db initialization:
92+
93+
```js
94+
// initializers/views.js
95+
var path = require('path'),
96+
exphbs = require('express3-handlebars');
97+
98+
module.exports = {
99+
name: 'views',
100+
after: 'static',
101+
102+
configure: function (app) {
103+
// Set up the handlebars view engine
104+
var hbs = exphbs.create({
105+
layoutsDir: path.join(__dirname, 'views', 'layouts'),
106+
partialsDir: path.join(__dirname, 'views', 'partials'),
107+
defaultLayout: path.join(__dirname, 'views', 'layouts', 'layout.stache'),
108+
extname: '.stache',
109+
// Specify helpers here
110+
helpers: {
111+
foo: function () { return 'FOO!'; },
112+
bar: function () { return 'BAR!'; }
113+
}
114+
});
115+
app.engine('.stache', hbs.engine);
116+
117+
app.set('views', path.join(__dirname, 'views'));
118+
app.set('view engine', '.stache');
119+
}
120+
};
121+
```
122+
123+
```js
124+
// initializers/db.js
125+
var db = require('../models/db'),
126+
Promise = require('bluebird');
127+
128+
module.exports = {
129+
configure: function (app) {
130+
return new Promise(function (resolve, reject) {
131+
// Start the db connection
132+
db.init(function (err) {
133+
if (err) {
134+
return reject(new Error('Failed to initialize database: ' + err.message));
135+
}
136+
137+
// Sync all the associations
138+
db.sync(function (err) {
139+
if (err) {
140+
return reject(new Error('Failed to sync database: ' + err.message));
141+
}
142+
143+
app.set('db', db.instance);
144+
145+
resolve();
146+
});
147+
});
148+
});
149+
}
150+
};
151+
```
152+
153+
A more thorough implementation can be seen at [node-site](https://github.com/jgable/node-site).
154+
155+
### Configuration
156+
157+
The `initializers` function returned from `require('express-initializers')` can accept options as the second parameter, and an optional callback as the third parameter (if you really hate promises).
158+
159+
```js
160+
initialize(app, {
161+
// Defaults to the 'initializers' directory relative to the calling file
162+
directory: path.join(__dirname, 'configurers'),
163+
// Defaults to '**/*.js'
164+
fileMatch: '**/*.coffee'
165+
}, function (err) {
166+
if (err) {
167+
throw err;
168+
}
169+
170+
app.listen(app.get('port'));
171+
});
172+
```
173+
174+
### Initializers
175+
176+
Each individual initializer must be a module that exports an object of the form:
177+
178+
```js
179+
module.exports = {
180+
name: 'something',
181+
after: 'otherthing',
182+
183+
configure: function (app) {
184+
app.set('something', 42);
185+
}
186+
};
187+
```
188+
189+
The `name` property can be unique or shared amongst a group of initializers.
190+
191+
The `after` property allows you to order your initializers, it signals that this initializer should be ran after another or a group of other initializers.
192+
193+
The `configure` method can optionally return a promise for asynchronous configuration.
194+
195+
### LICENSE
196+
197+
MIT License, Copyright 2014 [Jacob Gable](https://jacobgable.com)

index.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
var _ = require('lodash'),
2+
path = require('path'),
3+
caller = require('caller'),
4+
Initializer = require('./lib/Initializer'),
5+
ExpressInitializer = require('./lib/ExpressInitializer'),
6+
/*jshint -W079 */
7+
Promise = require('bluebird');
8+
9+
function expressInitializers(app, opts, done) {
10+
opts = _.defaults(opts || {}, {
11+
// Default to the initializers directory where we were called from
12+
directory: path.join(path.dirname(caller()), 'initializers')
13+
});
14+
15+
var init = new ExpressInitializer(opts);
16+
17+
return init.configureApp(app)
18+
.then(function () {
19+
if (_.isFunction(done)) {
20+
done(null, app);
21+
}
22+
23+
return app;
24+
})
25+
.catch(function (err) {
26+
if (_.isFunction(done)) {
27+
done(err);
28+
}
29+
30+
return Promise.reject(err);
31+
});
32+
}
33+
34+
expressInitializers.ExpressInitializer = ExpressInitializer;
35+
expressInitializers.Initializer = Initializer;
36+
37+
module.exports = expressInitializers;

0 commit comments

Comments
 (0)